#pragma once #include #include /* * A thread functions much like a GNU job -> it's just a simple execution stack * We just need to modify the following datastructures: * * 1. Need to store the list of all "active" and "foreground" threads * - Right now we just have Thread *proc which is the running process. * - Need to move this to a linked list (how does this interact with the link?) * - Linked list stores the independent roots of each individual process tree * 2. Child pids are stored inside waitpid right now. Need to associate this more explictly with a thread. * 3. Wait needs to be generalized to act on threads. * 4. our "start" function is equivalent to the launch_job function * 5. running the interpreter runs the launch_process implicitly (with forks called as interpreter functions) */ // ----------------------------------------------------------------------- // 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[]; }; struct Tree { int type; char *str; 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; }; enum { Rclose, Rdup, Ropen, }; 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 Redir *redir; // list of redirections struct { ushort i : 1; ushort eof : 1; } flag; struct { ushort status; int len, cap; struct WaitItem *on; } wait; int pid, pgid, status; long line; Thread *link; // process we return to Thread *next; // 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*); /* read.c */ int readline(char *); void enablevi(void); /* prompt.c */ 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 at); void freeparsetree(void); /* sys.c */ void initenv(void); void execute(Word *, Word*); /* wait.c */ void addwait(Thread *, int); void clearwait(Thread*); int waitall(Thread *); 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); void initpath(void); /* var.c */ Var *var(char*); Var *definevar(char*, Var *); Var *globalvar(char*); Var *makevar(char *name, Var *link); void setvar(char *, Word *); char **mkenv(void); /* code.c */ int compile(Tree *); Code *copycode(Code *c); void freecode(Code *c);