shithub: fsgen

ref: e8de389e5962bafe0c32c8911b44809a7af861da
dir: /main.c/

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