#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);
}