Commit 278b1ab0 authored by Russ Cox's avatar Russ Cox

make godefs work better for generating Go.

R=r
DELTA=121  (92 added, 4 deleted, 25 changed)
OCL=29706
CL=29721
parent d7acfc75
...@@ -51,6 +51,7 @@ struct Type ...@@ -51,6 +51,7 @@ struct Type
int saved; // recorded in typ array int saved; // recorded in typ array
int warned; // warned about needing type int warned; // warned about needing type
int printed; // has the definition been printed yet?
}; };
struct Field struct Field
......
...@@ -85,13 +85,14 @@ ...@@ -85,13 +85,14 @@
void void
usage(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); exit(1);
} }
int gotypefmt(Fmt*); int gotypefmt(Fmt*);
int ctypefmt(Fmt*); int ctypefmt(Fmt*);
int prefixlen(Type*); int prefixlen(Type*);
int cutprefix(char*);
Lang go = Lang go =
{ {
...@@ -102,8 +103,8 @@ Lang go = ...@@ -102,8 +103,8 @@ Lang go =
"type", "type",
"type %s struct {\n", "type %s struct {\n",
"type %s union {\n", // not really, but readable "type %s struct {\n",
"\tpad%d [%d]byte;\n", "\tPad%d [%d]byte;\n",
"}\n", "}\n",
gotypefmt, gotypefmt,
...@@ -125,6 +126,8 @@ Lang c = ...@@ -125,6 +126,8 @@ Lang c =
ctypefmt, ctypefmt,
}; };
char *pkg;
int oargc; int oargc;
char **oargv; char **oargv;
Lang *lang = &c; Lang *lang = &c;
...@@ -135,11 +138,17 @@ int ncon; ...@@ -135,11 +138,17 @@ int ncon;
Type **typ; Type **typ;
int ntyp; int ntyp;
void
waitforgcc(void)
{
waitpid();
}
void void
main(int argc, char **argv) main(int argc, char **argv)
{ {
int p[2], pid, i, j, n, off, npad, prefix; 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; Biobuf *bin, *bout;
Type *t; Type *t;
Field *f; Field *f;
...@@ -148,32 +157,36 @@ main(int argc, char **argv) ...@@ -148,32 +157,36 @@ main(int argc, char **argv)
oargc = argc; oargc = argc;
oargv = argv; oargv = argv;
av = emalloc((30+argc)*sizeof av[0]);
atexit(waitforgcc);
n = 0; n = 0;
av[n++] = "gcc"; av[n++] = "gcc";
av[n++] = "-c";
av[n++] = "-fdollars-in-identifiers"; av[n++] = "-fdollars-in-identifiers";
av[n++] = "-S"; // write assembly av[n++] = "-S"; // write assembly
av[n++] = "-gstabs"; // include stabs info av[n++] = "-gstabs"; // include stabs info
av[n++] = "-o-"; // to stdout av[n++] = "-o-"; // to stdout
av[n++] = "-xc"; // read C
ARGBEGIN{ ARGBEGIN{
case 'g': case 'g':
lang = &go; lang = &go;
pkg = EARGF(usage());
break; break;
case 'c': case 'c':
av[0] = EARGF(usage()); av[0] = EARGF(usage());
break; break;
case 'f': case 'f':
if(n+2 >= nelem(av))
sysfatal("too many -f options");
av[n++] = EARGF(usage()); av[n++] = EARGF(usage());
break; break;
default: default:
usage(); usage();
}ARGEND }ARGEND
if(argc != 1) if(argc == 0)
usage(); av[n++] = "-";
else
av[n++] = argv[0]; av[n++] = argv[0];
av[n] = nil; av[n] = nil;
...@@ -187,12 +200,29 @@ main(int argc, char **argv) ...@@ -187,12 +200,29 @@ main(int argc, char **argv)
if(pid == 0) { if(pid == 0) {
close(p[0]); close(p[0]);
dup(p[1], 1); 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); close(0);
open("/dev/null", OREAD); open("/dev/null", OREAD);
for(i=0; i<argc; i++) {
pid = fork();
if(pid < 0)
sysfatal("fork: %r");
if(pid == 0) {
av[n-1] = argv[i];
exec(av[0], av); exec(av[0], av);
fprint(2, "exec gcc: %r\n"); fprint(2, "exec gcc: %r\n");
exit(1); exit(1);
} }
waitpid();
}
exit(0);
}
close(p[1]); close(p[1]);
// Read assembly, pulling out .stabs lines. // Read assembly, pulling out .stabs lines.
...@@ -244,6 +274,9 @@ main(int argc, char **argv) ...@@ -244,6 +274,9 @@ main(int argc, char **argv)
Bprint(bout, "// MACHINE GENERATED - DO NOT EDIT.\n"); Bprint(bout, "// MACHINE GENERATED - DO NOT EDIT.\n");
Bprint(bout, "\n"); Bprint(bout, "\n");
if(pkg)
Bprint(bout, "package %s\n\n", pkg);
// Constants. // Constants.
Bprint(bout, "// Constants\n"); Bprint(bout, "// Constants\n");
if(ncon > 0) { if(ncon > 0) {
...@@ -276,9 +309,25 @@ main(int argc, char **argv) ...@@ -276,9 +309,25 @@ main(int argc, char **argv)
for(i=0; i<ntyp; i++) { for(i=0; i<ntyp; i++) {
Bprint(bout, "\n"); Bprint(bout, "\n");
t = typ[i]; t = typ[i];
while(t && t->kind == Typedef) name = t->name;
while(t && t->kind == Typedef) {
if(name == nil && t->name != nil) {
name = t->name;
if(t->printed)
break;
}
t = t->type; t = t->type;
}
if(name == nil && t->name != nil) {
name = t->name; 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] == '$') if(name[0] == '$')
name++; name++;
npad = 0; npad = 0;
...@@ -293,10 +342,8 @@ main(int argc, char **argv) ...@@ -293,10 +342,8 @@ main(int argc, char **argv)
Bprint(bout, "%s %lT\n", lang->typdef, name, t); Bprint(bout, "%s %lT\n", lang->typdef, name, t);
break; break;
case Union: case Union:
if(lang == &go) { // In Go, print union as struct with only first element,
fprint(2, "%s: cannot emit unions in go\n", name); // padded the rest of the way.
continue;
}
Bprint(bout, lang->unionbegin, name, name, name); Bprint(bout, lang->unionbegin, name, name, name);
goto StructBody; goto StructBody;
case Struct: case Struct:
...@@ -308,7 +355,7 @@ main(int argc, char **argv) ...@@ -308,7 +355,7 @@ main(int argc, char **argv)
for(j=0; j<t->nf; j++) { for(j=0; j<t->nf; j++) {
f = &t->f[j]; f = &t->f[j];
// padding // padding
if(t->kind == Struct) { if(t->kind == Struct || lang == &go) {
if(f->offset%8 != 0 || f->size%8 != 0) { if(f->offset%8 != 0 || f->size%8 != 0) {
fprint(2, "ignoring bitfield %s.%s\n", t->name, f->name); fprint(2, "ignoring bitfield %s.%s\n", t->name, f->name);
continue; continue;
...@@ -321,10 +368,15 @@ main(int argc, char **argv) ...@@ -321,10 +368,15 @@ main(int argc, char **argv)
} }
off += f->size; 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 // final padding
if(t->kind == Struct) { if(t->kind == Struct || lang == &go) {
if(off/8 < t->size) if(off/8 < t->size)
Bprint(bout, lang->structpadfmt, npad++, t->size - off/8); Bprint(bout, lang->structpadfmt, npad++, t->size - off/8);
} }
...@@ -444,13 +496,13 @@ gotypefmt(Fmt *f) ...@@ -444,13 +496,13 @@ gotypefmt(Fmt *f)
s = t->name; s = t->name;
if(s == nil) { if(s == nil) {
fprint(2, "need name for anonymous struct\n"); fprint(2, "need name for anonymous struct\n");
s = "STRUCT"; fmtprint(f, "STRUCT");
} }
else if(s[0] != '$') else if(s[0] != '$') {
fprint(2, "need name for struct %s\n", s); fprint(2, "warning: missing name for struct %s\n", s);
else fmtprint(f, "[%d]byte /* %s */", t->size, s);
s++; } else
fmtprint(f, "%s", s); fmtprint(f, "%s", s+1);
break; break;
case Array: case Array:
...@@ -471,6 +523,21 @@ gotypefmt(Fmt *f) ...@@ -471,6 +523,21 @@ gotypefmt(Fmt *f)
return 0; 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 // Figure out common struct prefix len
int int
prefixlen(Type *t) prefixlen(Type *t)
...@@ -484,6 +551,8 @@ prefixlen(Type *t) ...@@ -484,6 +551,8 @@ prefixlen(Type *t)
name = nil; name = nil;
for(i=0; i<t->nf; i++) { for(i=0; i<t->nf; i++) {
f = &t->f[i]; f = &t->f[i];
if(!cutprefix(f->name))
continue;
p = strchr(f->name, '_'); p = strchr(f->name, '_');
if(p == nil) if(p == nil)
return 0; return 0;
......
...@@ -209,6 +209,7 @@ parsedef(char **pp, char *name) ...@@ -209,6 +209,7 @@ parsedef(char **pp, char *name)
t = emalloc(sizeof *t); t = emalloc(sizeof *t);
switch(*p) { switch(*p) {
default: default:
fprint(2, "unknown type char %c\n", *p);
*pp = ""; *pp = "";
return t; return t;
...@@ -380,7 +381,24 @@ parsedef(char **pp, char *name) ...@@ -380,7 +381,24 @@ parsedef(char **pp, char *name)
} }
break; 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; *pp = p;
return t; return t;
......
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