#include #include #include // ----------------------------------------------------------------------- // types typedef struct Io Io; typedef struct Var Var; typedef struct Word Word; typedef struct List List; typedef struct Tree Tree; typedef struct Redir Redir; typedef union Code Code; typedef struct Thread Thread; typedef struct Shell Shell; struct Io { int fd, cap; char *s; char *b, *e, buf[]; }; enum { Rappend, Rwrite, Rread, Rhere, Rdupfd, Ropen, Rclose, Rrdwr }; struct Tree { int type; union{ struct { ushort quoted; char *str; // Tword }; struct { ushort type; // Tpipe, Tredir, Tdup int fd[2]; } redir; }; Tree *child[3]; Tree *link; }; struct Word { char *str; Word *link; }; struct List { Word *word; List *link; }; /* * the first word of any code vector is a reference count * always create a new reference to a code vector by calling copycode() * always call freecode() when deleting a reference */ union Code { int i; void (*f)(void); char *s; }; struct Var { char *name; Word *val; short new : 1; short newfunc : 1; Code *func; void (*update)(Var *); Var *link; }; struct Redir { char type; /* what to do */ short from, to; /* what to do it to */ struct Redir *link; /* what else to do (reverse order) */ }; enum { Pnil, Prun, Pstop, Psig, Pagain, Pdone, }; struct WaitItem { int pid; ushort status; }; struct Thread { struct { int i; Code *exe; } code; // execution stack struct { Io *io; char *path; } cmd; // command input List *args; // argument stack Var *local; // local variables struct { Redir *start; Redir *end; } redir; // list of redirections struct { ushort user : 1; ushort eof : 1; } flag; struct { ushort status; int len, cap; struct WaitItem *on; } wait; int pid, pgid, status; long line; Thread *caller; // process we return to Thread *link; // next job }; struct Shell { int pid; Io *err; int status; int interactive; Thread *jobs; }; // ----------------------------------------------------------------------- // globals extern Shell shell; extern Thread *runner; extern Code *compiled; // ----------------------------------------------------------------------- // functions /* util.c */ void itoa(char*, long i); void fatal(char *, ...); void *emalloc(uintptr); void *erealloc(void*, uintptr); void efree(void*); /* input.c */ int readline(char *); void enablevi(void); void inithistory(void); int addhistory(char *); /* prompt.c */ void resetprompt(void); int prompt(ushort *); /* io.c */ Io *openfd(int fd); Io *openstr(void); void terminate(Io *io); int get(Io *); int put(Io **, char); void flush(Io *io); void print(Io *, char *, ...); /* lex.c */ int iswordchar(int c); int yylex(void); /* tree.c */ Tree *maketree(void); Tree *maketree1(int, Tree*); Tree *maketree2(int, Tree*, Tree*); Tree *maketree3(int, Tree*, Tree*, Tree*); Tree *token(int, char *); Tree *hangchild1(Tree *, Tree *, int); Tree *hangchild2(Tree *, Tree *, int, Tree *, int); Tree *hangchild3(Tree *, Tree *, Tree *, Tree *); Tree *hangepilog(Tree *, Tree*); void freeparsetree(void); /* sys.c */ void initenv(void); void redirect(struct Redir *); void execute(Word *, Word*); int mapfd(int fd); /* wait.c */ void addwait(Thread *, int); void delwait(Thread *, int); void clearwait(Thread*); int waitall(Thread *); int waitfor(Thread *, int); void killzombies(void); /* job.c */ Thread *getjob(int, int*); void addjob(Thread *); void deljob(Thread *); void wakeup(Thread *); void report(Thread *, int); void foreground(Thread *, int); void background(Thread *, int); /* exec.c */ // XXX: odd place for this int count(Word *); Word *makeword(char *str, Word *link); void freeword(Word *w); /* var.c */ Var *var(char*); Var *definevar(char*, Var *); Var *globalvar(char*); Var *makevar(char *name, Var *link); void setvar(char *, Word *); int iskeyword(char *); void initpath(void); void initkeywords(void); char **mkenv(void); /* code.c */ int compile(Tree *); Code *copycode(Code *c); void freecode(Code *c);