#include <u.h>#include <libc.h>#include <bio.h> 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;} voidmain(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; i<n->count; 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);}
#include <u.h>
#include <libc.h>
#include <bio.h>
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; i<n->count; 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);
}