| // Copyright 2012 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| #include "a.h" |
| |
| /* |
| * Helpers for building cmd/gc. |
| */ |
| |
| // gcopnames creates opnames.h from go.h. |
| // It finds the OXXX enum, pulls out all the constants |
| // from OXXX to OEND, and writes a table mapping |
| // op to string. |
| void |
| gcopnames(char *dir, char *file) |
| { |
| char *p, *q; |
| int i, j, end; |
| Buf in, b, out; |
| Vec lines, fields; |
| |
| binit(&in); |
| binit(&b); |
| binit(&out); |
| vinit(&lines); |
| vinit(&fields); |
| |
| bwritestr(&out, bprintf(&b, "// auto generated by go tool dist\n")); |
| bwritestr(&out, bprintf(&b, "static char *opnames[] = {\n")); |
| |
| readfile(&in, bprintf(&b, "%s/go.h", dir)); |
| splitlines(&lines, bstr(&in)); |
| i = 0; |
| while(i<lines.len && !contains(lines.p[i], "OXXX")) |
| i++; |
| end = 0; |
| for(; i<lines.len && !end; i++) { |
| p = xstrstr(lines.p[i], "//"); |
| if(p != nil) |
| *p = '\0'; |
| end = contains(lines.p[i], "OEND"); |
| splitfields(&fields, lines.p[i]); |
| for(j=0; j<fields.len; j++) { |
| q = fields.p[j]; |
| if(*q == 'O') |
| q++; |
| p = q+xstrlen(q)-1; |
| if(*p == ',') |
| *p = '\0'; |
| bwritestr(&out, bprintf(&b, " [O%s] = \"%s\",\n", q, q)); |
| } |
| } |
| |
| bwritestr(&out, bprintf(&b, "};\n")); |
| |
| writefile(&out, file, 0); |
| |
| bfree(&in); |
| bfree(&b); |
| bfree(&out); |
| vfree(&lines); |
| vfree(&fields); |
| } |
| |
| static int |
| xatoi(char *s, char **end) |
| { |
| int val = 0; |
| for(; *s && *s >= '0' && *s <= '9'; ++s) |
| val = val * 10 + (*s - '0'); |
| *end = s; |
| return val; |
| } |
| |
| // mkanames reads [5689].out.h and writes anames[5689].c |
| // The format is much the same as the Go opcodes above. |
| // It also writes out cnames array for C_* constants and the dnames |
| // array for D_* constants. |
| void |
| mkanames(char *dir, char *file) |
| { |
| int i, j, ch, n, unknown; |
| Buf in, b, out, out2; |
| Vec lines; |
| char *p, *p2; |
| Vec dnames[128]; |
| |
| binit(&b); |
| binit(&in); |
| binit(&out); |
| binit(&out2); |
| vinit(&lines); |
| for(i=0; i<nelem(dnames); i++) |
| vinit(&dnames[i]); |
| |
| ch = file[xstrlen(file)-3]; |
| bprintf(&b, "%s/../cmd/%cl/%c.out.h", dir, ch, ch); |
| readfile(&in, bstr(&b)); |
| splitlines(&lines, bstr(&in)); |
| |
| // Include link.h so that the extern declaration there is |
| // checked against the non-extern declaration we are generating. |
| bwritestr(&out, bprintf(&b, "// auto generated by go tool dist\n")); |
| bwritestr(&out, bprintf(&b, "#include <u.h>\n")); |
| bwritestr(&out, bprintf(&b, "#include <libc.h>\n")); |
| bwritestr(&out, bprintf(&b, "#include <bio.h>\n")); |
| bwritestr(&out, bprintf(&b, "#include <link.h>\n")); |
| bwritestr(&out, bprintf(&b, "#include \"../cmd/%cl/%c.out.h\"\n", ch, ch)); |
| bwritestr(&out, bprintf(&b, "\n")); |
| |
| bwritestr(&out, bprintf(&b, "char* anames%c[] = {\n", ch)); |
| for(i=0; i<lines.len; i++) { |
| if(hasprefix(lines.p[i], "\tA")) { |
| p = xstrstr(lines.p[i], ","); |
| if(p) |
| *p = '\0'; |
| p = xstrstr(lines.p[i], "\n"); |
| if(p) |
| *p = '\0'; |
| p = lines.p[i] + 2; |
| bwritestr(&out, bprintf(&b, "\t\"%s\",\n", p)); |
| } |
| } |
| bwritestr(&out, "};\n"); |
| |
| j=0; |
| bprintf(&out2, "char* cnames%c[] = {\n", ch); |
| for(i=0; i<lines.len; i++) { |
| if(hasprefix(lines.p[i], "\tC_")) { |
| p = xstrstr(lines.p[i], ","); |
| if(p) |
| *p = '\0'; |
| p = xstrstr(lines.p[i], "\n"); |
| if(p) |
| *p = '\0'; |
| p = lines.p[i] + 3; |
| bwritestr(&out2, bprintf(&b, "\t\"%s\",\n", p)); |
| j++; |
| } |
| } |
| bwritestr(&out2, "};\n"); |
| if(j>0) |
| bwriteb(&out, &out2); |
| |
| j=unknown=0; |
| n=-1; |
| for(i=0; i<lines.len; i++) { |
| if(hasprefix(lines.p[i], "\tD_")) { |
| p = xstrstr(lines.p[i], ","); |
| if(p) |
| *p = '\0'; |
| p = xstrstr(lines.p[i], "\n"); |
| if(p) |
| *p = '\0'; |
| |
| // Parse explicit value, if any |
| p = xstrstr(lines.p[i], "="); |
| if(p) { |
| // Skip space after '=' |
| p2 = p + 1; |
| while(*p2 == ' ' || *p2 == '\t') |
| p2++; |
| n = xatoi(p2, &p2); |
| // We can't do anything about |
| // non-numeric values or anything that |
| // follows |
| while(*p2 == ' ' || *p2 == '\t') |
| p2++; |
| if(*p2 != 0) { |
| unknown = 1; |
| continue; |
| } |
| // Truncate space before '=' |
| while(*(p-1) == ' ' || *(p-1) == '\t') |
| p--; |
| *p = '\0'; |
| unknown = 0; |
| } else { |
| n++; |
| } |
| |
| if(unknown || n >= nelem(dnames)) |
| continue; |
| |
| p = lines.p[i] + 3; |
| if(xstrcmp(p, "LAST") == 0) |
| continue; |
| vadd(&dnames[n], p); |
| j++; |
| } |
| } |
| if(j>0){ |
| bwritestr(&out, bprintf(&b, "char* dnames%c[D_LAST] = {\n", ch)); |
| for(i=0; i<nelem(dnames); i++) { |
| if(dnames[i].len == 0) |
| continue; |
| bwritestr(&out, bprintf(&b, "\t[D_%s] = \"", dnames[i].p[0])); |
| for(j=0; j<dnames[i].len; j++) { |
| if(j != 0) |
| bwritestr(&out, "/"); |
| bwritestr(&out, dnames[i].p[j]); |
| } |
| bwritestr(&out, "\",\n"); |
| } |
| bwritestr(&out, "};\n"); |
| } |
| |
| writefile(&out, file, 0); |
| |
| bfree(&b); |
| bfree(&in); |
| bfree(&out); |
| bfree(&out2); |
| vfree(&lines); |
| for(i=0; i<nelem(dnames); i++) |
| vfree(&dnames[i]); |
| } |