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
--
⑨