#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);