Commit ef40d943 authored by Russ Cox's avatar Russ Cox

6g:

	make sure methods end up immediately following
	the struct they are methods on.
ar:
	eliminate duplicate definitions from __.PKGDEF.
	check that multiple .6 do not give different defs for same
		exported type/var/func/const.
	increase ar header name size from 16 to 64 bytes

R=r
DELTA=379  (333 added, 18 deleted, 28 changed)
OCL=17477
CL=17481
parent 03a9872f
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#define SARMAG 8 #define SARMAG 8
#define ARFMAG "`\n" #define ARFMAG "`\n"
#define SARNAME 16 #define SARNAME 64
struct ar_hdr struct ar_hdr
{ {
......
...@@ -126,8 +126,6 @@ int errors; ...@@ -126,8 +126,6 @@ int errors;
Arfile *astart, *amiddle, *aend; /* Temp file control block pointers */ Arfile *astart, *amiddle, *aend; /* Temp file control block pointers */
int allobj = 1; /* set when all members are object files of the same type */ int allobj = 1; /* set when all members are object files of the same type */
int symdefsize; /* size of symdef file */ int symdefsize; /* size of symdef file */
int pkgdefsize; /* size of pkgdef data */
char *pkgdata; /* pkgdef data */
char *pkgstmt; /* string "package foo" */ char *pkgstmt; /* string "package foo" */
int dupfound; /* flag for duplicate symbol */ int dupfound; /* flag for duplicate symbol */
Hashchain *hash[NHASH]; /* hash table of text symbols */ Hashchain *hash[NHASH]; /* hash table of text symbols */
...@@ -143,7 +141,8 @@ void arcopy(Biobuf*, Arfile*, Armember*); ...@@ -143,7 +141,8 @@ void arcopy(Biobuf*, Arfile*, Armember*);
int arcreate(char*); int arcreate(char*);
void arfree(Arfile*); void arfree(Arfile*);
void arinsert(Arfile*, Armember*); void arinsert(Arfile*, Armember*);
char *armalloc(int); void *armalloc(int);
char *arstrdup(char*);
void armove(Biobuf*, Arfile*, Armember*); void armove(Biobuf*, Arfile*, Armember*);
void arread(Biobuf*, Armember*, int); void arread(Biobuf*, Armember*, int);
void arstream(int, Arfile*); void arstream(int, Arfile*);
...@@ -151,8 +150,10 @@ int arwrite(int, Armember*); ...@@ -151,8 +150,10 @@ int arwrite(int, Armember*);
int bamatch(char*, char*); int bamatch(char*, char*);
int duplicate(char*); int duplicate(char*);
Armember *getdir(Biobuf*); Armember *getdir(Biobuf*);
void getpkgdef(char**, int*);
int getspace(void); int getspace(void);
void install(char*, Arfile*, Arfile*, Arfile*, int); void install(char*, Arfile*, Arfile*, Arfile*, int);
void loadpkgdata(char*, int);
void longt(Armember*); void longt(Armember*);
int match(int, char**); int match(int, char**);
void mesg(int, char*); void mesg(int, char*);
...@@ -648,9 +649,7 @@ scanpkg(Biobuf *b, long size) ...@@ -648,9 +649,7 @@ scanpkg(Biobuf *b, long size)
long n; long n;
int c; int c;
long start, end, pkgsize; long start, end, pkgsize;
char* data; char *data, *line, pkgbuf[1024], *pkg;
char* line;
char pkg[1024];
int first; int first;
/* /*
...@@ -675,6 +674,7 @@ scanpkg(Biobuf *b, long size) ...@@ -675,6 +674,7 @@ scanpkg(Biobuf *b, long size)
return; return;
foundstart: foundstart:
pkg = nil;
/* how big is it? */ /* how big is it? */
first = 1; first = 1;
start = end = 0; start = end = 0;
...@@ -683,10 +683,15 @@ foundstart: ...@@ -683,10 +683,15 @@ foundstart:
if (line == 0) if (line == 0)
goto bad; goto bad;
if (first && strstrn(line, Blinelen(b), "package ")) { if (first && strstrn(line, Blinelen(b), "package ")) {
if (Blinelen(b) > sizeof(pkg)-1) if (Blinelen(b) > sizeof(pkgbuf)-1)
goto bad;
memmove(pkgbuf, line, Blinelen(b));
pkgbuf[Blinelen(b)] = '\0';
pkg = pkgbuf;
while(*pkg == ' ' || *pkg == '\t')
pkg++;
if(strncmp(pkg, "package ", 8) != 0)
goto bad; goto bad;
memmove(pkg, line, Blinelen(b));
pkg[Blinelen(b)] = '\0';
start = Boffset(b); // after package statement start = Boffset(b); // after package statement
first = 0; first = 0;
continue; continue;
...@@ -702,29 +707,24 @@ bad: ...@@ -702,29 +707,24 @@ bad:
foundend: foundend:
if (start == 0 || end == 0) if (start == 0 || end == 0)
goto bad; goto bad;
if (pkgdefsize == 0) { if (pkgstmt == nil) {
/* this is the first package */ /* this is the first package */
pkgstmt = armalloc(strlen(pkg)+1); pkgstmt = arstrdup(pkg);
strcpy(pkgstmt, pkg);
pkgdefsize = 7 + 3 + strlen(pkg); /* "import\n$$\npackage foo\n" */
pkgdata = armalloc(pkgdefsize);
sprint(pkgdata, "import\n$$\n%s", pkgstmt);
} else { } else {
if (strcmp(pkg, pkgstmt) != 0) { if (strcmp(pkg, pkgstmt) != 0) {
fprint(2, "ar: inconsistent package name\n"); fprint(2, "ar: inconsistent package name\n");
return; return;
} }
} }
pkgsize = end-start; pkgsize = end-start;
data = armalloc(pkgdefsize + pkgsize); /* should chain instead of reallocate */ data = armalloc(pkgsize);
memmove(data, pkgdata, pkgdefsize);
Bseek(b, start, 0); Bseek(b, start, 0);
if (Bread(b, data+pkgdefsize, pkgsize) != pkgsize) { if (Bread(b, data, pkgsize) != pkgsize) {
fprint(2, "ar: error reading package import section in %s\n", file); fprint(2, "ar: error reading package import section in %s\n", file);
return; return;
} }
pkgdefsize += pkgsize; loadpkgdata(data, pkgsize);
pkgdata = data;
} }
/* /*
...@@ -740,11 +740,9 @@ objsym(Sym *s, void *p) ...@@ -740,11 +740,9 @@ objsym(Sym *s, void *p)
if (s->type != 'T' && s->type != 'D') if (s->type != 'T' && s->type != 'D')
return; return;
ap = (Arfile*)p; ap = (Arfile*)p;
as = (Arsymref*)armalloc(sizeof(Arsymref)); as = armalloc(sizeof(Arsymref));
as->offset = ap->size; as->offset = ap->size;
n = strlen(s->name); as->name = arstrdup(s->name);
as->name = armalloc(n+1);
strcpy(as->name, s->name);
if(s->type == 'T' && duplicate(as->name)) { if(s->type == 'T' && duplicate(as->name)) {
dupfound = 1; dupfound = 1;
fprint(2, "duplicate text symbol: %s\n", as->name); fprint(2, "duplicate text symbol: %s\n", as->name);
...@@ -753,6 +751,7 @@ objsym(Sym *s, void *p) ...@@ -753,6 +751,7 @@ objsym(Sym *s, void *p)
return; return;
} }
as->type = s->type; as->type = s->type;
n = strlen(s->name);
symdefsize += 4+(n+1)+1; symdefsize += 4+(n+1)+1;
as->len = n; as->len = n;
as->next = ap->sym; as->next = ap->sym;
...@@ -763,23 +762,32 @@ objsym(Sym *s, void *p) ...@@ -763,23 +762,32 @@ objsym(Sym *s, void *p)
* Check the symbol table for duplicate text symbols * Check the symbol table for duplicate text symbols
*/ */
int int
duplicate(char *name) hashstr(char *name)
{ {
Hashchain *p;
char *cp;
int h; int h;
char *cp;
h = 0; h = 0;
for(cp = name; *cp; h += *cp++) for(cp = name; *cp; h += *cp++)
h *= 1119; h *= 1119;
if(h < 0) if(h < 0)
h = ~h; h = ~h;
h %= NHASH; return h;
}
int
duplicate(char *name)
{
Hashchain *p;
char *cp;
int h;
h = hashstr(name) % NHASH;
for(p = hash[h]; p; p = p->next) for(p = hash[h]; p; p = p->next)
if(strcmp(p->name, name) == 0) if(strcmp(p->name, name) == 0)
return 1; return 1;
p = (Hashchain*) armalloc(sizeof(Hashchain)); p = armalloc(sizeof(Hashchain));
p->next = hash[h]; p->next = hash[h];
p->name = name; p->name = name;
hash[h] = p; hash[h] = p;
...@@ -989,12 +997,16 @@ install(char *arname, Arfile *astart, Arfile *amiddle, Arfile *aend, int createf ...@@ -989,12 +997,16 @@ install(char *arname, Arfile *astart, Arfile *amiddle, Arfile *aend, int createf
void void
rl(int fd) rl(int fd)
{ {
Biobuf b; Biobuf b;
char *cp; char *cp;
struct ar_hdr a; struct ar_hdr a;
long len; long len;
int headlen; int headlen;
char *pkgdefdata;
int pkgdefsize;
pkgdefdata = nil;
pkgdefsize = 0;
Binit(&b, fd, OWRITE); Binit(&b, fd, OWRITE);
Bseek(&b,seek(fd,0,1), 0); Bseek(&b,seek(fd,0,1), 0);
...@@ -1018,7 +1030,8 @@ rl(int fd) ...@@ -1018,7 +1030,8 @@ rl(int fd)
headlen = Boffset(&b); headlen = Boffset(&b);
len += headlen; len += headlen;
if (gflag) { if (gflag) {
len += SAR_HDR + pkgdefsize + 3; /* +3 for "$$\n" */ getpkgdef(&pkgdefdata, &pkgdefsize);
len += SAR_HDR + pkgdefsize;
if (len & 1) if (len & 1)
len++; len++;
} }
...@@ -1037,7 +1050,7 @@ rl(int fd) ...@@ -1037,7 +1050,7 @@ rl(int fd)
Bputc(&b, 0); Bputc(&b, 0);
if (gflag) { if (gflag) {
len = pkgdefsize + 3; /* for "$$\n" at close */ len = pkgdefsize;
sprint(a.date, "%-12ld", time(0)); sprint(a.date, "%-12ld", time(0));
sprint(a.uid, "%-6d", 0); sprint(a.uid, "%-6d", 0);
sprint(a.gid, "%-6d", 0); sprint(a.gid, "%-6d", 0);
...@@ -1051,9 +1064,7 @@ rl(int fd) ...@@ -1051,9 +1064,7 @@ rl(int fd)
if(HEADER_IO(Bwrite, &b, a)) if(HEADER_IO(Bwrite, &b, a))
wrerr(); wrerr();
if (Bwrite(&b, pkgdata, pkgdefsize) != pkgdefsize) if (Bwrite(&b, pkgdefdata, pkgdefsize) != pkgdefsize)
wrerr();
if (Bwrite(&b, "$$\n", 3) != 3)
wrerr(); wrerr();
if(len&0x01) if(len&0x01)
Bputc(&b, 0); Bputc(&b, 0);
...@@ -1242,7 +1253,7 @@ newtempfile(char *name) /* allocate a file control block */ ...@@ -1242,7 +1253,7 @@ newtempfile(char *name) /* allocate a file control block */
{ {
Arfile *ap; Arfile *ap;
ap = (Arfile *) armalloc(sizeof(Arfile)); ap = armalloc(sizeof(Arfile));
ap->fname = name; ap->fname = name;
return ap; return ap;
} }
...@@ -1250,7 +1261,7 @@ newtempfile(char *name) /* allocate a file control block */ ...@@ -1250,7 +1261,7 @@ newtempfile(char *name) /* allocate a file control block */
Armember * Armember *
newmember(void) /* allocate a member buffer */ newmember(void) /* allocate a member buffer */
{ {
return (Armember *)armalloc(sizeof(Armember)); return armalloc(sizeof(Armember));
} }
void void
...@@ -1368,11 +1379,11 @@ getspace(void) ...@@ -1368,11 +1379,11 @@ getspace(void)
{ {
fprint(2, "IN GETSPACE\n"); fprint(2, "IN GETSPACE\n");
if (astart && astart->head && page(astart)) if (astart && astart->head && page(astart))
return 1; return 1;
if (amiddle && amiddle->head && page(amiddle)) if (amiddle && amiddle->head && page(amiddle))
return 1; return 1;
if (aend && aend->head && page(aend)) if (aend && aend->head && page(aend))
return 1; return 1;
return 0; return 0;
} }
...@@ -1395,7 +1406,7 @@ arfree(Arfile *ap) /* free a member buffer */ ...@@ -1395,7 +1406,7 @@ arfree(Arfile *ap) /* free a member buffer */
* fails we try to reclaim space by spilling previously allocated * fails we try to reclaim space by spilling previously allocated
* member buffers. * member buffers.
*/ */
char * void *
armalloc(int n) armalloc(int n)
{ {
char *cp; char *cp;
...@@ -1411,3 +1422,305 @@ armalloc(int n) ...@@ -1411,3 +1422,305 @@ armalloc(int n)
exits("malloc"); exits("malloc");
return 0; return 0;
} }
char *
arstrdup(char *s)
{
char *t;
t = armalloc(strlen(s) + 1);
strcpy(t, s);
return t;
}
/*
* package import data
*/
typedef struct Import Import;
struct Import
{
Import *hash; // next in hash table
int export; // marked as export?
char *prefix; // "type", "var", "func", "const"
char *name;
char *def;
char *file;
};
enum {
NIHASH = 1024
};
Import *ihash[NIHASH];
int nimport;
Import *
ilookup(char *name)
{
int h;
Import *x;
h = hashstr(name) % NIHASH;
for(x=ihash[h]; x; x=x->hash)
if(x->name[0] == name[0] && strcmp(x->name, name) == 0)
return x;
x = armalloc(sizeof *x);
x->name = name;
x->hash = ihash[h];
ihash[h] = x;
nimport++;
return x;
}
int parsemethod(char**, char*, char**);
int parsepkgdata(char**, char*, int*, char**, char**, char**);
void
loadpkgdata(char *data, int len)
{
int export;
char *p, *ep, *prefix, *name, *def;
Import *x;
file = arstrdup(file);
p = data;
ep = data + len;
while(parsepkgdata(&p, ep, &export, &prefix, &name, &def) > 0) {
x = ilookup(name);
if(x->prefix == nil) {
x->prefix = prefix;
x->def = def;
x->file = file;
x->export = export;
} else {
if(strcmp(x->prefix, prefix) != 0) {
fprint(2, "ar: conflicting definitions for %s\n", name);
fprint(2, "%s:\t%s %s ...\n", x->file, x->prefix, name);
fprint(2, "%s:\t%s %s ...\n", file, prefix, name);
errors++;
}
else if(strcmp(x->def, def) != 0) {
fprint(2, "ar: conflicting definitions for %s\n", name);
fprint(2, "%s:\t%s %s %s\n", x->file, x->prefix, name, x->def);
fprint(2, "%s:\t%s %s %s\n", file, prefix, name, def);
errors++;
}
// okay if some .6 say export and others don't.
// all it takes is one.
if(export)
x->export = 1;
}
}
}
int
parsepkgdata(char **pp, char *ep, int *exportp, char **prefixp, char **namep, char **defp)
{
char *p, *prefix, *name, *def, *edef, *meth;
int n;
// skip white space
p = *pp;
while(p < ep && (*p == ' ' || *p == '\t'))
p++;
if(p == ep)
return 0;
// [export ]
*exportp = 0;
if(p + 7 <= ep && strncmp(p, "export ", 7) == 0) {
*exportp = 1;
p += 7;
}
// prefix: (var|type|func|const)
prefix = p;
prefix = p;
if(p + 6 > ep)
return -1;
if(strncmp(p, "var ", 4) == 0)
p += 4;
else if(strncmp(p, "type ", 5) == 0)
p += 5;
else if(strncmp(p, "func ", 5) == 0)
p += 5;
else if(strncmp(p, "const ", 6) == 0)
p += 6;
else{
fprint(2, "ar: confused in pkg data near <<%.20s>>\n", p);
errors++;
return -1;
}
p[-1] = '\0';
// name: a.b followed by space
name = p;
while(p < ep && *p != ' ')
p++;
if(p >= ep)
return -1;
*p++ = '\0';
// def: free form to new line
def = p;
while(p < ep && *p != '\n')
p++;
if(p >= ep)
return -1;
edef = p;
*p++ = '\0';
// include methods on successive lines in def of named type
while(parsemethod(&p, ep, &meth) > 0) {
*edef++ = '\n'; // overwrites '\0'
if(edef+1 > meth) {
// We want to indent methods with a single \t.
// 6g puts at least one char of indent before all method defs,
// so there will be room for the \t. If the method def wasn't
// indented we could do something more complicated,
// but for now just diagnose the problem and assume
// 6g will keep indenting for us.
fprint(2, "ar: %s: expected methods to be indented %p %p %.10s\n", file, edef, meth, meth);
errors++;
return -1;
}
*edef++ = '\t';
n = strlen(meth);
memmove(edef, meth, n);
edef += n;
}
// done
*pp = p;
*prefixp = prefix;
*namep = name;
*defp = def;
return 1;
}
int
parsemethod(char **pp, char *ep, char **methp)
{
char *p, *prefix, *name, *def;
int n;
// skip white space
p = *pp;
while(p < ep && (*p == ' ' || *p == '\t'))
p++;
if(p == ep)
return 0;
// if it says "func (", it's a method
if(p + 6 >= ep || strncmp(p, "func (", 6) != 0)
return 0;
// definition to end of line
*methp = p;
while(p < ep && *p != '\n')
p++;
if(p >= ep) {
fprint(2, "ar: lost end of line in method definition\n");
*pp = ep;
return -1;
}
*p++ = '\0';
*pp = p;
return 1;
}
int
importcmp(const void *va, const void *vb)
{
Import *a, *b;
int i;
a = *(Import**)va;
b = *(Import**)vb;
i = strcmp(a->prefix, b->prefix);
if(i != 0) {
// rewrite so "type" comes first
if(strcmp(a->prefix, "type") == 0)
return -1;
if(strcmp(b->prefix, "type") == 0)
return 1;
return i;
}
return strcmp(a->name, b->name);
}
char*
strappend(char *s, char *t)
{
int n;
n = strlen(t);
memmove(s, t, n);
return s+n;
}
void
getpkgdef(char **datap, int *lenp)
{
Fmt f;
int i, j, len;
char *data, *p, *ep;
Import **all, *x;
// make a list of all the exports and count string sizes
all = armalloc(nimport*sizeof all[0]);
j = 0;
len = 7 + 3 + strlen(pkgstmt) + 1; // import\n$$\npkgstmt\n
for(i=0; i<NHASH; i++) {
for(x=ihash[i]; x; x=x->hash) {
all[j++] = x;
len += strlen(x->prefix) + 1
+ strlen(x->name) + 1
+ strlen(x->def) + 1;
if(x->export)
len += 7;
}
}
if(j != nimport) {
fprint(2, "ar: import count mismatch (internal error)\n");
exits("oops");
}
len += 3; // $$\n
// sort exports (unnecessary but nicer to look at)
qsort(all, nimport, sizeof all[0], importcmp);
// print them into buffer
data = armalloc(len);
// import\n
// $$\n
// pkgstmt\n
p = data;
p = strappend(p, "import\n$$\n");
p = strappend(p, pkgstmt);
p = strappend(p, "\n");
for(i=0; i<nimport; i++) {
x = all[i];
// [export] prefix name def\n
if(x->export)
p = strappend(p, "export ");
p = strappend(p, x->prefix);
p = strappend(p, " ");
p = strappend(p, x->name);
p = strappend(p, " ");
p = strappend(p, x->def);
p = strappend(p, "\n");
}
p = strappend(p, "$$\n");
if(p != data+len) {
fprint(2, "ar: internal math error\n");
exits("oops");
}
*datap = data;
*lenp = len;
}
...@@ -154,12 +154,14 @@ dumpsym(Sym *s) ...@@ -154,12 +154,14 @@ dumpsym(Sym *s)
break; break;
case LATYPE: case LATYPE:
case LBASETYPE: case LBASETYPE:
dumpexporttype(s); // TODO(rsc): sort methods by name
for(f=s->otype->method; f!=T; f=f->down) { for(f=s->otype->method; f!=T; f=f->down)
dumpprereq(f); dumpprereq(f);
dumpexporttype(s);
for(f=s->otype->method; f!=T; f=f->down)
Bprint(bout, "\tfunc (%#T) %hS %#T\n", Bprint(bout, "\tfunc (%#T) %hS %#T\n",
f->type->type->type, f->sym, f->type); f->type->type->type, f->sym, f->type);
}
break; break;
case LNAME: case LNAME:
dumpexportvar(s); dumpexportvar(s);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment