From 5d3642b8ef920316693031d2ea34b9def0b1abc5 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Thu, 22 Apr 2021 08:55:35 -0700 Subject: chore: rm unfinished projects --- sys/cmd/rc/code.c | 335 ----------------------------------- sys/cmd/rc/code.dep | 166 ------------------ sys/cmd/rc/exec.c | 139 --------------- sys/cmd/rc/glob.c | 199 --------------------- sys/cmd/rc/io.c | 446 ---------------------------------------------- sys/cmd/rc/lex.c | 417 ------------------------------------------- sys/cmd/rc/main.c | 86 --------- sys/cmd/rc/parse.c | 496 ---------------------------------------------------- sys/cmd/rc/rc.h | 312 --------------------------------- sys/cmd/rc/rules.mk | 22 --- sys/cmd/rc/simple.c | 13 -- sys/cmd/rc/tree.c | 144 --------------- sys/cmd/rc/util.c | 40 ----- sys/cmd/rc/var.c | 129 -------------- sys/cmd/rc/word.c | 64 ------- 15 files changed, 3008 deletions(-) delete mode 100644 sys/cmd/rc/code.c delete mode 100644 sys/cmd/rc/code.dep delete mode 100644 sys/cmd/rc/exec.c delete mode 100644 sys/cmd/rc/glob.c delete mode 100644 sys/cmd/rc/io.c delete mode 100644 sys/cmd/rc/lex.c delete mode 100644 sys/cmd/rc/main.c delete mode 100644 sys/cmd/rc/parse.c delete mode 100644 sys/cmd/rc/rc.h delete mode 100644 sys/cmd/rc/rules.mk delete mode 100644 sys/cmd/rc/simple.c delete mode 100644 sys/cmd/rc/tree.c delete mode 100644 sys/cmd/rc/util.c delete mode 100644 sys/cmd/rc/var.c delete mode 100644 sys/cmd/rc/word.c (limited to 'sys/cmd/rc') diff --git a/sys/cmd/rc/code.c b/sys/cmd/rc/code.c deleted file mode 100644 index edf47cf..0000000 --- a/sys/cmd/rc/code.c +++ /dev/null @@ -1,335 +0,0 @@ -#include "rc.h" - -#define delcode 100 -#define c0 t->child[0] -#define c1 t->child[1] -#define c2 t->child[2] - -#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 -{ - int cap; - Code *buf, *ip, *end; -} code; - -static -int -morecode(void) -{ - code.cap += delcode; - code.buf = erealloc(code.buf, code.cap*sizeof(*code.buf)); - code.end = code.ip + delcode; - memset(code.ip, 0, delcode*sizeof(*code.buf)); - - return 0; -} - -static -void -stuffdot(Code *p) -{ - int a; - - a = p - code.buf; - if (code.ip <= p || p < code.buf) - panic("bad address %d in stuffdot", a); - code.buf[a].i = code.ip-code.buf; -} - -static -void -rcc(Tree *t, int eflag) -{ - Code *p, *q; - Tree *tt; - - if (!t) - return; - - switch(t->type) { - default: - pfmt(errio, "bad type %d in rc compiler\n", t->type); - break; - case Tdol: - emitf(Xmark); - rcc(c0, eflag); - emitf(Xdol); - break; - case Tquote: - emitf(Xmark); - rcc(c0, eflag); - emitf(Xflatten); - break; - case Tsub: - emitf(Xmark); - rcc(c0, eflag); - emitf(Xmark); - rcc(c1, eflag); - emitf(Xsub); - break; - case Tand: - emitf(Xasync); - p = emiti(0); - rcc(c0, eflag); - emitf(Xexit); - stuffdot(p); - break; - case Tsemi: - rcc(c0, eflag); - rcc(c1, eflag); - break; - case Tcarot: - emitf(Xmark); - rcc(c1, eflag); - emitf(Xmark); - rcc(c0, eflag); - emitf(Xcat); - break; - case Ttick: - emitf(Xcmdsub); - p = emiti(0); - rcc(c0, 0); - emitf(Xexit); - stuffdot(p); - break; - case Tandand: - rcc(c0, 0); - emitf(Xtrue); - p = emiti(0); - rcc(c1, eflag); - stuffdot(p); - break; - case Targs: - rcc(c1, eflag); - rcc(c0, eflag); - break; - case Tbang: - rcc(c0, eflag); - emitf(Xnegate); - break; - case Tparen: - case Tbrace: - rcc(c0, eflag); - break; - case Tcount: - emitf(Xmark); - rcc(c0, eflag); - emitf(Xcount); - break; - case Tfunc: - emitf(Xmark); - rcc(c0, eflag); - if(c1){ - emitf(Xfunc); - p = emiti(0); - emits(fnstr(c1)); - rcc(c1, eflag); - emitf(Xunlocal); /* get rid of $* */ - emitf(Xkill); - stuffdot(p); - } 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) - // rcerror("`else' does not follow `if(...)'"); - // emitf(Xelse); - // p = emiti(0); - // rcc(c0, eflag); - // stuffdot(p); - // break; - case Toror: - rcc(c0, 0); - emitf(Xfalse); - p = emiti(0); - rcc(c1, eflag); - stuffdot(p); - break; - case Tpcmd: - rcc(c0, eflag); - break; - case Tsimple: - emitf(Xmark); - rcc(c0, eflag); - emitf(Xsimple); - if(eflag) - emitf(Xeflag); - break; - case Tsubshell: - emitf(Xsubshell); - p = emiti(0); - rcc(c0, eflag); - emitf(Xexit); - stuffdot(p); - if(eflag) - emitf(Xeflag); - break; - case Tswitch: - codeswitch(t, eflag); - break; - case Ttwiddle: - emitf(Xmark); - rcc(c1, eflag); - emitf(Xmark); - rcc(c0, eflag); - emitf(Xmatch); - if(eflag) - emitf(Xeflag); - break; - case Twhile: - q = code.ip; - rcc(c0, 0); - if(q==code.ip) - emitf(Xsettrue); /* empty condition == while(true) */ - emitf(Xtrue); - p = emiti(0); - rcc(c1, eflag); - emitf(Xjump); - emiti(q-code.buf); - stuffdot(p); - break; - case Twords: - rcc(c1, eflag); - rcc(c0, eflag); - break; - case Tfor: - emitf(Xmark); - if(c1){ - rcc(c1, eflag); - emitf(Xglob); - } else{ - emitf(Xmark); - emitf(Xword); - emits(strdup("*")); - emitf(Xdol); - } - emitf(Xmark); /* dummy value for Xlocal */ - emitf(Xmark); - rcc(c0, eflag); - emitf(Xlocal); - p = emitf(Xfor); - q = emiti(0); - rcc(c2, eflag); - emitf(Xjump); - emiti(p-code.buf); - stuffdot(q); - emitf(Xunlocal); - break; - case Tword: - emitf(Xword); - emits(strdup(t->str)); - break; - case Tdup: - if(t->redir.type == Rdupfd){ - emitf(Xdup); - emiti(t->redir.fd[0]); - emiti(t->redir.fd[1]); - } else{ - emitf(Xclose); - emiti(t->redir.fd[0]); - } - rcc(c1, eflag); - emitf(Xpopredir); - break; - case Tpipefd: - emitf(Xpipefd); - 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->redir.type){ - case Rappend: - emitf(Xappend); - break; - case Rwrite: - emitf(Xwrite); - break; - case Rread: - case Rhere: - emitf(Xread); - break; - case Rrdwr: - emitf(Xrdwr); - break; - } - emiti(t->redir.fd[0]); - rcc(c1, eflag); - emitf(Xpopredir); - break; - case Teq: - tt = t; - for(;t && t->type==Teq;t = c2); - if(t){ - for(t = tt;t->type==Teq;t = c2){ - emitf(Xmark); - rcc(c1, eflag); - emitf(Xmark); - rcc(c0, eflag); - emitf(Xlocal); - } - rcc(t, eflag); - for(t = tt; t->type==Teq; t = c2) - emitf(Xunlocal); - } else{ - for(t = tt;t;t = c2){ - emitf(Xmark); - rcc(c1, eflag); - emitf(Xmark); - rcc(c0, eflag); - emitf(Xassign); - } - } - t = tt; /* so tests below will work */ - break; - case Tpipe: - emitf(Xpipe); - 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(Xkill); - stuffdot(q); - emitf(Xpipewait); - break; - } - if(t->type!=Telse && t->type!=Tsemi) - shell->iflast = t->type==Tif; - else if (c0) - shell->iflast = c0->type==Tif; -} - -Code* -compile(Tree *t) -{ - code.cap = delcode; - code.buf = code.ip = emalloc(code.cap*sizeof *code.buf); - code.end = code.ip + code.cap; - - emiti(0); - rcc(t, 0); - emitf(Xkill); - emitf(nil); - - return code.buf; -} diff --git a/sys/cmd/rc/code.dep b/sys/cmd/rc/code.dep deleted file mode 100644 index 7fdd4bc..0000000 --- a/sys/cmd/rc/code.dep +++ /dev/null @@ -1,166 +0,0 @@ -#if 0 -// simple example code -error -cd(Args args) -{ - switch (args.len) { - case 0: - errorf("reached cd with no arguments!"); - return 1; - case 1: - one: - errorf("sh: expected argument to command 'cd'"); - return 1; - case 2: - if (args.a[1] == nil) - goto one; - break; - default: - errorf("sh: too many arguments to command 'cd'"); - return 1; - } - if (chdir(args.a[1])) - errorf("cd fail: %s", strerror(errno)); - - return 0; -} - -error -quit(Args args) -{ - exit(0); -} - -Builtin builtins[] = { - { "cd", cd }, - { "exit", quit }, -}; - -void -clear(Header *arr) -{ - arr->len = 0; -} - -int -readline(Code *code) -{ - int n, b; - - n = code->len; -getchar: - if (code->len >= code->cap) { - code->cap += 100; - code->s = realloc(code->s, code->cap); - } - /* TODO: unicode? */ - switch ((b = getchar())) { - case EOF: - n = -1; - goto null; - case '\n': - n = code->len - n; - null: - code->s[code->len] = '\0'; - break; - default: - code->s[code->len++] = b; - goto getchar; - } - - return n; -} - -/* TODO: unicode */ -int -readargs(Code code, Args *args) -{ - if (args->a) - clear(&args->hdr); - else { - args->cap += 20; - args->a = realloc(args->a, args->cap); - } - - args->a[args->len++] = code.s; - while (*code.s) { - if (!isspace(*code.s++)) - continue; - - code.s[-1] = '\0'; - /* consume all remaining space */ - while (isspace(*code.s)) - code.s++; - - if (args->len >= args->cap-1) { - args->cap += 20; - args->a = realloc(args->a, args->cap); - } - args->a[args->len++] = code.s; - } - /* nil acts as a sentinel value */ - args->a[args->len] = nil; - - return args->len; -} - -error -execute(Args args) -{ - int i, status; - pid_t cid, wid; - - for (i = 0; i < arrlen(builtins); i++) { - if (strcmp(args.a[0], builtins[i].cmd) == 0) - return builtins[i].func(args); - } - - if ((cid = fork()) == 0) { - if (execvp(args.a[0], args.a) == -1) - errorf("exec failed: %s", strerror(errno)); - exit(1); - } else if (cid > 0) - do - wid = waitpid(cid, &status, WUNTRACED); - while (!WIFEXITED(status) && !WIFSIGNALED(status)); - else - errorf("fork failed: %s", strerror(errno)); - - return status; -} - -static -void -flush(void) -{ - io·flush(stdout); -} - -static -void -prompt(void) -{ - printf(";"); - flush(); -} - -int -main(int argc, char *argv[]) -{ - int i, err, n; - Code code = {0}; - Args args = {0}; - - ARGBEGIN { - } ARGEND; - - do { - clear(&code.hdr); - prompt(); - - n = readline(&code); - readargs(code, &args); - err = execute(args); - } while (!err && n > 0); -} -#endif diff --git a/sys/cmd/rc/exec.c b/sys/cmd/rc/exec.c deleted file mode 100644 index d4822a7..0000000 --- a/sys/cmd/rc/exec.c +++ /dev/null @@ -1,139 +0,0 @@ -#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 -Xmark(void) -{ - pushlist(); -} - -void -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 deleted file mode 100644 index 95b2ef3..0000000 --- a/sys/cmd/rc/glob.c +++ /dev/null @@ -1,199 +0,0 @@ -#include "rc.h" -#include - -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); -} - -#if 0 -int -main() -{ - errio = openfd(2); - glob("\x01*"); - pval(errio, matches); - flush(&errio); -} -#endif diff --git a/sys/cmd/rc/io.c b/sys/cmd/rc/io.c deleted file mode 100644 index e06bfcc..0000000 --- a/sys/cmd/rc/io.c +++ /dev/null @@ -1,446 +0,0 @@ -#include "rc.h" - -#define c0 t->child[0] -#define c1 t->child[1] -#define c2 t->child[2] - -#undef bufsize -#define bufsize 512 -#define strsize 100 - -//------------------------------------------------------------------------ -// buffer operations - -/* open file */ -Io* -openfd(int fd) -{ - Io *f; - - f = emalloc(sizeof *f + bufsize); - f->fd = fd; - f->b = f->e = f->buf; - return f; -} - -/* open string */ -Io* -openstr(void) -{ - Io *f; - - f = emalloc(sizeof *f + strsize + 1); - f->fd = -1; - f->b = f->buf; - f->e = f->buf+strsize; - memset(f->b, 0, strsize+1); - - return f; -} - -/* open core (not nil terminated) */ -Io* -opencore(int len, char *s) -{ - Io *f; - - f = emalloc(sizeof *f + len); - f->fd = -1; - f->b = f->buf; - f->e = f->buf+len; - memcpy(f->b, s, len); - - return f; -} - -void -rewindio(Io *f) -{ - if (f->fd < 0) - f->b = f->buf; - else { - f->b = f->e = f->buf; - lseek(f->fd, 0, 0); - } -} - -void -closeio(Io *f) -{ - if (f->fd >= 0) - close(f->fd); - - efree(f); -} - -/* has the chance to realloc */ -void -flush(Io **fp) -{ - int n; - char *s; - Io *f; - - f = *fp; - if (f->fd < 0) { - n = f->e - f->b; - f = erealloc(f, sizeof *f + n + strsize + 1); - if (!f) - panic("can't realloc %d bytes in flush", n+strsize+1); - f->b = f->buf+n; - f->e = f->buf+n+strsize; - memset(f->b, 0, strsize+1); - } else { - n = f->b - f->buf; - if (n && write(f->fd, f->buf, n) < 0) { - write(3, "write error\n", 12); - // if (ntrap) - // dotrap(); - } - f->b = f->buf; - f->e = f->buf + bufsize; - } - - *fp = f; -} - -//------------------------------------------------------------------------ -// read from io - -int -rchr(Io *f) -{ - int n; - if (f->b == f->e) { - if (f->fd < 0 || (n = read(f->fd, f->buf, bufsize)) <= 0) - return EOF; - - f->b = f->buf; - f->e = f->b + n; - } - - return *f->b++&0xFF; -} - -//------------------------------------------------------------------------ -// printf functionality - -/* character literal */ -int -pchr(Io *f, int c) -{ - if (f->b == f->e) - flush(&f); - - return *f->b++=c; -} - -/* quote */ -void -pquo(Io *f, char *s) -{ - pchr(f, '\''); - for (; *s; s++) - if (*s == '\'') - pfmt(f, "''"); - else - pchr(f, *s); - pchr(f, '\''); -} - -/* word */ -void -pwrd(Io *f, char *s) -{ - char *t; - for(t = s; *t; t++) - if(!wordchr(*t)) - break; - if(t == s || *t) - pquo(f, s); - else - pstr(f, s); -} - -/* pointer */ -void -pptr(Io *f, void *v) -{ - int n; - uintptr p; - - if (!v) { - pstr(f, ""); - return; - } - - p = (uintptr)v; - if ((sizeof(uintptr) == sizeof(uvlong)) && p >>32) - for (n = 60; n >= 32; n-=4) - pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]); - for (n = 28; n >= 0; n-=4) - pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]); -} - -/* string */ -void -pstr(Io *f, char *s) -{ - if(!s || !s[0]) - s = ""; - - while(*s) - pchr(f, *s++); -} - -/* decimal */ -void -pdec(Io *f, int n) -{ - if (n < 0) { - n = -n; - pchr(f, '-'); - if (n >= 0) { - pdec(f, n); - return; - } - n = 1 - n; - pdec(f, n/10); - pchr(f, n%10+'1'); - return; - } - - if (n > 9) - pdec(f, n/10); - pchr(f, n%10+'0'); -} - -/* octal */ -void -poct(Io *f, uint n) -{ - if (n > 7) - poct(f, n>>3); - pchr(f, (n&7)+'0'); -} - -/* value */ -void -pval(Io *f, Word *a) -{ - if(a) { - while(a->link && a->link->word) { - pwrd(f, a->word); - pchr(f, ' '); - a = a->link; - } - pwrd(f, a->word); - } -} - -/* tree */ -static -void -pdeglob(Io *f, char *s) -{ - while(*s){ - if(*s==GLOB) - s++; - pchr(f, *s++); - } -} - -void -pcmd(Io *f, Tree *t) -{ - if(!t) - return; - - switch(t->type){ - default: pfmt(f, "bad<%d> %p %p %p", t->type, c0, c1, c2); - break; - case Tdol: pfmt(f, "$%t", c0); - break; - case Tquote: pfmt(f, "$\"%t", c0); - break; - case Tand: pfmt(f, "%t&", c0); - break; - case Tcarot: pfmt(f, "%t^%t", c0, c1); - break; - case Ttick: pfmt(f, "`%t", c0); - break; - case Tandand: pfmt(f, "%t && %t", c0, c1); - break; - case Tbang: pfmt(f, "! %t", c0); - break; - case Tbrace: pfmt(f, "{%t}", c0); - break; - case Tcount: pfmt(f, "$#%t", c0); - break; - case Tfunc: pfmt(f, "func %t %t", c0, c1); - break; - case Tif: (c2) ? pfmt(f, "if%t%t else %t", c0, c1, c2): pfmt(f, "if%t%t", c0, c1); - break; - case Toror: pfmt(f, "%t || %t", c0, c1); - break; - case Tpcmd: /* fallthrough */ - case Tparen: pfmt(f, "(%t)", c0); - break; - case Tsub: pfmt(f, "$%t(%t)", c0, c1); - break; - case Tsimple: pfmt(f, "%t", c0); - break; - case Tsubshell: pfmt(f, "@ %t", c0); - break; - case Tswitch: pfmt(f, "switch %t %t", c0, c1); - break; - case Tcase: pfmt(f, "case %t:\n%t", c0, c1); - break; - case Ttwiddle: pfmt(f, "~ %t %t", c0, c1); - break; - case Twhile: pfmt(f, "while %t%t", c0, c1); - break; - case Targs: - if(c0==0) - pfmt(f, "%t", c1); - else if(c1==0) - pfmt(f, "%t", c0); - else - pfmt(f, "%t %t", c0, c1); - break; - case Tsemi: - if(c0) { - if(c1) - pfmt(f, "%t%c%t", c0, '\n', c1); - else - pfmt(f, "%t", c0); - } else - pfmt(f, "%t", c1); - break; - case Twords: - if(c0) - pfmt(f, "%t ", c0); - pfmt(f, "%t", c1); - break; - case Tfor: - pfmt(f, "for(%t", c0); - if(c1) - pfmt(f, " in %t", c1); - pfmt(f, ")%t", c2); - break; - case Tword: - if(t->quoted) - pfmt(f, "%Q", t->str); - else - pdeglob(f, t->str); - break; - case Tdup: - if(t->redir.type==Rdupfd) - pfmt(f, ">[%d=%d]", t->redir.fd[1], t->redir.fd[0]); /* yes, fd1, then fd0; read lex.c */ - else - pfmt(f, ">[%d=]", t->redir.fd[0]); - pfmt(f, "%t", c1); - break; - case Tpipefd: - case Tredir: - switch(t->redir.type){ - case Rhere: - pchr(f, '<'); - case Rread: - case Rrdwr: - pchr(f, '<'); - if(t->redir.type==Rrdwr) - pchr(f, '>'); - if(t->redir.fd[0]!=0) - pfmt(f, "[%d]", t->redir.fd[0]); - break; - case Rappend: - pchr(f, '>'); - case Rwrite: - pchr(f, '>'); - if(t->redir.fd[0]!=1) - pfmt(f, "[%d]", t->redir.fd[0]); - break; - } - pfmt(f, "%t", c0); - if(c1) - pfmt(f, " %t", c1); - break; - case Teq: - pfmt(f, "%t=%t", c0, c1); - if(c2) - pfmt(f, " %t", c2); - break; - case Tpipe: - pfmt(f, "%t|", c0); - if(t->redir.fd[1]==0){ - if(t->redir.fd[0]!=1) - pfmt(f, "[%d]", t->redir.fd[0]); - } - else pfmt(f, "[%d=%d]", t->redir.fd[0], t->redir.fd[1]); - pfmt(f, "%t", c1); - break; - } -} - -/* rc specific printf */ -static int pfmtlev; - -void -vpfmt(Io *f, char *fmt, va_list args) -{ - char err[124]; - - pfmtlev++; - for (; *fmt; fmt++) - if (*fmt!='%') - pchr(f, *fmt); - else switch(*++fmt) { - case '\0': - break; - case 'c': - pchr(f, va_arg(args, int)); - break; - case 'd': - pdec(f, va_arg(args, int)); - break; - case 'o': - poct(f, va_arg(args, uint)); - break; - case 'p': - pptr(f, va_arg(args, void*)); - break; - case 'Q': - pquo(f, va_arg(args, char*)); - break; - 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; - case 't': - pcmd(f, va_arg(args, Tree*)); - break; - case 'v': - pval(f, va_arg(args, Word*)); - break; - } - - if (--pfmtlev==0) - flush(&f); -} - -void -pfmt(Io *f, char *fmt, ...) -{ - va_list args; - char err[124]; - - va_start(args, fmt); - vpfmt(f, fmt, args); - va_end(args); -} diff --git a/sys/cmd/rc/lex.c b/sys/cmd/rc/lex.c deleted file mode 100644 index f6e2b4e..0000000 --- a/sys/cmd/rc/lex.c +++ /dev/null @@ -1,417 +0,0 @@ -#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) - -// ----------------------------------------------------------------------- -// globals - -static int lastc, nextc=EOF, lastdol, lastword, doprompt = 1; -static char buf[8*1024]; - -// ----------------------------------------------------------------------- -// utilities - -static uchar nwordc[256] = -{ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -int -wordchr(int c) -{ - return !nwordc[c] && c!=EOF; -} - - -static uchar nquotec[256] = -{ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -int -quotechr(char c) -{ - return !nquotec[c] && c!=EOF; -} - -static uchar nvarc[256] = -{ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - - -int -varchr(char c) -{ - return !nvarc[c] && c!=EOF; -} - -static -void -prompt(void) -{ - shell->cmd.line++; - doprompt = 0; -} - -/* lookahead one byte */ -static -int -lookahead(void) -{ - int c; - - if(nextc != EOF) - return nextc; - if(shell->cmd.eof) - return EOF; - - if(doprompt) - prompt(); - - c = rchr(shell->cmd.io); - doprompt = c == '\n' || c == EOF; - - if(c == EOF) - shell->cmd.eof++; - - return nextc = c; -} - -/* consumes the lookahead */ -static -int -advance(void) -{ - int c = lookahead(); - lastc = nextc, nextc = EOF; - - return c; -} - -/* - * advance until we no longer hit horizontal space - * consumes all comments - */ -static -void -skipws(void) -{ - int c; - for(;;) { - c = lookahead(); - if(c=='#'){ - for(;;){ - c = lookahead(); - if(c=='\n' || c==EOF) - break; - advance(); - } - } - if(c==' ' || c=='\t') - advance(); - else - return; - } -} - -/* advance until we no longer hit any space */ -void -skipnl(void) -{ - int c; - for(;;) { - skipws(); - if ((c = lookahead()) != '\n') - return; - advance(); - } -} - -/* advance if next char is equal to c */ -static -int -nextis(int c) -{ - if(lookahead()==c) { - advance(); - return 1; - } - return 0; -} - -/* functions to append to our write buffer */ -static -char* -putbyte(char *s, int c) -{ - if(!s) - return s; - if(s == arrend(buf)){ - *s = 0; - rcerror("out of buffer space"); - return nil; - } - *s++ = c; - return s; -} - -static -char* -putrune(char *s, int c) -{ - s = putbyte(s, c); - if (onebyte(c)) - return s; - if (twobyte(c)) - return putbyte(s, advance()); - if (threebyte(c)) { - putbyte(s, advance()); - return putbyte(s, advance()); - } - if (fourbyte(c)) { - putbyte(s, advance()); - putbyte(s, advance()); - return putbyte(s, advance()); - } - rcerror("malformed utf8 stream"); - return nil; -} - -// ----------------------------------------------------------------------- -// main exports - -void -rcerror(char *fmt, ...) -{ - va_list args; - - pfmt(errio, "rc:"); - if (shell->cmd.io) - pfmt(errio, "%s:%d ", shell->cmd.name, shell->cmd.line); - - va_start(args, fmt); - vpfmt(errio, fmt, args); - va_end(args); - - pfmt(errio, "\n"); - - flush(&errio); - lastword = lastdol = 0; - while (lastc != '\n' && lastc != EOF) - advance(); - /* for debugging only */ - abort(); -} - -/* word is only modified in the event of a lexed word */ -int -lex(Tree **node) -{ - int c; - char *w = buf; - /* - * NOTE: - * we inject tokens into the lexer based on context if last token = word: - * if we see a (, then we interpret that as a subscript - * otherwise, if the next character is the first char of a word, we return a ^ operator. - */ - if(lastword){ - lastword=0; - c = lookahead(); - if(c=='('){ - advance(); - return Tlparen; - } - if(quotechr(c)) - return Tcarot; - } - - skipws(); - switch(c=advance()) { - case EOF: - lastdol = 0; - return EOF; - case '$': - lastdol = 1; - if(nextis('#')) - return Tcount; - if (nextis('"')) - return Tquote; - return Tdol; - case '&': - lastdol = 0; - if(nextis('&')) - return Tandand; - return Tand; - - case '!': - return Tbang; - case '@': - return Tsubshell; - case '~': - return Ttwiddle; - - case '|': - lastdol = 0; - if(nextis('|')){ - skipnl(); - return Toror; - } - (*node) = newtree(); - (*node)->type = Tpipe; - (*node)->redir.fd[0] = 0; - (*node)->redir.fd[1] = 1; - goto redir; - case '>': - (*node) = newtree(); - (*node)->type = Tredir; - if (nextis(c)) - (*node)->redir.type = Rappend; - else - (*node)->redir.type = Rwrite; - (*node)->redir.fd[0] = 1; - goto redir; - case '<': - (*node) = newtree(); - (*node)->type = Tredir; - if(nextis(c)) - (*node)->redir.type = Rhere; - else if(nextis('>')) - (*node)->redir.type = Rrdwr; - else - (*node)->redir.type = Rread; - (*node)->redir.fd[0] = 0; - /* fallthrough */ - redir: - if(nextis('[')) { - c = advance(); - if(c < '0' || '9' < c) { - redirerr: - rcerror("incorrect redirection syntax"); - return EOF; - } - (*node)->redir.fd[0] = 0; - do { - (*node)->redir.fd[0] = 10*(*node)->redir.fd[0]+(c-'0'); - c = advance(); - } while('0'<=c && c<='9'); - - if(c == '=') { - if((*node)->type == Tredir) - (*node)->type = Tdup; - c = advance(); - if('0'<=c && c<='9') { - (*node)->redir.type = Rdupfd; - (*node)->redir.fd[1] = (*node)->redir.fd[0]; - (*node)->redir.fd[0] = 0; - do { - (*node)->redir.fd[0] = 10*(*node)->redir.fd[0]+(c-'0'); - c = advance(); - } while('0'<=c && c<='9'); - } else { - if((*node)->type == Tpipe) - goto redirerr; - (*node)->redir.type = Rclose; - } - } - if (c != ']' - ||(*node)->type==Tdup && ((*node)->redir.type==Rhere || (*node)->redir.type==Rappend)) - goto redirerr; - } - if ((c = ((*node)->type)) == Tpipe) - skipnl(); - return c; - - case '\'': - lastdol = 0; - lastword = 1; - for(;;){ - c = advance(); - if(c==EOF) - break; - if(c=='\''){ - if(lookahead()!='\'') - break; - advance(); - } - w = putrune(w, c); - } - *w = 0; - *node = wordnode(buf); - (*node)->quoted = 1; - return Tword; - } - if (!wordchr(c)) { - lastdol = 0; - return c; - } - for(;;){ - if(c=='*'||c=='['||c=='?'||c==GLOB) - w = putbyte(w, GLOB); - w = putrune(w, c); - c = lookahead(); - if(lastdol?!varchr(c):!wordchr(c)) - break; - advance(); - } - *w = 0; - - if ((c = kwlookup(buf)) == -1) { - (*node) = wordnode(buf); - (*node)->type = c = Tword; - (*node)->quoted = 0; - lastword = 1; - } - - lastdol = 0; - return c; -} diff --git a/sys/cmd/rc/main.c b/sys/cmd/rc/main.c deleted file mode 100644 index b4a355e..0000000 --- a/sys/cmd/rc/main.c +++ /dev/null @@ -1,86 +0,0 @@ -#include "rc.h" - -/* globals */ -Thread *shell = nil; -int ntrap = 0; -Io *errio; - -/* main execution */ - -void -dotrap(void) -{ - exit(1); -} - -void -bootup(Code *c, int off, Var *vars) -{ - Thread *sh; - - alloc(sh); - sh->code = c, c->i++; - sh->ip = sh->code + off; - sh->local = vars; - sh->stack = nil; - - sh->link = shell, shell = sh; -} - -int -main(int argc, char *argv[]) -{ - int i; - Code *ip, sh[32]; - - ARGBEGIN { - } ARGEND; - - errio = openfd(2); - - initkw(); - - ip = sh; - memset(sh, 0, sizeof(sh)); - /* - * NOTE: first element of code is a reference count - * bootup runs: - * 1. *=argv[1:] - * 2. . rcmain $* - */ -#if 0 - ip++->i = 1; - ip++->f = Xmark; - ip++->f = Xword; - ip++->s = "*"; - ip++->f = Xassign; - ip++->f = Xmark; - ip++->f = Xmark; - ip++->s = "*"; - ip++->f = Xdol; - ip++->s = "rcmain"; - ip++->f = Xword; - ip++->s = "."; - ip++->f = Xsimple; - ip++->f = Xexit; - ip++->i = 0; - - bootup(sh, 1, nil); - pushlist(); - for (i = argc-1; i != 0; i--) - pushword(argv[i]); - - for (;;) { - shell->ip++->f(); - if (ntrap) - dotrap(); - } -#else - bootup(sh, 1, nil); - shell->cmd.io = openfd(0); - while (parse()) - ; - -#endif - exit(0); -} diff --git a/sys/cmd/rc/parse.c b/sys/cmd/rc/parse.c deleted file mode 100644 index b61ac3c..0000000 --- a/sys/cmd/rc/parse.c +++ /dev/null @@ -1,496 +0,0 @@ -#include "rc.h" - -/* TODO: better error messages */ - -// ----------------------------------------------------------------------- -// global data - -static int lastt, nextt=EOF; -static Tree *node; /* if token was lexed as a tree node (redirs and words), its here */ - -/* anything that is not listed will automatically terminate parsing the given command */ -static uchar prectab[256] = { - [Tif] = 1, [Tfor] = 1, [Tswitch] = 1, /* NOTE: we give else lower precedence than if [Telse] = 1, */ - [Tandand] = 2, [Toror] = 2, - [Tbang] = 3, [Tsubshell] = 3, - [Tpipe] = 4, - [Tcarot] = 5, - [Tdol] = 6, [Tcount] = 6, [Tquote] = 6, - [Tsub] = 7, -}; - -// ----------------------------------------------------------------------- -// helpers - -static -int -lookahead(void) -{ - int tok; - - if (nextt != EOF) - return nextt; - - tok = lex(&node); - return nextt = tok; -} - -static -int -advance(void) -{ - int tok = lookahead(); - lastt = nextt, nextt = EOF; - node = nil; - - return tok; -} - -static -int -nextis(int tok) -{ - if (lookahead() == tok) { - advance(); - return 1; - } - return 0; -} - -// ----------------------------------------------------------------------- -// subparsers - -/* forward declarations */ -static Tree *word(void); -static Tree *words(void); -static Tree* body(int c); -static Tree *comword(void); -static Tree *cmd(int prec); - -/* implementations */ - -/* - * TODO: - * i don't like all this branching. - * think of a better way - */ - -static -Tree* -case_or_cmd(int c) -{ - Tree *t; - if (!c || !nextis(Tcase)) - return cmd(1); - - t = words(); - if (!nextis(';') && !nextis('\n')) - rcerror("case: missing terminator: recieved %d", nextt); - - t = tree2(Tcase, t, body(0)); - pfmt(errio, "%t\n", t); - - return t; -} - -static -Tree* -body(int c) -{ - int tok; - Tree *l, *r; - - skipnl(); - l = case_or_cmd(c); -loop: - switch((tok=lookahead())){ - case '&': - l = tree1('&', l); - /* fallthrough */ - case ';': case '\n': - advance(); - /* fallthrough */ - case Tcase: - if ((r = case_or_cmd(c))) { - l = tree2(';', l, r); - goto loop; - } - /* fallthrough */ - default: - ; - } - - return l; -} - -static -Tree* -brace(int c) -{ - Tree *t; - - if (!nextis('{')) - rcerror("brace: expected { found: %c", nextt); - t = tree1(Tbrace, body(c)); - if (!nextis('}')) - rcerror("brace: expected } found: %c", nextt); - - return t; -} - -static -Tree* -paren(void) -{ - Tree *t; - - if (!nextis('(')) - rcerror("not a paren"); - t = tree1(Tparen, body(0)); - if (!nextis(')')) - rcerror("unmatched paren"); - - return t; -} - -/* TODO: fill in */ -static -Tree* -heredoc(Tree* t) -{ - return t; -} - -static -Tree* -redir(void) -{ - int tok; - Tree *t; - - switch (tok = lookahead()) { - case Tdup: - t = node; - advance(); - break; - case Tredir: - t = node; - advance(); - t = hang1(t, (t->redir.type == Rhere) ? heredoc(word()) : word()); - break; - default: - t = nil; - } - - return t; -} - -static -Tree* -epilog(void) -{ - Tree *t, *tt; - - t = redir(); - while((tt = redir())) - t = hang2(t, t->child[0], tt); - - return t; -} - -static -Tree* -sword(void) -{ - int tok; - if (Kstart < (tok=lookahead()) && tok < Kend) - return node; - - return comword(); -} - -static -Tree* -word(void) -{ - int tok; - Tree *t; - - t = sword(); - while(nextis('^')) - t = tree2('^', t, sword()); - - return t; -} - - -static -Tree* -words(void) -{ - Tree *t, *tt; - t = word(); - while((tt=word())) - t = tree2(Twords, t, tt); - - return t; -} - -/* - * NOTE: we divergence from Duff's yacc grammar here. - * he has [dol|count|"]->word, we have [dol|count]->sword - * calling sword ensures we don't cat strings - * this was done in Tom's version by setting precedence - */ -static -Tree* -comword(void) -{ - int tok; - Tree *t, *tt; - - switch(tok=lookahead()){ - case Tdol: - advance(); - t = sword(); - if(nextis('(')) { - t = tree2(Tsub, t, words()); - if (!nextis(')')) - rcerror("malformed index expression"); - } - return tree1(Tdol, t); - case Tquote: - return tree1(Tquote, sword()); - case Tcount: - advance(); - return tree1(Tcount, sword()); - case Ttick: - advance(); - return tree1(Ttick, brace(0)); - case Tlparen: - return paren(); - case Tredir: - advance(); - t = hang1(node, brace(0)); - t->type = Tpipefd; - return t; - case Tword: - t = node; - advance(); - return t; - } - return nil; -} - -static -Tree* -first(void) -{ - int tok; - Tree *t; - - t = comword(); - while(nextis('^')) { - t = tree2('^', t, word()); - } - - return t; -} - -/* simple _or_ assignment */ -static -Tree* -simple_or_assign(void) -{ - int tok; - Tree *t, *tt; - - /* can't continue */ - if (!(t = first())) - return nil; - - /* is an assignment */ -assign: - if(nextis('=')) { - tt = word(); - return tree3(Teq, t, tt, cmd(prectab[Tbang])); - } - - /* is a 'simple' */ -simple: - switch ((tok=lookahead())) { - case Tredir: - case Tdup: - t = tree2(Targs, t, redir()); - goto simple; - default: - if ((tt = word())) { - t = tree2(Targs, t, tt); - goto simple; - } - /* fallthrough */ - } - - return simplehang(t); -} - -static -Tree* -opand(void) -{ - int tok; - Tree *t, *tt; - - switch(tok=lookahead()) { - case Tif: - advance(); - t = paren(); - skipnl(); - tt = cmd(prectab[Tif]); - if (nextis(Telse)) { - skipnl(); - t = tree3(Tif, t, tt, cmd(prectab[Tif])); - } else - t = tree3(Tif, t, tt, nil); - return t; - case Telse: - rcerror("invalid hanging else"); - break; - - case Tswitch: - advance(); - t = word(); - skipnl(); - tt = brace(1); - t = tree2(Tswitch, t, tt); - return t; - - case Tfor: - advance(); - - if (!nextis('(')) - rcerror("for: missing opening paren"); - t = word(); - if (nextis(Tin)) { - advance(); - tt = words(); - t = tree3(Tfor, t, tt, nil); - } else - t = tree3(Tfor, t, nil, nil); - if (!nextis(')')) - rcerror("for: missing closing paren"); - - skipnl(); - tt = cmd(prectab[Tfor]); - t->child[2] = tt; - return t; - - case Twhile: - advance(); - t = paren(); - skipnl(); - tt = cmd(1); - return tree2(Twhile, t, tt); - - case Tfunc: - advance(); - t = words(); - if ((tok=lookahead()) == '{') { - tt = brace(0); - t = tree2(Tfunc, t, tt); - } else - t = tree1(Tfunc, t); - return t; - - case Tsubshell: - advance(); - t = tree1(Tsubshell, cmd(prectab[Tsubshell])); - return t; - - case Tbang: - advance(); - t = tree1(Tbang, cmd(prectab[Tbang])); - return t; - - case Ttwiddle: - advance(); - tt = word(); - t = tree2(Ttwiddle, tt, words()); - return t; - - case Tlbrace: - t = brace(0); - tt = epilog(); - return epihang(t, tt); - - case Tredir: /* fallthrough */ - case Tdup: - t = redir(); - tt = cmd(prectab[Tbang]); - t = hang2(t, t->child[0], tt); - return t; - } - - return simple_or_assign(); -} - -static -Tree * -cmd(int prec) -{ - int np, tok; - Tree *l, *r, *p; - - if (!(l = opand())) - return nil; - - for(;;) { - tok = lookahead(); - np = prectab[tok]; - if (np < prec) - break; - p = node; - advance(); - r = cmd(np+1); - if (tok == Tpipe) - l = hang2(p, l, r); - else - l = tree2(tok, l, r); - } - - return l; -} - -// ----------------------------------------------------------------------- -// main function - -int -parse(void) -{ - int tok; - Tree *t, *tt; - - t = cmd(1); -loop: - switch(tok=lookahead()) { - case '&': - t = tree1('&', t); - /* fallthrough */ - case ';': - advance(); - tt = cmd(1); - t = tree2(';', t, tt); - goto loop; - case '\n': - advance(); - case EOF: - pfmt(errio, "%t\n", t); - break; - default: - if (tok > 0x20) - rcerror("unrecognized token: %c[%d]", tok, tok); - else - rcerror("unrecognized token: %d", tok, tok); - } - return tok != EOF; -} diff --git a/sys/cmd/rc/rc.h b/sys/cmd/rc/rc.h deleted file mode 100644 index f32a737..0000000 --- a/sys/cmd/rc/rc.h +++ /dev/null @@ -1,312 +0,0 @@ -#pragma once - -#include -#include - -#include -#include - -#define alloc(ptr) ptr = emalloc(sizeof(*ptr)) - -// ----------------------------------------------------------------------- -// main enums - -#define GLOB 0x01 - -enum -{ - /* keywords */ - Kstart = 11, - Tfor, Tin, Twhile, Tif, Telse, - Tswitch, Tcase, Tfunc, Ttwiddle, - Tbang, Tsubshell, - Kend, - - /* tokens */ - Tword='w', Tredir='r', Tdup='d', Tsimple='s', - Targs='A', Twords='W', Tbrace='b', Tparen='p', Tsub='S', - Tpcmd='c', Tpipefd='-', Tandand='%', Toror='@', Tcount='#', - - Ttick='`', Tpipe = '|', Tdol='$', Tquote='"', Tand='&', - Tlparen = '(', Trparen = ')', Tlbrace='{', Trbrace='}', - Tsemi=';', Tcarot='^', Teq='=', -}; - -enum -{ - Rappend = 1, - Rwrite = 2, - Rread = 3, - Rhere = 4, - Rdupfd = 5, - Rclose = 6, - Rrdwr = 7, -}; - -enum -{ - Fopen = 1, - Fdup = 2, - Fclose = 3, -}; - -// ----------------------------------------------------------------------- -// main types - -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; -typedef struct Io Io; - -union Code -{ - int i; - char *s; - void (*f)(void); -}; - -struct Word -{ - char *word; - Word *link; -}; - -struct List -{ - Word *words; - List *link; -}; - -struct Redir -{ - uchar type; - short from, to; - Redir *link; -}; - -struct Var -{ - string name; - Word *val; - struct { - Code *func, *ip; - uint funcnew : 1; - }; - struct { - uint new : 1; - void (*update)(Var*); - }; - Var *link; -}; - -struct Tree -{ - ushort type; - uchar quoted : 1; - union { - char *str; - struct { - ushort type; - int fd[2]; - } redir; - }; - - Tree *child[3], *link; -}; - -struct Builtin -{ - char *cmd; - void (*func)(void); -}; - -struct Thread -{ - Code *code, *ip; - List *stack; - Redir *redir, *root; - Var *local; - uchar interactive : 1; - struct { - uchar eof : 1; - int line; - char *name; - Io *io; - } cmd; - - int pid; - Tree *nodes; - Thread *link; /* continuation */ -}; - -struct Io -{ - int fd; - uchar *b, *e, buf[]; -}; - -// ----------------------------------------------------------------------- -// global interpreter variables - -extern Thread *shell; -extern int ntrap; -extern int status; - -extern Io *errio; - -extern Builtin builtins[]; -extern Var *globals[1021]; /* for now must be prime */ - -// ----------------------------------------------------------------------- -// interpreter functions (defined in exec.c) - -/* - * notation: - * (var1, var2, ...) : items from stack - * [var1, var2, ...] : items from code stream - * {var1, var2, ...} : jump block from code stream - * -> moves value (stack) [code stream] - */ -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 Xdup(void); /* Xdup[i, j]: duplicate file descriptor */ -extern void Xexit(void); /* Xexit: exit with status */ -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 - -/* - * util.c - */ -void *emalloc(uintptr size); -void *erealloc(void *ptr, uintptr size); -void efree(void *); -void panic(char *msg, int n); - -/* - * io.c - */ -Io *openfd(int fd); -Io *openstr(void); -Io *opencore(int len, char *s); -void rewindio(Io *f); -void closeio(Io *f); -void flush(Io **fp); - -/* reads */ -int rchr(Io *f); - -/* writes */ -int pchr(Io *f, int c); -void pquo(Io *f, char *s); -void pwrd(Io *f, char *s); -void pptr(Io *f, void *v); -void pstr(Io *f, char *s); -void pdec(Io *f, int n); -void poct(Io *f, uint n); -void pval(Io *f, Word *a); -void pcmd(Io *f, Tree *t); -void pfmt(Io *f, char *fmt, ...); -void vpfmt(Io *f, char *fmt, va_list args); - -/* - * word.c - */ -void pushlist(void); -void freelist(Word *w); -void poplist(void); - -int count(Word *w); -Word *newword(char *w, Word *link); -void pushword(char *w); - -/* - * tree.c - */ - -Tree *newtree(void); -void freetree(Tree *t); -Tree *tree3(int type, Tree *c0, Tree *c1, Tree *c2); -Tree *tree2(int type, Tree *c0, Tree *c1); -Tree *tree1(int type, Tree *c0); - -Tree *hang1(Tree *p, Tree *c0); -Tree *hang2(Tree *p, Tree *c0, Tree *c1); -Tree *hang3(Tree *p, Tree *c0, Tree *c1, Tree *c2); -Tree *epihang(Tree *c, Tree *epi); -Tree *simplehang(Tree *t); -Tree *wordnode(char *w); - -/* - * var.c - */ - -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); - -/* - * lex.c - */ - -void skipnl(void); -int wordchr(int c); - -void rcerror(char *msg, ...); -int lex(Tree **node); - -/* - * parse.c - */ - -int parse(void); - -/* - * main.c - */ - -void dotrap(void); diff --git a/sys/cmd/rc/rules.mk b/sys/cmd/rc/rules.mk deleted file mode 100644 index 654a44e..0000000 --- a/sys/cmd/rc/rules.mk +++ /dev/null @@ -1,22 +0,0 @@ -include share/push.mk - -# Local sources -SRCS_$(d) := \ - $(d)/glob.c \ - $(d)/word.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 - -# Local rules -$(BINS_$(d)): $(OBJS_$(d)) $(OBJ_DIR)/libn/libn.a - $(COMPLINK) - -include share/pop.mk diff --git a/sys/cmd/rc/simple.c b/sys/cmd/rc/simple.c deleted file mode 100644 index f934aa1..0000000 --- a/sys/cmd/rc/simple.c +++ /dev/null @@ -1,13 +0,0 @@ -void -Xsimple(void) -{ - Word *a; - Var *v; - - a = shell->stack->words; - if (!a) { - Xerror("empty argument list"); - return; - } - v = vlookup(a->word); -} diff --git a/sys/cmd/rc/tree.c b/sys/cmd/rc/tree.c deleted file mode 100644 index 14049e5..0000000 --- a/sys/cmd/rc/tree.c +++ /dev/null @@ -1,144 +0,0 @@ -#include "rc.h" - -// ----------------------------------------------------------------------- -// globals - -static Tree *nodes; - -// ----------------------------------------------------------------------- -// exported funcs - -Tree* -newtree(void) -{ - Tree *t; - - alloc(t); - t->str = nil; - t->child[0] = t->child[1] = t->child[2] = nil; - t->redir.fd[0] = t->redir.fd[1] = t->redir.type = 0; - - t->link = nodes, nodes = t; - return t; -} - -void -freetree(Tree *t) -{ - if (!t) - return; - - freetree(t->child[0]); - freetree(t->child[1]); - freetree(t->child[2]); - - if (t->str) - efree(t->str); - efree(t); -} - -void -freenodes(void) -{ - Tree *t, *u; - - for (t = nodes;t;t = u) { - u = t->link; - if (t->str) - efree(t->str); - efree(t); - } - nodes = nil; -} - -/* tree creation */ -Tree* -tree3(int type, Tree *c0, Tree *c1, Tree *c2) -{ - Tree *t; - - t = newtree(); - t->type = type; - t->child[0] = c0; - t->child[1] = c1; - t->child[2] = c2; - - return t; -} - -Tree* -tree2(int type, Tree *c0, Tree *c1) -{ - return tree3(type, c0, c1, nil); -} - -Tree* -tree1(int type, Tree *c0) -{ - return tree3(type, c0, nil, nil); -} - -/* tree hang */ -Tree* -hang1(Tree *p, Tree *c0) -{ - p->child[0] = c0; - return p; -} - -Tree* -hang2(Tree *p, Tree *c0, Tree *c1) -{ - p->child[0] = c0; - p->child[1] = c1; - return p; -} - -Tree* -hang3(Tree *p, Tree *c0, Tree *c1, Tree *c2) -{ - p->child[0] = c0; - p->child[1] = c1; - p->child[2] = c2; - return p; -} - -/* hangs the cmd underneath the epilogue */ -Tree* -epihang(Tree *c, Tree *epi) -{ - Tree *p; - if(!epi) - return c; - for(p=epi;p->child[1];p = p->child[1]) - ; - p->child[1] = c; - return epi; -} - -/* hangs tree t from a new simple node. percolates redirections to root */ -Tree* -simplehang(Tree *t) -{ - Tree *u; - t = tree1(Tsimple, t); - for(u = t->child[0];u->type==Targs;u=u->child[0]) { - if (u->child[1]->type==Tdup - || u->child[1]->type==Tredir){ - u->child[1]->child[1] = t; - t = u->child[1]; - u->child[1] = nil; - } - } - return t; -} - -Tree* -wordnode(char *w) -{ - Tree *t = newtree(); - t->type = Tword; - t->str = strdup(w); - - return t; -} diff --git a/sys/cmd/rc/util.c b/sys/cmd/rc/util.c deleted file mode 100644 index 02b3611..0000000 --- a/sys/cmd/rc/util.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "rc.h" - -void * -emalloc(uintptr n) -{ - void *p = malloc(n); - if (!p) - panic("can't malloc %d bytes", n); - - return p; -} - -void * -erealloc(void *p, uintptr n) -{ - void *new = realloc(p, n); - if (!new) - panic("can't realloc %d bytes", n); - - return new; -} - -void -efree(void *p) -{ - if (p) - free(p); - else - pfmt(errio, "free \n"); -} - -void -panic(char *s, int n) -{ - pfmt(errio, "rc: "); - pfmt(errio, s, n); - pchr(errio, '\n'); - flush(&errio); - abort(); -} diff --git a/sys/cmd/rc/var.c b/sys/cmd/rc/var.c deleted file mode 100644 index d442369..0000000 --- a/sys/cmd/rc/var.c +++ /dev/null @@ -1,129 +0,0 @@ -#include "rc.h" - -Var *globals[1021] = { 0 }; - -struct Keyword { - ushort type; - char *name; - struct Keyword *link; -} *keywords[41]; - -// ----------------------------------------------------------------------- -// utility - -static -int -hash(char *s, int n) -{ - int i = 1, h = 0; - while (*s) - h += *s++*i++; - h %= n; - return (h<0)?h+n:h; -} - -// ----------------------------------------------------------------------- -// keywords - -static -void -putkw(int type, char *name) -{ - struct Keyword *kw; - int h = hash(name, arrlen(keywords)); - - alloc(kw); - kw->type = type; - kw->name = name; - kw->link = keywords[h]; - - keywords[h] = kw; -} - -void -initkw(void) -{ - putkw(Tfor, "for"); - putkw(Tin, "in"); - putkw(Twhile, "while"); - putkw(Tif, "if"); - putkw(Telse, "else"); - putkw(Tswitch, "switch"); - putkw(Tcase, "case"); - putkw(Tfunc, "func"); -} - -int -kwlookup(char *name) -{ - int t; - struct Keyword *it; - for(t=-1,it = keywords[hash(name, arrlen(keywords))];it;it = it->link) - if(!strcmp(it->name, name)) - t = it->type; - return t; -} - -// ----------------------------------------------------------------------- -// variables - -Var * -newvar(char *name, Var *link) -{ - Var *v; - - alloc(v); - v->name = name; - v->val = 0; - v->func = nil; - v->funcnew = 0; - v->new = 0; - v->update = nil; - v->link = link; - - return v; -} - -/* only global lookup */ - -Var * -gvlookup(char *name) -{ - Var *v; - int h = hash(name, arrlen(globals)); - for (v = globals[h]; v; v = v->link) - if (!strcmp(v->name, name)) - return v; - - return globals[h] = newvar(strdup(name), globals[h]); -} - -/* local + global lookup */ -Var * -vlookup(char *name) -{ - Var *v; - if (shell) - for (v = shell->local; v; v = v->link) - if (!strcmp(v->name, 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 deleted file mode 100644 index 84ff40c..0000000 --- a/sys/cmd/rc/word.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "rc.h" - -void -pushlist(void) -{ - List *ls; - - alloc(ls); - ls->words = nil; - ls->link = shell->stack, shell->stack = ls; -} - -void -freelist(Word *w) -{ - Word *it; - while (w) { - it = w->link; - efree(w->word); - efree(w); - w = it; - } -} - -void -poplist(void) -{ - List *ls = shell->stack; - if (!ls) - panicf("shell stack underflow"); - - freelist(ls->words); - shell->stack = ls->link; - efree(ls); -} - -int -count(Word *w) -{ - int n; - for (n=0; w; n++) - w = w->link; - return n; -} - -Word* -newword(char *w, Word *link) -{ - Word *wd; - - alloc(wd); - wd->word = strdup(w); - wd->link = link; - - return wd; -} - -void -pushword(char *w) -{ - if (shell->stack == nil) - panicf("no active stack"); - shell->stack->words = newword(w, shell->stack->words); -} -- cgit v1.2.1