shithub: fsgen

Download patch

ref: 8c1650529794e4aaee6a217c85bff0b402de8c29
author: sirjofri <sirjofri@sirjofri.de>
date: Mon Dec 15 04:46:40 EST 2025

first general parsing steps

--- /dev/null
+++ b/code.c
@@ -1,0 +1,22 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+void
+printread(VFile *file)
+{
+	print("static void\nfsread_%s(Req *r)\n", file->path);
+}
+
+void
+printwrite(VFile *file)
+{
+	print("static void\nfswrite_%s(Req *r)\n", file->path);
+}
+
+void
+printls(VFile *file)
+{
+	print("static void\nfsls_%s(...)\n", file->path);
+}
\ No newline at end of file
--- /dev/null
+++ b/dat.h
@@ -1,0 +1,11 @@
+typedef struct VFile VFile;
+
+#pragma varargck type "V" VFile*
+struct VFile {
+	char *path;
+	int isdir;
+	int hasread;
+	int haswrite;
+	char **parts;
+	VFile *next;
+};
--- /dev/null
+++ b/files.c
@@ -1,0 +1,75 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+VFile *files = nil;
+
+static char**
+parsepath(char *path)
+{
+	char **args;
+	char *s;
+	int numparts = 1, n;
+	
+	for (s = path; *s; s++) {
+		if (*s == '/')
+			numparts++;
+	}
+	/* root dir, each directory part, ending nil */
+	args = mallocz(numparts+1, 1);
+	s = strdup(path);
+	n = getfields(s, args, numparts, 0, "/");
+	assert(s == args[0]);
+	if (n == numparts)
+		return args;
+	free(args);
+	free(s);
+	werrstr("invalid path");
+	return nil;
+}
+
+VFile*
+addfile(char *path)
+{
+	VFile *old;
+	if (!files) {
+		files = mallocz(sizeof(VFile), 1);
+	} else {
+		old = files;
+		files = mallocz(sizeof(VFile), 1);
+		files->next = old;
+	}
+	files->path = strdup(path);
+	files->parts = parsepath(path);
+	if (!files->parts)
+		return nil;
+	return files;
+}
+
+void
+foreachfile(void (*f)(VFile*,void*), void *aux)
+{
+	VFile *vf;
+	
+	for (vf = files; vf; vf = vf->next)
+		f(vf, aux);
+}
+
+static int
+Vfmt(Fmt *f)
+{
+	VFile *v;
+	v = va_arg(f->args, VFile*);
+	return fmtprint(f, "%s (%s%s%s)", v->path,
+		v->isdir ? "D," : "",
+		v->hasread ? "R," : "",
+		v->haswrite ? "W" : ""
+	);
+}
+
+void
+vfileinit()
+{
+	fmtinstall('V', Vfmt);
+}
--- /dev/null
+++ b/fns.h
@@ -1,0 +1,7 @@
+void vfileinit(void);
+VFile *addfile(char *path);
+void foreachfile(void (*f)(VFile*,void*), void*);
+
+void printread(VFile*);
+void printwrite(VFile*);
+void printls(VFile*);
--- /dev/null
+++ b/main.c
@@ -1,0 +1,157 @@
+#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
+process(Biobuf *bin)
+{
+	char *s;
+	int line = 0;
+	
+	while (s = Brdstr(bin, '\n', 1)) {
+		line++;
+		switch (state) {
+		case OUTSIDE:
+			if (s[0] == 0)
+				break;
+			if (s[0] == '/') {
+				print("has path: %s\n", s);
+				currentfile = addfile(s);
+				if (!currentfile)
+					goto Err;
+				state = HASFILE;
+				break;
+			}
+			if (strcmp("%{", s) == 0) {
+				state = COPY;
+				break;
+			}
+			goto Err;
+		case COPY:
+			if (strcmp("r}", s) == 0) {
+				print("}\n");
+				state = HASFILE;
+				break;
+			}
+			if (strcmp("w}", s) == 0) {
+				print("}\n");
+				state = HASFILE;
+				break;
+			}
+			if (strcmp("ls}", s) == 0) {
+				print("}\n");
+				state = HASFILE;
+				break;
+			}
+			if (strcmp("%}", s) == 0) {
+				state = OUTSIDE;
+				break;
+			}
+			print("%s\n", s);
+			break;
+		case HASFILE:
+			if (s[0] == 0)
+				break;
+			if (strcmp("r{", s) == 0) {
+				if (currentfile->hasread) {
+					werrstr("file already has a read function");
+					goto Err;
+				}
+				currentfile->hasread++;
+				printread(currentfile);
+				print("#line %d \"%s\"\n", line, file);
+				print("{\n");
+				state = COPY;
+				break;
+			}
+			if (strcmp("w{", s) == 0) {
+				if (currentfile->haswrite) {
+					werrstr("file already has a write function");
+					goto Err;
+				}
+				currentfile->haswrite++;
+				printwrite(currentfile);
+				print("#line %d \"%s\"\n", line, file);
+				print("{\n");
+				state = COPY;
+				break;
+			}
+			if (strcmp("ls{", s) == 0) {
+				if (currentfile->isdir) {
+					werrstr("file already has a ls function");
+					goto Err;
+				}
+				currentfile->isdir++;
+				printls(currentfile);
+				print("#line %d \"%s\"\n", line, file);
+				print("{\n");
+				state = COPY;
+				break;
+			}
+			goto Err;
+		}
+		free(s);
+	}
+	return;
+Err:
+	fprint(2, "parse error at %s:%d: %r\n", file, line);
+}
+
+static void
+p(VFile *f, void*)
+{
+	char **a;
+	fprint(2, "file: %V\n", f);
+	
+	if (!f->parts)
+		return;
+	
+	for (a = f->parts; *a; a++)
+		fprint(2, "  /%s\n", *a);
+}
+
+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();
+	
+	process(bin);
+	
+	foreachfile(p, nil);
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,11 @@
+</$objtype/mkfile
+
+TARG=fsgen
+OFILES=\
+	main.$O\
+	files.$O\
+	code.$O\
+
+HFILES=dat.h fns.h
+
+</sys/src/cmd/mkone
--