From 955516759cfed29122439938632964fed4f8a347 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Sat, 20 Jun 2020 11:30:56 -0700 Subject: feat: file globbing in shell. added dynamic.mk --- sys/cmd/rc/code.c | 165 +++++++++++++++++++------------------------ sys/cmd/rc/exec.c | 120 +++++++++++++++++++++++++++++++ sys/cmd/rc/glob.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++ sys/cmd/rc/io.c | 21 +++--- sys/cmd/rc/lex.c | 8 +-- sys/cmd/rc/parse.c | 2 + sys/cmd/rc/rc.h | 75 +++++++++++++++++--- sys/cmd/rc/rules.mk | 15 ++-- sys/cmd/rc/var.c | 29 ++++++-- sys/cmd/rc/word.c | 6 ++ sys/cmd/walk/walk.c | 4 +- sys/libn/fs.c | 12 ++-- 12 files changed, 524 insertions(+), 131 deletions(-) create mode 100644 sys/cmd/rc/glob.c (limited to 'sys') diff --git a/sys/cmd/rc/code.c b/sys/cmd/rc/code.c index 9aa1037..edf47cf 100644 --- a/sys/cmd/rc/code.c +++ b/sys/cmd/rc/code.c @@ -5,9 +5,9 @@ #define c1 t->child[1] #define c2 t->child[2] -#define emitf(x) ((code.ip!=code.end || morecode()), code.ip++->f = (x)) -#define emiti(x) ((code.ip!=code.end || morecode()), code.ip++->i = (x)) -#define emits(x) ((code.ip!=code.end || morecode()), code.ip++->s = (x)) +#define emitf(x) ((code.ip!=code.end || morecode()), code.ip++->f = (x), code.ip) +#define emiti(x) ((code.ip!=code.end || morecode()), code.ip++->i = (x), code.ip) +#define emits(x) ((code.ip!=code.end || morecode()), code.ip++->s = (x), code.ip) static struct { @@ -53,15 +53,15 @@ rcc(Tree *t, int eflag) default: pfmt(errio, "bad type %d in rc compiler\n", t->type); break; - case '$': + case Tdol: emitf(Xmark); rcc(c0, eflag); emitf(Xdol); break; - case '"': + case Tquote: emitf(Xmark); rcc(c0, eflag); - emitf(Xqdol); + emitf(Xflatten); break; case Tsub: emitf(Xmark); @@ -70,36 +70,30 @@ rcc(Tree *t, int eflag) rcc(c1, eflag); emitf(Xsub); break; - case '&': + case Tand: emitf(Xasync); - if(havefork){ - p = emiti(0); - rcc(c0, eflag); - emitf(Xexit); - stuffdot(p); - } else - emits(fnstr(c0)); + p = emiti(0); + rcc(c0, eflag); + emitf(Xexit); + stuffdot(p); break; - case ';': + case Tsemi: rcc(c0, eflag); rcc(c1, eflag); break; - case '^': + case Tcarot: emitf(Xmark); rcc(c1, eflag); emitf(Xmark); rcc(c0, eflag); - emitf(Xconc); + emitf(Xcat); break; - case '`': - emitf(Xbackq); - if(havefork){ - p = emiti(0); - rcc(c0, 0); - emitf(Xexit); - stuffdot(p); - } else - emits(fnstr(c0)); + case Ttick: + emitf(Xcmdsub); + p = emiti(0); + rcc(c0, 0); + emitf(Xexit); + stuffdot(p); break; case Tandand: rcc(c0, 0); @@ -114,7 +108,7 @@ rcc(Tree *t, int eflag) break; case Tbang: rcc(c0, eflag); - emitf(Xbang); + emitf(Xnegate); break; case Tparen: case Tbrace: @@ -129,33 +123,32 @@ rcc(Tree *t, int eflag) emitf(Xmark); rcc(c0, eflag); if(c1){ - emitf(Xfn); + emitf(Xfunc); p = emiti(0); emits(fnstr(c1)); rcc(c1, eflag); emitf(Xunlocal); /* get rid of $* */ - emitf(Xreturn); + emitf(Xkill); stuffdot(p); - } - else - emitf(Xdelfn); + } else + emitf(Xunfunc); break; case Tif: rcc(c0, 0); emitf(Xif); p = emiti(0); rcc(c1, eflag); - emitf(Xwastrue); - stuffdot(p); - break; - case Telse: - if(!runq->iflast) - error("`else' does not follow `if(...)'"); - emitf(Xelse); - p = emiti(0); - rcc(c0, eflag); + // emitf(Xwastrue); stuffdot(p); break; + // case Telse: + // if(!runq->iflast) + // rcerror("`else' does not follow `if(...)'"); + // emitf(Xelse); + // p = emiti(0); + // rcc(c0, eflag); + // stuffdot(p); + // break; case Toror: rcc(c0, 0); emitf(Xfalse); @@ -163,7 +156,7 @@ rcc(Tree *t, int eflag) rcc(c1, eflag); stuffdot(p); break; - case Tparen: + case Tpcmd: rcc(c0, eflag); break; case Tsimple: @@ -175,13 +168,10 @@ rcc(Tree *t, int eflag) break; case Tsubshell: emitf(Xsubshell); - if(havefork){ - p = emiti(0); - rcc(c0, eflag); - emitf(Xexit); - stuffdot(p); - } else - emits(fnstr(c0)); + p = emiti(0); + rcc(c0, eflag); + emitf(Xexit); + stuffdot(p); if(eflag) emitf(Xeflag); break; @@ -197,7 +187,7 @@ rcc(Tree *t, int eflag) if(eflag) emitf(Xeflag); break; - case Kwhile: + case Twhile: q = code.ip; rcc(c0, 0); if(q==code.ip) @@ -206,7 +196,7 @@ rcc(Tree *t, int eflag) p = emiti(0); rcc(c1, eflag); emitf(Xjump); - emiti(q); + emiti(q-code.buf); stuffdot(p); break; case Twords: @@ -218,8 +208,7 @@ rcc(Tree *t, int eflag) if(c1){ rcc(c1, eflag); emitf(Xglob); - } - else{ + } else{ emitf(Xmark); emitf(Xword); emits(strdup("*")); @@ -242,35 +231,30 @@ rcc(Tree *t, int eflag) emits(strdup(t->str)); break; case Tdup: - if(t->rtype==Tdupfd){ + if(t->redir.type == Rdupfd){ emitf(Xdup); - emiti(t->fd0); - emiti(t->fd1); - } - else{ + emiti(t->redir.fd[0]); + emiti(t->redir.fd[1]); + } else{ emitf(Xclose); - emiti(t->fd0); + emiti(t->redir.fd[0]); } rcc(c1, eflag); emitf(Xpopredir); break; case Tpipefd: emitf(Xpipefd); - emiti(t->rtype); - if(havefork){ - p = emiti(0); - rcc(c0, eflag); - emitf(Xexit); - stuffdot(p); - } else { - emits(fnstr(c0)); - } + emiti(t->redir.type); + p = emiti(0); + rcc(c0, eflag); + emitf(Xexit); + stuffdot(p); break; case Tredir: emitf(Xmark); rcc(c0, eflag); emitf(Xglob); - switch(t->rtype){ + switch(t->redir.type){ case Rappend: emitf(Xappend); break; @@ -285,15 +269,15 @@ rcc(Tree *t, int eflag) emitf(Xrdwr); break; } - emiti(t->fd0); + emiti(t->redir.fd[0]); rcc(c1, eflag); emitf(Xpopredir); break; - case '=': + case Teq: tt = t; - for(;t && t->type=='=';t = c2); + for(;t && t->type==Teq;t = c2); if(t){ - for(t = tt;t->type=='=';t = c2){ + for(t = tt;t->type==Teq;t = c2){ emitf(Xmark); rcc(c1, eflag); emitf(Xmark); @@ -301,10 +285,9 @@ rcc(Tree *t, int eflag) emitf(Xlocal); } rcc(t, eflag); - for(t = tt; t->type=='='; t = c2) + for(t = tt; t->type==Teq; t = c2) emitf(Xunlocal); - } - else{ + } else{ for(t = tt;t;t = c2){ emitf(Xmark); rcc(c1, eflag); @@ -317,27 +300,23 @@ rcc(Tree *t, int eflag) break; case Tpipe: emitf(Xpipe); - emiti(t->fd0); - emiti(t->fd1); - if(havefork){ - p = emiti(0); - q = emiti(0); - rcc(c0, eflag); - emitf(Xexit); - stuffdot(p); - } else { - emits(fnstr(c0)); - q = emiti(0); - } + emiti(t->redir.fd[0]); + emiti(t->redir.fd[1]); + p = emiti(0); + q = emiti(0); + rcc(c0, eflag); + emitf(Xexit); + stuffdot(p); rcc(c1, eflag); - emitf(Xreturn); + emitf(Xkill); stuffdot(q); emitf(Xpipewait); break; } - if(t->type!=Telse && t->type!=';') - runq->iflast = t->type==IF; - else if(c0) runq->iflast = c0->type==IF; + if(t->type!=Telse && t->type!=Tsemi) + shell->iflast = t->type==Tif; + else if (c0) + shell->iflast = c0->type==Tif; } Code* @@ -349,7 +328,7 @@ compile(Tree *t) emiti(0); rcc(t, 0); - emitf(Xreturn); + emitf(Xkill); emitf(nil); return code.buf; diff --git a/sys/cmd/rc/exec.c b/sys/cmd/rc/exec.c index 2879678..d4822a7 100644 --- a/sys/cmd/rc/exec.c +++ b/sys/cmd/rc/exec.c @@ -1,9 +1,93 @@ #include "rc.h" +#define W0 shell->stack->words +// ----------------------------------------------------------------------- +// helper functions + +static +void +setstatus(char *s) +{ + setvar("status", newword(s, nil)); +} + +static +void +pushredir(int type, int from, int to) +{ + Redir *r; + + alloc(r); + r->type = type; + r->from = from; + r->to = to; + r->link = shell->redir, shell->redir = r; +} + +// ----------------------------------------------------------------------- +// interpreter functions + void Xerror(char *s) { + if(!strcmp(argv0, "rc")||!strcmp(argv0, "/bin/rc")) + pfmt(errio, "rc: %s: %r\n", s); + else + pfmt(errio, "rc (%s): %s: %r\n", argv0, s); + flush(&errio); + setstatus("error"); + while(!shell->interactive) + Xkill(); +} + +void +Xappend(void) +{ + int fd; + char *path; + + switch(count(W0)) { + default: + Xerror(">> requires a singleton list"); + return; + case 0: + Xerror(">> requires one file"); + return; + case 1: + ; + } + + path = shell->stack->words->word; + if ((fd=open(path, 1))< 0 && (fd=creat(path, 0666L))<0) { + pfmt(errio, "%s: ", path); + Xerror("can't open"); + return; + } + lseek(fd, 0L, 2); + pushredir(Fopen, fd, shell->ip++->i); + poplist(); +} + +void +Xassign(void) +{ + Var *v; + if(count(W0)!=1) { + Xerror("variable name not singleton"); + return; + } + unglob(W0->word); + v = vlookup(W0->word); + poplist(); + globlist(); + freelist(v->val); + + v->val = W0; + if(v->update) + v->update(v); + W0 = nil; + poplist(); } void @@ -17,3 +101,39 @@ Xword(void) { pushword(shell->ip++->s); } + +void Xasync(void); +void Xcat(void); +void Xclose(void); +void Xcmdsub(void); +void Xcount(void); +void Xdol(void); +void Xdup(void); +void Xexit(void); +void Xfalse(void); +void Xflatten(void); +void Xfor(void); +void Xfunc(void); +void Xglob(void); +void Xif(void); +void Xjump(void); +void Xkill(void); +void Xlocal(void); +void Xmark(void); +void Xmatch(void); +void Xnegate(void); +void Xpipe(void); +void Xpipefd(void); +void Xpipewait(void); +void Xpop(void); +void Xpopredir(void); +void Xrdwr(void); +void Xread(void); +void Xsub(void); +void Xsimple(void); +void Xsubshell(void); +void Xtrue(void); +void Xunfunc(void); +void Xunlocal(void); +void Xword(void); +void Xwrite(void); diff --git a/sys/cmd/rc/glob.c b/sys/cmd/rc/glob.c new file mode 100644 index 0000000..8a9c940 --- /dev/null +++ b/sys/cmd/rc/glob.c @@ -0,0 +1,198 @@ +#include "rc.h" +#include + +Io *errio; +static Word *matches; +static char buffer[6*1024]; + +// ----------------------------------------------------------------------- +// main exports + +void +unglob(char *s) +{ + char *t = s; + do { + if(*t==GLOB) + t++; + *s++ = *t; + } while(*t++); +} + +/* + * inspiration from rsc's blog post + * modified for utf8 sequences and character classes + * returns 1 if string matches pattern is found, 0 otherwise + */ +static +int +match(char *s, char *p) +{ + int c, ns, np; + rune sr, pr, lo, tr, hi; + char *sb = s, *ss = s, *pp = p; + while(*s || *p){ + if(*p){ + ns = utf8·bytetorune(&sr, s); + np = utf8·bytetorune(&pr, p); + + if(pr==GLOB){ + np = utf8·bytetorune(&pr, ++p); + switch(pr){ + case '?': /* single match */ + if(*s){ + p+=np, s+=ns; + continue; + } + case '[': /* class match */ + np = utf8·bytetorune(&pr, ++p); + if((c = (pr == '~'))) + np = utf8·bytetorune(&pr, ++p); + + lo = pr; + while(lo != ']' && *p){ + utf8·bytetorune(&tr, p+np); /* peek ahead */ + if(tr != '-') + hi = lo; + else { + p += np + 1, np = utf8·bytetorune(&hi, p); + if(!hi) /* we hit a syntax error */ + return 0; + if(hi < lo) + tr = hi, hi = lo, lo = tr; + } + if(c ^ (lo<=sr && sr<= hi)) + goto match; + p += np, np = utf8·bytetorune(&lo, p); + } + return 0; + match: + while (*p++ != ']' && *p); /* just iterate byte-wise */ + s += ns; + continue; + case '*': /* zero-or-more match */ + pp = p-1, ss = s+ns; + p++; + continue; + case GLOB: + if (sr != GLOB) + return 0; + s++, p++; + continue; + default: + panic("unrecognized glob operation", pr); + } + } + + if (sr==pr){ + s+=ns, p+=np; + continue; + } + } + /* hit end of pattern with no match, restart at last star */ + if (ss > sb) { + if (!*ss) /* hit end of string while matching a star */ + return 1; + + s = ss, p = pp; + continue; + } + /* mismatch */ + return 0; + } + return 1; +} + +static +void +globdir(char *p, char *path, int fd) +{ + DIR *d = nil; + char *g; /* pattern offset (base of new GLOB) */ + char *b; /* pointer into path */ + int i, j; + struct dirent *e; + + if(!*p) { + printf("making path %s\n", path); + matches = newword(buffer, matches); + return; + } + + if((fd = openat(fd, path[0]?path:".", O_RDONLY|O_CLOEXEC|O_DIRECTORY)) < 0) + return; + d = fdopendir(fd); + + for(g = p, b = path; *g; b++) { + if(*g==GLOB) + break; + *b=*g++; + if(*b == '/') { + *b = 0; + /* open new directory (close if we have opened another already */ + if ((fd = openat(fd, path, O_RDONLY|O_CLOEXEC|O_DIRECTORY)) < 0) + goto cleanup; + closedir(d); + d = fdopendir(fd); + *b = '/'; + path = b, p = g; + } + } + + /* if we are at the end of the pattern, check if name exists */ + if(!*g) { + *b = 0; + if(faccessat(fd, path, F_OK, AT_SYMLINK_NOFOLLOW) == 0) + matches = newword(buffer, matches); + goto cleanup; + } + + /* we have a non-trivial pattern to match */ + /* partition on the next directory */ + while(*g && *g!='/') + g++; + + if(*g){ + j = 1; + *g = 0; + } else + j = 0; + + while((e = readdir(d))) { + if (e->d_name[0] == '.') + if (e->d_name[1] == 0 || /* . */ + (e->d_name[1] == '.' && e->d_name[2] == 0)) /* .. */ + continue; + + for(i=0;e->d_name[i];i++) + b[i]=e->d_name[i]; + b[i]=0; + + if(match(path, p)) + globdir(g+j, b, fd); + } + + printf("successful\n"); +cleanup: + printf("cleaning up\n"); + /* NOTE: a successful closedir also closes the file descriptor */ + closedir(d); + return; +} + +void +glob(char *p) +{ + char *path = buffer; + + globdir(p, path, AT_FDCWD); +} + +int +main() +{ + errio = openfd(2); + glob("\x01*"); + pval(errio, matches); + flush(&errio); +} diff --git a/sys/cmd/rc/io.c b/sys/cmd/rc/io.c index 2fbe57f..e06bfcc 100644 --- a/sys/cmd/rc/io.c +++ b/sys/cmd/rc/io.c @@ -94,8 +94,8 @@ flush(Io **fp) n = f->b - f->buf; if (n && write(f->fd, f->buf, n) < 0) { write(3, "write error\n", 12); - if (ntrap) - dotrap(); + // if (ntrap) + // dotrap(); } f->b = f->buf; f->e = f->buf + bufsize; @@ -153,10 +153,10 @@ void pwrd(Io *f, char *s) { char *t; - for (t = s; *t; t++) - if (!wordchr(*t)) + for(t = s; *t; t++) + if(!wordchr(*t)) break; - if (t == s || *t) + if(t == s || *t) pquo(f, s); else pstr(f, s); @@ -186,10 +186,10 @@ pptr(Io *f, void *v) void pstr(Io *f, char *s) { - if (!s) + if(!s || !s[0]) s = ""; - while (*s) + while(*s) pchr(f, *s++); } @@ -228,8 +228,8 @@ poct(Io *f, uint n) void pval(Io *f, Word *a) { - if (a) { - while (a->link && a->link->word) { + if(a) { + while(a->link && a->link->word) { pwrd(f, a->word); pchr(f, ' '); a = a->link; @@ -416,6 +416,9 @@ vpfmt(Io *f, char *fmt, va_list args) case 'q': pwrd(f, va_arg(args, char*)); break; + case 'r': + pstr(f, strerror(errno)); + break; case 's': pstr(f, va_arg(args, char*)); break; diff --git a/sys/cmd/rc/lex.c b/sys/cmd/rc/lex.c index 8b4cdec..f6e2b4e 100644 --- a/sys/cmd/rc/lex.c +++ b/sys/cmd/rc/lex.c @@ -1,9 +1,9 @@ #include "rc.h" -#define onebyte(c) ((c&0x80)==0x00) -#define twobyte(c) ((c&0xe0)==0xc0) -#define threebyte(c) ((c&0xf0)==0xe0) -#define fourbyte(c) ((c&0xf8)==0xf0) +#define onebyte(c) ((c&0x80)==0x00) +#define twobyte(c) ((c&0xe0)==0xc0) +#define threebyte(c) ((c&0xf0)==0xe0) +#define fourbyte(c) ((c&0xf8)==0xf0) // ----------------------------------------------------------------------- // globals diff --git a/sys/cmd/rc/parse.c b/sys/cmd/rc/parse.c index c5c77d3..b61ac3c 100644 --- a/sys/cmd/rc/parse.c +++ b/sys/cmd/rc/parse.c @@ -1,5 +1,7 @@ #include "rc.h" +/* TODO: better error messages */ + // ----------------------------------------------------------------------- // global data diff --git a/sys/cmd/rc/rc.h b/sys/cmd/rc/rc.h index 7146aa0..f32a737 100644 --- a/sys/cmd/rc/rc.h +++ b/sys/cmd/rc/rc.h @@ -43,6 +43,13 @@ enum Rrdwr = 7, }; +enum +{ + Fopen = 1, + Fdup = 2, + Fclose = 3, +}; + // ----------------------------------------------------------------------- // main types @@ -50,6 +57,7 @@ typedef union Code Code; typedef struct Word Word; typedef struct List List; typedef struct Var Var; +typedef struct Redir Redir; typedef struct Tree Tree; typedef struct Builtin Builtin; typedef struct Thread Thread; @@ -74,12 +82,26 @@ struct List List *link; }; +struct Redir +{ + uchar type; + short from, to; + Redir *link; +}; + struct Var { - string name; + string name; Word *val; - Code *func; - Var *link; + struct { + Code *func, *ip; + uint funcnew : 1; + }; + struct { + uint new : 1; + void (*update)(Var*); + }; + Var *link; }; struct Tree @@ -107,7 +129,9 @@ struct Thread { Code *code, *ip; List *stack; + Redir *redir, *root; Var *local; + uchar interactive : 1; struct { uchar eof : 1; int line; @@ -145,16 +169,48 @@ extern Var *globals[1021]; /* for now must be prime */ * notation: * (var1, var2, ...) : items from stack * [var1, var2, ...] : items from code stream - * -> moves value + * {var1, var2, ...} : jump block from code stream + * -> moves value (stack) [code stream] */ -extern void Xmark(void); /* Xmark: delimit stack with new list */ -extern void Xword(void); /* Xword[val] -> (val) */ +extern void Xappend(void); /* Xappend(file)[fd]: open file to append */ extern void Xassign(void); /* Xassign(name, val): assign name to val */ +extern void Xasync(void); /* Xasync(cmd): run command asynchronously */ +extern void Xcat(void); /* Xcat(list1, list2): concatenate strings */ +extern void Xclose(void); /* Xclose[fd]: close file descriptor */ +extern void Xcmdsub(void); /* Xcmdsub(cmd): use output of command as input to other */ +extern void Xcount(void); /* Xcount(name) -> (number): count items in list*/ extern void Xdol(void); /* Xdol(name): get variable value */ -extern void Xsimple(void); /* Xsimple(args): run command */ +extern void Xdup(void); /* Xdup[i, j]: duplicate file descriptor */ extern void Xexit(void); /* Xexit: exit with status */ -extern void Xerror(char *s); /* Xerror: report an error */ -extern void Xparse(void); +extern void Xfalse(void); /* Xfalse{...}: run only if $status=1 */ +extern void Xflatten(void); /* Xflatten(list) -> (string): flatten list */ +extern void Xfor(void); /* Xfor(list): flatten list */ +extern void Xfunc(void); /* Xfunc(name){... Xreturn}: define function */ +extern void Xglob(void); /* Xglob(list): globs value */ +extern void Xif(void); /* Xif: execute if $status */ +extern void Xjump(void); /* Xjump[addr]: jump to address */ +extern void Xkill(void); /* Xkill kill thread */ +extern void Xlocal(void); /* Xlocal(name, val): define local variable */ +extern void Xmark(void); /* Xmark: delimit stack with new list */ +extern void Xmatch(void); /* Xmatch(pat, str): sets status with result */ +extern void Xnegate(void); /* Xnegate: negate condition */ +extern void Xpipe(void); /* Xpipe[i j]{... Xkill}{... Xkill}: construct a pipe between 2 threads*/ +extern void Xpipefd(void); /* Xpipe[type]{... Xkill}: connect {} to a pipe */ +extern void Xpipewait(void); /* Xpipewait: wait on a pipe */ +extern void Xpop(void); /* Xpop(value): pops value from stack */ +extern void Xpopredir(void); /* Xpopredir(value): pops redir from redir stack */ +extern void Xrdwr(void); /* Xrdwr(file)[fd]: open file for reads/writes */ +extern void Xread(void); /* Xread(file)[fd]: open file for reads */ +extern void Xsub(void); /* Xsub(list, index): subscript list */ +extern void Xsimple(void); /* Xsimple(args): run command */ +extern void Xsubshell(void); /* Xsubshell(args): run command in a subshell */ +extern void Xtrue(void); /* Xtrue{...}: run only if $status=0 */ +extern void Xunfunc(void); /* Xunfunc(name) undefine function */ +extern void Xunlocal(void); /* Xunlocal(name) undefine local */ +extern void Xword(void); /* Xword[val] -> (val) */ +extern void Xwrite(void); /* Xwrite(file)[fd]: open file to write */ + +extern void Xerror(char *s); /* Xerror report an error */ // ----------------------------------------------------------------------- // shell functions @@ -228,6 +284,7 @@ Tree *wordnode(char *w); Var *newvar(char *name, Var *link); Var *gvlookup(char *name); Var *vlookup(char *name); +void setvar(char *name, Word *val); int kwlookup(char *name); void initkw(void); diff --git a/sys/cmd/rc/rules.mk b/sys/cmd/rc/rules.mk index 33d6ba8..4f47886 100644 --- a/sys/cmd/rc/rules.mk +++ b/sys/cmd/rc/rules.mk @@ -2,14 +2,15 @@ include share/push.mk # Local sources SRCS_$(d) := \ - $(d)/io.c \ - $(d)/util.c \ - $(d)/var.c \ + $(d)/glob.c \ $(d)/word.c \ - $(d)/tree.c \ - $(d)/lex.c \ - $(d)/parse.c \ - $(d)/main.c + $(d)/util.c \ + $(d)/io.c + # $(d)/var.c \ + # $(d)/tree.c \ + # $(d)/lex.c \ + # $(d)/parse.c \ + # $(d)/main.c BINS_$(d) := $(d)/rc include share/paths.mk diff --git a/sys/cmd/rc/var.c b/sys/cmd/rc/var.c index ef339d7..d442369 100644 --- a/sys/cmd/rc/var.c +++ b/sys/cmd/rc/var.c @@ -73,10 +73,13 @@ newvar(char *name, Var *link) Var *v; alloc(v); - v->name = name; - v->val = 0; - v->func = nil; - v->link = link; + v->name = name; + v->val = 0; + v->func = nil; + v->funcnew = 0; + v->new = 0; + v->update = nil; + v->link = link; return v; } @@ -106,3 +109,21 @@ vlookup(char *name) return v; return gvlookup(name); } + +static +void +set(char *name, Word *val, int call) +{ + Var *v = vlookup(name); + freelist(v->val); + v->val = val; + v->new = 1; + if (call && v->update) + v->update(v); +} + +void +setvar(char *name, Word *val) +{ + set(name, val, 1); +} diff --git a/sys/cmd/rc/word.c b/sys/cmd/rc/word.c index 84ff40c..56a6756 100644 --- a/sys/cmd/rc/word.c +++ b/sys/cmd/rc/word.c @@ -1,5 +1,6 @@ #include "rc.h" +#if 0 void pushlist(void) { @@ -9,6 +10,7 @@ pushlist(void) ls->words = nil; ls->link = shell->stack, shell->stack = ls; } +#endif void freelist(Word *w) @@ -22,6 +24,7 @@ freelist(Word *w) } } +#if 0 void poplist(void) { @@ -33,6 +36,7 @@ poplist(void) shell->stack = ls->link; efree(ls); } +#endif int count(Word *w) @@ -55,6 +59,7 @@ newword(char *w, Word *link) return wd; } +#if 0 void pushword(char *w) { @@ -62,3 +67,4 @@ pushword(char *w) panicf("no active stack"); shell->stack->words = newword(w, shell->stack->words); } +#endif diff --git a/sys/cmd/walk/walk.c b/sys/cmd/walk/walk.c index 12f6c55..853369c 100644 --- a/sys/cmd/walk/walk.c +++ b/sys/cmd/walk/walk.c @@ -13,7 +13,7 @@ flush(void) } static -void +int print(void *data, char *rel, char *abs, io·Stat *info) { copy: @@ -25,6 +25,8 @@ copy: goto copy; } *c++ = '\n'; + + return 0; } static diff --git a/sys/libn/fs.c b/sys/libn/fs.c index 5d06997..10cd93e 100644 --- a/sys/libn/fs.c +++ b/sys/libn/fs.c @@ -6,7 +6,6 @@ /* * path history */ - struct Key { ino_t ino; @@ -151,9 +150,14 @@ fs·walk(fs·Walker *fs) return; } - /* operate on directory if preorder traversal */ - if (fs->flags & fs·preorder) - fs->func(fs->data, fs->base, fs->path, &cwd); + /* + * operate on directory first if preorder traversal + * truncate recursion if callback returns an error code + */ + if (fs->flags & fs·preorder) { + if (fs->func(fs->data, fs->base, fs->path, &cwd)) + return; + } /* open directory */ if(!fs->max || fs->lev + 1 < fs->max) { -- cgit v1.2.1