#include #include #include enum { Nname = 20, }; typedef struct Name Name; struct Name { char name[Nname]; int count; int value; }; Name list[1000]; char name[Nname]; Name* lookup(char *s) { Name *n; for(n=list; n->name[0]; n++) if(strcmp(s, n->name) == 0) return n; strcpy(n->name, s); return n; } void main(int argc, char *argv[]) { Biobuf *bin, *bout; char *s, *p, *q; long lineno; Name *n; int i, value, swout;; ARGBEGIN { default: fprint(2, "usage: mkstate statefile cfile\n"); exits(0); } ARGEND if(argc != 2) { fprint(2, "usage: mkstate statefile cfile\n"); exits("usage"); } bin = Bopen(argv[0], OREAD); bout = Bopen(argv[1], OWRITE); lineno = 0; Bprint(bout, "#line %d \"%s\"\n", 1, argv[0]); n = 0; swout = 0; value = 1; for(;;) { s = Brdline(bin, '\n'); if(s == 0) break; lineno++; s[Blinelen(bin)-1] = 0; p = strchr(s, '@'); if(p == 0) goto prline; if(p[1] == '@') { for(n=list; n->name[0]; n++) { Bprint(bout, "case %6d: goto A%s;\n", n->value, n->name); for(i=1; icount; i++) Bprint(bout, "case %6d: goto A%s_%d;\n", n->value+i, n->name, i); } Bprint(bout, "#line %ld \"%s\"\n%s\n", lineno, argv[0], p+2); swout = 1; continue; } if(p[1] == '"') { for(n=list; n->name[0]; n++) Bprint(bout, "\t\"%s\", %d,\n", n->name, n->value); Bprint(bout, "\t0\n"); Bprint(bout, "#line %ld \"%s\"\n%s\n", lineno, argv[0], p+2); swout = 1; continue; } if(p[1] == '\'') { for(n=list; n->name[0]; n++) Bprint(bout, "\t[%d] = \"%s\",\n", n->value, n->name); Bprint(bout, "#line %ld \"%s\"\n%s\n", lineno, argv[0], p+2); swout = 1; continue; } if(p[1] >= '1' && p[1] <= '9' && (p[2] == 'b' || p[2] == 'f')) { p[0] = 0; i = p[1] - '1'; if(p[2] == 'b') i = -i - 1; i += n->count; if(i) Bprint(bout, "%s%s_%d%s\n", s, name, i, p+3); else Bprint(bout, "%s%s%s\n", s, name, p+3); continue; } q = strchr(p, ':'); if(q) { if(swout) fprint(2, "%ld: cannot create label after switch has been generated\n", lineno); if(p[1] == ':') { n = lookup(name); if(n->count == 0) fprint(2, "%ld: no base name\n", lineno); goto prbreak; } i = 0; if(n != nil) i = n->count; memset(name, 0, sizeof(name)); memcpy(name, p+1, q-p-1); n = lookup(name); if(n->count) fprint(2, "%ld: %s: redefined\n", lineno, name); value += i; n->value = value; prbreak: if(n->count) { Bprint(bout, "goto B%s_%d; B%s_%d: x->state = %d; goto out; A%s_%d: x->state = %d;\n", name, n->count, name, n->count, n->value+n->count, name, n->count, n->value); } else { Bprint(bout, "goto B%s; B%s: x->state = %d; goto out; A%s: x->state = %d;\n", name, name, n->value, name, n->value); } n->count++; Bprint(bout, "#line %ld \"%s\"\n%s\n", lineno, argv[0], q+1); continue; } prline: Bprint(bout, "%s\n", s); } exits(0); }