ref: a976de46123b51045a1ea123ad452e8465e71b08
dir: /main.c/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "dat.h"
#include "fns.h"
void
usage(void)
{
fprint(2, "usage: %s file\n", argv0);
exits("usage");
}
char *file = nil;
typedef enum {
OUTSIDE,
COPY,
HASFILE,
} State;
State state = OUTSIDE;
VFile *currentfile = nil;
static void
prepass(Biobuf *bin)
{
char *s;
int line = 0;
state = OUTSIDE;
while (s = Brdstr(bin, '\n', 1)) {
line++;
Retry:
switch (state) {
case OUTSIDE:
if (s[0] == 0)
break;
if (s[0] == '/') {
currentfile = addfile(s);
if (!currentfile)
goto Err;
state = HASFILE;
break;
}
if (strcmp("%{", s) == 0) {
state = COPY;
break;
}
werrstr("prepass: invalid input in OUTSIDE: %s", s);
goto Err;
case COPY:
if (strcmp("r}", s) == 0) {
state = HASFILE;
break;
}
if (strcmp("w}", s) == 0) {
state = HASFILE;
break;
}
if (strcmp("ls}", s) == 0) {
state = HASFILE;
break;
}
if (strcmp("s}", s) == 0) {
state = HASFILE;
break;
}
if (strcmp("%}", s) == 0) {
state = OUTSIDE;
break;
}
break;
case HASFILE:
if (s[0] == 0)
break;
if (s[0] == '/') {
state = OUTSIDE;
goto Retry;
}
if (strcmp("r{", s) == 0) {
if (currentfile->hasread) {
werrstr("%s already has a read function", currentfile->path);
goto Err;
}
currentfile->hasread++;
state = COPY;
break;
}
if (strcmp("w{", s) == 0) {
if (currentfile->haswrite) {
werrstr("%s already has a write function", currentfile->path);
goto Err;
}
currentfile->haswrite++;
state = COPY;
break;
}
if (strcmp("ls{", s) == 0) {
if (currentfile->isdir) {
werrstr("%s already has a ls function", currentfile->path);
goto Err;
}
currentfile->isdir++;
state = COPY;
break;
}
if (strcmp("s{", s) == 0) {
if (currentfile->hasstat) {
werrstr("%s already has a stat function", currentfile->path);
goto Err;
}
currentfile->hasstat++;
state = COPY;
break;
}
werrstr("invalid input in HASFILE: %s", s);
goto Err;
}
free(s);
}
return;
Err:
fprint(2, "prepass %s:%d: %r\n", file, line);
free(s);
}
static void
process(Biobuf *bin)
{
char *s;
int line = 0;
state = OUTSIDE;
while (s = Brdstr(bin, '\n', 1)) {
line++;
Retry:
switch (state) {
case OUTSIDE:
if (s[0] == 0)
break;
if (s[0] == '/') {
currentfile = addfile(s);
if (!currentfile)
goto Err;
state = HASFILE;
break;
}
if (strcmp("%{", s) == 0) {
state = COPY;
break;
}
werrstr("invalid input in OUTSIDE: %s", s);
goto Err;
case COPY:
if (strcmp("r}", s) == 0) {
printgenfuncend(currentfile, "read");
state = HASFILE;
break;
}
if (strcmp("w}", s) == 0) {
printgenfuncend(currentfile, "write");
state = HASFILE;
break;
}
if (strcmp("ls}", s) == 0) {
printgenfuncend(currentfile, "ls");
state = HASFILE;
break;
}
if (strcmp("s}", s) == 0) {
printgenfuncend(currentfile, "stat");
state = HASFILE;
break;
}
if (strcmp("%}", s) == 0) {
print("\n");
state = OUTSIDE;
break;
}
print("%s\n", s);
break;
case HASFILE:
if (s[0] == 0)
break;
if (s[0] == '/') {
state = OUTSIDE;
goto Retry;
}
if (strcmp("r{", s) == 0) {
printgenfunc(currentfile, "read");
print("#line %d \"%s\"\n", line, file);
print("{\n");
state = COPY;
break;
}
if (strcmp("w{", s) == 0) {
printgenfunc(currentfile, "write");
print("#line %d \"%s\"\n", line, file);
print("{\n");
state = COPY;
break;
}
if (strcmp("ls{", s) == 0) {
printgenfunc(currentfile, "ls");
print("#line %d \"%s\"\n", line, file);
print("{\n");
state = COPY;
break;
}
if (strcmp("s{", s) == 0) {
printgenfunc(currentfile, "stat");
print("#line %d \"%s\"\n", line, file);
print("{\n");
state = COPY;
break;
}
werrstr("invalid input in HASFILE: %s", s);
goto Err;
}
free(s);
}
return;
Err:
fprint(2, "process %s:%d: %r\n", file, line);
free(s);
}
void
main(int argc, char **argv)
{
Biobuf *bin;
ARGBEGIN{
case 'h':
usage();
}ARGEND;
if (argc != 1)
usage();
file = argv[0];
bin = Bopen(file, OREAD);
if (!bin)
sysfatal("open: %r");
vfileinit();
prepass(bin);
print("/* this file was generated from %s */\n", file);
printpre();
printauxvars();
Bseek(bin, 0, 0);
process(bin);
Bterm(bin);
foreachfile(genqids, nil);
printqids();
printfs();
exits(nil);
}