From: Russ Cox Date: Tue, 2 Jun 2009 05:14:25 +0000 (-0700) Subject: make godefs work better for generating Go. X-Git-Tag: weekly.2009-11-06~1496 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=278b1ab0537afd72832e5f6d8aa463ced75f1840;p=gostls13.git make godefs work better for generating Go. R=r DELTA=121 (92 added, 4 deleted, 25 changed) OCL=29706 CL=29721 --- diff --git a/src/cmd/godefs/a.h b/src/cmd/godefs/a.h index c33b10b54c..5d6f724714 100644 --- a/src/cmd/godefs/a.h +++ b/src/cmd/godefs/a.h @@ -51,6 +51,7 @@ struct Type int saved; // recorded in typ array int warned; // warned about needing type + int printed; // has the definition been printed yet? }; struct Field diff --git a/src/cmd/godefs/main.c b/src/cmd/godefs/main.c index 2c22611822..02912f2006 100644 --- a/src/cmd/godefs/main.c +++ b/src/cmd/godefs/main.c @@ -85,13 +85,14 @@ void usage(void) { - fprint(2, "usage: godefs [-g] [-c cc] [-f cc-flag] defs.c\n"); + fprint(2, "usage: godefs [-g package] [-c cc] [-f cc-flag] [defs.c ...]\n"); exit(1); } int gotypefmt(Fmt*); int ctypefmt(Fmt*); int prefixlen(Type*); +int cutprefix(char*); Lang go = { @@ -102,8 +103,8 @@ Lang go = "type", "type %s struct {\n", - "type %s union {\n", // not really, but readable - "\tpad%d [%d]byte;\n", + "type %s struct {\n", + "\tPad%d [%d]byte;\n", "}\n", gotypefmt, @@ -125,6 +126,8 @@ Lang c = ctypefmt, }; +char *pkg; + int oargc; char **oargv; Lang *lang = &c; @@ -135,11 +138,17 @@ int ncon; Type **typ; int ntyp; +void +waitforgcc(void) +{ + waitpid(); +} + void main(int argc, char **argv) { int p[2], pid, i, j, n, off, npad, prefix; - char *av[30], *q, *r, *tofree, *name; + char **av, *q, *r, *tofree, *name; Biobuf *bin, *bout; Type *t; Field *f; @@ -148,33 +157,37 @@ main(int argc, char **argv) oargc = argc; oargv = argv; + av = emalloc((30+argc)*sizeof av[0]); + atexit(waitforgcc); n = 0; av[n++] = "gcc"; + av[n++] = "-c"; av[n++] = "-fdollars-in-identifiers"; av[n++] = "-S"; // write assembly av[n++] = "-gstabs"; // include stabs info av[n++] = "-o-"; // to stdout + av[n++] = "-xc"; // read C ARGBEGIN{ case 'g': lang = &go; + pkg = EARGF(usage()); break; case 'c': av[0] = EARGF(usage()); break; case 'f': - if(n+2 >= nelem(av)) - sysfatal("too many -f options"); av[n++] = EARGF(usage()); break; default: usage(); }ARGEND - if(argc != 1) - usage(); - av[n++] = argv[0]; + if(argc == 0) + av[n++] = "-"; + else + av[n++] = argv[0]; av[n] = nil; // Run gcc writing assembly and stabs debugging to p[1]. @@ -187,11 +200,28 @@ main(int argc, char **argv) if(pid == 0) { close(p[0]); dup(p[1], 1); + if(argc == 0) { + exec(av[0], av); + fprint(2, "exec gcc: %r\n"); + exit(1); + } + // Some versions of gcc do not accept -S with multiple files. + // Run gcc once for each file. close(0); open("/dev/null", OREAD); - exec(av[0], av); - fprint(2, "exec gcc: %r\n"); - exit(1); + for(i=0; i 0) { @@ -276,9 +309,25 @@ main(int argc, char **argv) for(i=0; ikind == Typedef) - t = t->type; name = t->name; + while(t && t->kind == Typedef) { + if(name == nil && t->name != nil) { + name = t->name; + if(t->printed) + break; + } + t = t->type; + } + if(name == nil && t->name != nil) { + name = t->name; + if(t->printed) + continue; + t->printed = 1; + } + if(name == nil) { + fprint(2, "unknown name for %T", typ[i]); + continue; + } if(name[0] == '$') name++; npad = 0; @@ -293,10 +342,8 @@ main(int argc, char **argv) Bprint(bout, "%s %lT\n", lang->typdef, name, t); break; case Union: - if(lang == &go) { - fprint(2, "%s: cannot emit unions in go\n", name); - continue; - } + // In Go, print union as struct with only first element, + // padded the rest of the way. Bprint(bout, lang->unionbegin, name, name, name); goto StructBody; case Struct: @@ -308,7 +355,7 @@ main(int argc, char **argv) for(j=0; jnf; j++) { f = &t->f[j]; // padding - if(t->kind == Struct) { + if(t->kind == Struct || lang == &go) { if(f->offset%8 != 0 || f->size%8 != 0) { fprint(2, "ignoring bitfield %s.%s\n", t->name, f->name); continue; @@ -321,10 +368,15 @@ main(int argc, char **argv) } off += f->size; } - Bprint(bout, "\t%lT;\n", f->name+prefix, f->type); + name = f->name; + if(cutprefix(name)) + name += prefix; + Bprint(bout, "\t%lT;\n", name, f->type); + if(t->kind == Union && lang == &go) + break; } // final padding - if(t->kind == Struct) { + if(t->kind == Struct || lang == &go) { if(off/8 < t->size) Bprint(bout, lang->structpadfmt, npad++, t->size - off/8); } @@ -444,13 +496,13 @@ gotypefmt(Fmt *f) s = t->name; if(s == nil) { fprint(2, "need name for anonymous struct\n"); - s = "STRUCT"; + fmtprint(f, "STRUCT"); } - else if(s[0] != '$') - fprint(2, "need name for struct %s\n", s); - else - s++; - fmtprint(f, "%s", s); + else if(s[0] != '$') { + fprint(2, "warning: missing name for struct %s\n", s); + fmtprint(f, "[%d]byte /* %s */", t->size, s); + } else + fmtprint(f, "%s", s+1); break; case Array: @@ -471,6 +523,21 @@ gotypefmt(Fmt *f) return 0; } +// Is this the kind of name we should cut a prefix from? +// The rule is that the name cannot begin with underscore +// and must have an underscore eventually. +int +cutprefix(char *name) +{ + char *p; + + for(p=name; *p; p++) { + if(*p == '_') + return p-name > 0; + } + return 0; +} + // Figure out common struct prefix len int prefixlen(Type *t) @@ -484,6 +551,8 @@ prefixlen(Type *t) name = nil; for(i=0; inf; i++) { f = &t->f[i]; + if(!cutprefix(f->name)) + continue; p = strchr(f->name, '_'); if(p == nil) return 0; diff --git a/src/cmd/godefs/stabs.c b/src/cmd/godefs/stabs.c index e3f175f37c..8d3be19134 100644 --- a/src/cmd/godefs/stabs.c +++ b/src/cmd/godefs/stabs.c @@ -209,6 +209,7 @@ parsedef(char **pp, char *name) t = emalloc(sizeof *t); switch(*p) { default: + fprint(2, "unknown type char %c\n", *p); *pp = ""; return t; @@ -380,7 +381,24 @@ parsedef(char **pp, char *name) } break; - + case 'x': + // reference to struct, union not yet defined. + p++; + switch(*p) { + case 's': + t->kind = Struct; + break; + case 'u': + t->kind = Union; + break; + default: + fprint(2, "unknown x type char x%c", *p); + *pp = ""; + return t; + } + if(parsename(&p, &t->name) < 0) + return nil; + break; } *pp = p; return t;