From ee0bca35a437505e2dd38c28abb4c9dc35410008 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 11 Jun 2010 15:29:19 -0700 Subject: [PATCH] gopack: simplify go metadata code There's only one Go object file per package now, so there's no need to parse the metadata and merge metadata from multiple files. Just save the original and use it as __.PKGDEF verbatim. R=r CC=golang-dev https://golang.org/cl/1647042 --- src/cmd/gopack/ar.c | 350 +++++--------------------------------------- 1 file changed, 36 insertions(+), 314 deletions(-) diff --git a/src/cmd/gopack/ar.c b/src/cmd/gopack/ar.c index ff7f298187..be72d305f0 100644 --- a/src/cmd/gopack/ar.c +++ b/src/cmd/gopack/ar.c @@ -630,7 +630,7 @@ scanobj(Biobuf *b, Arfile *ap, long size) } /* - * does line contain substring (length-limited) + * does line contain substring (length-limited) */ int strstrn(char *line, int len, char *sub) @@ -646,7 +646,26 @@ strstrn(char *line, int len, char *sub) } /* - * Extract the package definition data from an object file + * package import data + */ +char* pkgname; +char* importblock; + +void +getpkgdef(char **datap, int *lenp) +{ + if(pkgname == nil) { + pkgname = "__emptyarchive__"; + importblock = ""; + } + + *datap = smprint("import\n$$\npackage %s\n%s\n$$\n", pkgname, importblock); + *lenp = strlen(*datap); +} + +/* + * extract the package definition data from an object file. + * there can be only one. */ void scanpkg(Biobuf *b, long size) @@ -702,6 +721,13 @@ foundstart: pkg++; if(strncmp(pkg, "package ", 8) != 0) goto bad; + pkg += 8; + data = pkg; + while(*pkg != ' ' && *pkg != '\n' && *pkg != '\0') + pkg++; + pkgname = armalloc(pkg - data + 1); + memmove(pkgname, data, pkg - data); + pkgname[pkg-data] = '\0'; start = Boffset(b); // after package statement first = 0; continue; @@ -719,24 +745,21 @@ foundend: return; if (end == 0) goto bad; - if (pkgstmt == nil) { - /* this is the first package */ - pkgstmt = arstrdup(pkg); - } else { - if (strcmp(pkg, pkgstmt) != 0) { - fprint(2, "gopack: inconsistent package name\n"); - return; - } + if(importblock != nil) { + fprint(2, "gopack: multiple Go object files\n"); + errors++; + return; } - pkgsize = end-start; - data = armalloc(pkgsize); + data = armalloc(end - start + 1); Bseek(b, start, 0); if (Bread(b, data, pkgsize) != pkgsize) { fprint(2, "gopack: error reading package import section in %s\n", file); + errors++; return; } - loadpkgdata(data, pkgsize); + data[end-start] = '\0'; + importblock = data; } /* @@ -1464,304 +1487,3 @@ arstrdup(char *s) } -/* - * package import data - */ -typedef struct Import Import; -struct Import -{ - Import *hash; // next in hash table - 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*, char**, char**, char**); - -void -loadpkgdata(char *data, int len) -{ - char *p, *ep, *prefix, *name, *def; - Import *x; - - p = data; - ep = data + len; - while(parsepkgdata(&p, ep, &prefix, &name, &def) > 0) { - if(strcmp(prefix, "import") == 0) { - // backwards from the rest: def is unique, name is not. - x = ilookup(def); - if(x->prefix == nil) { - x->prefix = prefix; - x->def = name; - x->file = file; - } else if(strcmp(x->def, name) != 0) { - fprint(2, "gopack: conflicting package names for %s\n", def); - fprint(2, "%s:\t%s\n", x->file, x->def); - fprint(2, "%s:\t%s\n", file, name); - errors++; - } - continue; - } - - x = ilookup(name); - if(x->prefix == nil) { - x->prefix = prefix; - x->def = def; - x->file = file; - } else if(strcmp(x->prefix, prefix) != 0) { - fprint(2, "gopack: 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, "gopack: 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++; - } - } -} - -int -parsepkgdata(char **pp, char *ep, 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; - - // prefix: (var|type|func|const) - prefix = p; - - prefix = p; - if(p + 7 > 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 if(strncmp(p, "import ", 7) == 0) - p += 7; - else { - fprint(2, "gopack: 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, "gopack: %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; - - // 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, "gopack: 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) -{ - int i, j, len; - char *data, *p; - Import **all, *x; - - if(pkgstmt == nil) { - // Write out non-empty, parseable __.PKGDEF, - // so that import of an empty archive works. - *datap = "import\n$$\npackage __emptypackage__\n$$\n"; - *lenp = strlen(*datap); - return; - } - - // 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; ihash) { - all[j++] = x; - len += strlen(x->prefix) + 1 - + strlen(x->name) + 1 - + strlen(x->def) + 1; - } - } - if(j != nimport) { - fprint(2, "gopack: 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; iprefix, "import") == 0) { - // prefix def name\n - p = strappend(p, x->prefix); - p = strappend(p, " "); - p = strappend(p, x->def); - p = strappend(p, " "); - p = strappend(p, x->name); - p = strappend(p, "\n"); - continue; - } - // prefix name def\n - 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, "gopack: internal math error\n"); - exits("oops"); - } - - *datap = data; - *lenp = len; -} -