ref: fbdac038aad6c5873e6ce3323a92591a14575583
dir: /code.c/
#include <u.h>
#include <libc.h>
#include "dat.h"
#include "fns.h"
typedef struct Vqid Vqid;
struct Vqid {
char *name;
VFile *vfile;
Vqid *children;
Vqid *next;
};
Vqid *vqids = nil;
static void
printvars(VFile *file, char *prefix)
{
char **a;
char *s;
char buf[64];
int n;
for (a = file->parts; *a; a++) {
s = *a;
if (!s)
break;
if (!s[0])
continue;
n = strlen(s) - 1;
if (!(s[0] == '{' && s[n] == '}'))
continue;
strcpy(buf, s);
buf[n] = 0;
print("%s%s", prefix, buf+1);
}
}
char *invalid = "/{}";
static void
pathtostring(char *buf, int max, char *path)
{
char *s;
strncpy(buf, path, max);
buf[max-1] = 0;
for (s = buf; *s; s++)
if (strchr(invalid, *s))
*s = '_';
}
static void
genfuncname(VFile *file, char *buf, int size, char *nm)
{
char pbuf[32];
pathtostring(pbuf, sizeof(pbuf), file->path);
snprint(buf, size, "fs%s_%s", nm, pbuf);
}
void
printgenfunc(VFile *file, char *nm)
{
char buf[32];
genfuncname(file, buf, sizeof(buf), nm);
print("static void\n%s(Req *r", buf);
printvars(file, ", char *");
print(")\n");
}
void
printgenfuncend(VFile *file, char *nm)
{
char buf[32];
genfuncname(file, buf, sizeof(buf), nm);
print("}\n\n");
print("static void\nCall_%s(Req *r)\n{\n", buf);
print(" FileAux *a = r->fid->aux;\n");
print(" %s(r", buf);
printvars(file, ", a->");
print(");\n");
print("}\n\n");
}
void
printls(VFile *file)
{
char buf[64];
pathtostring(buf, sizeof(buf), file->path);
print("static void\nfsls_%s(...)\n", buf);
}
void
printpre()
{
print("%s",
#include "preamble.cinc"
);
}
static int
countvq(Vqid *v)
{
int n = 0;
for (; v; v = v->next)
n++;
return n;
}
static void
printfilehierarchy(Vqid *vq)
{
Vqid *v, *cv;
int n, i;
char buf[32];
char cbuf[32];
if (!vq) return;
for (v = vq; v; v = v->next) {
n = countvq(v->children);
pathtostring(buf, sizeof(buf), v->name);
if (!n) {
/* be verbose */
print(" filehierarchy[Q%s] = nil;\n", buf);
continue;
}
print(" filehierarchy[Q%s] = mallocz(%d, 1);\n", buf, n + 1);
i = 0;
for (cv = v->children; cv; cv = cv->next) {
pathtostring(cbuf, sizeof(cbuf), cv->name);
print(" filehierarchy[Q%s][%d] = Q%s;\n", buf, i++, cbuf);
}
print(" filehierarchy[Q%s][%d] = 0;\n", buf, i);
for (cv = v->children; cv; cv = cv->next) {
printfilehierarchy(cv);
}
}
}
extern char* file;
void
printfs()
{
char buf[64];
char *s;
int n;
strcpy(buf, file);
s = strrchr(buf, '.');
if (strcmp(s, ".fs") == 0)
*s = 0;
for (s = buf; *s; s++)
if (*s == '.')
*s = '_';
s = strrchr(buf, '/');
if (s)
s++;
else
s = buf;
print("%s", "\n"
#include "fshandler.cinc"
);
print("\n"
"Srv fs = {\n"
" .attach = fsattach,\n"
" .read = fsread,\n"
" .stat = fsstat,\n"
" .walk1 = fswalk,\n"
" .clone = fsclone,\n"
"};\n\n");
print(
"static void\n"
"buildfilehierarchy(void)\n"
"{\n");
n = getnfiles();
print(" filehierarchy = mallocz(%d, 1);\n", n+1);
printfilehierarchy(vqids);
print("}\n\n");
print(
"Srv*\n"
"getfs_%s()\n", s);
print("%s",
#include "fsfunc.cinc"
);
}
static Vqid*
findchild(Vqid *parent, char *child)
{
Vqid *v;
for (v = parent->children; v; v = v->next) {
if (strcmp(v->name, child) == 0)
return v;
}
return nil;
}
void
genqids(VFile *f, void*)
{
Vqid *v, *nv;
char **a;
char *s;
char buf[64];
if (!vqids) {
/* root element */
vqids = mallocz(sizeof(Vqid), 1);
vqids->name = "root";
vqids->vfile = getfile("/");
vqids->vfile->isdir = 1;
}
v = vqids;
for (a = f->parts; *a; a++) {
s = *a;
if (*s == 0) {
/* if root element */
continue;
}
nv = findchild(v, s);
if (nv) {
v = nv;
continue;
}
nv = mallocz(sizeof(Vqid), 1);
pathtostring(buf, sizeof(buf), f->path+1);
nv->name = strdup(buf);
nv->vfile = f;
nv->next = v->children;
v->children = nv;
v = nv;
}
}
static void
rprintqids(Vqid *vq, int nest)
{
Vqid *v;
char buf[32];
if (!vq) return;
for (v = vq; v; v = v->next) {
pathtostring(buf, sizeof(buf), v->name);
print("%*sQ%s,\n", nest*4, "", buf);
rprintqids(v->children, nest+1);
}
}
static void
rprintfilenames(Vqid *vq)
{
Vqid *v;
VFile *f;
char *s;
char buf[32];
if (!vq) return;
for (v = vq; v; v = v->next) {
f = v->vfile;
assert(f);
pathtostring(buf, sizeof(buf), v->name);
print(" [Q%s] {\n", buf);
print(" .dir = {\n");
s = strrchr(f->path, '/');
print(" .name = \"%s\",\n", s+1);
if (f->isdir) {
print(" .mode = DMDIR,\n");
}
print(" },\n");
if (f->hasread) {
genfuncname(f, buf, sizeof(buf), "read");
print(" .read = Call_%s,\n", buf);
}
if (f->haswrite) {
genfuncname(f, buf, sizeof(buf), "write");
print(" .write = Call_%s,\n", buf);
}
if (f->hasstat) {
genfuncname(f, buf, sizeof(buf), "stat");
print(" .stat = Call_%s,\n", buf);
}
print(" },\n");
rprintfilenames(v->children);
}
}
void
printqids()
{
print("enum {\n");
rprintqids(vqids, 1);
print(" Qmax,\n");
print("};\n\n");
print("Filedata filedata[] = {\n");
rprintfilenames(vqids);
print("};\n\n");
}