diff --git a/rcmain b/rcmain index 461cb3eca0..7ccbe1b90d 100644 --- a/rcmain +++ b/rcmain @@ -1,51 +1,38 @@ -# rcmain: Plan 9 on Unix version +# rcmain: unix version if(~ $#home 0) home=$HOME -if(~ $#home 0) home=/ if(~ $#ifs 0) ifs=' ' +profile=$home/.rcrc switch($#prompt){ case 0 prompt=('% ' ' ') case 1 prompt=($prompt ' ') } -if(~ $rcname ?.out ?.rc */?.rc */?.out) prompt=('broken! ' ' ') -if(flag p) path=(/bin /usr/bin) -if not{ +if(~ $rcname ?.out) prompt=('broken! ' ' ') +if(flag p) path=/bin +if not { finit - # should be taken care of by rc now, but leave just in case + if(~ $#path 0) path=(. /bin /usr/bin /usr/local/bin) } fn sigexit if(! ~ $#cflag 0){ - if(flag l && test -r $home/lib/profile) . $home/lib/profile + if(flag l) { + . -q $profile + } status='' eval $cflag - exit $status } -if(flag i){ - if(~ $termprog 9term || ~ $termprog win){ - fn cd { - # builtin cd $1 && flag i && awd - # is not sufficient when running in a subshell - # that is rc -e (like mk uses!) - if(builtin cd $1){ - if(flag i) $PLAN9/bin/9 awd || status='' - status='' - } - } - $PLAN9/bin/9 awd +if not if(flag i){ + if(flag l) { + . -q $profile } - if(flag l && test -r $home/lib/profile) . $home/lib/profile status='' if(! ~ $#* 0) . $* - . -i '/dev/stdin' - exit $status + . -i /dev/fd/0 } -if(flag l && test -r $home/lib/profile) . $home/lib/profile -if(~ $#* 0){ - . /dev/stdin - exit $status +if not if(~ $#* 0) . /dev/fd/0 +if not{ + status='' + . $* } -status='' -. $* -exit $status diff --git a/src/cmd/rc/code.c b/src/cmd/rc/code.c index 208476ae3e..3b940ccd31 100644 --- a/src/cmd/rc/code.c +++ b/src/cmd/rc/code.c @@ -6,12 +6,13 @@ #define c0 t->child[0] #define c1 t->child[1] #define c2 t->child[2] -int codep, ncode; -#define emitf(x) ((void)(codep!=ncode || morecode()), codebuf[codep].f = (x), codep++) -#define emiti(x) ((void)(codep!=ncode || morecode()), codebuf[codep].i = (x), codep++) -#define emits(x) ((void)(codep!=ncode || morecode()), codebuf[codep].s = (x), codep++) +code *codebuf; +static int codep, ncode, codeline; +#define emitf(x) ((codep!=ncode || morecode()), codebuf[codep].f = (x), codep++) +#define emiti(x) ((codep!=ncode || morecode()), codebuf[codep].i = (x), codep++) +#define emits(x) ((codep!=ncode || morecode()), codebuf[codep].s = (x), codep++) + void stuffdot(int); -char *fnstr(tree*); void outcode(tree*, int); void codeswitch(tree*, int); int iscase(tree*); @@ -21,12 +22,8 @@ void codefree(code*); int morecode(void) { - ncode+=100; - codebuf = (code *)realloc((char *)codebuf, ncode*sizeof codebuf[0]); - if(codebuf==0) - panic("Can't realloc %d bytes in morecode!", - ncode*sizeof codebuf[0]); - memset(codebuf+ncode-100, 0, 100*sizeof codebuf[0]); + ncode+=ncode; + codebuf = (code *)erealloc((char *)codebuf, ncode*sizeof codebuf[0]); return 0; } @@ -41,93 +38,124 @@ stuffdot(int a) int compile(tree *t) { - if(flag['D']) { - struct io *s; - s = openstr(); - pfmt(s, "compile: %u\n", t); - write(2, s->strp, strlen(s->strp)); - closeio(s); - if(eflagok) // made it out of rcmain - stop executing commands, just print them - t = nil; - } - ncode = 100; - codebuf = (code *)emalloc(ncode*sizeof codebuf[0]); + codebuf = emalloc(ncode*sizeof codebuf[0]); codep = 0; + codeline = 0; /* force source */ emiti(0); /* reference count */ - outcode(t, flag['e']?1:0); + emits(estrdup(lex->file)); /* source file name */ + outcode(t, !lex->qflag && flag['e']!=0); if(nerror){ - efree((char *)codebuf); + free(codebuf); return 0; } - readhere(); emitf(Xreturn); emitf(0); return 1; } +/* + * called on a tree where we expect eigther + * a pattern or a string instead of a glob to + * remove the GLOB chars from the strings + * or set glob to 2 for pattern so Xglob + * is not inserted when compiling the tree. + */ void -cleanhere(char *f) +noglobs(tree *t, int pattern) { - emitf(Xdelhere); - emits(strdup(f)); -} - -char* -fnstr(tree *t) -{ - io *f = openstr(); - char *v; - extern char nl; - char svnl = nl; - nl=';'; - pfmt(f, "%t", t); - nl = svnl; - v = f->strp; - f->strp = 0; - closeio(f); - return v; +Again: + if(t==0) + return; + if(t->type==WORD && t->glob){ + if(pattern) + t->glob=2; + else{ + deglob(t->str); + t->glob=0; + } + } + if(t->type==PAREN || t->type==WORDS || t->type=='^'){ + t->glob=0; + noglobs(c1, pattern); + t = c0; + goto Again; + } } void outcode(tree *t, int eflag) { + void (*f)(void); int p, q; tree *tt; if(t==0) return; if(t->type!=NOT && t->type!=';') - runq->iflast = 0; + lex->iflast = 0; + if(t->line != codeline){ + codeline = t->line; + if(codebuf && codep >= 2 && codebuf[codep-2].f == Xsrcline) + codebuf[codep-1].i = codeline; + else { + emitf(Xsrcline); + emiti(codeline); + } + } switch(t->type){ default: pfmt(err, "bad type %d in outcode\n", t->type); break; case '$': emitf(Xmark); + noglobs(c0, 0); outcode(c0, eflag); emitf(Xdol); break; case '"': emitf(Xmark); + emitf(Xmark); + noglobs(c0, 0); outcode(c0, eflag); - emitf(Xqdol); + emitf(Xdol); + emitf(Xqw); + emitf(Xpush); break; case SUB: emitf(Xmark); + noglobs(c0, 0); outcode(c0, eflag); emitf(Xmark); + noglobs(c1, 0); outcode(c1, eflag); emitf(Xsub); break; case '&': emitf(Xasync); - if(havefork){ - p = emiti(0); - outcode(c0, eflag); - emitf(Xexit); - stuffdot(p); - } else - emits(fnstr(c0)); + p = emiti(0); + + /* undocumented? */ + emitf(Xmark); + emitf(Xword); + emits(estrdup("/dev/null")); + emitf(Xread); + emiti(0); + + /* insert rfork s for plan9 */ + f = builtinfunc("rfork"); + if(f){ + emitf(Xmark); + emitf(Xword); + emits(estrdup("s")); + emitf(Xword); + emits(estrdup("rfork")); + emitf(f); + } + + codeline = 0; /* force source */ + outcode(c0, eflag); + emitf(Xexit); + stuffdot(p); break; case ';': outcode(c0, eflag); @@ -141,14 +169,23 @@ outcode(tree *t, int eflag) emitf(Xconc); break; case '`': - emitf(Xbackq); - if(havefork){ - p = emiti(0); + emitf(Xmark); + if(c0){ + noglobs(c0, 0); outcode(c0, 0); - emitf(Xexit); - stuffdot(p); - } else - emits(fnstr(c0)); + } else { + emitf(Xmark); + emitf(Xword); + emits(estrdup("ifs")); + emitf(Xdol); + } + emitf(Xqw); + emitf(Xbackq); + p = emiti(0); + codeline = 0; /* force source */ + outcode(c1, 0); + emitf(Xexit); + stuffdot(p); break; case ANDAND: outcode(c0, 0); @@ -171,18 +208,20 @@ outcode(tree *t, int eflag) break; case COUNT: emitf(Xmark); + noglobs(c0, 0); outcode(c0, eflag); emitf(Xcount); break; case FN: emitf(Xmark); + noglobs(c0, 0); outcode(c0, eflag); if(c1){ emitf(Xfn); p = emiti(0); emits(fnstr(c1)); + codeline = 0; /* force source */ outcode(c1, eflag); - emitf(Xunlocal); /* get rid of $* */ emitf(Xreturn); stuffdot(p); } @@ -198,7 +237,7 @@ outcode(tree *t, int eflag) stuffdot(p); break; case NOT: - if(!runq->iflast) + if(!lex->iflast) yyerror("`if not' does not follow `if(...)'"); emitf(Xifnot); p = emiti(0); @@ -224,13 +263,11 @@ outcode(tree *t, int eflag) break; case SUBSHELL: emitf(Xsubshell); - if(havefork){ - p = emiti(0); - outcode(c0, eflag); - emitf(Xexit); - stuffdot(p); - } else - emits(fnstr(c0)); + p = emiti(0); + codeline = 0; /* force source */ + outcode(c0, eflag); + emitf(Xexit); + stuffdot(p); if(eflag) emitf(Xeflag); break; @@ -239,9 +276,11 @@ outcode(tree *t, int eflag) break; case TWIDDLE: emitf(Xmark); + noglobs(c1, 1); outcode(c1, eflag); emitf(Xmark); outcode(c0, eflag); + emitf(Xqw); emitf(Xmatch); if(eflag) emitf(Xeflag); @@ -266,16 +305,16 @@ outcode(tree *t, int eflag) emitf(Xmark); if(c1){ outcode(c1, eflag); - emitf(Xglob); } else{ emitf(Xmark); emitf(Xword); - emits(strdup("*")); + emits(estrdup("*")); emitf(Xdol); } emitf(Xmark); /* dummy value for Xlocal */ emitf(Xmark); + noglobs(c0, 0); outcode(c0, eflag); emitf(Xlocal); p = emitf(Xfor); @@ -288,7 +327,8 @@ outcode(tree *t, int eflag) break; case WORD: emitf(Xword); - emits(strdup(t->str)); + emits(t->str); + t->str=0; /* passed ownership */ break; case DUP: if(t->rtype==DUPFD){ @@ -306,19 +346,17 @@ outcode(tree *t, int eflag) case PIPEFD: emitf(Xpipefd); emiti(t->rtype); - if(havefork){ - p = emiti(0); - outcode(c0, eflag); - emitf(Xexit); - stuffdot(p); - } else { - emits(fnstr(c0)); - } + p = emiti(0); + codeline = 0; /* force source */ + outcode(c0, eflag); + emitf(Xexit); + stuffdot(p); break; case REDIR: - emitf(Xmark); - outcode(c0, eflag); - emitf(Xglob); + if(t->rtype!=HERE){ + emitf(Xmark); + outcode(c0, eflag); + } switch(t->rtype){ case APPEND: emitf(Xappend); @@ -327,12 +365,16 @@ outcode(tree *t, int eflag) emitf(Xwrite); break; case READ: - case HERE: emitf(Xread); break; case RDWR: emitf(Xrdwr); break; + case HERE: + emitf(c0->quoted?Xhereq:Xhere); + emits(t->str); + t->str=0; /* passed ownership */ + break; } emiti(t->fd0); outcode(c1, eflag); @@ -341,25 +383,27 @@ outcode(tree *t, int eflag) case '=': tt = t; for(;t && t->type=='=';t = c2); - if(t){ + if(t){ /* var=value cmd */ for(t = tt;t->type=='=';t = c2){ emitf(Xmark); outcode(c1, eflag); emitf(Xmark); + noglobs(c0, 0); outcode(c0, eflag); - emitf(Xlocal); + emitf(Xlocal); /* push var for cmd */ } - outcode(t, eflag); - for(t = tt; t->type=='='; t = c2) - emitf(Xunlocal); + outcode(t, eflag); /* gen. code for cmd */ + for(t = tt; t->type == '='; t = c2) + emitf(Xunlocal); /* pop var */ } - else{ + else{ /* var=value */ for(t = tt;t;t = c2){ emitf(Xmark); outcode(c1, eflag); emitf(Xmark); + noglobs(c0, 0); outcode(c0, eflag); - emitf(Xassign); + emitf(Xassign); /* set var permanently */ } } t = tt; /* so tests below will work */ @@ -368,25 +412,25 @@ outcode(tree *t, int eflag) emitf(Xpipe); emiti(t->fd0); emiti(t->fd1); - if(havefork){ - p = emiti(0); - q = emiti(0); - outcode(c0, eflag); - emitf(Xexit); - stuffdot(p); - } else { - emits(fnstr(c0)); - q = emiti(0); - } + p = emiti(0); + q = emiti(0); + codeline = 0; /* force source */ + outcode(c0, eflag); + emitf(Xexit); + stuffdot(p); + codeline = 0; /* force source */ outcode(c1, eflag); emitf(Xreturn); stuffdot(q); emitf(Xpipewait); break; } + if(t->glob==1) + emitf(Xglob); if(t->type!=NOT && t->type!=';') - runq->iflast = t->type==IF; - else if(c0) runq->iflast = c0->type==IF; + lex->iflast = t->type==IF; + else if(c0) + lex->iflast = c0->type==IF; } /* * switch code looks like this: @@ -416,7 +460,7 @@ codeswitch(tree *t, int eflag) int out; /* jump here to leave switch */ int nextcase; /* patch jump address to next case */ tree *tt; - if(c1->child[0]==nil + if(c1->child[0]==0 || c1->child[0]->type!=';' || !iscase(c1->child[0]->child[0])){ yyerror("case missing in switch"); @@ -424,6 +468,7 @@ codeswitch(tree *t, int eflag) } emitf(Xmark); outcode(c0, eflag); + emitf(Xqw); emitf(Xjump); nextcase = emiti(0); out = emitf(Xjump); @@ -433,7 +478,10 @@ codeswitch(tree *t, int eflag) while(t->type==';'){ tt = c1; emitf(Xmark); - for(t = c0->child[0];t->type==ARGLIST;t = c0) outcode(c1, eflag); + for(t = c0->child[0];t->type==ARGLIST;t = c0) { + noglobs(c1, 1); + outcode(c1, eflag); + } emitf(Xcase); nextcase = emiti(0); t = tt; @@ -478,19 +526,22 @@ codefree(code *cp) code *p; if(--cp[0].i!=0) return; - for(p = cp+1;p->f;p++){ + for(p = cp+2;p->f;p++){ if(p->f==Xappend || p->f==Xclose || p->f==Xread || p->f==Xwrite || p->f==Xrdwr || p->f==Xasync || p->f==Xbackq || p->f==Xcase || p->f==Xfalse || p->f==Xfor || p->f==Xjump + || p->f==Xsrcline || p->f==Xsubshell || p->f==Xtrue) p++; else if(p->f==Xdup || p->f==Xpipefd) p+=2; else if(p->f==Xpipe) p+=4; - else if(p->f==Xword || p->f==Xdelhere) efree((++p)->s); + else if(p->f==Xhere || p->f==Xhereq) free(p[1].s), p+=2; + else if(p->f==Xword) free((++p)->s); else if(p->f==Xfn){ - efree(p[2].s); + free(p[2].s); p+=2; } } - efree((char *)cp); + free(cp[1].s); + free(cp); } diff --git a/src/cmd/rc/exec.c b/src/cmd/rc/exec.c index 0320976a2d..d81274855d 100644 --- a/src/cmd/rc/exec.c +++ b/src/cmd/rc/exec.c @@ -3,49 +3,105 @@ #include "exec.h" #include "io.h" #include "fns.h" + +char *argv0="rc"; +io *err; +int mypid; +thread *runq; +char **environ; + /* * Start executing the given code at the given pc with the given redirection */ -char *argv0="rc"; - void -start(code *c, int pc, var *local) +start(code *c, int pc, var *local, redir *redir) { - struct thread *p = new(struct thread); - + thread *p = new(thread); p->code = codecopy(c); + p->line = 0; p->pc = pc; p->argv = 0; - p->redir = p->startredir = runq?runq->redir:0; + p->redir = p->startredir = redir; + p->lex = 0; p->local = local; - p->cmdfile = 0; - p->cmdfd = 0; - p->eof = 0; p->iflag = 0; - p->lineno = 1; + p->pid = 0; + p->status = 0; p->ret = runq; runq = p; } +void +startfunc(var *func, word *starval, var *local, redir *redir) +{ + start(func->fn, func->pc, local, redir); + runq->local = newvar("*", runq->local); + runq->local->val = starval; + runq->local->changed = 1; +} + +static void +popthread(void) +{ + thread *p = runq; + while(p->argv) poplist(); + while(p->local && (p->ret==0 || p->local!=p->ret->local)) + Xunlocal(); + runq = p->ret; + if(p->lex) freelexer(p->lex); + codefree(p->code); + free(p->status); + free(p); +} + word* -newword(char *wd, word *next) +Newword(char *s, word *next) { - word *p = new(word); - p->word = strdup(wd); + word *p=new(word); + p->word = s; p->next = next; return p; } - -void -pushword(char *wd) +word* +newword(char *s, word *next) +{ + return Newword(estrdup(s), next); +} +word* +Pushword(char *s) { + word *p; + if(s==0) + panic("null pushword", 0); if(runq->argv==0) panic("pushword but no argv!", 0); - runq->argv->words = newword(wd, runq->argv->words); + p = Newword(s, runq->argv->words); + runq->argv->words = p; + return p; +} +word* +pushword(char *s) +{ + return Pushword(estrdup(s)); +} +char* +Freeword(word *p) +{ + char *s = p->word; + free(p); + return s; } - void -popword(void) +freewords(word *w) +{ + word *p; + while((p = w)!=0){ + w = w->next; + free(Freeword(p)); + } +} +char* +Popword(void) { word *p; if(runq->argv==0) @@ -54,40 +110,38 @@ popword(void) if(p==0) panic("popword but no word!", 0); runq->argv->words = p->next; - efree(p->word); - efree((char *)p); + return Freeword(p); } - void -freelist(word *w) +popword(void) { - word *nw; - while(w){ - nw = w->next; - efree(w->word); - efree((char *)w); - w = nw; - } + free(Popword()); } void pushlist(void) { list *p = new(list); - p->next = runq->argv; p->words = 0; + p->next = runq->argv; runq->argv = p; } - -void -poplist(void) +word* +Poplist(void) { + word *w; list *p = runq->argv; if(p==0) panic("poplist but no argv", 0); - freelist(p->words); + w = p->words; runq->argv = p->next; - efree((char *)p); + free(p); + return w; +} +void +poplist(void) +{ + freewords(Poplist()); } int @@ -101,7 +155,7 @@ count(word *w) void pushredir(int type, int from, int to) { - redir * rp = new(redir); + redir *rp = new(redir); rp->type = type; rp->from = from; rp->to = to; @@ -109,37 +163,80 @@ pushredir(int type, int from, int to) runq->redir = rp; } -var* -newvar(char *name, var *next) +static void +dontclose(int fd) { - var *v = new(var); - v->name = name; - v->val = 0; - v->fn = 0; - v->changed = 0; - v->fnchanged = 0; - v->next = next; - v->changefn = 0; - return v; + redir *rp; + + if(fd<0) + return; + for(rp = runq->redir; rp != runq->startredir; rp = rp->next){ + if(rp->type == RCLOSE && rp->from == fd){ + rp->type = 0; + break; + } + } } + +/* + * we are about to start a new thread that should exit on + * return, so the current stack is not needed anymore. + * free all the threads and lexers, but preserve the + * redirections and anything referenced by local. + */ +void +turfstack(var *local) +{ + while(local){ + thread *p; + + for(p = runq; p && p->local == local; p = p->ret) + p->local = local->next; + local = local->next; + } + while(runq) { + if(runq->lex) dontclose(runq->lex->input->fd); + popthread(); + } +} + +void +shuffleredir(void) +{ + redir **rr, *rp; + + rp = runq->redir; + if(rp==0) + return; + runq->redir = rp->next; + rp->next = runq->startredir; + for(rr = &runq->redir; *rr != rp->next; rr = &((*rr)->next)) + ; + *rr = rp; +} + /* * get command line flags, initialize keywords & traps. * get values from environment. * set $pid, $cflag, $* - * fabricate bootstrap code and start it (*=(argv);. /usr/lib/rcmain $*) + * fabricate bootstrap code and start it (*=(argv);. -bq /usr/lib/rcmain $*) * start interpreting code */ -int -main(int argc, char *argv[]) +void +main(int argc, char *argv[], char *envp[]) { - code bootstrap[32]; - char num[12], *rcmain; - int i; + code bootstrap[20]; + char num[12]; + char *rcmain=Rcmain; + + if(snprint(Rcmain, sizeof(Rcmain), "%s/rcmain", unsharp("#9")) <= 0) + return; - /* needed for rcmain later */ - putenv("PLAN9", unsharp("#9")); + environ = envp; - argc = getflags(argc, argv, "DSYsrdiIlxepvVc:1m:1[command]", 1); + int i; + argv0 = argv[0]; + argc = getflags(argc, argv, "srdiIlxebpvVc:1m:1[command]", 1); if(argc==-1) usage("[file [arg ...]]"); if(argv[0][0]=='-') @@ -147,49 +244,49 @@ main(int argc, char *argv[]) if(flag['I']) flag['i'] = 0; else if(flag['i']==0 && argc==1 && Isatty(0)) flag['i'] = flagset; - rcmain = flag['m'] ? flag['m'][0] : Rcmain(); - err = openfd(2); + if(flag['m']) rcmain = flag['m'][0]; + err = openiofd(2); kinit(); Trapinit(); Vinit(); inttoascii(num, mypid = getpid()); - pathinit(); setvar("pid", newword(num, (word *)0)); setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0) :(word *)0); setvar("rcname", newword(argv[0], (word *)0)); - i = 0; - bootstrap[i++].i = 1; - bootstrap[i++].f = Xmark; - bootstrap[i++].f = Xword; - bootstrap[i++].s="*"; - bootstrap[i++].f = Xassign; - bootstrap[i++].f = Xmark; - bootstrap[i++].f = Xmark; - bootstrap[i++].f = Xword; - bootstrap[i++].s="*"; - bootstrap[i++].f = Xdol; - bootstrap[i++].f = Xword; - bootstrap[i++].s = rcmain; - bootstrap[i++].f = Xword; - bootstrap[i++].s="."; - bootstrap[i++].f = Xsimple; - bootstrap[i++].f = Xexit; - bootstrap[i].i = 0; - start(bootstrap, 1, (var *)0); + bootstrap[0].i = 1; + bootstrap[1].s="*bootstrap*"; + bootstrap[2].f = Xmark; + bootstrap[3].f = Xword; + bootstrap[4].s="*"; + bootstrap[5].f = Xassign; + bootstrap[6].f = Xmark; + bootstrap[7].f = Xmark; + bootstrap[8].f = Xword; + bootstrap[9].s="*"; + bootstrap[10].f = Xdol; + bootstrap[11].f = Xword; + bootstrap[12].s = rcmain; + bootstrap[13].f = Xword; + bootstrap[14].s="-bq"; + bootstrap[15].f = Xword; + bootstrap[16].s="."; + bootstrap[17].f = Xsimple; + bootstrap[18].f = Xexit; + bootstrap[19].f = 0; + start(bootstrap, 2, (var*)0, (redir*)0); + /* prime bootstrap argv */ pushlist(); - argv0 = strdup(argv[0]); for(i = argc-1;i!=0;--i) pushword(argv[i]); + for(;;){ if(flag['r']) pfnc(err, runq); - runq->pc++; - (*runq->code[runq->pc-1].f)(); + (*runq->code[runq->pc++].f)(); if(ntrap) dotrap(); } - return 0; /* not reached; silence OS X Lion gcc */ } /* * Opcode routines @@ -200,7 +297,7 @@ main(int argc, char *argv[]) * Xappend(file)[fd] open file to append * Xassign(name, val) assign val to name * Xasync{... Xexit} make thread for {}, no wait - * Xbackq{... Xreturn} make thread for {}, push stdout + * Xbackq(split){... Xreturn} make thread for {}, push stdout * Xbang complement condition * Xcase(pat, value){...} exec code on match, leave (value) on * stack @@ -208,14 +305,13 @@ main(int argc, char *argv[]) * Xconc(left, right) concatenate, push results * Xcount(name) push var count * Xdelfn(name) delete function definition - * Xdeltraps(names) delete named traps * Xdol(name) get variable value - * Xqdol(name) concatenate variable components * Xdup[i j] dup file descriptor * Xexit rc exits with status * Xfalse{...} execute {} if false - * Xfn(name){... Xreturn} define function + * Xfn(name){... Xreturn} define function * Xfor(var, list){... Xreturn} for loop + * Xglob(list) glob a list of words inplace * Xjump[addr] goto * Xlocal(name, val) create local variable, assign value * Xmark mark stack @@ -225,12 +321,13 @@ main(int argc, char *argv[]) * Xpipefd[type]{... Xreturn} connect {} to pipe (input or output, * depending on type), push /dev/fd/?? * Xpopm(value) pop value from stack + * Xpush(words) push words down a list + * Xqw(words) quote words inplace * Xrdwr(file)[fd] open file for reading and writing * Xread(file)[fd] open file to read - * Xsettraps(names){... Xreturn} define trap functions - * Xshowtraps print trap list - * Xsimple(args) run command and wait * Xreturn kill thread + * Xsimple(args) run command and wait + * Xsrcline[line] set current source line number * Xsubshell{... Xexit} execute {} in a subshell and wait * Xtrue{...} execute {} if true * Xunlocal delete local variable @@ -242,7 +339,8 @@ void Xappend(void) { char *file; - int f; + int fd; + switch(count(runq->argv->words)){ default: Xerror1(">> requires singleton"); @@ -254,14 +352,12 @@ Xappend(void) break; } file = runq->argv->words->word; - if((f = open(file, 1))<0 && (f = Creat(file))<0){ - pfmt(err, "%s: ", file); - Xerror("can't open"); + if((fd = Open(file, 1))<0 && (fd = Creat(file))<0){ + Xerror3(">> can't open", file, Errstr()); return; } - Seek(f, 0L, 2); - pushredir(ROPEN, f, runq->code[runq->pc].i); - runq->pc++; + Seek(fd, 0L, 2); + pushredir(ROPEN, fd, runq->code[runq->pc++].i); poplist(); } @@ -280,8 +376,7 @@ Xbang(void) void Xclose(void) { - pushredir(RCLOSE, runq->code[runq->pc].i, 0); - runq->pc++; + pushredir(RCLOSE, runq->code[runq->pc++].i, 0); } void @@ -294,30 +389,25 @@ Xdup(void) void Xeflag(void) { - if(eflagok && !truestatus()) Xexit(); + if(!truestatus()) Xexit(); } void Xexit(void) { - struct var *trapreq; - struct word *starval; static int beenhere = 0; + if(getpid()==mypid && !beenhere){ - trapreq = vlook("sigexit"); + var *trapreq = vlook("sigexit"); + word *starval = vlook("*")->val; if(trapreq->fn){ beenhere = 1; --runq->pc; - starval = vlook("*")->val; - start(trapreq->fn, trapreq->pc, (struct var *)0); - runq->local = newvar(strdup("*"), runq->local); - runq->local->val = copywords(starval, (struct word *)0); - runq->local->changed = 1; - runq->redir = runq->startredir = 0; + startfunc(trapreq, copywords(starval, (word*)0), (var*)0, (redir*)0); return; } } - Exit(getstatus()); + Exit(); } void @@ -355,29 +445,110 @@ Xpopm(void) poplist(); } +void +Xpush(void) +{ + word *t, *h = Poplist(); + for(t = h; t->next; t = t->next) + ; + t->next = runq->argv->words; + runq->argv->words = h; +} + +static int +herefile(char *tmp) +{ + char *s = tmp+strlen(tmp)-1; + static int ser; + int fd, i; + + i = ser++; + while(*s == 'Y'){ + *s-- = (i%26) + 'A'; + i = i/26; + } + i = getpid(); + while(*s == 'X'){ + *s-- = (i%10) + '0'; + i = i/10; + } + s++; + for(i='a'; i<'z'; i++){ + if(access(tmp, 0)!=0 && (fd = Creat(tmp))>=0) + return fd; + *s = i; + } + return -1; +} + +void +Xhere(void) +{ + char file[]="/tmp/hereXXXXXXXXXXYY"; + int fd; + io *io; + + if((fd = herefile(file))<0){ + Xerror3("<< can't get temp file", file, Errstr()); + return; + } + io = openiofd(fd); + psubst(io, (unsigned char*)runq->code[runq->pc++].s); + flushio(io); + closeio(io); + + /* open for reading and unlink */ + if((fd = Open(file, 3))<0){ + Xerror3("<< can't open", file, Errstr()); + return; + } + pushredir(ROPEN, fd, runq->code[runq->pc++].i); +} + +void +Xhereq(void) +{ + char file[]="/tmp/hereXXXXXXXXXXYY", *body; + int fd; + + if((fd = herefile(file))<0){ + Xerror3("<< can't get temp file", file, Errstr()); + return; + } + body = runq->code[runq->pc++].s; + Write(fd, body, strlen(body)); + Close(fd); + + /* open for reading and unlink */ + if((fd = Open(file, 3))<0){ + Xerror3("<< can't open", file, Errstr()); + return; + } + pushredir(ROPEN, fd, runq->code[runq->pc++].i); +} + void Xread(void) { char *file; - int f; + int fd; + switch(count(runq->argv->words)){ default: - Xerror1("< requires singleton\n"); + Xerror1("< requires singleton"); return; case 0: - Xerror1("< requires file\n"); + Xerror1("< requires file"); return; case 1: break; } file = runq->argv->words->word; - if((f = open(file, 0))<0){ - pfmt(err, "%s: ", file); - Xerror("can't open"); + if((fd = Open(file, 0))<0){ + Xerror3("< can't open", file, Errstr()); return; } - pushredir(ROPEN, f, runq->code[runq->pc].i); - runq->pc++; + pushredir(ROPEN, fd, runq->code[runq->pc++].i); poplist(); } @@ -385,59 +556,48 @@ void Xrdwr(void) { char *file; - int f; + int fd; switch(count(runq->argv->words)){ default: - Xerror1("<> requires singleton\n"); + Xerror1("<> requires singleton"); return; case 0: - Xerror1("<> requires file\n"); + Xerror1("<> requires file"); return; case 1: break; } file = runq->argv->words->word; - if((f = open(file, ORDWR))<0){ - pfmt(err, "%s: ", file); - Xerror("can't open"); + if((fd = Open(file, 2))<0){ + Xerror3("<> can't open", file, Errstr()); return; } - pushredir(ROPEN, f, runq->code[runq->pc].i); - runq->pc++; + pushredir(ROPEN, fd, runq->code[runq->pc++].i); poplist(); } -void -turfredir(void) -{ - while(runq->redir!=runq->startredir) - Xpopredir(); -} - void Xpopredir(void) { - struct redir *rp = runq->redir; + redir *rp = runq->redir; + if(rp==0) - panic("turfredir null!", 0); + panic("Xpopredir null!", 0); runq->redir = rp->next; if(rp->type==ROPEN) - close(rp->from); - efree((char *)rp); + Close(rp->from); + free(rp); } void Xreturn(void) { - struct thread *p = runq; - turfredir(); - while(p->argv) poplist(); - codefree(p->code); - runq = p->ret; - efree((char *)p); + while(runq->redir!=runq->startredir) + Xpopredir(); + popthread(); if(runq==0) - Exit(getstatus()); + Exit(); } void @@ -471,61 +631,40 @@ void Xwrite(void) { char *file; - int f; + int fd; + switch(count(runq->argv->words)){ default: - Xerror1("> requires singleton\n"); + Xerror1("> requires singleton"); return; case 0: - Xerror1("> requires file\n"); + Xerror1("> requires file"); return; case 1: break; } file = runq->argv->words->word; - if((f = Creat(file))<0){ - pfmt(err, "%s: ", file); - Xerror("can't open"); + if((fd = Creat(file))<0){ + Xerror3("> can't create", file, Errstr()); return; } - pushredir(ROPEN, f, runq->code[runq->pc].i); - runq->pc++; + pushredir(ROPEN, fd, runq->code[runq->pc++].i); poplist(); } -char* -list2str(word *words) -{ - char *value, *s, *t; - int len = 0; - word *ap; - for(ap = words;ap;ap = ap->next) - len+=1+strlen(ap->word); - value = emalloc(len+1); - s = value; - for(ap = words;ap;ap = ap->next){ - for(t = ap->word;*t;) *s++=*t++; - *s++=' '; - } - if(s==value) - *s='\0'; - else s[-1]='\0'; - return value; -} - void Xmatch(void) { word *p; - char *subject; - subject = list2str(runq->argv->words); + char *s; + setstatus("no match"); + s = runq->argv->words->word; for(p = runq->argv->next->words;p;p = p->next) - if(match(subject, p->word, '\0')){ + if(match(s, p->word, '\0')){ setstatus(""); break; } - efree(subject); poplist(); poplist(); } @@ -536,14 +675,14 @@ Xcase(void) word *p; char *s; int ok = 0; - s = list2str(runq->argv->next->words); + + s = runq->argv->next->words->word; for(p = runq->argv->words;p;p = p->next){ if(match(s, p->word, '\0')){ ok = 1; break; } } - efree(s); if(ok) runq->pc++; else @@ -551,19 +690,24 @@ Xcase(void) poplist(); } -word* +static word* conclist(word *lp, word *rp, word *tail) { - char *buf; - word *v; - if(lp->next || rp->next) - tail = conclist(lp->next==0?lp:lp->next, rp->next==0?rp:rp->next, - tail); - buf = emalloc(strlen(lp->word)+strlen(rp->word)+1); - strcpy(buf, lp->word); - strcat(buf, rp->word); - v = newword(buf, tail); - efree(buf); + word *v, *p, **end; + int ln, rn; + + for(end = &v;;){ + ln = strlen(lp->word), rn = strlen(rp->word); + p = Newword(emalloc(ln+rn+1), (word *)0); + memmove(p->word, lp->word, ln); + memmove(p->word+ln, rp->word, rn+1); + *end = p, end = &p->next; + if(lp->next == 0 && rp->next == 0) + break; + if(lp->next) lp = lp->next; + if(rp->next) rp = rp->next; + } + *end = tail; return v; } @@ -594,30 +738,26 @@ void Xassign(void) { var *v; + if(count(runq->argv->words)!=1){ - Xerror1("variable name not singleton!"); + Xerror1("= variable name not singleton!"); return; } - deglob(runq->argv->words->word); v = vlook(runq->argv->words->word); poplist(); - globlist(); freewords(v->val); - v->val = runq->argv->words; + v->val = Poplist(); v->changed = 1; - if(v->changefn) - v->changefn(v); - runq->argv->words = 0; - poplist(); } + /* * copy arglist a, adding the copy to the front of tail */ - word* copywords(word *a, word *tail) { word *v = 0, **end; + for(end=&v;a;a = a->next,end=&(*end)->next) *end = newword(a->word, 0); *end = tail; @@ -630,13 +770,13 @@ Xdol(void) word *a, *star; char *s, *t; int n; + if(count(runq->argv->words)!=1){ - Xerror1("variable name not singleton!"); + Xerror1("$ variable name not singleton!"); return; } - s = runq->argv->words->word; - deglob(s); n = 0; + s = runq->argv->words->word; for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0'; a = runq->argv->next->words; if(n==0 || *t) @@ -653,44 +793,40 @@ Xdol(void) } void -Xqdol(void) +Xqw(void) { + char *s, *d; word *a, *p; - char *s; int n; - if(count(runq->argv->words)!=1){ - Xerror1("variable name not singleton!"); - return; - } - s = runq->argv->words->word; - deglob(s); - a = vlook(s)->val; - poplist(); - n = count(a); - if(n==0){ + + a = runq->argv->words; + if(a==0){ pushword(""); return; } - for(p = a;p;p = p->next) n+=strlen(p->word); - s = emalloc(n); - if(a){ - strcpy(s, a->word); - for(p = a->next;p;p = p->next){ - strcat(s, " "); - strcat(s, p->word); - } + if(a->next==0) + return; + n=0; + for(p=a;p;p=p->next) + n+=1+strlen(p->word); + s = emalloc(n+1); + d = s; + d += strlen(strcpy(d, a->word)); + for(p=a->next;p;p=p->next){ + *d++=' '; + d += strlen(strcpy(d, p->word)); } - else - s[0]='\0'; - pushword(s); - efree(s); + free(a->word); + freewords(a->next); + a->word = s; + a->next = 0; } -word* +static word* copynwords(word *a, word *tail, int n) { word *v, **end; - + v = 0; end = &v; while(n-- > 0){ @@ -702,16 +838,16 @@ copynwords(word *a, word *tail, int n) return v; } -word* +static word* subwords(word *val, int len, word *sub, word *a) { int n, m; char *s; - if(!sub) + + if(sub==0) return a; a = subwords(val, len, sub->next, a); s = sub->word; - deglob(s); m = 0; n = 0; while('0'<=*s && *s<='9') @@ -739,12 +875,12 @@ Xsub(void) { word *a, *v; char *s; + if(count(runq->argv->next->words)!=1){ - Xerror1("variable name not singleton!"); + Xerror1("$() variable name not singleton!"); return; } s = runq->argv->next->words->word; - deglob(s); a = runq->argv->next->next->words; v = vlook(s)->val; a = subwords(v, count(v), runq->argv->words, a); @@ -757,16 +893,15 @@ void Xcount(void) { word *a; - char *s, *t; + char *s, *t, num[12]; int n; - char num[12]; + if(count(runq->argv->words)!=1){ - Xerror1("variable name not singleton!"); + Xerror1("$# variable name not singleton!"); return; } - s = runq->argv->words->word; - deglob(s); n = 0; + s = runq->argv->words->word; for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0'; if(n==0 || *t){ a = vlook(s)->val; @@ -784,41 +919,25 @@ void Xlocal(void) { if(count(runq->argv->words)!=1){ - Xerror1("variable name must be singleton\n"); + Xerror1("local variable name must be singleton"); return; } - deglob(runq->argv->words->word); - runq->local = newvar(strdup(runq->argv->words->word), runq->local); - runq->local->val = copywords(runq->argv->next->words, (word *)0); - runq->local->changed = 1; - poplist(); + runq->local = newvar(runq->argv->words->word, runq->local); poplist(); + runq->local->val = Poplist(); + runq->local->changed = 1; } void Xunlocal(void) { - var *v = runq->local, *hid; + var *hid, *v = runq->local; if(v==0) panic("Xunlocal: no locals!", 0); runq->local = v->next; hid = vlook(v->name); hid->changed = 1; - efree(v->name); - freewords(v->val); - efree((char *)v); -} - -void -freewords(word *w) -{ - word *nw; - while(w){ - efree(w->word); - nw = w->next; - efree((char *)w); - w = nw; - } + freevar(v); } void @@ -826,17 +945,16 @@ Xfn(void) { var *v; word *a; - int end; - end = runq->code[runq->pc].i; + int pc = runq->pc; + runq->pc = runq->code[pc].i; for(a = runq->argv->words;a;a = a->next){ v = gvlook(a->word); if(v->fn) codefree(v->fn); v->fn = codecopy(runq->code); - v->pc = runq->pc+2; + v->pc = pc+2; v->fnchanged = 1; } - runq->pc = end; poplist(); } @@ -855,105 +973,153 @@ Xdelfn(void) poplist(); } -char* +static char* concstatus(char *s, char *t) { - static char v[NSTATUS+1]; - int n = strlen(s); - strncpy(v, s, NSTATUS); - if(n 0) s[n++]='|'; + memmove(s+n, t, m+1); + free(t); + return s; } void Xpipewait(void) { - char status[NSTATUS+1]; - if(runq->pid==-1) - setstatus(concstatus(runq->status, getstatus())); - else{ - strncpy(status, getstatus(), NSTATUS); - status[NSTATUS]='\0'; - Waitfor(runq->pid, 1); + char *old = Getstatus(); + if(runq->pid==-1){ + Setstatus(concstatus(runq->status, old)); + runq->status=0; + }else{ + while(Waitfor(runq->pid) < 0) + ; runq->pid=-1; - setstatus(concstatus(getstatus(), status)); + Setstatus(concstatus(Getstatus(), old)); } } +static char *promptstr; + void Xrdcmds(void) { - struct thread *p = runq; - word *prompt; - flush(err); - nerror = 0; + thread *p = runq; + if(flag['s'] && !truestatus()) pfmt(err, "status=%v\n", vlook("status")->val); - if(runq->iflag){ - prompt = vlook("prompt")->val; + flushio(err); + + lex = p->lex; + if(p->iflag){ + word *prompt = vlook("prompt")->val; if(prompt) promptstr = prompt->word; else promptstr="% "; } Noerror(); - if((flag['Y'] ? yyparse : parse)()){ - if(!p->iflag || p->eof && !Eintr()){ - if(p->cmdfile) - efree(p->cmdfile); - closeio(p->cmdfd); - Xreturn(); /* should this be omitted? */ - } - else{ + nerror = 0; + if(yyparse()){ + if(p->iflag && (!lex->eof || Eintr())){ if(Eintr()){ pchr(err, '\n'); - p->eof = 0; + lex->eof = 0; } --p->pc; /* go back for next command */ } } else{ - ntrap = 0; /* avoid double-interrupts during blocked writes */ - --p->pc; /* re-execute Xrdcmds after codebuf runs */ - start(codebuf, 1, runq->local); + if(lex->eof){ + dontclose(lex->input->fd); + freelexer(lex); + p->lex = 0; + } else + --p->pc; /* re-execute Xrdcmds after codebuf runs */ + start(codebuf, 2, p->local, p->redir); } + lex = 0; freenodes(); } void -Xerror(char *s) +pprompt(void) { - if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0) - pfmt(err, "rc: %s: %r\n", s); + word *prompt; + + if(!runq->iflag) + return; + + Prompt(promptstr); + doprompt = 0; + + prompt = vlook("prompt")->val; + if(prompt && prompt->next) + promptstr = prompt->next->word; else - pfmt(err, "rc (%s): %s: %r\n", argv0, s); - flush(err); - setstatus("error"); - while(!runq->iflag) Xreturn(); + promptstr = "\t"; +} + +char* +srcfile(thread *p) +{ + return p->code[1].s; } void Xerror1(char *s) { - if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0) - pfmt(err, "rc: %s\n", s); - else - pfmt(err, "rc (%s): %s\n", argv0, s); - flush(err); setstatus("error"); + pfln(err, srcfile(runq), runq->line); + pfmt(err, ": %s\n", s); + flushio(err); + while(!runq->iflag) Xreturn(); +} +void +Xerror2(char *s, char *e) +{ + setstatus(e); + pfln(err, srcfile(runq), runq->line); + pfmt(err, ": %s: %s\n", s, e); + flushio(err); + while(!runq->iflag) Xreturn(); +} +void +Xerror3(char *s, char *m, char *e) +{ + setstatus(e); + pfln(err, srcfile(runq), runq->line); + pfmt(err, ": %s: %s: %s\n", s, m, e); + flushio(err); while(!runq->iflag) Xreturn(); } +void +Setstatus(char *s) +{ + setvar("status", Newword(s?s:estrdup(""), (word *)0)); +} void setstatus(char *s) { - setvar("status", newword(s, (word *)0)); + Setstatus(estrdup(s)); +} +char* +Getstatus(void) +{ + var *status = vlook("status"); + word *val = status->val; + if(val==0) return 0; + status->val=0; + status->changed=1; + freewords(val->next); + return Freeword(val); } - char* getstatus(void) { @@ -971,25 +1137,20 @@ truestatus(void) return 1; } -void -Xdelhere(void) -{ - Unlink(runq->code[runq->pc++].s); -} - void Xfor(void) { - if(runq->argv->words==0){ + word *a = runq->argv->words; + if(a==0){ poplist(); runq->pc = runq->code[runq->pc].i; } else{ - freelist(runq->local->val); - runq->local->val = runq->argv->words; + runq->argv->words = a->next; + a->next = 0; + freewords(runq->local->val); + runq->local->val = a; runq->local->changed = 1; - runq->argv->words = runq->argv->words->next; - runq->local->val->next = 0; runq->pc++; } } @@ -997,5 +1158,16 @@ Xfor(void) void Xglob(void) { - globlist(); + word *a, *x; + + for(a = runq->argv->words; a; a = x){ + x = a->next; + globword(a); + } +} + +void +Xsrcline(void) +{ + runq->line = runq->code[runq->pc++].i; } diff --git a/src/cmd/rc/exec.h b/src/cmd/rc/exec.h index 06cfd64e4d..69b1004ca2 100644 --- a/src/cmd/rc/exec.h +++ b/src/cmd/rc/exec.h @@ -2,17 +2,19 @@ * Definitions used in the interpreter */ extern void Xappend(void), Xasync(void), Xbackq(void), Xbang(void), Xclose(void); -extern void Xconc(void), Xcount(void), Xdelfn(void), Xdol(void), Xqdol(void), Xdup(void); +extern void Xconc(void), Xcount(void), Xdelfn(void), Xdol(void), Xqw(void), Xdup(void); extern void Xexit(void), Xfalse(void), Xfn(void), Xfor(void), Xglob(void); -extern void Xjump(void), Xmark(void), Xmatch(void), Xpipe(void), Xread(void); -extern void Xrdwr(void); -extern void Xrdfn(void), Xunredir(void), Xstar(void), Xreturn(void), Xsubshell(void); +extern void Xjump(void), Xmark(void), Xmatch(void), Xpipe(void), Xread(void), Xhere(void), Xhereq(void); +extern void Xrdwr(void), Xsrcline(void); +extern void Xunredir(void), Xstar(void), Xreturn(void), Xsubshell(void); extern void Xtrue(void), Xword(void), Xwrite(void), Xpipefd(void), Xcase(void); -extern void Xlocal(void), Xunlocal(void), Xassign(void), Xsimple(void), Xpopm(void); +extern void Xlocal(void), Xunlocal(void), Xassign(void), Xsimple(void), Xpopm(void), Xpush(void); extern void Xrdcmds(void), Xwastrue(void), Xif(void), Xifnot(void), Xpipewait(void); -extern void Xdelhere(void), Xpopredir(void), Xsub(void), Xeflag(void), Xsettrue(void); -extern void Xerror(char*); +extern void Xpopredir(void), Xsub(void), Xeflag(void), Xsettrue(void); extern void Xerror1(char*); +extern void Xerror2(char*,char*); +extern void Xerror3(char*,char*,char*); + /* * word lists are in correct order, * i.e. word0->word1->word2->word3->0 @@ -26,51 +28,58 @@ struct list{ list *next; }; word *newword(char *, word *), *copywords(word *, word *); + struct redir{ - char type; /* what to do */ - short from, to; /* what to do it to */ - struct redir *next; /* what else to do (reverse order) */ + int type; /* what to do */ + int from, to; /* what to do it to */ + redir *next; /* what else to do (reverse order) */ }; -#define NSTATUS ERRMAX /* length of status (from plan 9) */ + /* * redir types */ #define ROPEN 1 /* dup2(from, to); close(from); */ #define RDUP 2 /* dup2(from, to); */ #define RCLOSE 3 /* close(from); */ +void shuffleredir(void); + struct thread{ - union code *code; /* code for this thread */ + code *code; /* code for this thread */ int pc; /* code[pc] is the next instruction */ - struct list *argv; /* argument stack */ - struct redir *redir; /* redirection stack */ - struct redir *startredir; /* redir inheritance point */ - struct var *local; /* list of local variables */ - char *cmdfile; /* file name in Xrdcmd */ - struct io *cmdfd; /* file descriptor for Xrdcmd */ - int iflast; /* static `if not' checking */ - int eof; /* is cmdfd at eof? */ + int line; /* source code line for Xsrcline */ + list *argv; /* argument stack */ + redir *redir; /* redirection stack */ + redir *startredir; /* redir inheritance point */ + var *local; /* list of local variables */ + lexer *lex; /* lexer for Xrdcmds */ int iflag; /* interactive? */ - int lineno; /* linenumber */ int pid; /* process for Xpipewait to wait for */ - char status[NSTATUS]; /* status for Xpipewait */ - tree *treenodes; /* tree nodes created by this process */ - thread *ret; /* who continues when this finishes */ + char *status; /* status for Xpipewait */ + thread *ret; /* who continues when this finishes */ }; -thread *runq; +extern thread *runq; +void turfstack(var*); + +extern int mypid; +extern int ntrap; /* number of outstanding traps */ +extern int trap[NSIG]; /* number of outstanding traps per type */ + code *codecopy(code*); -code *codebuf; /* compiler output */ -int ntrap; /* number of outstanding traps */ -int trap[NSIG]; /* number of outstanding traps per type */ +extern code *codebuf; /* compiler output */ +extern int ifnot; + struct builtin{ char *name; void (*fnc)(void); }; -extern struct builtin Builtin[]; -int eflagok; /* kludge flag so that -e doesn't exit in startup */ -extern int havefork; +extern void (*builtinfunc(char *name))(void); void execcd(void), execwhatis(void), execeval(void), execexec(void); int execforkexec(void); void execexit(void), execshift(void); void execwait(void), execumask(void), execdot(void), execflag(void); -void execfunc(var*), execcmds(io *); +void execfunc(var*), execcmds(io*, char*, var*, redir*); +void startfunc(var*, word*, var*, redir*); + +char *srcfile(thread*); +char *getstatus(void); diff --git a/src/cmd/rc/fmtquote.c b/src/cmd/rc/fmtquote.c deleted file mode 100644 index e6b91e34b3..0000000000 --- a/src/cmd/rc/fmtquote.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include -#include -#include "fmt.h" -#include "fmtdef.h" - -extern int (*doquote)(int); - -/* - * How many bytes of output UTF will be produced by quoting (if necessary) this string? - * How many runes? How much of the input will be consumed? - * The parameter q is filled in by _quotesetup. - * The string may be UTF or Runes (s or r). - * Return count does not include NUL. - * Terminate the scan at the first of: - * NUL in input - * count exceeded in input - * count exceeded on output - * *ninp is set to number of input bytes accepted. - * nin may be <0 initially, to avoid checking input by count. - */ -void -__quotesetup(char *s, int nin, int nout, Quoteinfo *q, int sharp) -{ - int c; - - q->quoted = 0; - q->nbytesout = 0; - q->nrunesout = 0; - q->nbytesin = 0; - q->nrunesin = 0; - if(sharp || nin==0 || *s=='\0'){ - if(nout < 2) - return; - q->quoted = 1; - q->nbytesout = 2; - q->nrunesout = 2; - } - for(; nin!=0; nin-=1){ - c = *s; - - if(c == '\0') - break; - if(q->nrunesout+1 > nout) - break; - - if((c <= L' ') || (c == L'\'') || (doquote!=nil && doquote(c))){ - if(!q->quoted){ - if(1+q->nrunesout+1+1 > nout) /* no room for quotes */ - break; - q->nrunesout += 2; /* include quotes */ - q->nbytesout += 2; /* include quotes */ - q->quoted = 1; - } - if(c == '\'') { - q->nbytesout++; - q->nrunesout++; /* quotes reproduce as two characters */ - } - } - - /* advance input */ - s++; - q->nbytesin++; - q->nrunesin++; - - /* advance output */ - q->nbytesout++; - q->nrunesout++; - } -} - -static int -qstrfmt(char *sin, Quoteinfo *q, Fmt *f) -{ - int r; - char *t, *s, *m, *me; - ulong fl; - int nc, w; - - m = sin; - me = m + q->nbytesin; - - w = f->width; - fl = f->flags; - if(!(fl & FmtLeft) && __fmtpad(f, w - q->nbytesout) < 0) - return -1; - t = f->to; - s = f->stop; - FMTCHAR(f, t, s, '\''); - for(nc = q->nrunesin; nc > 0; nc--){ - r = *(uchar*)m++; - FMTCHAR(f, t, s, r); - if(r == '\'') - FMTCHAR(f, t, s, r); - } - - FMTCHAR(f, t, s, '\''); - f->nfmt += t - (char *)f->to; - f->to = t; - if(fl & FmtLeft && __fmtpad(f, w - q->nbytesout) < 0) - return -1; - return 0; -} - -int -__quotestrfmt(int runesin, Fmt *f) -{ - int outlen; - char *s; - Quoteinfo q; - - f->flags &= ~FmtPrec; /* ignored for %q %Q, so disable for %s %S in easy case */ - s = va_arg(f->args, char *); - if(!s) - return __fmtcpy(f, "", 5, 5); - - if(f->flush) - outlen = 0x7FFFFFFF; /* if we can flush, no output limit */ - else - outlen = (char*)f->stop - (char*)f->to; - - __quotesetup(s, -1, outlen, &q, f->flags&FmtSharp); - - if(!q.quoted) - return __fmtcpy(f, s, q.nrunesin, q.nbytesin); - return qstrfmt(s, &q, f); -} - -int -quotestrfmt(Fmt *f) -{ - return __quotestrfmt(0, f); -} - -void -quotefmtinstall(void) -{ - fmtinstall('q', quotestrfmt); -} - -int -__needsquotes(char *s, int *quotelenp) -{ - Quoteinfo q; - - __quotesetup(s, -1, 0x7FFFFFFF, &q, 0); - *quotelenp = q.nbytesout; - - return q.quoted; -} diff --git a/src/cmd/rc/fns.h b/src/cmd/rc/fns.h index 5721d61757..5f6c0ebfc1 100644 --- a/src/cmd/rc/fns.h +++ b/src/cmd/rc/fns.h @@ -1,68 +1,71 @@ void Abort(void); -void Closedir(int); +int Chdir(char*); +void Close(int); +void Closedir(void*); int Creat(char*); int Dup(int, int); int Dup1(int); int Eintr(void); int Executable(char*); -void Execute(word*, word*); -void Exit(char*); -int ForkExecute(char*, char**, int, int, int); -int Globsize(char*); +void Exec(char**); +void Exit(void); +char* Errstr(void); +char* Freeword(word*); +int Fork(void); +char* Getstatus(void); int Isatty(int); -void Memcpy(char*, char*, long); +word* Newword(char*,word*); void Noerror(void); -int Opendir(char*); -long Read(int, char*, long); -int Readdir(int, char*, int); +int Open(char*, int); +void* Opendir(char*); +word* Poplist(void); +char* Popword(void); +word* Pushword(char*); +long Read(int, void*, long); +char* Readdir(void*, int); long Seek(int, long, long); +void Setstatus(char*); void Trapinit(void); -void Unlink(char*); void Updenv(void); void Vinit(void); -int Waitfor(int, int); -long Write(int, char*, long); +int Waitfor(int); +long Write(int, void*, long); void addwaitpid(int); -int advance(void); -int back(int); -void cleanhere(char*); +void clearwaitpids(void); void codefree(code*); int compile(tree*); -char * list2str(word*); int count(word*); -void deglob(char*); +char* deglob(char*); void delwaitpid(int); void dotrap(void); void freenodes(void); void freewords(word*); -void globlist(void); +void globword(word*); int havewaitpid(int); int idchr(int); -void inttoascii(char*, long); +void inttoascii(char*, int); void kinit(void); int mapfd(int); int match(char*, char*, int); -int matchfn(char*, char*); -char** mkargv(word*); -void clearwaitpids(void); +char* makepath(char*, char*); void panic(char*, int); -void pathinit(void); +void pfln(io*, char*, int); void poplist(void); void popword(void); void pprompt(void); +void Prompt(char*); +void psubst(io*, unsigned char*); void pushlist(void); void pushredir(int, int, int); -void pushword(char*); -void readhere(void); -word* searchpath(char*); +word* pushword(char*); +void readhere(io*); +tree* heredoc(tree*); void setstatus(char*); -void setvar(char*, word*); void skipnl(void); -void start(code*, int, var*); +void start(code*, int, var*, redir*); int truestatus(void); void usage(char*); int wordchr(int); void yyerror(char*); int yylex(void); int yyparse(void); -int parse(void); diff --git a/src/cmd/rc/getflags.c b/src/cmd/rc/getflags.c index 09f6e3a71e..7a46c435c9 100644 --- a/src/cmd/rc/getflags.c +++ b/src/cmd/rc/getflags.c @@ -1,11 +1,8 @@ -/*% cyntax -DTEST % && cc -DTEST -go # % - */ #include "rc.h" #include "getflags.h" #include "fns.h" char *flagset[] = {""}; char **flag[NFLAG]; -char cmdline[NCMDLINE+1]; char *cmdname; static char *flagarg=""; static void reverse(char**, char**); @@ -23,24 +20,16 @@ static int badflag; int getflags(int argc, char *argv[], char *flags, int stop) { - char *s, *t; + char *s; int i, j, c, count; flagarg = flags; if(cmdname==0) cmdname = argv[0]; - s = cmdline; - for(i = 0;i!=argc;i++){ - for(t = argv[i];*t;t++) - if(s!=&cmdline[NCMDLINE]) - *s++=*t; - if(i!=argc-1 && s!=&cmdline[NCMDLINE]) - *s++=' '; - } - *s='\0'; + i = 1; while(i!=argc){ - if(argv[i][0]!='-' || argv[i][1]=='\0'){ - if(stop) + if(argv[i][0] != '-' || argv[i][1] == '\0'){ + if(stop) /* always true in rc */ return argc; i++; continue; @@ -216,7 +205,8 @@ usage(char *tail) errs(tail); } errs("\n"); - Exit("bad flags"); + setstatus("bad flags"); + Exit(); } static void diff --git a/src/cmd/rc/getflags.h b/src/cmd/rc/getflags.h index 9afb32ec52..84c4d8ee16 100644 --- a/src/cmd/rc/getflags.h +++ b/src/cmd/rc/getflags.h @@ -1,7 +1,7 @@ #define NFLAG 128 -#define NCMDLINE 512 + extern char **flag[NFLAG]; -extern char cmdline[NCMDLINE+1]; extern char *cmdname; extern char *flagset[]; + int getflags(int, char*[], char*, int); diff --git a/src/cmd/rc/glob.c b/src/cmd/rc/glob.c index baea44d99d..e455a59e29 100644 --- a/src/cmd/rc/glob.c +++ b/src/cmd/rc/glob.c @@ -1,30 +1,32 @@ #include "rc.h" #include "exec.h" #include "fns.h" -char *globname; -struct word *globv; + /* * delete all the GLOB marks from s, in place */ - -void +char* deglob(char *s) { - char *t = s; - do{ - if(*t==GLOB) - t++; - *s++=*t; - }while(*t++); + char *r = strchr(s, GLOB); + if(r){ + char *w = r++; + do{ + if(*r==GLOB) + r++; + *w++=*r; + }while(*r++); + } + return s; } -int +static int globcmp(const void *s, const void *t) { return strcmp(*(char**)s, *(char**)t); } -void +static void globsort(word *left, word *right) { char **list; @@ -35,156 +37,170 @@ globsort(word *left, word *right) for(a = left,n = 0;a!=right;a = a->next,n++) list[n] = a->word; qsort((void *)list, n, sizeof(void *), globcmp); for(a = left,n = 0;a!=right;a = a->next,n++) a->word = list[n]; - efree((char *)list); + free(list); } + /* - * Push names prefixed by globname and suffixed by a match of p onto the astack. - * namep points to the end of the prefix in globname. + * Does the string s match the pattern p + * . and .. are only matched by patterns starting with . + * * matches any sequence of characters + * ? matches any single character + * [...] matches the enclosed list of characters */ -void -globdir(char *p, char *namep) +static int +matchfn(char *s, char *p) { - char *t, *newp; - int f; - /* scan the pattern looking for a component with a metacharacter in it */ - if(*p=='\0'){ - globv = newword(globname, globv); - return; - } - t = namep; - newp = p; - while(*newp){ - if(*newp==GLOB) - break; - *t=*newp++; - if(*t++=='/'){ - namep = t; - p = newp; - } + if(s[0]=='.' && (s[1]=='\0' || s[1]=='.' && s[2]=='\0') && p[0]!='.') + return 0; + return match(s, p, '/'); +} + +static void +pappend(char **pdir, char *name) +{ + char *path = makepath(*pdir, name); + free(*pdir); + *pdir = path; +} + +static word* +globdir(word *list, char *pattern, char *name) +{ + char *slash, *glob, *entry; + void *dir; + +#ifdef Plan9 + /* append slashes, Readdir() already filtered directories */ + while(*pattern=='/'){ + pappend(&name, "/"); + pattern++; } +#endif + if(*pattern=='\0') + return Newword(name, list); + + /* scan the pattern looking for a component with a metacharacter in it */ + glob=strchr(pattern, GLOB); + /* If we ran out of pattern, append the name if accessible */ - if(*newp=='\0'){ - *t='\0'; - if(access(globname, 0)==0) - globv = newword(globname, globv); - return; + if(glob==0){ + pappend(&name, pattern); + if(access(name, 0)==0) + return Newword(name, list); + goto out; + } + + *glob='\0'; + slash=strrchr(pattern, '/'); + if(slash){ + *slash='\0'; + pappend(&name, pattern); + *slash='/'; + pattern=slash+1; } + *glob=GLOB; + /* read the directory and recur for any entry that matches */ - *namep='\0'; - if((f = Opendir(globname[0]?globname:"."))<0) return; - while(*newp!='/' && *newp!='\0') newp++; - while(Readdir(f, namep, *newp=='/')){ - if(matchfn(namep, p)){ - for(t = namep;*t;t++); - globdir(newp, t); - } + dir = Opendir(name[0]?name:"."); + if(dir==0) + goto out; + slash=strchr(glob, '/'); + while((entry=Readdir(dir, slash!=0)) != 0){ + if(matchfn(entry, pattern)) + list = globdir(list, slash?slash:"", makepath(name, entry)); } - Closedir(f); + Closedir(dir); +out: + free(name); + return list; } + /* - * Push all file names matched by p on the current thread's stack. - * If there are no matches, the list consists of p. + * Subsitute a word with its glob in place. */ - void -glob(char *p) +globword(word *w) { - word *svglobv = globv; - int globlen = Globsize(p); - if(!globlen){ - deglob(p); - globv = newword(p, globv); + word *left, *right; + + if(w==0 || strchr(w->word, GLOB)==0) return; + right = w->next; + left = globdir(right, w->word, estrdup("")); + if(left == right) { + deglob(w->word); + } else { + free(w->word); + globsort(left, right); + w->next = left->next; + w->word = Freeword(left); } - globname = emalloc(globlen); - globname[0]='\0'; - globdir(p, globname); - efree(globname); - if(svglobv==globv){ - deglob(p); - globv = newword(p, globv); - } - else - globsort(globv, svglobv); } -/* - * Do p and q point at equal utf codes - */ -int -equtf(char *p, char *q) -{ - if(*p!=*q) - return 0; - if(twobyte(*p)) return p[1]==q[1]; - if(threebyte(*p)){ - if(p[1]!=q[1]) - return 0; - if(p[1]=='\0') - return 1; /* broken code at end of string! */ - return p[2]==q[2]; - } - if(fourbyte(*p)){ - if(p[1]!=q[1]) - return 0; - if(p[1]=='\0') - return 1; - if(p[2]!=q[2]) - return 0; - if(p[2]=='\0') - return 1; - return p[3]==q[3]; - } - return 1; -} /* * Return a pointer to the next utf code in the string, * not jumping past nuls in broken utf codes! */ - -char* +static char* nextutf(char *p) { - if(twobyte(*p)) return p[1]=='\0'?p+1:p+2; - if(threebyte(*p)) return p[1]=='\0'?p+1:p[2]=='\0'?p+2:p+3; - if(fourbyte(*p)) return p[1]=='\0'?p+1:p[2]=='\0'?p+2:p[3]=='\0'?p+3:p+4; - return p+1; + int i, n, c = *p; + + if(onebyte(c)) + return p+1; + if(twobyte(c)) + n = 2; + else if(threebyte(c)) + n = 3; + else + n = 4; + for(i = 1; i < n; i++) + if(!xbyte(p[i])) + break; + return p+i; } + /* * Convert the utf code at *p to a unicode value */ - -int +static int unicode(char *p) { - int u=*p&0xff; - if(twobyte(u)) return ((u&0x1f)<<6)|(p[1]&0x3f); - if(threebyte(u)) return (u<<12)|((p[1]&0x3f)<<6)|(p[2]&0x3f); - if(fourbyte(u)) return (u<<18)|((p[1]&0x3f)<<12)|((p[2]&0x3f)<<6)|(p[3]&0x3f); - return u; + int c = *p; + + if(onebyte(c)) + return c&0xFF; + if(twobyte(c)){ + if(xbyte(p[1])) + return ((c&0x1F)<<6) | (p[1]&0x3F); + } else if(threebyte(c)){ + if(xbyte(p[1]) && xbyte(p[2])) + return ((c&0x0F)<<12) | ((p[1]&0x3F)<<6) | (p[2]&0x3F); + } else if(fourbyte(c)){ + if(xbyte(p[1]) && xbyte(p[2]) && xbyte(p[3])) + return ((c&0x07)<<18) | ((p[1]&0x3F)<<12) | ((p[2]&0x3F)<<6) | (p[3]&0x3F); + } + return -1; } + /* - * Does the string s match the pattern p - * . and .. are only matched by patterns starting with . - * * matches any sequence of characters - * ? matches any single character - * [...] matches the enclosed list of characters + * Do p and q point at equal utf codes */ - -int -matchfn(char *s, char *p) +static int +equtf(char *p, char *q) { - if(s[0]=='.' && (s[1]=='\0' || s[1]=='.' && s[2]=='\0') && p[0]!='.') - return 0; - return match(s, p, '/'); + if(*p!=*q) + return 0; + return unicode(p) == unicode(q); } int match(char *s, char *p, int stop) { int compl, hit, lo, hi, t, c; - for(;*p!=stop && *p!='\0';s = nextutf(s),p = nextutf(p)){ + + for(; *p!=stop && *p!='\0'; s = nextutf(s), p = nextutf(p)){ if(*p!=GLOB){ if(!equtf(p, s)) return 0; } @@ -241,27 +257,3 @@ match(char *s, char *p, int stop) } return *s=='\0'; } - -void -globlist1(word *gl) -{ - if(gl){ - globlist1(gl->next); - glob(gl->word); - } -} - -void -globlist(void) -{ - word *a; - globv = 0; - globlist1(runq->argv->words); - poplist(); - pushlist(); - if(globv){ - for(a = globv;a->next;a = a->next); - a->next = runq->argv->words; - runq->argv->words = globv; - } -} diff --git a/src/cmd/rc/havefork.c b/src/cmd/rc/havefork.c index 63f83354d3..e50197b810 100644 --- a/src/cmd/rc/havefork.c +++ b/src/cmd/rc/havefork.c @@ -1,68 +1,64 @@ -#include -#include -#if defined(PLAN9PORT) && defined(__sun__) -# define BSD_COMP /* sigh. for TIOCNOTTY */ -#endif -#include #include "rc.h" #include "getflags.h" #include "exec.h" #include "io.h" #include "fns.h" -int havefork = 1; +static int *waitpids; +static int nwaitpids; + +void +addwaitpid(int pid) +{ + waitpids = erealloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]); + waitpids[nwaitpids++] = pid; +} + +void +delwaitpid(int pid) +{ + int r, w; + + for(r=w=0; r= 0){ - /* - * Should make reads of tty fail, writes succeed. - */ - signal(SIGTTIN, SIG_IGN); - signal(SIGTTOU, SIG_IGN); - ioctl(tty, TIOCNOTTY); - close(tty); - } - if(isatty(0)) - pushredir(ROPEN, null, 0); - else - close(null); - start(runq->code, runq->pc+1, runq->local); + start(runq->code, runq->pc+1, runq->local, runq->redir); runq->ret = 0; break; default: addwaitpid(pid); - close(null); runq->pc = runq->code[runq->pc].i; inttoascii(npid, pid); setvar("apid", newword(npid, (word *)0)); @@ -73,33 +69,34 @@ Xasync(void) void Xpipe(void) { - struct thread *p = runq; - int pc = p->pc, forkid; + thread *p = runq; + int pid, pc = p->pc; int lfd = p->code[pc++].i; int rfd = p->code[pc++].i; int pfd[2]; + if(pipe(pfd)<0){ - Xerror("can't get pipe"); + Xerror2("can't get pipe", Errstr()); return; } - switch(forkid = fork()){ + switch(pid = Fork()){ case -1: - Xerror("try again"); + Xerror2("try again", Errstr()); break; case 0: clearwaitpids(); - start(p->code, pc+2, runq->local); + Close(pfd[PRD]); + start(p->code, pc+2, runq->local, runq->redir); runq->ret = 0; - close(pfd[PRD]); pushredir(ROPEN, pfd[PWR], lfd); break; default: - addwaitpid(forkid); - start(p->code, p->code[pc].i, runq->local); - close(pfd[PWR]); + addwaitpid(pid); + Close(pfd[PWR]); + start(p->code, p->code[pc].i, runq->local, runq->redir); pushredir(ROPEN, pfd[PRD], rfd); p->pc = p->code[pc+1].i; - p->pid = forkid; + p->pid = pid; break; } } @@ -107,75 +104,51 @@ Xpipe(void) /* * Who should wait for the exit from the fork? */ + void Xbackq(void) { - struct thread *p = runq; - char wd[8193]; - int c, n; - char *s, *ewd=&wd[8192], *stop, *q; - struct io *f; - var *ifs = vlook("ifs"); - word *v, *nextv; - int pfd[2]; - int pid; - Rune r; - stop = ifs->val?ifs->val->word:""; + int pid, pfd[2]; + char *s, *split; + word *end, **link; + io *f; + if(pipe(pfd)<0){ - Xerror("can't make pipe"); + Xerror2("can't make pipe", Errstr()); return; } - switch(pid = fork()){ + switch(pid = Fork()){ case -1: - Xerror("try again"); - close(pfd[PRD]); - close(pfd[PWR]); + Xerror2("try again", Errstr()); + Close(pfd[PRD]); + Close(pfd[PWR]); return; case 0: clearwaitpids(); - close(pfd[PRD]); - start(runq->code, runq->pc+1, runq->local); + Close(pfd[PRD]); + start(runq->code, runq->pc+1, runq->local, runq->redir); pushredir(ROPEN, pfd[PWR], 1); return; default: addwaitpid(pid); - close(pfd[PWR]); - f = openfd(pfd[PRD]); - s = wd; - v = 0; - while((c = rchr(f))!=EOF){ - if(s != ewd) { - *s++ = c; - for(q=stop; *q; q+=n) { - n = chartorune(&r, q); - if(s-wd >= n && memcmp(s-n, q, n) == 0) { - s -= n; - goto stop; - } - } - continue; - } - stop: - if(s != wd) { - *s = '\0'; - v = newword(wd, v); - } - s = wd; - } - if(s!=wd){ - *s='\0'; - v = newword(wd, v); + Close(pfd[PWR]); + + split = Popword(); + poplist(); + f = openiofd(pfd[PRD]); + end = runq->argv->words; + link = &runq->argv->words; + while((s = rstr(f, split)) != 0){ + *link = Newword(s, (word*)0); + link = &(*link)->next; } + *link = end; closeio(f); - Waitfor(pid, 0); - /* v points to reversed arglist -- reverse it onto argv */ - while(v){ - nextv = v->next; - v->next = runq->argv->words; - runq->argv->words = v; - v = nextv; - } - p->pc = p->code[p->pc].i; + free(split); + + Waitfor(pid); + + runq->pc = runq->code[runq->pc].i; return; } } @@ -183,71 +156,43 @@ Xbackq(void) void Xpipefd(void) { - struct thread *p = runq; - int pc = p->pc, pid; + thread *p = runq; + int pid, pc = p->pc; char name[40]; int pfd[2]; - struct { int sidefd, mainfd; } fd[2], *r, *w; + int sidefd, mainfd; - r = &fd[0]; - w = &fd[1]; - switch(p->code[pc].i){ - case READ: - w = nil; - break; - case WRITE: - r = nil; + if(pipe(pfd)<0){ + Xerror2("can't get pipe", Errstr()); + return; } - - if(r){ - if(pipe(pfd)<0){ - Xerror("can't get pipe"); - return; - } - r->sidefd = pfd[PWR]; - r->mainfd = pfd[PRD]; + if(p->code[pc].i==READ){ + sidefd = pfd[PWR]; + mainfd = pfd[PRD]; } - if(w){ - if(pipe(pfd)<0){ - Xerror("can't get pipe"); - return; - } - w->sidefd = pfd[PRD]; - w->mainfd = pfd[PWR]; + else{ + sidefd = pfd[PRD]; + mainfd = pfd[PWR]; } - switch(pid = fork()){ + switch(pid = Fork()){ case -1: - Xerror("try again"); + Xerror2("try again", Errstr()); break; case 0: clearwaitpids(); - start(p->code, pc+2, runq->local); - if(r){ - close(r->mainfd); - pushredir(ROPEN, r->sidefd, 1); - } - if(w){ - close(w->mainfd); - pushredir(ROPEN, w->sidefd, 0); - } + Close(mainfd); + start(p->code, pc+2, runq->local, runq->redir); + pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0); runq->ret = 0; break; default: addwaitpid(pid); - if(w){ - close(w->sidefd); - pushredir(ROPEN, w->mainfd, w->mainfd); /* so that Xpopredir can close it later */ - strcpy(name, Fdprefix); - inttoascii(name+strlen(name), w->mainfd); - pushword(name); - } - if(r){ - close(r->sidefd); - pushredir(ROPEN, r->mainfd, r->mainfd); - strcpy(name, Fdprefix); - inttoascii(name+strlen(name), r->mainfd); - pushword(name); - } + Close(sidefd); + pushredir(ROPEN, mainfd, mainfd); + shuffleredir(); /* shuffle redir to bottom of stack for Xpopredir() */ + strcpy(name, Fdprefix); + inttoascii(name+strlen(name), mainfd); + pushword(name); p->pc = p->code[pc+1].i; break; } @@ -257,18 +202,20 @@ void Xsubshell(void) { int pid; - switch(pid = fork()){ + + switch(pid = Fork()){ case -1: - Xerror("try again"); + Xerror2("try again", Errstr()); break; case 0: clearwaitpids(); - start(runq->code, runq->pc+1, runq->local); + start(runq->code, runq->pc+1, runq->local, runq->redir); runq->ret = 0; break; default: addwaitpid(pid); - Waitfor(pid, 1); + while(Waitfor(pid) < 0) + ; runq->pc = runq->code[runq->pc].i; break; } @@ -278,20 +225,15 @@ int execforkexec(void) { int pid; - int n; - char buf[ERRMAX]; - switch(pid = fork()){ + switch(pid = Fork()){ case -1: return -1; case 0: clearwaitpids(); pushword("exec"); execexec(); - strcpy(buf, "can't exec: "); - n = strlen(buf); - errstr(buf+n, ERRMAX-n); - Exit(buf); + /* does not return */ } addwaitpid(pid); return pid; diff --git a/src/cmd/rc/haventfork.c b/src/cmd/rc/haventfork.c deleted file mode 100644 index fc8f7608ec..0000000000 --- a/src/cmd/rc/haventfork.c +++ /dev/null @@ -1,211 +0,0 @@ -#include "rc.h" -#include "getflags.h" -#include "exec.h" -#include "io.h" -#include "fns.h" - -int havefork = 0; - -static char ** -rcargv(char *s) -{ - int argc; - char **argv; - word *p; - - p = vlook("*")->val; - argv = malloc((count(p)+6)*sizeof(char*)); - argc = 0; - argv[argc++] = argv0; - if(flag['e']) - argv[argc++] = "-Se"; - else - argv[argc++] = "-S"; - argv[argc++] = "-c"; - argv[argc++] = s; - for(p = vlook("*")->val; p; p = p->next) - argv[argc++] = p->word; - argv[argc] = 0; - return argv; -} - -void -Xasync(void) -{ - uint pid; - char buf[20], **argv; - - Updenv(); - - argv = rcargv(runq->code[runq->pc].s); - pid = ForkExecute(argv0, argv, -1, 1, 2); - free(argv); - - if(pid == 0) { - Xerror("proc failed"); - return; - } - - runq->pc++; - sprint(buf, "%d", pid); - setvar("apid", newword(buf, (word *)0)); -} - -void -Xbackq(void) -{ - char wd[8193], **argv; - int c; - char *s, *ewd=&wd[8192], *stop; - struct io *f; - var *ifs = vlook("ifs"); - word *v, *nextv; - int pfd[2]; - int pid; - - stop = ifs->val?ifs->val->word:""; - if(pipe(pfd)<0){ - Xerror("can't make pipe"); - return; - } - - Updenv(); - - argv = rcargv(runq->code[runq->pc].s); - pid = ForkExecute(argv0, argv, -1, pfd[1], 2); - free(argv); - - close(pfd[1]); - - if(pid == 0) { - Xerror("proc failed"); - close(pfd[0]); - return; - } - - f = openfd(pfd[0]); - s = wd; - v = 0; - while((c=rchr(f))!=EOF){ - if(strchr(stop, c) || s==ewd){ - if(s!=wd){ - *s='\0'; - v=newword(wd, v); - s=wd; - } - } - else *s++=c; - } - if(s!=wd){ - *s='\0'; - v=newword(wd, v); - } - closeio(f); - Waitfor(pid, 1); - /* v points to reversed arglist -- reverse it onto argv */ - while(v){ - nextv=v->next; - v->next=runq->argv->words; - runq->argv->words=v; - v=nextv; - } - runq->pc++; -} - -void -Xpipe(void) -{ - thread *p=runq; - int pc=p->pc, pid; - int rfd=p->code[pc+1].i; - int pfd[2]; - char **argv; - - if(pipe(pfd)<0){ - Xerror1("can't get pipe"); - return; - } - - Updenv(); - - argv = rcargv(runq->code[pc+2].s); - pid = ForkExecute(argv0, argv, 0, pfd[1], 2); - free(argv); - close(pfd[1]); - - if(pid == 0) { - Xerror("proc failed"); - close(pfd[0]); - return; - } - - start(p->code, pc+4, runq->local); - pushredir(ROPEN, pfd[0], rfd); - p->pc=p->code[pc+3].i; - p->pid=pid; -} - -void -Xpipefd(void) -{ - Abort(); -} - -void -Xsubshell(void) -{ - char **argv; - int pid; - - Updenv(); - - argv = rcargv(runq->code[runq->pc].s); - pid = ForkExecute(argv0, argv, -1, 1, 2); - free(argv); - - if(pid < 0) { - Xerror("proc failed"); - return; - } - - Waitfor(pid, 1); - runq->pc++; -} - -/* - * start a process running the cmd on the stack and return its pid. - */ -int -execforkexec(void) -{ - char **argv; - char file[1024]; - int nc; - word *path; - int pid; - - if(runq->argv->words==0) - return -1; - argv = mkargv(runq->argv->words); - - for(path = searchpath(runq->argv->words->word);path;path = path->next){ - nc = strlen(path->word); - if(ncword); - if(file[0]){ - strcat(file, "/"); - nc++; - } - if(nc+strlen(argv[1])= 0){ - free(argv); - return pid; - } - } - } - } - free(argv); - return -1; -} diff --git a/src/cmd/rc/here.c b/src/cmd/rc/here.c index 17c6245813..a988c2a14a 100644 --- a/src/cmd/rc/here.c +++ b/src/cmd/rc/here.c @@ -2,103 +2,91 @@ #include "exec.h" #include "io.h" #include "fns.h" -struct here *here, **ehere; -int ser = 0; -char tmp[]="/tmp/here0000.0000"; -char hex[]="0123456789abcdef"; -void psubst(io*, char*); + +void psubst(io*, unsigned char*); void pstrs(io*, word*); -void -hexnum(char *p, int n) +static char* +readhere1(tree *tag, io *in) { - *p++=hex[(n>>12)&0xF]; - *p++=hex[(n>>8)&0xF]; - *p++=hex[(n>>4)&0xF]; - *p = hex[n&0xF]; + io *out; + char c, *m; + + pprompt(); + out = openiostr(); + m = tag->str; + while((c = rchr(in)) != EOF){ + if(c=='\0'){ + yyerror("NUL bytes in here doc"); + closeio(out); + return 0; + } + if(c=='\n'){ + lex->line++; + if(m && *m=='\0'){ + out->bufp -= m - tag->str; + *out->bufp='\0'; + break; + } + pprompt(); + m = tag->str; + } else if(m){ + if(*m == c){ + m++; + } else { + m = 0; + } + } + pchr(out, c); + } + doprompt = 1; + return closeiostr(out); } +static tree *head, *tail; + tree* -heredoc(tree *tag) +heredoc(tree *redir) { - struct here *h = new(struct here); - if(tag->type!=WORD) + if(redir->child[0]->type!=WORD){ yyerror("Bad here tag"); - h->next = 0; - if(here) - *ehere = h; + return nil; + } + redir->child[2]=0; + if(head) + tail->child[2]=redir; else - here = h; - ehere=&h->next; - h->tag = tag; - hexnum(&tmp[9], getpid()); - hexnum(&tmp[14], ser++); - h->name = strdup(tmp); - return token(tmp, WORD); + head=redir; + tail=redir; + return tail; } -/* - * bug: lines longer than NLINE get split -- this can cause spurious - * missubstitution, or a misrecognized EOF marker. - */ -#define NLINE 4096 void -readhere(void) +readhere(io *in) { - struct here *h, *nexth; - io *f; - char *s, *tag; - int c, subst; - char line[NLINE+1]; - for(h = here;h;h = nexth){ - subst=!h->tag->quoted; - tag = h->tag->str; - c = Creat(h->name); - if(c<0) - yyerror("can't create here document"); - f = openfd(c); - s = line; - pprompt(); - while((c = rchr(runq->cmdfd))!=EOF){ - if(c=='\n' || s==&line[NLINE]){ - *s='\0'; - if(tag && strcmp(line, tag)==0) break; - if(subst) - psubst(f, line); - else pstr(f, line); - s = line; - if(c=='\n'){ - pprompt(); - pchr(f, c); - } - else *s++=c; - } - else *s++=c; - } - flush(f); - closeio(f); - cleanhere(h->name); - nexth = h->next; - efree((char *)h); + while(head){ + tail=head->child[2]; + head->child[2]=0; + head->str=readhere1(head->child[0], in); + head=tail; } - here = 0; - doprompt = 1; } void -psubst(io *f, char *s) +psubst(io *f, unsigned char *s) { - char *t, *u; - int savec, n; + unsigned char *t, *u; word *star; + int savec, n; + while(*s){ if(*s!='$'){ - if(0xa0<=(*s&0xff) && (*s&0xff)<=0xf5){ + if(0xa0 <= *s && *s <= 0xf5){ pchr(f, *s++); if(*s=='\0') break; } - else if(0xf6<=(*s&0xff) && (*s&0xff)<=0xf7){ + else if(0xf6 <= *s && *s <= 0xf7){ pchr(f, *s++); if(*s=='\0') break; @@ -126,7 +114,7 @@ psubst(io *f, char *s) } } else - pstrs(f, vlook(s)->val); + pstrs(f, vlook((char *)s)->val); *t = savec; if(savec=='^') t++; diff --git a/src/cmd/rc/io.c b/src/cmd/rc/io.c index 907ba86fbf..ee16f88840 100644 --- a/src/cmd/rc/io.c +++ b/src/cmd/rc/io.c @@ -1,25 +1,23 @@ -#include -#include #include "rc.h" #include "exec.h" #include "io.h" #include "fns.h" -int pfmtnest = 0; + +enum { + NBUF = 8192, +}; void -pfmt(io *f, char *fmt, ...) +vpfmt(io *f, char *fmt, va_list ap) { - va_list ap; - char err[ERRMAX]; - va_start(ap, fmt); - pfmtnest++; - for(;*fmt;fmt++) - if(*fmt!='%') + for(;*fmt;fmt++) { + if(*fmt!='%') { pchr(f, *fmt); - else switch(*++fmt){ - case '\0': - va_end(ap); - return; + continue; + } + if(*++fmt == '\0') /* "blah%"? */ + break; + switch(*fmt){ case 'c': pchr(f, va_arg(ap, int)); break; @@ -38,54 +36,101 @@ pfmt(io *f, char *fmt, ...) case 'q': pwrd(f, va_arg(ap, char *)); break; - case 'r': - rerrstr(err, sizeof err); pstr(f, err); - break; case 's': pstr(f, va_arg(ap, char *)); break; case 't': pcmd(f, va_arg(ap, tree *)); break; - case 'u': - pcmdu(f, va_arg(ap, tree *)); - break; case 'v': - pval(f, va_arg(ap, struct word *)); + pval(f, va_arg(ap, word *)); break; default: pchr(f, *fmt); break; } + } +} + +void +pfmt(io *f, char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vpfmt(f, fmt, ap); va_end(ap); - if(--pfmtnest==0) - flush(f); } void pchr(io *b, int c) { - if(b->bufp==b->ebuf) - fullbuf(b, c); - else *b->bufp++=c; + if(b->bufp>=b->ebuf) + flushio(b); + *b->bufp++=c; } int rchr(io *b) { - if(b->bufp==b->ebuf) - return emptybuf(b); - return *b->bufp++ & 0xFF; + if(b->bufp>=b->ebuf) + return emptyiobuf(b); + return *b->bufp++; +} + +char* +rstr(io *b, char *stop) +{ + char *s, *p; + int l, m, n; + + do { + l = rchr(b); + if(l == EOF) + return 0; + } while(l && strchr(stop, l)); + b->bufp--; + + s = 0; + l = 0; + for(;;){ + p = (char*)b->bufp; + n = (char*)b->ebuf - p; + if(n > 0){ + for(m = 0; m < n; m++){ + if(strchr(stop, p[m])==0) + continue; + + b->bufp += m+1; + if(m > 0 || s==0){ + s = erealloc(s, l+m+1); + memmove(s+l, p, m); + l += m; + } + s[l]='\0'; + return s; + } + s = erealloc(s, l+m+1); + memmove(s+l, p, m); + l += m; + b->bufp += m; + } + if(emptyiobuf(b) == EOF){ + if(s) s[l]='\0'; + return s; + } + b->bufp--; + } } void pquo(io *f, char *s) { pchr(f, '\''); - for(;*s;s++) + for(;*s;s++){ if(*s=='\'') - pfmt(f, "''"); - else pchr(f, *s); + pchr(f, *s); + pchr(f, *s); + } pchr(f, '\''); } @@ -93,23 +138,23 @@ void pwrd(io *f, char *s) { char *t; - for(t = s;*t;t++) if(!wordchr(*t)) break; + for(t = s;*t;t++) if(*t >= 0 && (*t <= ' ' || strchr("`^#*[]=|\\?${}()'<>&;", *t))) break; if(t==s || *t) pquo(f, s); else pstr(f, s); } void -pptr(io *f, void *v) +pptr(io *f, void *p) { + static char hex[] = "0123456789ABCDEF"; + unsigned long long v; int n; - uintptr p; - - 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]); + v = (unsigned long long)p; + if(sizeof(v) == sizeof(p) && v>>32) + for(n = 60;n>=32;n-=4) pchr(f, hex[(v>>n)&0xF]); + for(n = 28;n>=0;n-=4) pchr(f, hex[(v>>n)&0xF]); } void @@ -124,13 +169,14 @@ void pdec(io *f, int n) { if(n<0){ - if(n!=INT_MIN){ + n=-n; + if(n>=0){ pchr(f, '-'); - pdec(f, -n); + pdec(f, n); return; } /* n is two's complement minimum integer */ - n = -(INT_MIN+1); + n = 1-n; pchr(f, '-'); pdec(f, n/10); pchr(f, n%10+'1'); @@ -152,122 +198,104 @@ poct(io *f, unsigned n) void pval(io *f, word *a) { - if(a){ - while(a->next && a->next->word){ - pwrd(f, a->word); - pchr(f, ' '); - a = a->next; - } - pwrd(f, a->word); + if(a==0) + return; + while(a->next && a->next->word){ + pwrd(f, (char *)a->word); + pchr(f, ' '); + a = a->next; } + pwrd(f, (char *)a->word); } -int -fullbuf(io *f, int c) +io* +newio(unsigned char *buf, int len, int fd) { - flush(f); - return *f->bufp++=c; + io *f = new(io); + f->buf = buf; + f->bufp = buf; + f->ebuf = buf+len; + f->fd = fd; + return f; } -void -flush(io *f) +/* + * Open a string buffer for writing. + */ +io* +openiostr(void) { - int n; - char *s; - if(f->strp){ - n = f->ebuf-f->strp; - f->strp = realloc(f->strp, n+101); - if(f->strp==0) - panic("Can't realloc %d bytes in flush!", n+101); - f->bufp = f->strp+n; - f->ebuf = f->bufp+100; - for(s = f->bufp;s<=f->ebuf;s++) *s='\0'; - } - else{ - n = f->bufp-f->buf; - if(n && Write(f->fd, f->buf, n) < 0){ - Write(3, "Write error\n", 12); - if(ntrap) - dotrap(); - } - f->bufp = f->buf; - f->ebuf = f->buf+NBUF; - } + unsigned char *buf = emalloc(100+1); + memset(buf, '\0', 100+1); + return newio(buf, 100, -1); } -io* -openfd(int fd) +/* + * Return the buf, free the io + */ +char* +closeiostr(io *f) { - io *f = new(struct io); - f->fd = fd; - f->bufp = f->ebuf = f->buf; - f->strp = 0; - return f; + void *buf = f->buf; + free(f); + return buf; } +/* + * Use a open file descriptor for reading. + */ io* -openstr(void) +openiofd(int fd) { - io *f = new(struct io); - char *s; - f->fd=-1; - f->bufp = f->strp = emalloc(101); - f->ebuf = f->bufp+100; - for(s = f->bufp;s<=f->ebuf;s++) *s='\0'; - return f; + return newio(emalloc(NBUF), 0, fd); } + /* * Open a corebuffer to read. EOF occurs after reading len * characters from buf. */ - io* -opencore(char *s, int len) +openiocore(void *buf, int len) { - io *f = new(struct io); - char *buf = emalloc(len); - f->fd= -1 /*open("/dev/null", 0)*/; - f->bufp = f->strp = buf; - f->ebuf = buf+len; - Memcpy(buf, s, len); - return f; + return newio(buf, len, -1); } void -iorewind(io *io) +flushio(io *f) { - if(io->fd==-1) - io->bufp = io->strp; + int n; + + if(f->fd<0){ + n = f->ebuf - f->buf; + f->buf = erealloc(f->buf, n+n+1); + f->bufp = f->buf + n; + f->ebuf = f->bufp + n; + memset(f->bufp, '\0', n+1); + } else{ - io->bufp = io->ebuf = io->buf; - Seek(io->fd, 0L, 0); + n = f->bufp - f->buf; + if(n && Write(f->fd, f->buf, n) != n){ + if(ntrap) + dotrap(); + } + f->bufp = f->buf; + f->ebuf = f->buf+NBUF; } } void -closeio(io *io) +closeio(io *f) { - if(io->fd>=0) - close(io->fd); - if(io->strp) - efree(io->strp); - efree((char *)io); + if(f->fd>=0) Close(f->fd); + free(closeiostr(f)); } int -emptybuf(io *f) +emptyiobuf(io *f) { int n; - if(f->fd==-1) - return EOF; -Loop: - errno = 0; - n = Read(f->fd, f->buf, NBUF); - if(n < 0 && errno == EINTR) - goto Loop; - if(n <= 0) - return EOF; + if(f->fd<0 || (n = Read(f->fd, f->buf, NBUF))<=0) return EOF; f->bufp = f->buf; - f->ebuf = f->buf+n; - return *f->bufp++&0xff; + f->ebuf = f->buf + n; + return *f->bufp++; } diff --git a/src/cmd/rc/io.h b/src/cmd/rc/io.h index 6c75cc5bc6..1c345810c6 100644 --- a/src/cmd/rc/io.h +++ b/src/cmd/rc/io.h @@ -1,23 +1,19 @@ -/* - * on Mac OS X, err is something else, - * and assigning to it causes a bus error. - * what a crappy linker. - */ -#define err rc_err #define EOF (-1) -#define NBUF 512 + struct io{ - int fd; - char *bufp, *ebuf, *strp, buf[NBUF]; + int fd; + unsigned char *buf, *bufp, *ebuf; + io *next; }; -io *err; -io *openfd(int), *openstr(void), *opencore(char *, int); -int emptybuf(io*); + +io *openiofd(int), *openiostr(void), *openiocore(void*, int); void pchr(io*, int); int rchr(io*); +char *rstr(io*, char*); +char *closeiostr(io*); void closeio(io*); -void flush(io*); -int fullbuf(io*, int); +int emptyiobuf(io*); +void flushio(io*); void pdec(io*, int); void poct(io*, unsigned); void pptr(io*, void*); @@ -25,7 +21,8 @@ void pquo(io*, char*); void pwrd(io*, char*); void pstr(io*, char*); void pcmd(io*, tree*); -void pcmdu(io*, tree*); void pval(io*, word*); +void pfun(io*, void(*)(void)); void pfnc(io*, thread*); void pfmt(io*, char*, ...); +void vpfmt(io*, char*, va_list); diff --git a/src/cmd/rc/lex.c b/src/cmd/rc/lex.c index e4410c0026..5afb5f584a 100644 --- a/src/cmd/rc/lex.c +++ b/src/cmd/rc/lex.c @@ -1,9 +1,12 @@ #include "rc.h" -#include "exec.h" #include "io.h" #include "getflags.h" #include "fns.h" -int getnext(void); + +lexer *lex; + +int doprompt = 1; +int nerror; int wordchr(int c) @@ -21,113 +24,129 @@ idchr(int c) */ return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c); } -int future = EOF; -int doprompt = 1; -int inquote; -int incomm; -/* - * Look ahead in the input stream - */ -int -nextc(void) +lexer* +newlexer(io *input, char *file) { - if(future==EOF) - future = getnext(); - return future; + lexer *n = new(struct lexer); + n->input = input; + n->file = file; + n->line = 1; + n->eof = 0; + n->future = EOF; + n->peekc = '{'; + n->epilog = "}\n"; + n->lastc = 0; + n->inquote = 0; + n->incomm = 0; + n->lastword = 0; + n->lastdol = 0; + n->iflast = 0; + n->qflag = 0; + n->tok[0] = 0; + return n; } -/* - * Consume the lookahead character. - */ -int -advance(void) +void +freelexer(lexer *p) { - int c = nextc(); - lastc = future; - future = EOF; - return c; + closeio(p->input); + free(p->file); + free(p); } + /* * read a character from the input stream - */ - -int + */ +static int getnext(void) { int c; - static int peekc = EOF; - if(peekc!=EOF){ - c = peekc; - peekc = EOF; + + if(lex->peekc!=EOF){ + c = lex->peekc; + lex->peekc = EOF; return c; } - if(runq->eof) + if(lex->eof){ +epilog: + if(*lex->epilog) + return *lex->epilog++; + doprompt = 1; return EOF; + } if(doprompt) pprompt(); - c = rchr(runq->cmdfd); - if(!inquote && c=='\\'){ - c = rchr(runq->cmdfd); - if(c=='\n' && !incomm){ /* don't continue a comment */ + c = rchr(lex->input); + if(c=='\\' && !lex->inquote){ + c = rchr(lex->input); + if(c=='\n' && !lex->incomm){ /* don't continue a comment */ doprompt = 1; c=' '; } else{ - peekc = c; + lex->peekc = c; c='\\'; } } - doprompt = doprompt || c=='\n' || c==EOF; - if(c==EOF) - runq->eof++; - else if(flag['V'] || ndot>=2 && flag['v']) pchr(err, c); + if(c==EOF){ + lex->eof = 1; + goto epilog; + } else { + if(c=='\n') + doprompt = 1; + if((!lex->qflag && flag['v']!=0) || flag['V']) + pchr(err, c); + } return c; } -void -pprompt(void) +/* + * Look ahead in the input stream + */ +static int +nextc(void) { - var *prompt; - if(runq->iflag){ - pstr(err, promptstr); - flush(err); - prompt = vlook("prompt"); - if(prompt->val && prompt->val->next) - promptstr = prompt->val->next->word; - else - promptstr="\t"; - } - runq->lineno++; - doprompt = 0; + if(lex->future==EOF) + lex->future = getnext(); + return lex->future; } -int +/* + * Consume the lookahead character. + */ +static int +advance(void) +{ + int c = nextc(); + lex->lastc = lex->future; + lex->future = EOF; + if(c == '\n') + lex->line++; + return c; +} + +static void skipwhite(void) { - int c, skipped; - skipped = 0; + int c; for(;;){ c = nextc(); /* Why did this used to be if(!inquote && c=='#') ?? */ if(c=='#'){ - incomm = 1; - skipped = 1; + lex->incomm = 1; for(;;){ c = nextc(); if(c=='\n' || c==EOF) { - incomm = 0; + lex->incomm = 0; break; } advance(); } } - if(c==' ' || c=='\t') { - skipped = 1; + if(c==' ' || c=='\t') advance(); - } - else - return skipped; + else return; } } @@ -144,7 +163,7 @@ skipnl(void) } } -int +static int nextis(int c) { if(nextc()==c){ @@ -154,12 +173,12 @@ nextis(int c) return 0; } -char* +static char* addtok(char *p, int val) { if(p==0) return 0; - if(p==&tok[NTOK-1]){ + if(p==&lex->tok[NTOK-1]){ *p = 0; yyerror("token buffer too short"); return 0; @@ -168,33 +187,39 @@ addtok(char *p, int val) return p; } -char* +static char* addutf(char *p, int c) { - p = addtok(p, c); - if(twobyte(c)) /* 2-byte escape */ - return addtok(p, advance()); - if(threebyte(c)){ /* 3-byte escape */ - p = addtok(p, advance()); - return addtok(p, advance()); - } - if(fourbyte(c)){ /* 4-byte escape */ - p = addtok(p, advance()); + int i, n; + + p = addtok(p, c); /* 1-byte UTF runes are special */ + if(onebyte(c)) + return p; + if(twobyte(c)) + n = 2; + else if(threebyte(c)) + n = 3; + else + n = 4; + for(i = 1; i < n; i++) { + c = nextc(); + if(c == EOF || !xbyte(c)) + break; p = addtok(p, advance()); - return addtok(p, advance()); } return p; } -int lastdol; /* was the last token read '$' or '$#' or '"'? */ -int lastword; /* was the last token read a word or compound word terminator? */ int yylex(void) { - int c, d = nextc(); + int glob, c, d = nextc(); + char *tok = lex->tok; char *w = tok; tree *t; + yylval.tree = 0; + /* * Embarassing sneakiness: if the last token read was a quoted or unquoted * WORD then we alter the meaning of what follows. If the next character @@ -202,11 +227,11 @@ yylex(void) * if the next character is the first character of a simple or compound word, * we insert a `^' before it. */ - if(lastword && flag['Y']){ - lastword = 0; + if(lex->lastword){ + lex->lastword = 0; if(d=='('){ advance(); - strcpy(tok, "("); + strcpy(tok, "( [SUB]"); return SUB; } if(wordchr(d) || d=='\'' || d=='`' || d=='$' || d=='"'){ @@ -214,16 +239,15 @@ yylex(void) return '^'; } } - inquote = 0; - if(skipwhite() && !flag['Y']) - return ' '; + lex->inquote = 0; + skipwhite(); switch(c = advance()){ case EOF: - lastdol = 0; + lex->lastdol = 0; strcpy(tok, "EOF"); return EOF; case '$': - lastdol = 1; + lex->lastdol = 1; if(nextis('#')){ strcpy(tok, "$#"); return COUNT; @@ -235,26 +259,24 @@ yylex(void) strcpy(tok, "$"); return '$'; case '&': - lastdol = 0; + lex->lastdol = 0; if(nextis('&')){ - if(flag['Y']) - skipnl(); + skipnl(); strcpy(tok, "&&"); return ANDAND; } strcpy(tok, "&"); return '&'; case '|': - lastdol = 0; + lex->lastdol = 0; if(nextis(c)){ - if(flag['Y']) - skipnl(); + skipnl(); strcpy(tok, "||"); return OROR; } case '<': case '>': - lastdol = 0; + lex->lastdol = 0; /* * funny redirection tokens: * redir: arrow | arrow '[' fd ']' @@ -337,18 +359,13 @@ yylex(void) } *w='\0'; yylval.tree = t; - if(t->type==PIPE && flag['Y']) + if(t->type==PIPE) skipnl(); - if(t->type==REDIR) { - skipwhite(); - if(nextc() == '{') - t->type = REDIRW; - } return t->type; case '\'': - lastdol = 0; - lastword = 1; - inquote = 1; + lex->lastdol = 0; + lex->lastword = 1; + lex->inquote = 1; for(;;){ c = advance(); if(c==EOF) @@ -368,29 +385,51 @@ yylex(void) return t->type; } if(!wordchr(c)){ - lastdol = 0; + lex->lastdol = 0; tok[0] = c; tok[1]='\0'; return c; } + glob = 0; for(;;){ - /* next line should have (char)c==GLOB, but ken's compiler is broken */ - if(c=='*' || c=='[' || c=='?' || c==(unsigned char)GLOB) + if(c=='*' || c=='[' || c=='?' || c==GLOB){ + glob = 1; w = addtok(w, GLOB); + } w = addutf(w, c); c = nextc(); - if(lastdol?!idchr(c):!wordchr(c)) break; + if(lex->lastdol?!idchr(c):!wordchr(c)) break; advance(); } - lastword = 1; - lastdol = 0; + lex->lastword = 1; + lex->lastdol = 0; if(w!=0) *w='\0'; t = klook(tok); if(t->type!=WORD) - lastword = 0; + lex->lastword = 0; + else + t->glob = glob; t->quoted = 0; yylval.tree = t; return t->type; } + +void +yyerror(char *m) +{ + pfln(err, lex->file, lex->line); + pstr(err, ": "); + if(lex->tok[0] && lex->tok[0]!='\n') + pfmt(err, "token %q: ", lex->tok); + pfmt(err, "%s\n", m); + flushio(err); + + lex->lastword = 0; + lex->lastdol = 0; + while(lex->lastc!='\n' && lex->lastc!=EOF) advance(); + nerror++; + + setstatus(m); +} diff --git a/src/cmd/rc/mkfile b/src/cmd/rc/mkfile index c1e77aef5e..d6e219b33d 100644 --- a/src/cmd/rc/mkfile +++ b/src/cmd/rc/mkfile @@ -1,7 +1,6 @@ <$PLAN9/src/mkhdr TARG=rc - OFILES=\ code.$O\ exec.$O\ @@ -10,29 +9,39 @@ OFILES=\ here.$O\ io.$O\ lex.$O\ - parse.$O\ pcmd.$O\ pfnc.$O\ simple.$O\ subr.$O\ trap.$O\ tree.$O\ - unixcrap.$O\ var.$O\ - y.tab.$O\ - plan9ish.$O\ havefork.$O\ + unix.$O\ + parse.$O\ + y.tab.$O -HFILES=\ - rc.h\ - x.tab.h\ +HFILES=rc.h\ + y.tab.h\ io.h\ exec.h\ fns.h\ + getflags.h\ YFILES=syn.y +BIN=$PLAN9/bin + +UPDATE=\ + mkfile\ + $HFILES\ + ${OFILES:%.$O=%.c}\ + $YFILES\ + ${TARG:%=/386/bin/%}\ + +CFLAGS=$CFLAGS -DPlan9 + <$PLAN9/src/mkone -x.tab.h: y.tab.h - cmp -s x.tab.h y.tab.h || cp y.tab.h x.tab.h +clean:V: + rm -f [$OS].out *.[$OS] y.tab.? y.debug $TARG diff --git a/src/cmd/rc/pcmd.c b/src/cmd/rc/pcmd.c index cae8473799..0e51c0d4a5 100644 --- a/src/cmd/rc/pcmd.c +++ b/src/cmd/rc/pcmd.c @@ -1,12 +1,12 @@ #include "rc.h" #include "io.h" #include "fns.h" -char nl='\n'; /* change to semicolon for bourne-proofing */ + #define c0 t->child[0] #define c1 t->child[1] #define c2 t->child[2] -void +static void pdeglob(io *f, char *s) { while(*s){ @@ -16,6 +16,14 @@ pdeglob(io *f, char *s) } } +static int ntab = 0; + +static char* +tabs(void) +{ + return "\t\t\t\t\t\t\t\t"+8-(ntab%8); +} + void pcmd(io *f, tree *t) { @@ -32,13 +40,17 @@ pcmd(io *f, tree *t) break; case '^': pfmt(f, "%t^%t", c0, c1); break; - case '`': pfmt(f, "`%t", c0); + case '`': pfmt(f, "`%t%t", c0, c1); break; case ANDAND: pfmt(f, "%t && %t", c0, c1); break; case BANG: pfmt(f, "! %t", c0); break; - case BRACE: pfmt(f, "{%t}", c0); + case BRACE: + ntab++; + pfmt(f, "{\n%s%t", tabs(), c0); + ntab--; + pfmt(f, "\n%s}", tabs()); break; case COUNT: pfmt(f, "$#%t", c0); break; @@ -75,9 +87,14 @@ pcmd(io *f, tree *t) break; case ';': if(c0){ - if(c1) - pfmt(f, "%t%c%t", c0, nl, c1); - else pfmt(f, "%t", c0); + pfmt(f, "%t", c0); + if(c1){ + if(c0->line==c1->line) + pstr(f, "; "); + else + pfmt(f, "\n%s", tabs()); + pfmt(f, "%t", c1); + } } else pfmt(f, "%t", c1); break; @@ -106,8 +123,11 @@ pcmd(io *f, tree *t) break; case PIPEFD: case REDIR: + pchr(f, ' '); switch(t->rtype){ case HERE: + if(c1) + pfmt(f, "%t ", c1); pchr(f, '<'); case READ: case RDWR: @@ -126,7 +146,9 @@ pcmd(io *f, tree *t) break; } pfmt(f, "%t", c0); - if(c1) + if(t->rtype == HERE) + pfmt(f, "\n%s%s\n", t->str, c0->str); + else if(c1) pfmt(f, " %t", c1); break; case '=': @@ -145,121 +167,3 @@ pcmd(io *f, tree *t) break; } } - -void -pcmdu(io *f, tree *t) /* unambiguous */ -{ - if(t==0) { - pfmt(f, ""); - return; - } - - switch(t->type){ - default: pfmt(f, "(bad %d %p %p %p)", t->type, c0, c1, c2); - break; - case '$': pfmt(f, "($ %u)", c0); - break; - case '"': pfmt(f, "($\" %u)", c0); - break; - case '&': pfmt(f, "(& %u)", c0); - break; - case '^': pfmt(f, "(^ %u %u)", c0, c1); - break; - case '`': pfmt(f, "(` %u)", c0); - break; - case ANDAND: pfmt(f, "(&& %u %u)", c0, c1); - break; - case BANG: pfmt(f, "(! %u)", c0); - break; - case BRACE: pfmt(f, "(brace %u)", c0); - break; - case COUNT: pfmt(f, "($# %u)", c0); - break; - case FN: pfmt(f, "(fn %u %u)", c0, c1); - break; - case IF: pfmt(f, "(if %u %u)", c0, c1); - break; - case NOT: pfmt(f, "(if not %u)", c0); - break; - case OROR: pfmt(f, "(|| %u %u)", c0, c1); - break; - case PCMD: - case PAREN: pfmt(f, "(paren %u)", c0); - break; - case SUB: pfmt(f, "($sub %u %u)", c0, c1); - break; - case SIMPLE: pfmt(f, "(simple %u)", c0); - break; - case SUBSHELL: pfmt(f, "(@ %u)", c0); - break; - case SWITCH: pfmt(f, "(switch %u %u)", c0, c1); - break; - case TWIDDLE: pfmt(f, "(~ %u %u)", c0, c1); - break; - case WHILE: pfmt(f, "(while %u %u)", c0, c1); - break; - case ARGLIST: - pfmt(f, "(arglist %u %u)", c0, c1); - break; - case ';': - pfmt(f, "(; %u %u)", c0, c1); - break; - case WORDS: - pfmt(f, "(words %u %u)", c0, c1); - break; - case FOR: - pfmt(f, "(for %u %u %u)", c0, c1, c2); - break; - case WORD: - if(t->quoted) - pfmt(f, "%Q", t->str); - else pdeglob(f, t->str); - break; - case DUP: - if(t->rtype==DUPFD) - pfmt(f, "(>[%d=%d]", t->fd1, t->fd0); /* yes, fd1, then fd0; read lex.c */ - else - pfmt(f, "(>[%d=]", t->fd0); /*)*/ - pfmt(f, " %u)", c1); - break; - case PIPEFD: - case REDIR: - pfmt(f, "("); - switch(t->rtype){ - case HERE: - pchr(f, '<'); - case READ: - case RDWR: - pchr(f, '<'); - if(t->rtype==RDWR) - pchr(f, '>'); - if(t->fd0!=0) - pfmt(f, "[%d]", t->fd0); - break; - case APPEND: - pchr(f, '>'); - case WRITE: - pchr(f, '>'); - if(t->fd0!=1) - pfmt(f, "[%d]", t->fd0); - break; - } - if(t->rtype == HERE) - pfmt(f, "HERE %u)", c1); - else - pfmt(f, "%u %u)", c0, c1); - break; - case '=': - pfmt(f, "(%u=%u %u)", c0, c1, c2); - break; - case PIPE: - pfmt(f, "(|"); - if(t->fd1==0){ - if(t->fd0!=1) - pfmt(f, "[%d]", t->fd0); - } - else pfmt(f, "[%d=%d]", t->fd0, t->fd1); - pfmt(f, " %u %u", c0, c1); - break; - } -} diff --git a/src/cmd/rc/pfnc.c b/src/cmd/rc/pfnc.c index 3f2b4c98a3..ea552c1725 100644 --- a/src/cmd/rc/pfnc.c +++ b/src/cmd/rc/pfnc.c @@ -18,8 +18,11 @@ struct{ Xjump, "Xjump", Xmark, "Xmark", Xpopm, "Xpopm", + Xpush, "Xpush", Xrdwr, "Xrdwr", Xread, "Xread", + Xhere, "Xhere", + Xhereq, "Xhereq", Xreturn, "Xreturn", Xtrue, "Xtrue", Xif, "Xif", @@ -38,34 +41,38 @@ struct{ Xdelfn, "Xdelfn", Xpipe, "Xpipe", Xpipewait, "Xpipewait", + Xpopredir, "Xpopredir", Xrdcmds, "Xrdcmds", - (void (*)(void))Xerror, "Xerror", Xbackq, "Xbackq", Xpipefd, "Xpipefd", Xsubshell, "Xsubshell", - Xdelhere, "Xdelhere", Xfor, "Xfor", Xglob, "Xglob", - Xrdfn, "Xrdfn", Xsimple, "Xsimple", - Xrdfn, "Xrdfn", - Xqdol, "Xqdol", + Xqw, "Xqw", + Xsrcline, "Xsrcline", 0}; void -pfnc(io *fd, thread *t) +pfun(io *f, void (*fn)(void)) { int i; - void (*fn)(void) = t->code[t->pc].f; - list *a; - pfmt(fd, "pid %d cycle %p %d ", getpid(), t->code, t->pc); for(i = 0;fname[i].f;i++) if(fname[i].f==fn){ - pstr(fd, fname[i].name); - break; + pstr(f, fname[i].name); + return; } - if(!fname[i].f) - pfmt(fd, "%p", fn); - for(a = t->argv;a;a = a->next) pfmt(fd, " (%v)", a->words); - pchr(fd, '\n'); - flush(fd); + pfmt(f, "%p", fn); +} + +void +pfnc(io *f, thread *t) +{ + list *a; + + pfln(f, srcfile(t), t->line); + pfmt(f, " pid %d cycle %p %d ", getpid(), t->code, t->pc); + pfun(f, t->code[t->pc].f); + for(a = t->argv;a;a = a->next) pfmt(f, " (%v)", a->words); + pchr(f, '\n'); + flushio(f); } diff --git a/src/cmd/rc/plan9.c b/src/cmd/rc/plan9.c new file mode 100644 index 0000000000..ada169123a --- /dev/null +++ b/src/cmd/rc/plan9.c @@ -0,0 +1,494 @@ +/* + * Plan 9 versions of system-specific functions + * By convention, exported routines herein have names beginning with an + * upper case letter. + */ +#include "rc.h" +#include "exec.h" +#include "io.h" +#include "fns.h" +#include "getflags.h" + +static void execrfork(void); +static void execfinit(void); + +builtin Builtin[] = { + "cd", execcd, + "whatis", execwhatis, + "eval", execeval, + "exec", execexec, /* but with popword first */ + "exit", execexit, + "shift", execshift, + "wait", execwait, + ".", execdot, + "flag", execflag, + "finit", execfinit, + "rfork", execrfork, + 0 +}; + +char Rcmain[]="/rc/lib/rcmain"; +char Fdprefix[]="/fd/"; + +char *Signame[] = { + "sigexit", "sighup", "sigint", "sigquit", + "sigalrm", "sigkill", "sigfpe", "sigterm", + 0 +}; +static char *syssigname[] = { + "exit", /* can't happen */ + "hangup", + "interrupt", + "quit", /* can't happen */ + "alarm", + "kill", + "sys: fp: ", + "term", + 0 +}; + +/* + * finit could be removed but is kept for + * backwards compatibility, see: rcmain.plan9 + */ +static void +execfinit(void) +{ + char *cmds = estrdup("for(i in '/env/fn#'*){. -bq $i}\n"); + int line = runq->line; + poplist(); + execcmds(openiocore(cmds, strlen(cmds)), estrdup(srcfile(runq)), runq->local, runq->redir); + runq->lex->line = line; + runq->lex->qflag = 1; +} + +static void +execrfork(void) +{ + int arg; + char *s; + + switch(count(runq->argv->words)){ + case 1: + arg = RFENVG|RFNAMEG|RFNOTEG; + break; + case 2: + arg = 0; + for(s = runq->argv->words->next->word;*s;s++) switch(*s){ + default: + goto Usage; + case 'n': + arg|=RFNAMEG; break; + case 'N': + arg|=RFCNAMEG; + break; + case 'm': + arg|=RFNOMNT; break; + case 'e': + arg|=RFENVG; break; + case 'E': + arg|=RFCENVG; break; + case 's': + arg|=RFNOTEG; break; + case 'f': + arg|=RFFDG; break; + case 'F': + arg|=RFCFDG; break; + } + break; + default: + Usage: + pfmt(err, "Usage: %s [fnesFNEm]\n", runq->argv->words->word); + setstatus("rfork usage"); + poplist(); + return; + } + if(rfork(arg)==-1){ + pfmt(err, "%s: %s failed\n", argv0, runq->argv->words->word); + setstatus("rfork failed"); + } else { + if(arg & RFCFDG){ + redir *rp; + for(rp = runq->redir; rp; rp = rp->next) + rp->type = 0; + } + setstatus(""); + } + poplist(); +} + +char* +Env(char *name, int fn) +{ + static char buf[128]; + + strcpy(buf, "/env/"); + if(fn) strcat(buf, "fn#"); + return strncat(buf, name, sizeof(buf)-1); +} + +void +Vinit(void) +{ + int dir, fd, i, n; + Dir *ent; + + dir = Open(Env("", 0), 0); + if(dir<0){ + pfmt(err, "%s: can't open: %s\n", argv0, Errstr()); + return; + } + for(;;){ + ent = 0; + n = dirread(dir, &ent); + if(n <= 0) + break; + for(i = 0; i=0){ + io *f = openiofd(fd); + word *w = 0, **wp = &w; + char *s; + while((s = rstr(f, "")) != 0){ + *wp = Newword(s, (word*)0); + wp = &(*wp)->next; + } + closeio(f); + setvar(ent[i].name, w); + vlook(ent[i].name)->changed = 0; + } + } + free(ent); + } + Close(dir); +} + +char* +Errstr(void) +{ + static char err[ERRMAX]; + rerrstr(err, sizeof err); + return err; +} + +int +Waitfor(int pid) +{ + thread *p; + Waitmsg *w; + + if(pid >= 0 && !havewaitpid(pid)) + return 0; + + while((w = wait()) != nil){ + delwaitpid(w->pid); + if(w->pid==pid){ + setstatus(w->msg); + free(w); + return 0; + } + for(p = runq->ret;p;p = p->ret) + if(p->pid==w->pid){ + p->pid=-1; + p->status = estrdup(w->msg); + break; + } + free(w); + } + + if(strcmp(Errstr(), "interrupted")==0) return -1; + return 0; +} + +static void +addenv(var *v) +{ + word *w; + int fd; + io *f; + + if(v->changed){ + v->changed = 0; + if((fd = Creat(Env(v->name, 0)))<0) + pfmt(err, "%s: can't open: %s\n", argv0, Errstr()); + else{ + f = openiofd(fd); + for(w = v->val;w;w = w->next){ + pstr(f, w->word); + pchr(f, '\0'); + } + flushio(f); + closeio(f); + } + } + if(v->fnchanged){ + v->fnchanged = 0; + if((fd = Creat(Env(v->name, 1)))<0) + pfmt(err, "%s: can't open: %s\n", argv0, Errstr()); + else{ + f = openiofd(fd); + if(v->fn) + pfmt(f, "fn %q %s\n", v->name, v->fn[v->pc-1].s); + flushio(f); + closeio(f); + } + } +} + +static void +updenvlocal(var *v) +{ + if(v){ + updenvlocal(v->next); + addenv(v); + } +} + +void +Updenv(void) +{ + var *v, **h; + for(h = gvar;h!=&gvar[NVAR];h++) + for(v=*h;v;v = v->next) + addenv(v); + if(runq) + updenvlocal(runq->local); + if(err) + flushio(err); +} + +void +Exec(char **argv) +{ + exec(argv[0], argv+1); +} + +int +Fork(void) +{ + Updenv(); + return rfork(RFPROC|RFFDG|RFREND); +} + + +typedef struct readdir readdir; +struct readdir { + Dir *dbuf; + int i, n; + int fd; +}; + +void* +Opendir(char *name) +{ + readdir *rd; + int fd; + if((fd = Open(name, 0))<0) + return 0; + rd = new(readdir); + rd->dbuf = 0; + rd->i = 0; + rd->n = 0; + rd->fd = fd; + return rd; +} + +static int +trimdirs(Dir *d, int nd) +{ + int r, w; + + for(r=w=0; ri>=rd->n){ /* read */ + free(rd->dbuf); + rd->dbuf = 0; + n = dirread(rd->fd, &rd->dbuf); + if(n>0){ + if(onlydirs){ + n = trimdirs(rd->dbuf, n); + if(n == 0) + goto Again; + } + rd->n = n; + }else + rd->n = 0; + rd->i = 0; + } + if(rd->i>=rd->n) + return 0; + return rd->dbuf[rd->i++].name; +} + +void +Closedir(void *arg) +{ + readdir *rd = arg; + Close(rd->fd); + free(rd->dbuf); + free(rd); +} + +static int interrupted = 0; + +static void +notifyf(void*, char *s) +{ + int i; + + for(i = 0;syssigname[i];i++) if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){ + if(strncmp(s, "sys: ", 5)!=0) interrupted = 1; + goto Out; + } + noted(NDFLT); + return; +Out: + if(strcmp(s, "interrupt")!=0 || trap[i]==0){ + trap[i]++; + ntrap++; + } + noted(NCONT); +} + +void +Trapinit(void) +{ + notify(notifyf); +} + +long +Write(int fd, void *buf, long cnt) +{ + return write(fd, buf, cnt); +} + +long +Read(int fd, void *buf, long cnt) +{ + return read(fd, buf, cnt); +} + +long +Seek(int fd, long cnt, long whence) +{ + return seek(fd, cnt, whence); +} + +int +Executable(char *file) +{ + Dir *statbuf; + int ret; + + statbuf = dirstat(file); + if(statbuf == nil) + return 0; + ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0); + free(statbuf); + return ret; +} + +int +Open(char *file, int mode) +{ + static int tab[] = {OREAD,OWRITE,ORDWR,OREAD|ORCLOSE}; + return open(file, tab[mode&3]); +} + +void +Close(int fd) +{ + close(fd); +} + +int +Creat(char *file) +{ + return create(file, OWRITE, 0666L); +} + +int +Dup(int a, int b) +{ + return dup(a, b); +} + +int +Dup1(int a) +{ + return dup(a, -1); +} + +void +Exit(void) +{ + Updenv(); + exits(truestatus()?"":getstatus()); +} + +int +Eintr(void) +{ + return interrupted; +} + +void +Noerror(void) +{ + interrupted = 0; +} + +int +Isatty(int fd) +{ + char buf[64]; + + if(fd2path(fd, buf, sizeof buf) != 0) + return 0; + /* might be /mnt/term/dev/cons */ + return strlen(buf) >= 9 && strcmp(buf+strlen(buf)-9, "/dev/cons") == 0; +} + +void +Abort(void) +{ + abort(); +} + +static int newwdir; + +int +Chdir(char *dir) +{ + newwdir = 1; + return chdir(dir); +} + +void +Prompt(char *s) +{ + pstr(err, s); + flushio(err); + + if(newwdir){ + char dir[4096]; + int fd; + if((fd=Creat("/dev/wdir"))>=0){ + getwd(dir, sizeof(dir)); + Write(fd, dir, strlen(dir)); + Close(fd); + } + newwdir = 0; + } +} diff --git a/src/cmd/rc/plan9ish.c b/src/cmd/rc/plan9ish.c deleted file mode 100644 index d52def7d0f..0000000000 --- a/src/cmd/rc/plan9ish.c +++ /dev/null @@ -1,604 +0,0 @@ -/* - * Plan 9 versions of system-specific functions - * By convention, exported routines herein have names beginning with an - * upper case letter. - */ -#include "rc.h" -#include "exec.h" -#include "io.h" -#include "fns.h" -#include "getflags.h" -char *Signame[]={ - "sigexit", "sighup", "sigint", "sigquit", - "sigalrm", "sigkill", "sigfpe", "sigterm", - 0 -}; -char *syssigname[]={ - "exit", /* can't happen */ - "hangup", - "interrupt", - "quit", /* can't happen */ - "alarm", - "kill", - "sys: fp: ", - "term", - 0 -}; -char* -Rcmain(void) -{ - return unsharp("#9/rcmain"); -} - -char Fdprefix[]="/dev/fd/"; -long readnb(int, char *, long); -void execfinit(void); -void execbind(void); -void execmount(void); -void execulimit(void); -void execumask(void); -void execrfork(void); -builtin Builtin[]={ - "cd", execcd, - "whatis", execwhatis, - "eval", execeval, - "exec", execexec, /* but with popword first */ - "exit", execexit, - "shift", execshift, - "wait", execwait, - ".", execdot, - "finit", execfinit, - "flag", execflag, - "ulimit", execulimit, - "umask", execumask, - "rfork", execrfork, - 0 -}; - -void -execrfork(void) -{ - int arg; - char *s; - - switch(count(runq->argv->words)){ - case 1: - arg = RFENVG|RFNOTEG|RFNAMEG; - break; - case 2: - arg = 0; - for(s = runq->argv->words->next->word;*s;s++) switch(*s){ - default: - goto Usage; - case 'n': - arg|=RFNAMEG; break; - case 'N': - arg|=RFCNAMEG; - break; - case 'e': - /* arg|=RFENVG; */ break; - case 'E': - arg|=RFCENVG; break; - case 's': - arg|=RFNOTEG; break; - case 'f': - arg|=RFFDG; break; - case 'F': - arg|=RFCFDG; break; - } - break; - default: - Usage: - pfmt(err, "Usage: %s [nNeEsfF]\n", runq->argv->words->word); - setstatus("rfork usage"); - poplist(); - return; - } - if(rfork(arg)==-1){ - pfmt(err, "rc: %s failed\n", runq->argv->words->word); - setstatus("rfork failed"); - } - else - setstatus(""); - poplist(); -} - - - -#define SEP '\1' -char **environp; -struct word *enval(s) -register char *s; -{ - register char *t, c; - register struct word *v; - for(t=s;*t && *t!=SEP;t++); - c=*t; - *t='\0'; - v=newword(s, c=='\0'?(struct word *)0:enval(t+1)); - *t=c; - return v; -} -void Vinit(void){ - extern char **environ; - register char *s; - register char **env=environ; - environp=env; - for(;*env;env++){ - for(s=*env;*s && *s!='(' && *s!='=';s++); - switch(*s){ - case '\0': - /* pfmt(err, "rc: odd environment %q?\n", *env); */ - break; - case '=': - *s='\0'; - setvar(*env, enval(s+1)); - *s='='; - break; - case '(': /* ignore functions for now */ - break; - } - } -} -char **envp; -void Xrdfn(void){ - char *p; - register char *s; - register int len; - for(;*envp;envp++){ - s = *envp; - if(strncmp(s, "fn#", 3) == 0){ - p = strchr(s, '='); - if(p == nil) - continue; - *p = ' '; - s[2] = ' '; - len = strlen(s); - execcmds(opencore(s, len)); - s[len] = '\0'; - return; - } -#if 0 - for(s=*envp;*s && *s!='(' && *s!='=';s++); - switch(*s){ - case '\0': - pfmt(err, "environment %q?\n", *envp); - break; - case '=': /* ignore variables */ - break; - case '(': /* Bourne again */ - s=*envp+3; - envp++; - len=strlen(s); - s[len]='\n'; - execcmds(opencore(s, len+1)); - s[len]='\0'; - return; - } -#endif - } - Xreturn(); -} -union code rdfns[4]; -void execfinit(void){ - static int first=1; - if(first){ - rdfns[0].i=1; - rdfns[1].f=Xrdfn; - rdfns[2].f=Xjump; - rdfns[3].i=1; - first=0; - } - Xpopm(); - envp=environp; - start(rdfns, 1, runq->local); -} -extern int mapfd(int); -int Waitfor(int pid, int unused0){ - thread *p; - Waitmsg *w; - char errbuf[ERRMAX]; - - if(pid >= 0 && !havewaitpid(pid)) - return 0; - while((w = wait()) != nil){ - delwaitpid(w->pid); - if(w->pid==pid){ - if(strncmp(w->msg, "signal: ", 8) == 0) - fprint(mapfd(2), "%d: %s\n", w->pid, w->msg); - setstatus(w->msg); - free(w); - return 0; - } - if(runq->iflag && strncmp(w->msg, "signal: ", 8) == 0) - fprint(2, "%d: %s\n", w->pid, w->msg); - for(p=runq->ret;p;p=p->ret) - if(p->pid==w->pid){ - p->pid=-1; - strcpy(p->status, w->msg); - } - free(w); - } - - rerrstr(errbuf, sizeof errbuf); - if(strcmp(errbuf, "interrupted")==0) return -1; - return 0; -} -char **mkargv(word *a) -{ - char **argv=(char **)emalloc((count(a)+2)*sizeof(char *)); - char **argp=argv+1; /* leave one at front for runcoms */ - for(;a;a=a->next) *argp++=a->word; - *argp=0; - return argv; -} -/* -void addenv(var *v) -{ - char envname[256]; - word *w; - int f; - io *fd; - if(v->changed){ - v->changed=0; - snprint(envname, sizeof envname, "/env/%s", v->name); - if((f=Creat(envname))<0) - pfmt(err, "rc: can't open %s: %r\n", envname); - else{ - for(w=v->val;w;w=w->next) - write(f, w->word, strlen(w->word)+1L); - close(f); - } - } - if(v->fnchanged){ - v->fnchanged=0; - snprint(envname, sizeof envname, "/env/fn#%s", v->name); - if((f=Creat(envname))<0) - pfmt(err, "rc: can't open %s: %r\n", envname); - else{ - if(v->fn){ - fd=openfd(f); - pfmt(fd, "fn %s %s\n", v->name, v->fn[v->pc-1].s); - closeio(fd); - } - close(f); - } - } -} -void updenvlocal(var *v) -{ - if(v){ - updenvlocal(v->next); - addenv(v); - } -} -void Updenv(void){ - var *v, **h; - for(h=gvar;h!=&gvar[NVAR];h++) - for(v=*h;v;v=v->next) - addenv(v); - if(runq) updenvlocal(runq->local); -} -*/ -int -cmpenv(const void *a, const void *b) -{ - return strcmp(*(char**)a, *(char**)b); -} -char **mkenv(){ - register char **env, **ep, *p, *q; - register struct var **h, *v; - register struct word *a; - register int nvar=0, nchr=0, sep; - /* - * Slightly kludgy loops look at locals then globals - */ - for(h=gvar-1;h!=&gvar[NVAR];h++) for(v=h>=gvar?*h:runq->local;v;v=v->next){ - if((v==vlook(v->name)) && v->val){ - nvar++; - nchr+=strlen(v->name)+1; - for(a=v->val;a;a=a->next) - nchr+=strlen(a->word)+1; - } - if(v->fn){ - nvar++; - nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8; - } - } - env=(char **)emalloc((nvar+1)*sizeof(char *)+nchr); - ep=env; - p=(char *)&env[nvar+1]; - for(h=gvar-1;h!=&gvar[NVAR];h++) for(v=h>=gvar?*h:runq->local;v;v=v->next){ - if((v==vlook(v->name)) && v->val){ - *ep++=p; - q=v->name; - while(*q) *p++=*q++; - sep='='; - for(a=v->val;a;a=a->next){ - *p++=sep; - sep=SEP; - q=a->word; - while(*q) *p++=*q++; - } - *p++='\0'; - } - if(v->fn){ - *ep++=p; -#if 0 - *p++='#'; *p++='('; *p++=')'; /* to fool Bourne */ - *p++='f'; *p++='n'; *p++=' '; - q=v->name; - while(*q) *p++=*q++; - *p++=' '; -#endif - *p++='f'; *p++='n'; *p++='#'; - q=v->name; - while(*q) *p++=*q++; - *p++='='; - q=v->fn[v->pc-1].s; - while(*q) *p++=*q++; - *p++='\n'; - *p++='\0'; - } - } - *ep=0; - qsort((char *)env, nvar, sizeof ep[0], cmpenv); - return env; -} -void Updenv(void){} -void Execute(word *args, word *path) -{ - char **argv=mkargv(args); - char **env=mkenv(); - char file[1024]; - int nc; - Updenv(); - for(;path;path=path->next){ - nc=strlen(path->word); - if(nc<1024){ - strcpy(file, path->word); - if(file[0]){ - strcat(file, "/"); - nc++; - } - if(nc+strlen(argv[1])<1024){ - strcat(file, argv[1]); - execve(file, argv+1, env); - } - else werrstr("command name too long"); - } - } - rerrstr(file, sizeof file); - pfmt(err, "%s: %s\n", argv[1], file); - efree((char *)argv); -} -#define NDIR 256 /* shoud be a better way */ -int Globsize(char *p) -{ - ulong isglob=0, globlen=NDIR+1; - for(;*p;p++){ - if(*p==GLOB){ - p++; - if(*p!=GLOB) isglob++; - globlen+=*p=='*'?NDIR:1; - } - else - globlen++; - } - return isglob?globlen:0; -} -#define NFD 50 -#define NDBUF 32 -struct{ - Dir *dbuf; - int i; - int n; -}dir[NFD]; -int Opendir(char *name) -{ - Dir *db; - int f; - f=open(name, 0); - if(f==-1) - return f; - db = dirfstat(f); - if(db!=nil && (db->mode&DMDIR)){ - if(f=NFD) - return 0; - if(dir[f].i==dir[f].n){ /* read */ - free(dir[f].dbuf); - dir[f].dbuf=0; - n=dirread(f, &dir[f].dbuf); - if(n>=0) - dir[f].n=n; - else - dir[f].n=0; - dir[f].i=0; - } - if(dir[f].i==dir[f].n) - return 0; - strcpy(p, dir[f].dbuf[dir[f].i].name); - dir[f].i++; - return 1; -} -void Closedir(int f){ - if(f>=0 && f=32){ /* rc is probably in a trap loop */ - pfmt(err, "rc: Too many traps (trap %s), aborting\n", s); - abort(); - } - noted(NCONT); -} -void Trapinit(void){ - notify(notifyf); -} -void Unlink(char *name) -{ - remove(name); -} -long Write(int fd, char *buf, long cnt) -{ - return write(fd, buf, (long)cnt); -} -long Read(int fd, char *buf, long cnt) -{ - int i; - - i = readnb(fd, buf, cnt); - if(ntrap) dotrap(); - return i; -} -long Seek(int fd, long cnt, long whence) -{ - return seek(fd, cnt, whence); -} -int Executable(char *file) -{ - Dir *statbuf; - int ret; - - statbuf = dirstat(file); - if(statbuf == nil) return 0; - ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0); - free(statbuf); - return ret; -} -int Creat(char *file) -{ - return create(file, 1, 0666L); -} -int Dup(int a, int b){ - return dup(a, b); -} -int Dup1(int a){ - return dup(a, -1); -} -void Exit(char *stat) -{ - Updenv(); - setstatus(stat); - exits(truestatus()?"":getstatus()); -} -int Eintr(void){ - return interrupted; -} -void Noerror(void){ - interrupted=0; -} -int -Isatty(int fd){ - return isatty(fd); -} -void Abort(void){ - pfmt(err, "aborting\n"); - flush(err); - Exit("aborting"); -} -void Memcpy(char *a, char *b, long n) -{ - memmove(a, b, (long)n); -} -void *Malloc(ulong n){ - return malloc(n); -} - -int -exitcode(char *msg) -{ - int n; - - n = atoi(msg); - if(n == 0) - n = 1; - return n; -} - -int *waitpids; -int nwaitpids; - -void -addwaitpid(int pid) -{ - waitpids = realloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]); - if(waitpids == 0) - panic("Can't realloc %d waitpids", nwaitpids+1); - waitpids[nwaitpids++] = pid; -} - -void -delwaitpid(int pid) -{ - int r, w; - - for(r=w=0; r #include -#undef NSIG -#undef SIGINT -#undef SIGQUIT -#define NSIG 32 +#define NSIG 32 #define SIGINT 2 #define SIGQUIT 3 -#endif -#ifdef V9 +#else +#include +#include +#include +#include #include -#include +#ifndef NSIG +#define NSIG 32 #endif -#ifdef Sun -#include #endif + +#include + #define YYMAXDEPTH 500 #ifndef PAREN -#ifndef YYMAJOR -#include "x.tab.h" -#endif +#include "y.tab.h" #endif - -#undef pipe /* so that /dev/fd works */ -#define searchpath rcsearchpath /* avoid new libc function */ - -/* some systems define a global "var", "thread" */ -#undef var -#define var rcvar -#undef thread -#define thread rcthread - typedef struct tree tree; typedef struct word word; typedef struct io io; typedef union code code; typedef struct var var; typedef struct list list; +typedef struct lexer lexer; typedef struct redir redir; typedef struct thread thread; typedef struct builtin builtin; +#undef pipe /* so that /dev/fd works */ + +#pragma incomplete word +#pragma incomplete io + struct tree{ - int type; - int rtype, fd0, fd1; /* details of REDIR PIPE DUP tokens */ - char *str; - int quoted; - int iskw; - tree *child[3]; - tree *next; + int type; + int rtype, fd0, fd1; /* details of REDIR PIPE DUP tokens */ + int line; + char glob; /* 0=string, 1=glob, 2=pattern see globprop() and noglobs() */ + char quoted; + char iskw; + char *str; + tree *child[3]; + tree *next; }; tree *newtree(void); tree *token(char*, int), *klook(char*), *tree1(int, tree*); tree *tree2(int, tree*, tree*), *tree3(int, tree*, tree*, tree*); tree *mung1(tree*, tree*), *mung2(tree*, tree*, tree*); tree *mung3(tree*, tree*, tree*, tree*), *epimung(tree*, tree*); -tree *simplemung(tree*), *heredoc(tree*); -void freetree(tree*); -tree *cmdtree; +tree *simplemung(tree*); +tree *globprop(tree*); +char *fnstr(tree*); + /* - * The first word of any code vector is a reference count. + * The first word of any code vector is a reference count + * and the second word is a string for srcfile(). + * Code starts at pc 2. The last code word must be a zero + * terminator for codefree(). * Always create a new reference to a code vector by calling codecopy(.). * Always call codefree(.) when deleting a reference. */ union code{ - void (*f)(void); - int i; - char *s; + void (*f)(void); + int i; + char *s; }; -char *promptstr; + #define NTOK 8192 -char tok[NTOK]; + +struct lexer{ + io *input; + char *file; + int line; + + char *prolog; + char *epilog; + + int peekc; + int future; + int lastc; + + char eof; + char inquote; + char incomm; + char lastword; /* was the last token read a word or compound word terminator? */ + char lastdol; /* was the last token read '$' or '$#' or '"'? */ + char iflast; /* static `if not' checking */ + + char qflag; + + char tok[NTOK]; +}; +extern lexer *lex; /* current lexer */ +lexer *newlexer(io*, char*); +void freelexer(lexer*); + #define APPEND 1 #define WRITE 2 #define READ 3 #define HERE 4 #define DUPFD 5 #define CLOSE 6 -#define RDWR 7 +#define RDWR 7 + struct var{ - char *name; /* ascii name */ - word *val; /* value */ - int changed; - code *fn; /* pointer to function's code vector */ - int fnchanged; - int pc; /* pc of start of function */ - var *next; /* next on hash or local list */ - void (*changefn)(var*); + var *next; /* next on hash or local list */ + word *val; /* value */ + code *fn; /* pointer to function's code vector */ + int pc; /* pc of start of function */ + char fnchanged; + char changed; + char name[]; }; var *vlook(char*), *gvlook(char*), *newvar(char*, var*); +void setvar(char*, word*), freevar(var*); + #define NVAR 521 -var *gvar[NVAR]; /* hash for globals */ +extern var *gvar[NVAR]; /* hash for globals */ + #define new(type) ((type *)emalloc(sizeof(type))) -char *emalloc(long); -void *Malloc(ulong); -void efree(char*); -#define NOFILE 128 /* should come from */ -struct here{ - tree *tag; - char *name; - struct here *next; -}; -int mypid; + +void *emalloc(long); +void *erealloc(void *, long); +char *estrdup(char*); + /* * Glob character escape in strings: * In a string, GLOB must be followed by *?[ or GLOB. @@ -120,18 +145,19 @@ int mypid; */ #define GLOB ((char)0x01) /* - * onebyte(c), twobyte(c), threebyte(c) - * Is c the first character of a one- two- or three-byte utf sequence? + * Is c the first character of a utf sequence? */ -#define onebyte(c) ((c&0x80)==0x00) -#define twobyte(c) ((c&0xe0)==0xc0) -#define threebyte(c) ((c&0xf0)==0xe0) -#define fourbyte(c) ((c&0xf8)==0xf0) - -char **argp; -char **args; -int nerror; /* number of errors encountered during compilation */ +#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 xbyte(c) (((c)&0xc0)==0x80) + +extern char *argv0; +extern int nerror; /* number of errors encountered during compilation */ extern int doprompt; /* is it time for a prompt? */ +extern io *err; + /* * Which fds are the reading/writing end of a pipe? * Unfortunately, this can vary from system to system. @@ -140,14 +166,5 @@ extern int doprompt; /* is it time for a prompt? */ */ #define PRD 0 #define PWR 1 -extern char *Rcmain(), Fdprefix[]; -#define register -/* - * How many dot commands have we executed? - * Used to ensure that -v flag doesn't print rcmain. - */ -int ndot; -char *getstatus(void); -int lastc; -int lastword; -int kidpid; +extern char Rcmain[PATH_MAX], Fdprefix[]; +extern char *Signame[]; diff --git a/src/cmd/rc/rcmain.plan9 b/src/cmd/rc/rcmain.plan9 new file mode 100644 index 0000000000..f511e96b76 --- /dev/null +++ b/src/cmd/rc/rcmain.plan9 @@ -0,0 +1,41 @@ +# rcmain: Plan 9 version +if(~ $#home 0) home=/ +if(~ $#ifs 0) ifs=' +' +switch($#prompt){ +case 0 + prompt=('% ' ' ') +case 1 + prompt=($prompt ' ') +} +if(~ $rcname ?.out) prompt=('broken! ' ' ') +if(flag p) path=/bin +if not{ + for(i in '/env/fn#'*){ + . -bq $i + } + if(~ $#path 0) path=(/bin .) +} +fn sigexit +if(! ~ $#cflag 0){ + if(flag l){ + . -q /rc/lib/rcmain.local + . -q $home/lib/profile + } + status='' + eval $cflag +} +if not if(flag i){ + if(flag l){ + . -q /rc/lib/rcmain.local + . -q $home/lib/profile + } + status='' + if(! ~ $#* 0) . $* + . -i '#d/0' +} +if not if(~ $#* 0) . '#d/0' +if not{ + status='' + . $* +} diff --git a/src/cmd/rc/rcmain.unix b/src/cmd/rc/rcmain.unix new file mode 100644 index 0000000000..7ccbe1b90d --- /dev/null +++ b/src/cmd/rc/rcmain.unix @@ -0,0 +1,38 @@ +# rcmain: unix version +if(~ $#home 0) home=$HOME +if(~ $#ifs 0) ifs=' +' +profile=$home/.rcrc +switch($#prompt){ +case 0 + prompt=('% ' ' ') +case 1 + prompt=($prompt ' ') +} +if(~ $rcname ?.out) prompt=('broken! ' ' ') +if(flag p) path=/bin +if not { + finit + if(~ $#path 0) path=(. /bin /usr/bin /usr/local/bin) +} +fn sigexit +if(! ~ $#cflag 0){ + if(flag l) { + . -q $profile + } + status='' + eval $cflag +} +if not if(flag i){ + if(flag l) { + . -q $profile + } + status='' + if(! ~ $#* 0) . $* + . -i /dev/fd/0 +} +if not if(~ $#* 0) . /dev/fd/0 +if not{ + status='' + . $* +} diff --git a/src/cmd/rc/simple.c b/src/cmd/rc/simple.c index a7d78f6fcf..5c7f263cdf 100644 --- a/src/cmd/rc/simple.c +++ b/src/cmd/rc/simple.c @@ -6,75 +6,107 @@ #include "exec.h" #include "io.h" #include "fns.h" + /* * Search through the following code to see if we're just going to exit. */ int exitnext(void){ - union code *c=&runq->code[runq->pc]; - while(c->f==Xpopredir) c++; + int i=ifnot; + thread *p=runq; + code *c; +loop: + c=&p->code[p->pc]; + while(1){ + if(c->f==Xpopredir || c->f==Xunlocal) + c++; + else if(c->f==Xsrcline) + c += 2; + else if(c->f==Xwastrue){ + c++; + i=0; + } + else if(c->f==Xifnot){ + if(i) + c += 2; + else + c = &p->code[c[1].i]; + } + else if(c->f==Xreturn){ + p = p->ret; + if(p==0) + return 1; + goto loop; + }else + break; + } return c->f==Xexit; } +void (*builtinfunc(char *name))(void) +{ + extern builtin Builtin[]; + builtin *bp; + + for(bp = Builtin;bp->name;bp++) + if(strcmp(name, bp->name)==0) + return bp->fnc; + return 0; +} + void Xsimple(void) { + void (*f)(void); word *a; - thread *p = runq; var *v; - struct builtin *bp; int pid; - globlist(); + a = runq->argv->words; if(a==0){ Xerror1("empty argument list"); return; } if(flag['x']) - pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */ + pfmt(err, "%v\n", a); /* wrong, should do redirs */ v = gvlook(a->word); if(v->fn) execfunc(v); else{ if(strcmp(a->word, "builtin")==0){ - if(count(a)==1){ - pfmt(err, "builtin: empty argument list\n"); - setstatus("empty arg list"); - poplist(); - return; - } a = a->next; - popword(); - } - for(bp = Builtin;bp->name;bp++) - if(strcmp(a->word, bp->name)==0){ - (*bp->fnc)(); + if(a==0){ + Xerror1("builtin: empty argument list"); return; } + popword(); /* "builtin" */ + } + f = builtinfunc(a->word); + if(f){ + (*f)(); + return; + } if(exitnext()){ /* fork and wait is redundant */ pushword("exec"); execexec(); - Xexit(); + /* does not return */ } else{ - flush(err); - Updenv(); /* necessary so changes don't go out again */ if((pid = execforkexec()) < 0){ - Xerror("try again"); + Xerror2("try again", Errstr()); return; } + poplist(); /* interrupts don't get us out */ - poplist(); - while(Waitfor(pid, 1) < 0) + while(Waitfor(pid) < 0) ; } } } -struct word nullpath = { "", 0}; -void +static void doredir(redir *rp) { if(rp){ @@ -83,72 +115,89 @@ doredir(redir *rp) case ROPEN: if(rp->from!=rp->to){ Dup(rp->from, rp->to); - close(rp->from); + Close(rp->from); } break; case RDUP: Dup(rp->from, rp->to); break; case RCLOSE: - close(rp->from); + Close(rp->from); break; } } } word* -searchpath(char *w) +_searchpath(char *w, char *v) { + static struct word nullpath = { "", 0 }; word *path; - if(strncmp(w, "/", 1)==0 -/* || strncmp(w, "#", 1)==0 */ - || strncmp(w, "./", 2)==0 - || strncmp(w, "../", 3)==0 - || (path = vlook("path")->val)==0) - path=&nullpath; + + if(w[0] && w[0] != '/' && w[0] != '#' && + (w[0] != '.' || (w[1] && w[1] != '/' && (w[1] != '.' || w[2] && w[2] != '/')))){ + path = vlook(v)->val; + if(path) + return path; + } + return &nullpath; +} + +char* +makepath(char *dir, char *file) +{ + char *path; + int m, n = strlen(dir); + if(n==0) return estrdup(file); + while (n > 0 && dir[n-1]=='/') n--; + while (file[0]=='/') file++; + m = strlen(file); + path = emalloc(n + m + 2); + if(n>0) memmove(path, dir, n); + path[n++]='/'; + memmove(path+n, file, m+1); return path; } +static char** +mkargv(word *a) +{ + char **argv = (char **)emalloc((count(a)+2)*sizeof(char *)); + char **argp = argv+1; + for(;a;a = a->next) *argp++=a->word; + *argp = 0; + return argv; +} + void execexec(void) { + char **argv; + word *path; + popword(); /* "exec" */ if(runq->argv->words==0){ - Xerror1("empty argument list"); + Xerror1("exec: empty argument list"); return; } + argv = mkargv(runq->argv->words); + Updenv(); doredir(runq->redir); - Execute(runq->argv->words, searchpath(runq->argv->words->word)); - poplist(); + for(path = _searchpath(argv[1], "path"); path; path = path->next){ + argv[0] = makepath(path->word, argv[1]); + Exec(argv); + } + setstatus(Errstr()); + pfln(err, srcfile(runq), runq->line); + pfmt(err, ": %s: %s\n", argv[1], getstatus()); + Xexit(); } void execfunc(var *func) { - word *starval; - popword(); - starval = runq->argv->words; - runq->argv->words = 0; - poplist(); - start(func->fn, func->pc, runq->local); - runq->local = newvar(strdup("*"), runq->local); - runq->local->val = starval; - runq->local->changed = 1; -} - -int -dochdir(char *word) -{ - /* report to /dev/wdir if it exists and we're interactive */ - static int wdirfd = -2; - if(chdir(word)<0) return -1; - if(flag['i']!=0){ - if(wdirfd==-2) /* try only once */ - wdirfd = open("/dev/wdir", OWRITE|OCEXEC); - if(wdirfd>=0) - write(wdirfd, word, strlen(word)); - } - return 1; + popword(); /* name */ + startfunc(func, Poplist(), runq->local, runq->redir); } void @@ -156,39 +205,36 @@ execcd(void) { word *a = runq->argv->words; word *cdpath; - char dir[512]; + char *dir; + setstatus("can't cd"); - cdpath = vlook("cdpath")->val; switch(count(a)){ default: pfmt(err, "Usage: cd [directory]\n"); break; case 2: - if(a->next->word[0]=='/' || cdpath==0) - cdpath=&nullpath; - for(;cdpath;cdpath = cdpath->next){ - strcpy(dir, cdpath->word); - if(dir[0]) - strcat(dir, "/"); - strcat(dir, a->next->word); - if(dochdir(dir)>=0){ - if(strlen(cdpath->word) - && strcmp(cdpath->word, ".")!=0) + a = a->next; + for(cdpath = _searchpath(a->word, "cdpath"); cdpath; cdpath = cdpath->next){ + dir = makepath(cdpath->word, a->word); + if(Chdir(dir)>=0){ + if(cdpath->word[0] != '\0' && strcmp(cdpath->word, ".") != 0) pfmt(err, "%s\n", dir); + free(dir); setstatus(""); break; } + free(dir); } if(cdpath==0) - pfmt(err, "Can't cd %s: %r\n", a->next->word); + pfmt(err, "Can't cd %s: %s\n", a->word, Errstr()); break; case 1: a = vlook("home")->val; - if(count(a)>=1){ - if(dochdir(a->word)>=0) + if(a){ + if(Chdir(a->word)>=0) setstatus(""); else - pfmt(err, "Can't cd %s: %r\n", a->word); + pfmt(err, "Can't cd %s: %s\n", a->word, Errstr()); } else pfmt(err, "Can't cd -- $home empty\n"); @@ -229,10 +275,9 @@ execshift(void) break; } star = vlook("*"); - for(;n && star->val;--n){ + for(;n>0 && star->val;--n){ a = star->val->next; - efree(star->val->word); - efree((char *)star->val); + free(Freeword(star->val)); star->val = a; star->changed = 1; } @@ -240,15 +285,6 @@ execshift(void) poplist(); } -int -octal(char *s) -{ - int n = 0; - while(*s==' ' || *s=='\t' || *s=='\n') s++; - while('0'<=*s && *s<='7') n = n*8+*s++-'0'; - return n; -} - int mapfd(int fd) { @@ -268,128 +304,131 @@ mapfd(int fd) } return fd; } -union code rdcmds[4]; void -execcmds(io *f) +execcmds(io *input, char *file, var *local, redir *redir) { - static int first = 1; - if(first){ + static union code rdcmds[5]; + + if(rdcmds[0].i==0){ rdcmds[0].i = 1; - rdcmds[1].f = Xrdcmds; - rdcmds[2].f = Xreturn; - first = 0; + rdcmds[1].s="*rdcmds*"; + rdcmds[2].f = Xrdcmds; + rdcmds[3].f = Xreturn; + rdcmds[4].f = 0; } - start(rdcmds, 1, runq->local); - runq->cmdfd = f; - runq->iflast = 0; + + if(exitnext()) turfstack(local); + + start(rdcmds, 2, local, redir); + runq->lex = newlexer(input, file); } void execeval(void) { - char *cmdline, *s, *t; - int len = 0; - word *ap; - if(count(runq->argv->words)<=1){ + char *cmds; + int len; + io *f; + + popword(); /* "eval" */ + + if(runq->argv->words==0){ Xerror1("Usage: eval cmd ..."); return; } - eflagok = 1; - for(ap = runq->argv->words->next;ap;ap = ap->next) - len+=1+strlen(ap->word); - cmdline = emalloc(len); - s = cmdline; - for(ap = runq->argv->words->next;ap;ap = ap->next){ - for(t = ap->word;*t;) *s++=*t++; - *s++=' '; - } - s[-1]='\n'; + Xqw(); /* make into single word */ + cmds = Popword(); + len = strlen(cmds); + cmds[len++] = '\n'; poplist(); - execcmds(opencore(cmdline, len)); - efree(cmdline); + + f = openiostr(); + pfln(f, srcfile(runq), runq->line); + pstr(f, " *eval*"); + + execcmds(openiocore(cmds, len), closeiostr(f), runq->local, runq->redir); } -union code dotcmds[14]; void execdot(void) { - int iflag = 0; - int fd; - list *av; - thread *p = runq; - char *zero; - static int first = 1; - char file[512]; - word *path; + int fd, bflag, iflag, qflag; + word *path, *argv; + char *file; - if(first){ - dotcmds[0].i = 1; - dotcmds[1].f = Xmark; - dotcmds[2].f = Xword; - dotcmds[3].s="0"; - dotcmds[4].f = Xlocal; - dotcmds[5].f = Xmark; - dotcmds[6].f = Xword; - dotcmds[7].s="*"; - dotcmds[8].f = Xlocal; - dotcmds[9].f = Xrdcmds; - dotcmds[10].f = Xunlocal; - dotcmds[11].f = Xunlocal; - dotcmds[12].f = Xreturn; - first = 0; - } - else - eflagok = 1; - popword(); - if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){ - iflag = 1; + popword(); /* "." */ + + bflag = iflag = qflag = 0; + while(runq->argv->words && runq->argv->words->word[0]=='-'){ + char *f = runq->argv->words->word+1; + if(*f == '-'){ + popword(); + break; + } + for(; *f; f++){ + switch(*f){ + case 'b': + bflag = 1; + continue; + case 'i': + iflag = 1; + continue; + case 'q': + qflag = 1; + continue; + } + goto Usage; + } popword(); } + /* get input file */ - if(p->argv->words==0){ - Xerror1("Usage: . [-i] file [arg ...]"); + if(runq->argv->words==0){ +Usage: + Xerror1("Usage: . [-biq] file [arg ...]"); return; } - zero = strdup(p->argv->words->word); - popword(); - fd=-1; - for(path = searchpath(zero);path;path = path->next){ - strcpy(file, path->word); - if(file[0]) - strcat(file, "/"); - strcat(file, zero); - if((fd = open(file, 0))>=0) break; + argv = Poplist(); + + file = 0; + fd = -1; + for(path = _searchpath(argv->word, "path"); path; path = path->next){ + file = makepath(path->word, argv->word); + fd = Open(file, 0); + if(fd >= 0) + break; if(strcmp(file, "/dev/stdin")==0){ /* for sun & ucb */ fd = Dup1(0); if(fd>=0) break; } + free(file); } if(fd<0){ - pfmt(err, "%s: ", zero); - setstatus("can't open"); - Xerror(".: can't open"); + if(!qflag) + Xerror3(". can't open", argv->word, Errstr()); + freewords(argv); return; } - /* set up for a new command loop */ - start(dotcmds, 1, (struct var *)0); + + execcmds(openiofd(fd), file, (var*)0, runq->redir); pushredir(RCLOSE, fd, 0); - runq->cmdfile = zero; - runq->cmdfd = openfd(fd); + runq->lex->qflag = qflag; runq->iflag = iflag; - runq->iflast = 0; - /* push $* value */ - pushlist(); - runq->argv->words = p->argv->words; - /* free caller's copy of $* */ - av = p->argv; - p->argv = av->next; - efree((char *)av); - /* push $0 value */ - pushlist(); - pushword(zero); - ndot++; + if(iflag || !bflag && flag['b']==0){ + runq->lex->peekc=EOF; + runq->lex->epilog=""; + } + + runq->local = newvar("*", runq->local); + runq->local->val = argv->next; + argv->next=0; + runq->local->changed = 1; + + runq->local = newvar("0", runq->local); + runq->local->val = argv; + runq->local->changed = 1; } void @@ -398,18 +437,18 @@ execflag(void) char *letter, *val; switch(count(runq->argv->words)){ case 2: - setstatus(flag[(uchar)runq->argv->words->next->word[0]]?"":"flag not set"); + setstatus(flag[(unsigned char)runq->argv->words->next->word[0]]?"":"flag not set"); break; case 3: letter = runq->argv->words->next->word; val = runq->argv->words->next->next->word; if(strlen(letter)==1){ if(strcmp(val, "+")==0){ - flag[(uchar)letter[0]] = flagset; + flag[(unsigned char)letter[0]] = flagset; break; } if(strcmp(val, "-")==0){ - flag[(uchar)letter[0]] = 0; + flag[(unsigned char)letter[0]] = 0; break; } } @@ -424,9 +463,8 @@ void execwhatis(void){ /* mildly wrong -- should fork before writing */ word *a, *b, *path; var *v; - struct builtin *bp; - char file[512]; - struct io out[1]; + char *file; + io *out; int found, sep; a = runq->argv->words->next; if(a==0){ @@ -434,10 +472,7 @@ execwhatis(void){ /* mildly wrong -- should fork before writing */ return; } setstatus(""); - out->fd = mapfd(1); - out->bufp = out->buf; - out->ebuf = &out->buf[NBUF]; - out->strp = 0; + out = openiofd(mapfd(1)); for(;a;a = a->next){ v = vlook(a->word); if(v->val){ @@ -450,7 +485,7 @@ execwhatis(void){ /* mildly wrong -- should fork before writing */ pfmt(out, "%c%q", sep, b->word); sep=' '; } - pfmt(out, ")\n"); + pstr(out, ")\n"); } found = 1; } @@ -458,23 +493,19 @@ execwhatis(void){ /* mildly wrong -- should fork before writing */ found = 0; v = gvlook(a->word); if(v->fn) - pfmt(out, "fn %s %s\n", v->name, v->fn[v->pc-1].s); + pfmt(out, "fn %q %s\n", v->name, v->fn[v->pc-1].s); else{ - for(bp = Builtin;bp->name;bp++) - if(strcmp(a->word, bp->name)==0){ - pfmt(out, "builtin %s\n", a->word); - break; - } - if(!bp->name){ - for(path = searchpath(a->word);path;path = path->next){ - strcpy(file, path->word); - if(file[0]) - strcat(file, "/"); - strcat(file, a->word); + if(builtinfunc(a->word)) + pfmt(out, "builtin %s\n", a->word); + else { + for(path = _searchpath(a->word, "path"); path; path = path->next){ + file = makepath(path->word, a->word); if(Executable(file)){ pfmt(out, "%s\n", file); + free(file); break; } + free(file); } if(!path && !found){ pfmt(err, "%s: not found\n", a->word); @@ -482,9 +513,10 @@ execwhatis(void){ /* mildly wrong -- should fork before writing */ } } } + flushio(out); } poplist(); - flush(err); + free(closeiostr(out)); /* don't close fd */ } void @@ -495,10 +527,10 @@ execwait(void) Xerror1("Usage: wait [pid]"); return; case 2: - Waitfor(atoi(runq->argv->words->next->word), 0); + Waitfor(atoi(runq->argv->words->next->word)); break; case 1: - Waitfor(-1, 0); + Waitfor(-1); break; } poplist(); diff --git a/src/cmd/rc/subr.c b/src/cmd/rc/subr.c index 47f7439e64..c6bc64cbc4 100644 --- a/src/cmd/rc/subr.c +++ b/src/cmd/rc/subr.c @@ -1,50 +1,46 @@ #include "rc.h" -#include "exec.h" #include "io.h" #include "fns.h" -char* +void * emalloc(long n) { - char *p = (char *)Malloc(n); + void *p = malloc(n); if(p==0) panic("Can't malloc %d bytes", n); -/* if(err){ pfmt(err, "malloc %d->%p\n", n, p); flush(err); } /**/ - memset(p, 0, n); return p; } -void -efree(char *p) +void* +erealloc(void *p, long n) { -/* pfmt(err, "free %p\n", p); flush(err); /**/ - if(p) - free(p); - else pfmt(err, "free 0\n"); + p = realloc(p, n); + if(p==0 && n!=0) + panic("Can't realloc %d bytes\n", n); + return p; +} + +char* +estrdup(char *s) +{ + int n = strlen(s)+1; + char *d = emalloc(n); + memmove(d, s, n); + return d; } -extern int lastword, lastdol; void -yyerror(char *m) +pfln(io *fd, char *file, int line) { - pfmt(err, "rc: "); - if(runq->cmdfile && !runq->iflag) - pfmt(err, "%s:%d: ", runq->cmdfile, runq->lineno); - else if(runq->cmdfile) - pfmt(err, "%s: ", runq->cmdfile); - else if(!runq->iflag) - pfmt(err, "line %d: ", runq->lineno); - if(tok[0] && tok[0]!='\n') - pfmt(err, "token %q: ", tok); - pfmt(err, "%s\n", m); - flush(err); - lastword = 0; - lastdol = 0; - while(lastc!='\n' && lastc!=EOF) advance(); - nerror++; - setvar("status", newword(m, (word *)0)); + if(file && line) + pfmt(fd, "%s:%d", file, line); + else if(file) + pstr(fd, file); + else + pstr(fd, argv0); } -char *bp; + +static char *bp; static void iacvt(int n) @@ -59,7 +55,7 @@ iacvt(int n) } void -inttoascii(char *s, long n) +inttoascii(char *s, int n) { bp = s; iacvt(n); @@ -69,9 +65,10 @@ inttoascii(char *s, long n) void panic(char *s, int n) { - pfmt(err, "rc: "); + pfmt(err, "%s: ", argv0); pfmt(err, s, n); pchr(err, '\n'); - flush(err); + flushio(err); + Abort(); } diff --git a/src/cmd/rc/syn.y b/src/cmd/rc/syn.y index 5c98ef80c8..711e0ea737 100644 --- a/src/cmd/rc/syn.y +++ b/src/cmd/rc/syn.y @@ -75,7 +75,7 @@ simple: first | simple redir {$$=tree2(ARGLIST, $1, $2);} first: comword | first '^' word {$$=tree2('^', $1, $3);} -word: keyword {lastword=1; $1->type=WORD;} +word: keyword {lex->lastword=1; $1->type=WORD;} | comword | word '^' word {$$=tree2('^', $1, $3);} comword: '$' word {$$=tree1('$', $2);} diff --git a/src/cmd/rc/tags b/src/cmd/rc/tags new file mode 100644 index 0000000000..3685fc6351 --- /dev/null +++ b/src/cmd/rc/tags @@ -0,0 +1,795 @@ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/;" extras:pseudo +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/;" extras:pseudo +!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/;" extras:pseudo +!_TAG_OUTPUT_FILESEP slash /slash or backslash/;" extras:pseudo +!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/;" extras:pseudo +!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/;" extras:pseudo +!_TAG_PROC_CWD /home/grobe0ba/opt/x86_64/plan9port/src/cmd/rc/ //;" extras:pseudo +!_TAG_PROGRAM_AUTHOR Universal Ctags Team //;" extras:pseudo +!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/;" extras:pseudo +!_TAG_PROGRAM_URL https://ctags.io/ /official site/;" extras:pseudo +!_TAG_PROGRAM_VERSION 5.9.0 /p5.9.20220417.0/;" extras:pseudo +ANDAND y.tab.c /^#define ANDAND /;" kind:macro line:24 language:C file: roles:def extras:fileScope end:24 +ANDAND y.tab.h /^#define ANDAND /;" kind:macro line:24 language:C++ roles:def end:24 +APPEND rc.h /^#define APPEND /;" kind:macro line:109 language:C++ roles:def end:109 +ARGLIST y.tab.c /^#define ARGLIST /;" kind:macro line:18 language:C file: roles:def extras:fileScope end:18 +ARGLIST y.tab.h /^#define ARGLIST /;" kind:macro line:18 language:C++ roles:def end:18 +Abort plan9.c /^Abort(void)$/;" kind:function line:464 language:C typeref:typename:void signature:(void) roles:def end:467 +Abort unix.c /^Abort(void)$/;" kind:function line:408 language:C typeref:typename:void signature:(void) roles:def end:411 +BADFLAG getflags.c /^#define BADFLAG /;" kind:macro line:17 language:C file: roles:def extras:fileScope end:17 +BANG y.tab.c /^#define BANG /;" kind:macro line:7 language:C file: roles:def extras:fileScope end:7 +BANG y.tab.h /^#define BANG /;" kind:macro line:7 language:C++ roles:def end:7 +BRACE y.tab.c /^#define BRACE /;" kind:macro line:20 language:C file: roles:def extras:fileScope end:20 +BRACE y.tab.h /^#define BRACE /;" kind:macro line:20 language:C++ roles:def end:20 +Builtin plan9.c /^builtin Builtin[] = {$/;" kind:variable line:15 language:C typeref:typename:builtin[] roles:def end:28 +Builtin unix.c /^builtin Builtin[] = {$/;" kind:variable line:23 language:C typeref:typename:builtin[] roles:def end:35 +CLOSE rc.h /^#define CLOSE /;" kind:macro line:114 language:C++ roles:def end:114 +COUNT y.tab.c /^#define COUNT /;" kind:macro line:26 language:C file: roles:def extras:fileScope end:26 +COUNT y.tab.h /^#define COUNT /;" kind:macro line:26 language:C++ roles:def end:26 +Chdir plan9.c /^Chdir(char *dir)$/;" kind:function line:472 language:C typeref:typename:int signature:(char * dir) roles:def end:476 +Chdir unix.c /^Chdir(char *dir)$/;" kind:function line:414 language:C typeref:typename:int signature:(char * dir) roles:def end:417 +Close plan9.c /^Close(int fd)$/;" kind:function line:410 language:C typeref:typename:void signature:(int fd) roles:def end:413 +Close unix.c /^Close(int fd)$/;" kind:function line:359 language:C typeref:typename:void signature:(int fd) roles:def end:362 +Closedir plan9.c /^Closedir(void *arg)$/;" kind:function line:335 language:C typeref:typename:void signature:(void * arg) roles:def end:341 +Closedir unix.c /^Closedir(void *arg)$/;" kind:function line:318 language:C typeref:typename:void signature:(void * arg) roles:def end:322 +Creat plan9.c /^Creat(char *file)$/;" kind:function line:416 language:C typeref:typename:int signature:(char * file) roles:def end:419 +Creat unix.c /^Creat(char *file)$/;" kind:function line:365 language:C typeref:typename:int signature:(char * file) roles:def end:368 +DUP y.tab.c /^#define DUP /;" kind:macro line:14 language:C file: roles:def extras:fileScope end:14 +DUP y.tab.h /^#define DUP /;" kind:macro line:14 language:C++ roles:def end:14 +DUPFD rc.h /^#define DUPFD /;" kind:macro line:113 language:C++ roles:def end:113 +Dup plan9.c /^Dup(int a, int b)$/;" kind:function line:422 language:C typeref:typename:int signature:(int a,int b) roles:def end:425 +Dup unix.c /^Dup(int a, int b)$/;" kind:function line:371 language:C typeref:typename:int signature:(int a,int b) roles:def end:374 +Dup1 plan9.c /^Dup1(int a)$/;" kind:function line:428 language:C typeref:typename:int signature:(int a) roles:def end:431 +Dup1 unix.c /^Dup1(int a)$/;" kind:function line:377 language:C typeref:typename:int signature:(int a) roles:def end:380 +EOF io.h /^#define EOF /;" kind:macro line:1 language:C++ roles:def end:1 +Eintr plan9.c /^Eintr(void)$/;" kind:function line:441 language:C typeref:typename:int signature:(void) roles:def end:444 +Eintr unix.c /^Eintr(void)$/;" kind:function line:390 language:C typeref:typename:int signature:(void) roles:def end:393 +Env plan9.c /^Env(char *name, int fn)$/;" kind:function line:121 language:C typeref:typename:char * signature:(char * name,int fn) roles:def end:128 +Errstr plan9.c /^Errstr(void)$/;" kind:function line:168 language:C typeref:typename:char * signature:(void) roles:def end:173 +Errstr unix.c /^Errstr(void)$/;" kind:function line:242 language:C typeref:typename:char * signature:(void) roles:def end:245 +Exec plan9.c /^Exec(char **argv)$/;" kind:function line:262 language:C typeref:typename:void signature:(char ** argv) roles:def end:265 +Exec unix.c /^Exec(char **argv)$/;" kind:function line:288 language:C typeref:typename:void signature:(char ** argv) roles:def end:292 +Executable plan9.c /^Executable(char *file)$/;" kind:function line:389 language:C typeref:typename:int signature:(char * file) roles:def end:400 +Executable unix.c /^Executable(char *file)$/;" kind:function line:343 language:C typeref:typename:int signature:(char * file) roles:def end:346 +Exit plan9.c /^Exit(void)$/;" kind:function line:434 language:C typeref:typename:void signature:(void) roles:def end:438 +Exit unix.c /^Exit(void)$/;" kind:function line:383 language:C typeref:typename:void signature:(void) roles:def end:387 +FEWARGS getflags.c /^#define FEWARGS /;" kind:macro line:15 language:C file: roles:def extras:fileScope end:15 +FLAGSYN getflags.c /^#define FLAGSYN /;" kind:macro line:16 language:C file: roles:def extras:fileScope end:16 +FN y.tab.c /^#define FN /;" kind:macro line:10 language:C file: roles:def extras:fileScope end:10 +FN y.tab.h /^#define FN /;" kind:macro line:10 language:C++ roles:def end:10 +FOR y.tab.c /^#define FOR /;" kind:macro line:1 language:C file: roles:def extras:fileScope end:1 +FOR y.tab.h /^#define FOR /;" kind:macro line:1 language:C++ roles:def end:1 +Fdprefix plan9.c /^char Fdprefix[]="\/fd\/";$/;" kind:variable line:31 language:C typeref:typename:char[] roles:def end:31 +Fdprefix unix.c /^char Fdprefix[] = "\/dev\/fd\/";$/;" kind:variable line:38 language:C typeref:typename:char[] roles:def end:38 +Fork plan9.c /^Fork(void)$/;" kind:function line:268 language:C typeref:typename:int signature:(void) roles:def end:272 +Fork unix.c /^Fork(void)$/;" kind:function line:295 language:C typeref:typename:int signature:(void) roles:def end:299 +Freeword exec.c /^Freeword(word *p)$/;" kind:function line:88 language:C typeref:typename:char * signature:(word * p) roles:def end:93 +GLOB rc.h /^#define GLOB /;" kind:macro line:146 language:C++ roles:def end:146 +Getstatus exec.c /^Getstatus(void)$/;" kind:function line:1113 language:C typeref:typename:char * signature:(void) roles:def end:1122 +HERE rc.h /^#define HERE /;" kind:macro line:112 language:C++ roles:def end:112 +IF y.tab.c /^#define IF /;" kind:macro line:4 language:C file: roles:def extras:fileScope end:4 +IF y.tab.h /^#define IF /;" kind:macro line:4 language:C++ roles:def end:4 +IN y.tab.c /^#define IN /;" kind:macro line:2 language:C file: roles:def extras:fileScope end:2 +IN y.tab.h /^#define IN /;" kind:macro line:2 language:C++ roles:def end:2 +Isatty plan9.c /^Isatty(int fd)$/;" kind:function line:453 language:C typeref:typename:int signature:(int fd) roles:def end:461 +Isatty unix.c /^Isatty(int fd)$/;" kind:function line:402 language:C typeref:typename:int signature:(int fd) roles:def end:405 +NBUF getflags.c /^#define NBUF /;" kind:macro line:223 language:C file: roles:def extras:fileScope end:223 +NBUF io.c /^ NBUF = 8192,$/;" kind:enumerator line:7 language:C scope:enum:__anon7c9881ce0103 file: access:public roles:def extras:fileScope +NFLAG getflags.h /^#define NFLAG /;" kind:macro line:1 language:C++ roles:def end:1 +NKW var.c /^#define NKW /;" kind:macro line:15 language:C file: roles:def extras:fileScope end:15 +NOT y.tab.c /^#define NOT /;" kind:macro line:5 language:C file: roles:def extras:fileScope end:5 +NOT y.tab.h /^#define NOT /;" kind:macro line:5 language:C++ roles:def end:5 +NSIG rc.h /^#define NSIG /;" kind:macro line:10 language:C++ roles:def end:10 +NSIG rc.h /^#define NSIG /;" kind:macro line:20 language:C++ roles:def end:20 +NTOK rc.h /^#define NTOK /;" kind:macro line:80 language:C++ roles:def end:80 +NVAR rc.h /^#define NVAR /;" kind:macro line:129 language:C++ roles:def end:129 +Newword exec.c /^Newword(char *s, word *next)$/;" kind:function line:58 language:C typeref:typename:word * signature:(char * s,word * next) roles:def end:64 +Noerror plan9.c /^Noerror(void)$/;" kind:function line:447 language:C typeref:typename:void signature:(void) roles:def end:450 +Noerror unix.c /^Noerror(void)$/;" kind:function line:396 language:C typeref:typename:void signature:(void) roles:def end:399 +OROR y.tab.c /^#define OROR /;" kind:macro line:25 language:C file: roles:def extras:fileScope end:25 +OROR y.tab.h /^#define OROR /;" kind:macro line:25 language:C++ roles:def end:25 +Open plan9.c /^Open(char *file, int mode)$/;" kind:function line:403 language:C typeref:typename:int signature:(char * file,int mode) roles:def end:407 +Open unix.c /^Open(char *file, int mode)$/;" kind:function line:349 language:C typeref:typename:int signature:(char * file,int mode) roles:def end:356 +Opendir plan9.c /^Opendir(char *name)$/;" kind:function line:283 language:C typeref:typename:void * signature:(char * name) roles:def end:295 +Opendir unix.c /^Opendir(char *name)$/;" kind:function line:302 language:C typeref:typename:void * signature:(char * name) roles:def end:305 +PAREN y.tab.c /^#define PAREN /;" kind:macro line:21 language:C file: roles:def extras:fileScope end:21 +PAREN y.tab.h /^#define PAREN /;" kind:macro line:21 language:C++ roles:def end:21 +PCMD y.tab.c /^#define PCMD /;" kind:macro line:22 language:C file: roles:def extras:fileScope end:22 +PCMD y.tab.h /^#define PCMD /;" kind:macro line:22 language:C++ roles:def end:22 +PIPE y.tab.c /^#define PIPE /;" kind:macro line:15 language:C file: roles:def extras:fileScope end:15 +PIPE y.tab.h /^#define PIPE /;" kind:macro line:15 language:C++ roles:def end:15 +PIPEFD y.tab.c /^#define PIPEFD /;" kind:macro line:23 language:C file: roles:def extras:fileScope end:23 +PIPEFD y.tab.h /^#define PIPEFD /;" kind:macro line:23 language:C++ roles:def end:23 +PRD rc.h /^#define PRD /;" kind:macro line:167 language:C++ roles:def end:167 +PWR rc.h /^#define PWR /;" kind:macro line:168 language:C++ roles:def end:168 +Poplist exec.c /^Poplist(void)$/;" kind:function line:130 language:C typeref:typename:word * signature:(void) roles:def end:140 +Popword exec.c /^Popword(void)$/;" kind:function line:104 language:C typeref:typename:char * signature:(void) roles:def end:114 +Prompt plan9.c /^Prompt(char *s)$/;" kind:function line:479 language:C typeref:typename:void signature:(char * s) roles:def end:494 +Prompt unix.c /^Prompt(char *s)$/;" kind:function line:420 language:C typeref:typename:void signature:(char * s) roles:def end:424 +Pushword exec.c /^Pushword(char *s)$/;" kind:function line:71 language:C typeref:typename:word * signature:(char * s) roles:def end:81 +RCLOSE exec.h /^#define RCLOSE /;" kind:macro line:43 language:C++ roles:def end:43 +RDUP exec.h /^#define RDUP /;" kind:macro line:42 language:C++ roles:def end:42 +RDWR rc.h /^#define RDWR /;" kind:macro line:115 language:C++ roles:def end:115 +READ rc.h /^#define READ /;" kind:macro line:111 language:C++ roles:def end:111 +REDIR y.tab.c /^#define REDIR /;" kind:macro line:12 language:C file: roles:def extras:fileScope end:12 +REDIR y.tab.h /^#define REDIR /;" kind:macro line:12 language:C++ roles:def end:12 +REDIRW y.tab.c /^#define REDIRW /;" kind:macro line:13 language:C file: roles:def extras:fileScope end:13 +REDIRW y.tab.h /^#define REDIRW /;" kind:macro line:13 language:C++ roles:def end:13 +RESET getflags.c /^#define RESET /;" kind:macro line:14 language:C file: roles:def extras:fileScope end:14 +ROPEN exec.h /^#define ROPEN /;" kind:macro line:41 language:C++ roles:def end:41 +Rcmain plan9.c /^char Rcmain[]="\/rc\/lib\/rcmain";$/;" kind:variable line:30 language:C typeref:typename:char[] roles:def end:30 +Rcmain unix.c /^char Rcmain[PATH_MAX];$/;" kind:variable line:37 language:C typeref:typename:char[] roles:def end:37 +Read plan9.c /^Read(int fd, void *buf, long cnt)$/;" kind:function line:377 language:C typeref:typename:long signature:(int fd,void * buf,long cnt) roles:def end:380 +Read unix.c /^Read(int fd, void *buf, long cnt)$/;" kind:function line:331 language:C typeref:typename:long signature:(int fd,void * buf,long cnt) roles:def end:334 +Readdir plan9.c /^Readdir(void *arg, int onlydirs)$/;" kind:function line:309 language:C typeref:typename:char * signature:(void * arg,int onlydirs) roles:def end:332 +Readdir unix.c /^Readdir(void *arg, int onlydirs)$/;" kind:function line:308 language:C typeref:typename:char * signature:(void * arg,int onlydirs) roles:def end:315 +SEP unix.c /^#define SEP /;" kind:macro line:42 language:C file: roles:def extras:fileScope end:42 +SIGINT rc.h /^#define SIGINT /;" kind:macro line:11 language:C++ roles:def end:11 +SIGQUIT rc.h /^#define SIGQUIT /;" kind:macro line:12 language:C++ roles:def end:12 +SIMPLE y.tab.c /^#define SIMPLE /;" kind:macro line:17 language:C file: roles:def extras:fileScope end:17 +SIMPLE y.tab.h /^#define SIMPLE /;" kind:macro line:17 language:C++ roles:def end:17 +SUB y.tab.c /^#define SUB /;" kind:macro line:16 language:C file: roles:def extras:fileScope end:16 +SUB y.tab.h /^#define SUB /;" kind:macro line:16 language:C++ roles:def end:16 +SUBSHELL y.tab.c /^#define SUBSHELL /;" kind:macro line:8 language:C file: roles:def extras:fileScope end:8 +SUBSHELL y.tab.h /^#define SUBSHELL /;" kind:macro line:8 language:C++ roles:def end:8 +SWITCH y.tab.c /^#define SWITCH /;" kind:macro line:9 language:C file: roles:def extras:fileScope end:9 +SWITCH y.tab.h /^#define SWITCH /;" kind:macro line:9 language:C++ roles:def end:9 +Seek plan9.c /^Seek(int fd, long cnt, long whence)$/;" kind:function line:383 language:C typeref:typename:long signature:(int fd,long cnt,long whence) roles:def end:386 +Seek unix.c /^Seek(int fd, long cnt, long whence)$/;" kind:function line:337 language:C typeref:typename:long signature:(int fd,long cnt,long whence) roles:def end:340 +Setstatus exec.c /^Setstatus(char *s)$/;" kind:function line:1103 language:C typeref:typename:void signature:(char * s) roles:def end:1106 +Signame plan9.c /^char *Signame[] = {$/;" kind:variable line:33 language:C typeref:typename:char * [] roles:def end:37 +Signame unix.c /^char *Signame[NSIG];$/;" kind:variable line:40 language:C typeref:typename:char * [] roles:def end:40 +TWIDDLE y.tab.c /^#define TWIDDLE /;" kind:macro line:6 language:C file: roles:def extras:fileScope end:6 +TWIDDLE y.tab.h /^#define TWIDDLE /;" kind:macro line:6 language:C++ roles:def end:6 +Trapinit plan9.c /^Trapinit(void)$/;" kind:function line:365 language:C typeref:typename:void signature:(void) roles:def end:368 +Trapinit unix.c /^Trapinit(void)$/;" kind:function line:193 language:C typeref:typename:void signature:(void) roles:def end:239 +Updenv plan9.c /^Updenv(void)$/;" kind:function line:249 language:C typeref:typename:void signature:(void) roles:def end:259 +Updenv unix.c /^Updenv(void)$/;" kind:function line:277 language:C typeref:typename:void signature:(void) roles:def end:285 +Vinit plan9.c /^Vinit(void)$/;" kind:function line:131 language:C typeref:typename:void signature:(void) roles:def end:165 +Vinit unix.c /^Vinit(void)$/;" kind:function line:168 language:C typeref:typename:void signature:(void) roles:def end:183 +WHILE y.tab.c /^#define WHILE /;" kind:macro line:3 language:C file: roles:def extras:fileScope end:3 +WHILE y.tab.h /^#define WHILE /;" kind:macro line:3 language:C++ roles:def end:3 +WORD y.tab.c /^#define WORD /;" kind:macro line:11 language:C file: roles:def extras:fileScope end:11 +WORD y.tab.h /^#define WORD /;" kind:macro line:11 language:C++ roles:def end:11 +WORDS y.tab.c /^#define WORDS /;" kind:macro line:19 language:C file: roles:def extras:fileScope end:19 +WORDS y.tab.h /^#define WORDS /;" kind:macro line:19 language:C++ roles:def end:19 +WRITE rc.h /^#define WRITE /;" kind:macro line:110 language:C++ roles:def end:110 +Waitfor plan9.c /^Waitfor(int pid)$/;" kind:function line:176 language:C typeref:typename:int signature:(int pid) roles:def end:202 +Waitfor unix.c /^Waitfor(int pid)$/;" kind:function line:248 language:C typeref:typename:int signature:(int pid) roles:def end:272 +Write plan9.c /^Write(int fd, void *buf, long cnt)$/;" kind:function line:371 language:C typeref:typename:long signature:(int fd,void * buf,long cnt) roles:def end:374 +Write unix.c /^Write(int fd, void *buf, long cnt)$/;" kind:function line:325 language:C typeref:typename:long signature:(int fd,void * buf,long cnt) roles:def end:328 +Xappend exec.c /^Xappend(void)$/;" kind:function line:339 language:C typeref:typename:void signature:(void) roles:def end:362 +Xassign exec.c /^Xassign(void)$/;" kind:function line:738 language:C typeref:typename:void signature:(void) roles:def end:751 +Xasync havefork.c /^Xasync(void)$/;" kind:function line:46 language:C typeref:typename:void signature:(void) roles:def end:67 +Xbackq havefork.c /^Xbackq(void)$/;" kind:function line:109 language:C typeref:typename:void signature:(void) roles:def end:154 +Xbang exec.c /^Xbang(void)$/;" kind:function line:371 language:C typeref:typename:void signature:(void) roles:def end:374 +Xcase exec.c /^Xcase(void)$/;" kind:function line:673 language:C typeref:typename:void signature:(void) roles:def end:691 +Xclose exec.c /^Xclose(void)$/;" kind:function line:377 language:C typeref:typename:void signature:(void) roles:def end:380 +Xconc exec.c /^Xconc(void)$/;" kind:function line:715 language:C typeref:typename:void signature:(void) roles:def end:735 +Xcount exec.c /^Xcount(void)$/;" kind:function line:893 language:C typeref:typename:void signature:(void) roles:def end:916 +Xdelfn exec.c /^Xdelfn(void)$/;" kind:function line:962 language:C typeref:typename:void signature:(void) roles:def end:974 +Xdol exec.c /^Xdol(void)$/;" kind:function line:768 language:C typeref:typename:void signature:(void) roles:def end:793 +Xdup exec.c /^Xdup(void)$/;" kind:function line:383 language:C typeref:typename:void signature:(void) roles:def end:387 +Xeflag exec.c /^Xeflag(void)$/;" kind:function line:390 language:C typeref:typename:void signature:(void) roles:def end:393 +Xerror1 exec.c /^Xerror1(char *s)$/;" kind:function line:1075 language:C typeref:typename:void signature:(char * s) roles:def end:1082 +Xerror2 exec.c /^Xerror2(char *s, char *e)$/;" kind:function line:1084 language:C typeref:typename:void signature:(char * s,char * e) roles:def end:1091 +Xerror3 exec.c /^Xerror3(char *s, char *m, char *e)$/;" kind:function line:1093 language:C typeref:typename:void signature:(char * s,char * m,char * e) roles:def end:1100 +Xexit exec.c /^Xexit(void)$/;" kind:function line:396 language:C typeref:typename:void signature:(void) roles:def end:411 +Xfalse exec.c /^Xfalse(void)$/;" kind:function line:414 language:C typeref:typename:void signature:(void) roles:def end:418 +Xfn exec.c /^Xfn(void)$/;" kind:function line:944 language:C typeref:typename:void signature:(void) roles:def end:959 +Xfor exec.c /^Xfor(void)$/;" kind:function line:1141 language:C typeref:typename:void signature:(void) roles:def end:1156 +Xglob exec.c /^Xglob(void)$/;" kind:function line:1159 language:C typeref:typename:void signature:(void) roles:def end:1167 +Xhere exec.c /^Xhere(void)$/;" kind:function line:485 language:C typeref:typename:void signature:(void) roles:def end:506 +Xhereq exec.c /^Xhereq(void)$/;" kind:function line:509 language:C typeref:typename:void signature:(void) roles:def end:528 +Xif exec.c /^Xif(void)$/;" kind:function line:611 language:C typeref:typename:void signature:(void) roles:def end:616 +Xifnot exec.c /^Xifnot(void)$/;" kind:function line:422 language:C typeref:typename:void signature:(void) roles:def end:428 +Xjump exec.c /^Xjump(void)$/;" kind:function line:431 language:C typeref:typename:void signature:(void) roles:def end:434 +Xlocal exec.c /^Xlocal(void)$/;" kind:function line:919 language:C typeref:typename:void signature:(void) roles:def end:929 +Xmark exec.c /^Xmark(void)$/;" kind:function line:437 language:C typeref:typename:void signature:(void) roles:def end:440 +Xmatch exec.c /^Xmatch(void)$/;" kind:function line:656 language:C typeref:typename:void signature:(void) roles:def end:670 +Xpipe havefork.c /^Xpipe(void)$/;" kind:function line:70 language:C typeref:typename:void signature:(void) roles:def end:102 +Xpipefd havefork.c /^Xpipefd(void)$/;" kind:function line:157 language:C typeref:typename:void signature:(void) roles:def end:199 +Xpipewait exec.c /^Xpipewait(void)$/;" kind:function line:993 language:C typeref:typename:void signature:(void) roles:def end:1005 +Xpopm exec.c /^Xpopm(void)$/;" kind:function line:443 language:C typeref:typename:void signature:(void) roles:def end:446 +Xpopredir exec.c /^Xpopredir(void)$/;" kind:function line:581 language:C typeref:typename:void signature:(void) roles:def end:591 +Xpush exec.c /^Xpush(void)$/;" kind:function line:449 language:C typeref:typename:void signature:(void) roles:def end:456 +Xqw exec.c /^Xqw(void)$/;" kind:function line:796 language:C typeref:typename:void signature:(void) roles:def end:823 +Xrdcmds exec.c /^Xrdcmds(void)$/;" kind:function line:1010 language:C typeref:typename:void signature:(void) roles:def end:1048 +Xrdfn unix.c /^Xrdfn(void)$/;" kind:function line:47 language:C typeref:typename:void file: signature:(void) roles:def extras:fileScope end:70 +Xrdwr exec.c /^Xrdwr(void)$/;" kind:function line:556 language:C typeref:typename:void signature:(void) roles:def end:578 +Xread exec.c /^Xread(void)$/;" kind:function line:531 language:C typeref:typename:void signature:(void) roles:def end:553 +Xreturn exec.c /^Xreturn(void)$/;" kind:function line:594 language:C typeref:typename:void signature:(void) roles:def end:601 +Xsettrue exec.c /^Xsettrue(void)$/;" kind:function line:365 language:C typeref:typename:void signature:(void) roles:def end:368 +Xsimple simple.c /^Xsimple(void)$/;" kind:function line:58 language:C typeref:typename:void signature:(void) roles:def end:107 +Xsrcline exec.c /^Xsrcline(void)$/;" kind:function line:1170 language:C typeref:typename:void signature:(void) roles:def end:1173 +Xsub exec.c /^Xsub(void)$/;" kind:function line:874 language:C typeref:typename:void signature:(void) roles:def end:890 +Xsubshell havefork.c /^Xsubshell(void)$/;" kind:function line:202 language:C typeref:typename:void signature:(void) roles:def end:222 +Xtrue exec.c /^Xtrue(void)$/;" kind:function line:604 language:C typeref:typename:void signature:(void) roles:def end:608 +Xunlocal exec.c /^Xunlocal(void)$/;" kind:function line:932 language:C typeref:typename:void signature:(void) roles:def end:941 +Xwastrue exec.c /^Xwastrue(void)$/;" kind:function line:619 language:C typeref:typename:void signature:(void) roles:def end:622 +Xword exec.c /^Xword(void)$/;" kind:function line:625 language:C typeref:typename:void signature:(void) roles:def end:628 +Xwrite exec.c /^Xwrite(void)$/;" kind:function line:631 language:C typeref:typename:void signature:(void) roles:def end:653 +YYABORT y.tab.c /^#define YYABORT /;" kind:macro line:198 language:C file: roles:def extras:fileScope end:198 +YYACCEPT y.tab.c /^#define YYACCEPT /;" kind:macro line:197 language:C file: roles:def extras:fileScope end:197 +YYEOFCODE y.tab.c /^#define YYEOFCODE /;" kind:macro line:42 language:C file: roles:def extras:fileScope end:42 +YYERRCODE y.tab.c /^#define YYERRCODE /;" kind:macro line:43 language:C file: roles:def extras:fileScope end:43 +YYERROR y.tab.c /^#define YYERROR /;" kind:macro line:196 language:C file: roles:def extras:fileScope end:196 +YYFLAG y.tab.c /^#define YYFLAG /;" kind:macro line:195 language:C file: roles:def extras:fileScope end:195 +YYLAST y.tab.c /^#define YYLAST /;" kind:macro line:54 language:C file: roles:def extras:fileScope end:54 +YYMAXDEPTH rc.h /^#define YYMAXDEPTH /;" kind:macro line:26 language:C++ roles:def end:26 +YYMAXDEPTH y.tab.c /^#define YYMAXDEPTH /;" kind:macro line:38 language:C file: roles:def extras:fileScope end:38 +YYNPROD y.tab.c /^#define YYNPROD /;" kind:macro line:52 language:C file: roles:def extras:fileScope end:52 +YYPRIVATE y.tab.c /^#define YYPRIVATE /;" kind:macro line:53 language:C file: roles:def extras:fileScope end:53 +YYSTYPE y.tab.c /^} YYSTYPE;$/;" kind:typedef line:35 language:C typeref:union:__anond9bd93f4010a file: roles:def extras:fileScope +YYSTYPE y.tab.h /^} YYSTYPE;$/;" kind:typedef line:30 language:C++ typeref:union:__anond9bd93f9010a roles:def +__anon10643646010a syn.y /union{$/;" kind:union line:16 language:C file: roles:def extras:fileScope,guest,anonymous end:18 +__anon10643646010a::tree syn.y /^ struct tree *tree;$/;" kind:member line:17 language:C scope:union:__anon10643646010a typeref:struct:tree * file: access:public roles:def extras:fileScope,qualified,guest end:17 +__anon14948bbd0108 pfnc.c /^struct{$/;" kind:struct line:5 language:C file: roles:def extras:fileScope,anonymous end:8 +__anon14948bbd0108::f pfnc.c /^ void (*f)(void);$/;" kind:member line:6 language:C scope:struct:__anon14948bbd0108 typeref:typename:void (*)(void) file: access:public roles:def extras:fileScope,qualified end:6 +__anon14948bbd0108::name pfnc.c /^ char *name;$/;" kind:member line:7 language:C scope:struct:__anon14948bbd0108 typeref:typename:char * file: access:public roles:def extras:fileScope,qualified end:7 +__anon7c9881ce0103 io.c /^enum {$/;" kind:enum line:6 language:C file: roles:def extras:fileScope,anonymous end:8 +__anond9bd93f4010a y.tab.c /^typedef union {$/;" kind:union line:33 language:C file: roles:def extras:fileScope,anonymous end:35 +__anond9bd93f4010a::tree y.tab.c /^ struct tree *tree;$/;" kind:member line:34 language:C scope:union:__anond9bd93f4010a typeref:struct:tree * file: access:public roles:def extras:fileScope,qualified end:34 +__anond9bd93f40208 y.tab.c /^ {$/;" kind:struct line:304 language:C scope:function:yyparse file: roles:def extras:fileScope,anonymous end:307 +__anond9bd93f9010a y.tab.h /^typedef union {$/;" kind:union line:28 language:C++ roles:def extras:anonymous end:30 +__anond9bd93f9010a::tree y.tab.h /^ struct tree *tree;$/;" kind:member line:29 language:C++ scope:union:__anond9bd93f9010a typeref:struct:tree * access:public roles:def extras:qualified end:29 +_searchpath simple.c /^_searchpath(char *w, char *v)$/;" kind:function line:132 language:C typeref:typename:word * signature:(char * w,char * v) roles:def end:144 +addenv plan9.c /^addenv(var *v)$/;" kind:function line:205 language:C typeref:typename:void file: signature:(var * v) roles:def extras:fileScope end:237 +addtok lex.c /^addtok(char *p, int val)$/;" kind:function line:177 language:C typeref:typename:char * file: signature:(char * p,int val) roles:def extras:fileScope end:188 +addutf lex.c /^addutf(char *p, int c)$/;" kind:function line:191 language:C typeref:typename:char * file: signature:(char * p,int c) roles:def extras:fileScope end:211 +addwaitpid havefork.c /^addwaitpid(int pid)$/;" kind:function line:11 language:C typeref:typename:void signature:(int pid) roles:def end:15 +advance lex.c /^advance(void)$/;" kind:function line:119 language:C typeref:typename:int file: signature:(void) roles:def extras:fileScope end:127 +argv exec.h /^ list *argv; \/* argument stack *\/$/;" kind:member line:50 language:C++ scope:struct:thread typeref:typename:list * access:public roles:def end:50 +argv0 exec.c /^char *argv0="rc";$/;" kind:variable line:7 language:C typeref:typename:char * roles:def end:7 +badflag getflags.c /^static int badflag;$/;" kind:variable line:18 language:C typeref:typename:int file: roles:def extras:fileScope end:18 +body parse.c /^body(int tok, int *ptok)$/;" kind:function line:75 language:C typeref:typename:tree * file: signature:(int tok,int * ptok) roles:def extras:fileScope end:78 +bp subr.c /^static char *bp;$/;" kind:variable line:43 language:C typeref:typename:char * file: roles:def extras:fileScope end:43 +brace parse.c /^brace(int tok)$/;" kind:function line:120 language:C typeref:typename:tree * file: signature:(int tok) roles:def extras:fileScope end:133 +buf getflags.c /^static char buf[NBUF], *bufp = buf;$/;" kind:variable line:224 language:C typeref:typename:char[] file: roles:def extras:fileScope end:224 +buf io.h /^ unsigned char *buf, *bufp, *ebuf;$/;" kind:member line:5 language:C++ scope:struct:io typeref:typename:unsigned char * access:public roles:def end:5 +bufp getflags.c /^static char buf[NBUF], *bufp = buf;$/;" kind:variable line:224 language:C typeref:typename:char * file: roles:def extras:fileScope end:224 +bufp io.h /^ unsigned char *buf, *bufp, *ebuf;$/;" kind:member line:5 language:C++ scope:struct:io typeref:typename:unsigned char * access:public roles:def end:5 +builtin exec.h /^struct builtin{$/;" kind:struct line:71 language:C++ roles:def end:74 +builtin rc.h /^typedef struct builtin builtin;$/;" kind:typedef line:39 language:C++ typeref:struct:builtin roles:def +builtin::fnc exec.h /^ void (*fnc)(void);$/;" kind:member line:73 language:C++ scope:struct:builtin typeref:typename:void (*)(void) access:public roles:def extras:qualified end:73 +builtin::name exec.h /^ char *name;$/;" kind:member line:72 language:C++ scope:struct:builtin typeref:typename:char * access:public roles:def extras:qualified end:72 +builtinfunc simple.c /^void (*builtinfunc(char *name))(void)$/;" kind:function line:46 language:C typeref:typename:void (*)(void) signature:(char * name) roles:def end:55 +c0 code.c /^#define c0 /;" kind:macro line:6 language:C file: roles:def extras:fileScope end:6 +c0 pcmd.c /^#define c0 /;" kind:macro line:5 language:C file: roles:def extras:fileScope end:5 +c1 code.c /^#define c1 /;" kind:macro line:7 language:C file: roles:def extras:fileScope end:7 +c1 pcmd.c /^#define c1 /;" kind:macro line:6 language:C file: roles:def extras:fileScope end:6 +c2 code.c /^#define c2 /;" kind:macro line:8 language:C file: roles:def extras:fileScope end:8 +c2 pcmd.c /^#define c2 /;" kind:macro line:7 language:C file: roles:def extras:fileScope end:7 +changed rc.h /^ char changed;$/;" kind:member line:123 language:C++ scope:struct:var typeref:typename:char access:public roles:def end:123 +checkparse checkparse 1;" kind:file line:1 language:Sh roles:def extras:inputFile end:23 epoch:1658434441 +child rc.h /^ tree *child[3];$/;" kind:member line:54 language:C++ scope:struct:tree typeref:typename:tree * [3] access:public roles:def end:54 +clearwaitpids havefork.c /^clearwaitpids(void)$/;" kind:function line:29 language:C typeref:typename:void signature:(void) roles:def end:32 +closeio io.c /^closeio(io *f)$/;" kind:function line:287 language:C typeref:typename:void signature:(io * f) roles:def end:291 +closeiostr io.c /^closeiostr(io *f)$/;" kind:function line:237 language:C typeref:typename:char * signature:(io * f) roles:def end:242 +cmd parse.c /^cmd(int tok, int *ptok)$/;" kind:function line:196 language:C typeref:typename:tree * file: signature:(int tok,int * ptok) roles:def extras:fileScope end:213 +cmd2 parse.c /^cmd2(int tok, int *ptok)$/;" kind:function line:216 language:C typeref:typename:tree * file: signature:(int tok,int * ptok) roles:def extras:fileScope end:229 +cmd3 parse.c /^cmd3(int tok, int *ptok)$/;" kind:function line:232 language:C typeref:typename:tree * file: signature:(int tok,int * ptok) roles:def extras:fileScope end:381 +cmdname getflags.c /^char *cmdname;$/;" kind:variable line:6 language:C typeref:typename:char * roles:def end:6 +cmds parse.c /^cmds(int tok, int *ptok, int nlok)$/;" kind:function line:81 language:C typeref:typename:tree * file: signature:(int tok,int * ptok,int nlok) roles:def extras:fileScope end:117 +cmdsan syn.y /^cmdsan: cmdsa$/;" kind:label line:32 language:YACC typeref:typename:tree roles:def +cmpenv unix.c /^cmpenv(const void *aa, const void *ab)$/;" kind:function line:89 language:C typeref:typename:int file: signature:(const void * aa,const void * ab) roles:def extras:fileScope end:92 +code exec.h /^ code *code; \/* code for this thread *\/$/;" kind:member line:47 language:C++ scope:struct:thread typeref:typename:code * access:public roles:def end:47 +code rc.h /^typedef union code code;$/;" kind:typedef line:33 language:C++ typeref:union:code roles:def +code rc.h /^union code{$/;" kind:union line:74 language:C++ roles:def end:78 +code.c code.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:547 epoch:1659461020 +code::f rc.h /^ void (*f)(void);$/;" kind:member line:75 language:C++ scope:union:code typeref:typename:void (*)(void) access:public roles:def extras:qualified end:75 +code::i rc.h /^ int i;$/;" kind:member line:76 language:C++ scope:union:code typeref:typename:int access:public roles:def extras:qualified end:76 +code::s rc.h /^ char *s;$/;" kind:member line:77 language:C++ scope:union:code typeref:typename:char * access:public roles:def extras:qualified end:77 +codebuf code.c /^code *codebuf;$/;" kind:variable line:9 language:C typeref:typename:code * roles:def end:9 +codecopy code.c /^codecopy(code *cp)$/;" kind:function line:517 language:C typeref:typename:code * signature:(code * cp) roles:def end:521 +codefree code.c /^codefree(code *cp)$/;" kind:function line:524 language:C typeref:typename:void signature:(code * cp) roles:def end:547 +codeline code.c /^static int codep, ncode, codeline;$/;" kind:variable line:10 language:C typeref:typename:int file: roles:def extras:fileScope end:10 +codep code.c /^static int codep, ncode, codeline;$/;" kind:variable line:10 language:C typeref:typename:int file: roles:def extras:fileScope end:10 +codeswitch code.c /^codeswitch(tree *t, int eflag)$/;" kind:function line:457 language:C typeref:typename:void signature:(tree * t,int eflag) roles:def end:505 +compile code.c /^compile(tree *t)$/;" kind:function line:39 language:C typeref:typename:int signature:(tree * t) roles:def end:55 +conclist exec.c /^conclist(word *lp, word *rp, word *tail)$/;" kind:function line:694 language:C typeref:typename:word * file: signature:(word * lp,word * rp,word * tail) roles:def extras:fileScope end:712 +concstatus exec.c /^concstatus(char *s, char *t)$/;" kind:function line:977 language:C typeref:typename:char * file: signature:(char * s,char * t) roles:def extras:fileScope end:990 +copynwords exec.c /^copynwords(word *a, word *tail, int n)$/;" kind:function line:826 language:C typeref:typename:word * file: signature:(word * a,word * tail,int n) roles:def extras:fileScope end:839 +copywords exec.c /^copywords(word *a, word *tail)$/;" kind:function line:757 language:C typeref:typename:word * signature:(word * a,word * tail) roles:def end:765 +count exec.c /^count(word *w)$/;" kind:function line:148 language:C typeref:typename:int signature:(word * w) roles:def end:153 +dbuf plan9.c /^ Dir *dbuf;$/;" kind:member line:277 language:C scope:struct:readdir typeref:typename:Dir * file: access:public roles:def extras:fileScope end:277 +deglob glob.c /^deglob(char *s)$/;" kind:function line:9 language:C typeref:typename:char * signature:(char * s) roles:def end:21 +delwaitpid havefork.c /^delwaitpid(int pid)$/;" kind:function line:18 language:C typeref:typename:void signature:(int pid) roles:def end:26 +dirent.h unix.c /^#include /;" kind:header line:17 language:C roles:system extras:reference +dontclose exec.c /^dontclose(int fd)$/;" kind:function line:167 language:C typeref:typename:void file: signature:(int fd) roles:def extras:fileScope end:179 +doprompt lex.c /^int doprompt = 1;$/;" kind:variable line:8 language:C typeref:typename:int roles:def end:8 +doredir simple.c /^doredir(redir *rp)$/;" kind:function line:110 language:C typeref:typename:void file: signature:(redir * rp) roles:def extras:fileScope end:129 +dotrap trap.c /^dotrap(void)$/;" kind:function line:10 language:C typeref:typename:void signature:(void) roles:def end:34 +dropnl parse.c /^dropnl(int tok)$/;" kind:function line:23 language:C typeref:typename:int file: signature:(int tok) roles:def extras:fileScope end:28 +dropsp parse.c /^dropsp(int tok)$/;" kind:function line:31 language:C typeref:typename:int file: signature:(int tok) roles:def extras:fileScope end:36 +ebuf io.h /^ unsigned char *buf, *bufp, *ebuf;$/;" kind:member line:5 language:C++ scope:struct:io typeref:typename:unsigned char * access:public roles:def end:5 +emalloc subr.c /^emalloc(long n)$/;" kind:function line:6 language:C typeref:typename:void * signature:(long n) roles:def end:12 +emitf code.c /^#define emitf(/;" kind:macro line:11 language:C file: signature:(x) roles:def extras:fileScope end:11 +emiti code.c /^#define emiti(/;" kind:macro line:12 language:C file: signature:(x) roles:def extras:fileScope end:12 +emits code.c /^#define emits(/;" kind:macro line:13 language:C file: signature:(x) roles:def extras:fileScope end:13 +emptyiobuf io.c /^emptyiobuf(io *f)$/;" kind:function line:294 language:C typeref:typename:int signature:(io * f) roles:def end:301 +environ exec.c /^char **environ;$/;" kind:variable line:11 language:C typeref:typename:char ** roles:def end:11 +envp unix.c /^static char **envp;$/;" kind:variable line:44 language:C typeref:typename:char ** file: roles:def extras:fileScope end:44 +envval unix.c /^envval(char *s)$/;" kind:function line:155 language:C typeref:typename:word * file: signature:(char * s) roles:def extras:fileScope end:165 +eof rc.h /^ char eof;$/;" kind:member line:94 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def end:94 +epilog parse.c /^epilog(int tok, int *ptok)$/;" kind:function line:152 language:C typeref:typename:tree * file: signature:(int tok,int * ptok) roles:def extras:fileScope end:168 +epilog rc.h /^ char *epilog;$/;" kind:member line:88 language:C++ scope:struct:lexer typeref:typename:char * access:public roles:def end:88 +epimung tree.c /^epimung(tree *comp, tree *epi)$/;" kind:function line:116 language:C typeref:typename:tree * signature:(tree * comp,tree * epi) roles:def end:124 +equtf glob.c /^equtf(char *p, char *q)$/;" kind:function line:191 language:C typeref:typename:int file: signature:(char * p,char * q) roles:def extras:fileScope end:196 +erealloc subr.c /^erealloc(void *p, long n)$/;" kind:function line:15 language:C typeref:typename:void * signature:(void * p,long n) roles:def end:21 +err exec.c /^io *err;$/;" kind:variable line:8 language:C typeref:typename:io * roles:def end:8 +errc getflags.c /^errc(int c)$/;" kind:function line:227 language:C typeref:typename:void file: signature:(int c) roles:def extras:fileScope end:234 +errn getflags.c /^errn(char *s, int count)$/;" kind:function line:213 language:C typeref:typename:void file: signature:(char * s,int count) roles:def extras:fileScope end:216 +errno.h unix.c /^#include /;" kind:header line:15 language:C roles:system extras:reference +errs getflags.c /^errs(char *s)$/;" kind:function line:219 language:C typeref:typename:void file: signature:(char * s) roles:def extras:fileScope end:222 +estrdup subr.c /^estrdup(char *s)$/;" kind:function line:24 language:C typeref:typename:char * signature:(char * s) roles:def end:30 +exec.c exec.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:1173 epoch:1659460845 +exec.h code.c /^#include "exec.h"/;" kind:header line:3 language:C roles:local extras:reference +exec.h exec.c /^#include "exec.h"/;" kind:header line:3 language:C roles:local extras:reference +exec.h exec.h 1;" kind:file line:1 language:C++ roles:def extras:inputFile end:85 epoch:1659459892 +exec.h glob.c /^#include "exec.h"/;" kind:header line:2 language:C roles:local extras:reference +exec.h havefork.c /^#include "exec.h"/;" kind:header line:3 language:C roles:local extras:reference +exec.h here.c /^#include "exec.h"/;" kind:header line:2 language:C roles:local extras:reference +exec.h io.c /^#include "exec.h"/;" kind:header line:2 language:C roles:local extras:reference +exec.h pfnc.c /^#include "exec.h"/;" kind:header line:2 language:C roles:local extras:reference +exec.h plan9.c /^#include "exec.h"/;" kind:header line:7 language:C roles:local extras:reference +exec.h simple.c /^#include "exec.h"/;" kind:header line:6 language:C roles:local extras:reference +exec.h trap.c /^#include "exec.h"/;" kind:header line:2 language:C roles:local extras:reference +exec.h unix.c /^#include "exec.h"/;" kind:header line:7 language:C roles:local extras:reference +exec.h var.c /^#include "exec.h"/;" kind:header line:2 language:C roles:local extras:reference +execcd simple.c /^execcd(void)$/;" kind:function line:204 language:C typeref:typename:void signature:(void) roles:def end:244 +execcmds simple.c /^execcmds(io *input, char *file, var *local, redir *redir)$/;" kind:function line:309 language:C typeref:typename:void signature:(io * input,char * file,var * local,redir * redir) roles:def end:325 +execdot simple.c /^execdot(void)$/;" kind:function line:354 language:C typeref:typename:void signature:(void) roles:def end:432 +execeval simple.c /^execeval(void)$/;" kind:function line:328 language:C typeref:typename:void signature:(void) roles:def end:351 +execexec simple.c /^execexec(void)$/;" kind:function line:173 language:C typeref:typename:void signature:(void) roles:def end:194 +execexit simple.c /^execexit(void)$/;" kind:function line:247 language:C typeref:typename:void signature:(void) roles:def end:256 +execfinit plan9.c /^execfinit(void)$/;" kind:function line:55 language:C typeref:typename:void file: signature:(void) roles:def extras:fileScope end:63 +execfinit unix.c /^execfinit(void)$/;" kind:function line:73 language:C typeref:typename:void file: signature:(void) roles:def extras:fileScope end:86 +execflag simple.c /^execflag(void)$/;" kind:function line:435 language:C typeref:typename:void signature:(void) roles:def end:460 +execforkexec havefork.c /^execforkexec(void)$/;" kind:function line:225 language:C typeref:typename:int signature:(void) roles:def end:240 +execfunc simple.c /^execfunc(var *func)$/;" kind:function line:197 language:C typeref:typename:void signature:(var * func) roles:def end:201 +execrfork plan9.c /^execrfork(void)$/;" kind:function line:66 language:C typeref:typename:void file: signature:(void) roles:def extras:fileScope end:118 +execshift simple.c /^execshift(void)$/;" kind:function line:259 language:C typeref:typename:void signature:(void) roles:def end:286 +execwait simple.c /^execwait(void)$/;" kind:function line:523 language:C typeref:typename:void signature:(void) roles:def end:537 +execwhatis simple.c /^execwhatis(void){ \/* mildly wrong -- should fork before writing *\/$/;" kind:function line:463 language:C typeref:typename:void signature:(void) roles:def end:520 +exitnext simple.c /^exitnext(void){$/;" kind:function line:14 language:C typeref:typename:int signature:(void) roles:def end:44 +f pfnc.c /^ void (*f)(void);$/;" kind:member line:6 language:C scope:struct:__anon14948bbd0108 typeref:typename:void (*)(void) file: access:public roles:def extras:fileScope end:6 +f rc.h /^ void (*f)(void);$/;" kind:member line:75 language:C++ scope:union:code typeref:typename:void (*)(void) access:public roles:def end:75 +fcntl.h unix.c /^#include /;" kind:header line:16 language:C roles:system extras:reference +fd io.h /^ int fd;$/;" kind:member line:4 language:C++ scope:struct:io typeref:typename:int access:public roles:def end:4 +fd plan9.c /^ int fd;$/;" kind:member line:279 language:C scope:struct:readdir typeref:typename:int file: access:public roles:def extras:fileScope end:279 +fd0 rc.h /^ int rtype, fd0, fd1; \/* details of REDIR PIPE DUP tokens *\/$/;" kind:member line:48 language:C++ scope:struct:tree typeref:typename:int access:public roles:def end:48 +fd1 rc.h /^ int rtype, fd0, fd1; \/* details of REDIR PIPE DUP tokens *\/$/;" kind:member line:48 language:C++ scope:struct:tree typeref:typename:int access:public roles:def end:48 +file rc.h /^ char *file;$/;" kind:member line:84 language:C++ scope:struct:lexer typeref:typename:char * access:public roles:def end:84 +flag getflags.c /^char **flag[NFLAG];$/;" kind:variable line:5 language:C typeref:typename:char ** [] roles:def end:5 +flagarg getflags.c /^static char *flagarg="";$/;" kind:variable line:7 language:C typeref:typename:char * file: roles:def extras:fileScope end:7 +flagset getflags.c /^char *flagset[] = {""};$/;" kind:variable line:4 language:C typeref:typename:char * [] roles:def end:4 +flushio io.c /^flushio(io *f)$/;" kind:function line:264 language:C typeref:typename:void signature:(io * f) roles:def end:284 +fn rc.h /^ code *fn; \/* pointer to function's code vector *\/$/;" kind:member line:120 language:C++ scope:struct:var typeref:typename:code * access:public roles:def end:120 +fname pfnc.c /^}fname[] = {$/;" kind:variable line:8 language:C typeref:struct:__anon14948bbd0108[] roles:def end:54 +fnc exec.h /^ void (*fnc)(void);$/;" kind:member line:73 language:C++ scope:struct:builtin typeref:typename:void (*)(void) access:public roles:def end:73 +fnchanged rc.h /^ char fnchanged;$/;" kind:member line:122 language:C++ scope:struct:var typeref:typename:char access:public roles:def end:122 +fns.h code.c /^#include "fns.h"/;" kind:header line:4 language:C roles:local extras:reference +fns.h exec.c /^#include "fns.h"/;" kind:header line:5 language:C roles:local extras:reference +fns.h fns.h 1;" kind:file line:1 language:C++ roles:def extras:inputFile end:71 epoch:1659459892 +fns.h getflags.c /^#include "fns.h"/;" kind:header line:3 language:C roles:local extras:reference +fns.h glob.c /^#include "fns.h"/;" kind:header line:3 language:C roles:local extras:reference +fns.h havefork.c /^#include "fns.h"/;" kind:header line:5 language:C roles:local extras:reference +fns.h here.c /^#include "fns.h"/;" kind:header line:4 language:C roles:local extras:reference +fns.h io.c /^#include "fns.h"/;" kind:header line:4 language:C roles:local extras:reference +fns.h lex.c /^#include "fns.h"/;" kind:header line:4 language:C roles:local extras:reference +fns.h parse.c /^#include "fns.h"/;" kind:header line:3 language:C roles:local extras:reference +fns.h pcmd.c /^#include "fns.h"/;" kind:header line:3 language:C roles:local extras:reference +fns.h pfnc.c /^#include "fns.h"/;" kind:header line:4 language:C roles:local extras:reference +fns.h plan9.c /^#include "fns.h"/;" kind:header line:9 language:C roles:local extras:reference +fns.h simple.c /^#include "fns.h"/;" kind:header line:8 language:C roles:local extras:reference +fns.h subr.c /^#include "fns.h"/;" kind:header line:3 language:C roles:local extras:reference +fns.h syn.y /^#include "fns.h"/;" kind:header line:14 language:C roles:local extras:reference,guest +fns.h trap.c /^#include "fns.h"/;" kind:header line:3 language:C roles:local extras:reference +fns.h tree.c /^#include "fns.h"/;" kind:header line:3 language:C roles:local extras:reference +fns.h unix.c /^#include "fns.h"/;" kind:header line:9 language:C roles:local extras:reference +fns.h var.c /^#include "fns.h"/;" kind:header line:3 language:C roles:local extras:reference +fns.h y.tab.c /^#include "fns.h"/;" kind:header line:30 language:C roles:local extras:reference +fnstr tree.c /^fnstr(tree *t)$/;" kind:function line:149 language:C typeref:typename:char * signature:(tree * t) roles:def end:154 +fourbyte rc.h /^#define fourbyte(/;" kind:macro line:153 language:C++ signature:(c) roles:def end:153 +freelexer lex.c /^freelexer(lexer *p)$/;" kind:function line:51 language:C typeref:typename:void signature:(lexer * p) roles:def end:56 +freenodes tree.c /^freenodes(void)$/;" kind:function line:33 language:C typeref:typename:void signature:(void) roles:def end:52 +freevar var.c /^freevar(var *v)$/;" kind:function line:105 language:C typeref:typename:void signature:(var * v) roles:def end:109 +freewords exec.c /^freewords(word *w)$/;" kind:function line:95 language:C typeref:typename:void signature:(word * w) roles:def end:102 +from exec.h /^ int from, to; \/* what to do it to *\/$/;" kind:member line:34 language:C++ scope:struct:redir typeref:typename:int access:public roles:def end:34 +future rc.h /^ int future;$/;" kind:member line:91 language:C++ scope:struct:lexer typeref:typename:int access:public roles:def end:91 +getflags getflags.c /^getflags(int argc, char *argv[], char *flags, int stop)$/;" kind:function line:21 language:C typeref:typename:int signature:(int argc,char * argv[],char * flags,int stop) roles:def end:75 +getflags.c getflags.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:234 epoch:1659459892 +getflags.h code.c /^#include "getflags.h"/;" kind:header line:5 language:C roles:local extras:reference +getflags.h exec.c /^#include "getflags.h"/;" kind:header line:2 language:C roles:local extras:reference +getflags.h getflags.c /^#include "getflags.h"/;" kind:header line:2 language:C roles:local extras:reference +getflags.h getflags.h 1;" kind:file line:1 language:C++ roles:def extras:inputFile end:7 epoch:1659459892 +getflags.h havefork.c /^#include "getflags.h"/;" kind:header line:2 language:C roles:local extras:reference +getflags.h lex.c /^#include "getflags.h"/;" kind:header line:3 language:C roles:local extras:reference +getflags.h plan9.c /^#include "getflags.h"/;" kind:header line:10 language:C roles:local extras:reference +getflags.h simple.c /^#include "getflags.h"/;" kind:header line:5 language:C roles:local extras:reference +getflags.h unix.c /^#include "getflags.h"/;" kind:header line:10 language:C roles:local extras:reference +getnext lex.c /^getnext(void)$/;" kind:function line:62 language:C typeref:typename:int file: signature:(void) roles:def extras:fileScope end:102 +getstatus exec.c /^getstatus(void)$/;" kind:function line:1124 language:C typeref:typename:char * signature:(void) roles:def end:1128 +glob rc.h /^ char glob; \/* 0=string, 1=glob, 2=pattern see globprop() and noglobs() *\/$/;" kind:member line:50 language:C++ scope:struct:tree typeref:typename:char access:public roles:def end:50 +glob.c glob.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:259 epoch:1659459892 +globcmp glob.c /^globcmp(const void *s, const void *t)$/;" kind:function line:24 language:C typeref:typename:int file: signature:(const void * s,const void * t) roles:def extras:fileScope end:27 +globdir glob.c /^globdir(word *list, char *pattern, char *name)$/;" kind:function line:68 language:C typeref:typename:word * file: signature:(word * list,char * pattern,char * name) roles:def extras:fileScope end:117 +globprop tree.c /^globprop(tree *t)$/;" kind:function line:157 language:C typeref:typename:tree * signature:(tree * t) roles:def end:181 +globsort glob.c /^globsort(word *left, word *right)$/;" kind:function line:30 language:C typeref:typename:void file: signature:(word * left,word * right) roles:def extras:fileScope end:41 +globword glob.c /^globword(word *w)$/;" kind:function line:123 language:C typeref:typename:void signature:(word * w) roles:def end:139 +gvar var.c /^var *gvar[NVAR];$/;" kind:variable line:5 language:C typeref:typename:var * [] roles:def end:5 +gvlook var.c /^gvlook(char *name)$/;" kind:function line:77 language:C typeref:typename:var * signature:(char * name) roles:def end:83 +hash var.c /^hash(char *s, int n)$/;" kind:function line:8 language:C typeref:typename:int signature:(char * s,int n) roles:def end:14 +havefork.c havefork.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:240 epoch:1659459892 +havewaitpid havefork.c /^havewaitpid(int pid)$/;" kind:function line:35 language:C typeref:typename:int signature:(int pid) roles:def end:43 +head here.c /^static tree *head, *tail;$/;" kind:variable line:46 language:C typeref:typename:tree * file: roles:def extras:fileScope end:46 +here.c here.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:137 epoch:1659459892 +heredoc here.c /^heredoc(tree *redir)$/;" kind:function line:49 language:C typeref:typename:void signature:(tree * redir) roles:def end:61 +herefile exec.c /^herefile(char *tmp)$/;" kind:function line:459 language:C typeref:typename:int file: signature:(char * tmp) roles:def extras:fileScope end:482 +i plan9.c /^ int i, n;$/;" kind:member line:278 language:C scope:struct:readdir typeref:typename:int file: access:public roles:def extras:fileScope end:278 +i rc.h /^ int i;$/;" kind:member line:76 language:C++ scope:union:code typeref:typename:int access:public roles:def end:76 +iacvt subr.c /^iacvt(int n)$/;" kind:function line:46 language:C typeref:typename:void file: signature:(int n) roles:def extras:fileScope end:55 +idchr lex.c /^idchr(int c)$/;" kind:function line:18 language:C typeref:typename:int signature:(int c) roles:def end:26 +iflag exec.h /^ int iflag; \/* interactive? *\/$/;" kind:member line:55 language:C++ scope:struct:thread typeref:typename:int access:public roles:def end:55 +iflast rc.h /^ char iflast; \/* static `if not' checking *\/$/;" kind:member line:99 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def end:99 +ifnot exec.c /^int ifnot; \/* dynamic if not flag *\/$/;" kind:variable line:419 language:C typeref:typename:int roles:def end:419 +incomm rc.h /^ char incomm;$/;" kind:member line:96 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def end:96 +input rc.h /^ io *input;$/;" kind:member line:83 language:C++ scope:struct:lexer typeref:typename:io * access:public roles:def end:83 +inquote rc.h /^ char inquote;$/;" kind:member line:95 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def end:95 +interrupted plan9.c /^static int interrupted = 0;$/;" kind:variable line:343 language:C typeref:typename:int file: roles:def extras:fileScope end:343 +inttoascii subr.c /^inttoascii(char *s, int n)$/;" kind:function line:58 language:C typeref:typename:void signature:(char * s,int n) roles:def end:63 +io io.h /^struct io{$/;" kind:struct line:3 language:C++ roles:def end:7 +io rc.h /^typedef struct io io;$/;" kind:typedef line:32 language:C++ typeref:struct:io roles:def +io.c io.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:301 epoch:1659459892 +io.h code.c /^#include "io.h"/;" kind:header line:2 language:C roles:local extras:reference +io.h exec.c /^#include "io.h"/;" kind:header line:4 language:C roles:local extras:reference +io.h havefork.c /^#include "io.h"/;" kind:header line:4 language:C roles:local extras:reference +io.h here.c /^#include "io.h"/;" kind:header line:3 language:C roles:local extras:reference +io.h io.c /^#include "io.h"/;" kind:header line:3 language:C roles:local extras:reference +io.h io.h 1;" kind:file line:1 language:C++ roles:def extras:inputFile end:28 epoch:1659459892 +io.h lex.c /^#include "io.h"/;" kind:header line:2 language:C roles:local extras:reference +io.h parse.c /^#include "io.h"/;" kind:header line:2 language:C roles:local extras:reference +io.h pcmd.c /^#include "io.h"/;" kind:header line:2 language:C roles:local extras:reference +io.h pfnc.c /^#include "io.h"/;" kind:header line:3 language:C roles:local extras:reference +io.h plan9.c /^#include "io.h"/;" kind:header line:8 language:C roles:local extras:reference +io.h simple.c /^#include "io.h"/;" kind:header line:7 language:C roles:local extras:reference +io.h subr.c /^#include "io.h"/;" kind:header line:2 language:C roles:local extras:reference +io.h trap.c /^#include "io.h"/;" kind:header line:4 language:C roles:local extras:reference +io.h tree.c /^#include "io.h"/;" kind:header line:2 language:C roles:local extras:reference +io.h unix.c /^#include "io.h"/;" kind:header line:8 language:C roles:local extras:reference +io::buf io.h /^ unsigned char *buf, *bufp, *ebuf;$/;" kind:member line:5 language:C++ scope:struct:io typeref:typename:unsigned char * access:public roles:def extras:qualified end:5 +io::bufp io.h /^ unsigned char *buf, *bufp, *ebuf;$/;" kind:member line:5 language:C++ scope:struct:io typeref:typename:unsigned char * access:public roles:def extras:qualified end:5 +io::ebuf io.h /^ unsigned char *buf, *bufp, *ebuf;$/;" kind:member line:5 language:C++ scope:struct:io typeref:typename:unsigned char * access:public roles:def extras:qualified end:5 +io::fd io.h /^ int fd;$/;" kind:member line:4 language:C++ scope:struct:io typeref:typename:int access:public roles:def extras:qualified end:4 +io::next io.h /^ io *next;$/;" kind:member line:6 language:C++ scope:struct:io typeref:typename:io * access:public roles:def extras:qualified end:6 +iscase code.c /^iscase(tree *t)$/;" kind:function line:508 language:C typeref:typename:int signature:(tree * t) roles:def end:514 +iskw rc.h /^ char iskw;$/;" kind:member line:52 language:C++ scope:struct:tree typeref:typename:char access:public roles:def end:52 +iswordtok parse.c /^iswordtok(int tok)$/;" kind:function line:526 language:C typeref:typename:int file: signature:(int tok) roles:def extras:fileScope end:550 +kenter var.c /^kenter(int type, char *name)$/;" kind:function line:23 language:C typeref:typename:void signature:(int type,char * name) roles:def end:31 +kinit var.c /^kinit(void)$/;" kind:function line:34 language:C typeref:typename:void signature:(void) roles:def end:46 +klook var.c /^klook(char *name)$/;" kind:function line:49 language:C typeref:typename:tree * signature:(char * name) roles:def end:60 +kw var.c /^struct kw{$/;" kind:struct line:16 language:C file: roles:def extras:fileScope end:20 +kw var.c /^}*kw[NKW];$/;" kind:variable line:20 language:C typeref:struct:kw * [] roles:def end:20 +kw::name var.c /^ char *name;$/;" kind:member line:17 language:C scope:struct:kw typeref:typename:char * file: access:public roles:def extras:fileScope,qualified end:17 +kw::next var.c /^ struct kw *next;$/;" kind:member line:19 language:C scope:struct:kw typeref:struct:kw * file: access:public roles:def extras:fileScope,qualified end:19 +kw::type var.c /^ int type;$/;" kind:member line:18 language:C scope:struct:kw typeref:typename:int file: access:public roles:def extras:fileScope,qualified end:18 +lastc rc.h /^ int lastc;$/;" kind:member line:92 language:C++ scope:struct:lexer typeref:typename:int access:public roles:def end:92 +lastdol rc.h /^ char lastdol; \/* was the last token read '$' or '$#' or '"'? *\/$/;" kind:member line:98 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def end:98 +lastword rc.h /^ char lastword; \/* was the last token read a word or compound word terminator? *\/$/;" kind:member line:97 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def end:97 +lex exec.h /^ lexer *lex; \/* lexer for Xrdcmds *\/$/;" kind:member line:54 language:C++ scope:struct:thread typeref:typename:lexer * access:public roles:def end:54 +lex lex.c /^lexer *lex;$/;" kind:variable line:6 language:C typeref:typename:lexer * roles:def end:6 +lex.c lex.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:435 epoch:1659459892 +lexer rc.h /^struct lexer{$/;" kind:struct line:82 language:C++ roles:def end:104 +lexer rc.h /^typedef struct lexer lexer;$/;" kind:typedef line:36 language:C++ typeref:struct:lexer roles:def +lexer::eof rc.h /^ char eof;$/;" kind:member line:94 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def extras:qualified end:94 +lexer::epilog rc.h /^ char *epilog;$/;" kind:member line:88 language:C++ scope:struct:lexer typeref:typename:char * access:public roles:def extras:qualified end:88 +lexer::file rc.h /^ char *file;$/;" kind:member line:84 language:C++ scope:struct:lexer typeref:typename:char * access:public roles:def extras:qualified end:84 +lexer::future rc.h /^ int future;$/;" kind:member line:91 language:C++ scope:struct:lexer typeref:typename:int access:public roles:def extras:qualified end:91 +lexer::iflast rc.h /^ char iflast; \/* static `if not' checking *\/$/;" kind:member line:99 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def extras:qualified end:99 +lexer::incomm rc.h /^ char incomm;$/;" kind:member line:96 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def extras:qualified end:96 +lexer::input rc.h /^ io *input;$/;" kind:member line:83 language:C++ scope:struct:lexer typeref:typename:io * access:public roles:def extras:qualified end:83 +lexer::inquote rc.h /^ char inquote;$/;" kind:member line:95 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def extras:qualified end:95 +lexer::lastc rc.h /^ int lastc;$/;" kind:member line:92 language:C++ scope:struct:lexer typeref:typename:int access:public roles:def extras:qualified end:92 +lexer::lastdol rc.h /^ char lastdol; \/* was the last token read '$' or '$#' or '"'? *\/$/;" kind:member line:98 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def extras:qualified end:98 +lexer::lastword rc.h /^ char lastword; \/* was the last token read a word or compound word terminator? *\/$/;" kind:member line:97 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def extras:qualified end:97 +lexer::line rc.h /^ int line;$/;" kind:member line:85 language:C++ scope:struct:lexer typeref:typename:int access:public roles:def extras:qualified end:85 +lexer::peekc rc.h /^ int peekc;$/;" kind:member line:90 language:C++ scope:struct:lexer typeref:typename:int access:public roles:def extras:qualified end:90 +lexer::prolog rc.h /^ char *prolog;$/;" kind:member line:87 language:C++ scope:struct:lexer typeref:typename:char * access:public roles:def extras:qualified end:87 +lexer::qflag rc.h /^ char qflag;$/;" kind:member line:101 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def extras:qualified end:101 +lexer::tok rc.h /^ char tok[NTOK];$/;" kind:member line:103 language:C++ scope:struct:lexer typeref:typename:char[] access:public roles:def extras:qualified end:103 +libc.h rc.h /^#include /;" kind:header line:9 language:C++ roles:system extras:reference +limits.h rc.h /^#include /;" kind:header line:24 language:C++ roles:system extras:reference +limits.h unix.c /^#include /;" kind:header line:18 language:C roles:system extras:reference +line exec.h /^ int line; \/* source code line for Xsrcline *\/$/;" kind:member line:49 language:C++ scope:struct:thread typeref:typename:int access:public roles:def end:49 +line parse.c /^line(int tok, int *ptok)$/;" kind:function line:69 language:C typeref:typename:tree * file: signature:(int tok,int * ptok) roles:def extras:fileScope end:72 +line rc.h /^ int line;$/;" kind:member line:49 language:C++ scope:struct:tree typeref:typename:int access:public roles:def end:49 +line rc.h /^ int line;$/;" kind:member line:85 language:C++ scope:struct:lexer typeref:typename:int access:public roles:def end:85 +list exec.h /^struct list{$/;" kind:struct line:26 language:C++ roles:def end:29 +list rc.h /^typedef struct list list;$/;" kind:typedef line:35 language:C++ typeref:struct:list roles:def +list::next exec.h /^ list *next;$/;" kind:member line:28 language:C++ scope:struct:list typeref:typename:list * access:public roles:def extras:qualified end:28 +list::words exec.h /^ word *words;$/;" kind:member line:27 language:C++ scope:struct:list typeref:typename:word * access:public roles:def extras:qualified end:27 +local exec.h /^ var *local; \/* list of local variables *\/$/;" kind:member line:53 language:C++ scope:struct:thread typeref:typename:var * access:public roles:def end:53 +main exec.c /^main(int argc, char *argv[], char *envp[])$/;" kind:function line:226 language:C typeref:typename:void signature:(int argc,char * argv[],char * envp[]) roles:def end:290 +makepath simple.c /^makepath(char *dir, char *file)$/;" kind:function line:147 language:C typeref:typename:char * signature:(char * dir,char * file) roles:def end:160 +mapfd simple.c /^mapfd(int fd)$/;" kind:function line:289 language:C typeref:typename:int signature:(int fd) roles:def end:306 +match glob.c /^match(char *s, char *p, int stop)$/;" kind:function line:199 language:C typeref:typename:int signature:(char * s,char * p,int stop) roles:def end:259 +matchfn glob.c /^matchfn(char *s, char *p)$/;" kind:function line:52 language:C typeref:typename:int file: signature:(char * s,char * p) roles:def extras:fileScope end:57 +mkargv simple.c /^mkargv(word *a)$/;" kind:function line:163 language:C typeref:typename:char ** file: signature:(word * a) roles:def extras:fileScope end:170 +mkenv unix.c /^mkenv(void)$/;" kind:function line:95 language:C typeref:typename:char ** file: signature:(void) roles:def extras:fileScope end:152 +morecode code.c /^morecode(void)$/;" kind:function line:23 language:C typeref:typename:int signature:(void) roles:def end:28 +mung1 tree.c /^mung1(tree *t, tree *c0)$/;" kind:function line:92 language:C typeref:typename:tree * signature:(tree * t,tree * c0) roles:def end:96 +mung2 tree.c /^mung2(tree *t, tree *c0, tree *c1)$/;" kind:function line:99 language:C typeref:typename:tree * signature:(tree * t,tree * c0,tree * c1) roles:def end:104 +mung3 tree.c /^mung3(tree *t, tree *c0, tree *c1, tree *c2)$/;" kind:function line:107 language:C typeref:typename:tree * signature:(tree * t,tree * c0,tree * c1,tree * c2) roles:def end:113 +mypid exec.c /^int mypid;$/;" kind:variable line:9 language:C typeref:typename:int roles:def end:9 +n plan9.c /^ int i, n;$/;" kind:member line:278 language:C scope:struct:readdir typeref:typename:int file: access:public roles:def extras:fileScope end:278 +name exec.h /^ char *name;$/;" kind:member line:72 language:C++ scope:struct:builtin typeref:typename:char * access:public roles:def end:72 +name pfnc.c /^ char *name;$/;" kind:member line:7 language:C scope:struct:__anon14948bbd0108 typeref:typename:char * file: access:public roles:def extras:fileScope end:7 +name rc.h /^ char name[];$/;" kind:member line:124 language:C++ scope:struct:var typeref:typename:char[] access:public roles:def end:124 +name var.c /^ char *name;$/;" kind:member line:17 language:C scope:struct:kw typeref:typename:char * file: access:public roles:def extras:fileScope end:17 +ncode code.c /^static int codep, ncode, codeline;$/;" kind:variable line:10 language:C typeref:typename:int file: roles:def extras:fileScope end:10 +nerror lex.c /^int nerror;$/;" kind:variable line:9 language:C typeref:typename:int roles:def end:9 +new rc.h /^#define new(/;" kind:macro line:132 language:C++ signature:(type) roles:def end:132 +newio io.c /^newio(unsigned char *buf, int len, int fd)$/;" kind:function line:212 language:C typeref:typename:io * signature:(unsigned char * buf,int len,int fd) roles:def end:220 +newlexer lex.c /^newlexer(io *input, char *file)$/;" kind:function line:29 language:C typeref:typename:lexer * signature:(io * input,char * file) roles:def end:48 +newtree tree.c /^newtree(void)$/;" kind:function line:12 language:C typeref:typename:tree * signature:(void) roles:def end:30 +newvar var.c /^newvar(char *name, var *next)$/;" kind:function line:63 language:C typeref:typename:var * signature:(char * name,var * next) roles:def end:74 +newwdir plan9.c /^static int newwdir;$/;" kind:variable line:469 language:C typeref:typename:int file: roles:def extras:fileScope end:469 +newword exec.c /^newword(char *s, word *next)$/;" kind:function line:66 language:C typeref:typename:word * signature:(char * s,word * next) roles:def end:69 +next exec.h /^ list *next;$/;" kind:member line:28 language:C++ scope:struct:list typeref:typename:list * access:public roles:def end:28 +next exec.h /^ redir *next; \/* what else to do (reverse order) *\/$/;" kind:member line:35 language:C++ scope:struct:redir typeref:typename:redir * access:public roles:def end:35 +next exec.h /^ word *next;$/;" kind:member line:24 language:C++ scope:struct:word typeref:typename:word * access:public roles:def end:24 +next io.h /^ io *next;$/;" kind:member line:6 language:C++ scope:struct:io typeref:typename:io * access:public roles:def end:6 +next rc.h /^ tree *next;$/;" kind:member line:55 language:C++ scope:struct:tree typeref:typename:tree * access:public roles:def end:55 +next rc.h /^ var *next; \/* next on hash or local list *\/$/;" kind:member line:118 language:C++ scope:struct:var typeref:typename:var * access:public roles:def end:118 +next var.c /^ struct kw *next;$/;" kind:member line:19 language:C scope:struct:kw typeref:struct:kw * file: access:public roles:def extras:fileScope end:19 +nextc lex.c /^nextc(void)$/;" kind:function line:108 language:C typeref:typename:int file: signature:(void) roles:def extras:fileScope end:113 +nextenv unix.c /^static char **nextenv;$/;" kind:variable line:274 language:C typeref:typename:char ** file: roles:def extras:fileScope end:274 +nextis lex.c /^nextis(int c)$/;" kind:function line:167 language:C typeref:typename:int file: signature:(int c) roles:def extras:fileScope end:174 +nextutf glob.c /^nextutf(char *p)$/;" kind:function line:146 language:C typeref:typename:char * file: signature:(char * p) roles:def extras:fileScope end:162 +noglobs code.c /^noglobs(tree *t, int pattern)$/;" kind:function line:65 language:C typeref:typename:void signature:(tree * t,int pattern) roles:def end:84 +notifyf plan9.c /^notifyf(void*, char *s)$/;" kind:function line:346 language:C typeref:typename:void file: signature:(void *,char * s) roles:def extras:fileScope end:362 +ntab pcmd.c /^static int ntab = 0;$/;" kind:variable line:19 language:C typeref:typename:int file: roles:def extras:fileScope end:19 +ntrap trap.c /^int ntrap;$/;" kind:variable line:6 language:C typeref:typename:int roles:def end:6 +nwaitpids havefork.c /^static int nwaitpids;$/;" kind:variable line:8 language:C typeref:typename:int file: roles:def extras:fileScope end:8 +onebyte rc.h /^#define onebyte(/;" kind:macro line:150 language:C++ signature:(c) roles:def end:150 +openiocore io.c /^openiocore(void *buf, int len)$/;" kind:function line:258 language:C typeref:typename:io * signature:(void * buf,int len) roles:def end:261 +openiofd io.c /^openiofd(int fd)$/;" kind:function line:248 language:C typeref:typename:io * signature:(int fd) roles:def end:251 +openiostr io.c /^openiostr(void)$/;" kind:function line:226 language:C typeref:typename:io * signature:(void) roles:def end:231 +outcode code.c /^outcode(tree *t, int eflag)$/;" kind:function line:87 language:C typeref:typename:void signature:(tree * t,int eflag) roles:def end:434 +panic subr.c /^panic(char *s, int n)$/;" kind:function line:66 language:C typeref:typename:void signature:(char * s,int n) roles:def end:74 +pappend glob.c /^pappend(char **pdir, char *name)$/;" kind:function line:60 language:C typeref:typename:void file: signature:(char ** pdir,char * name) roles:def extras:fileScope end:65 +paren parse.c /^paren(int tok)$/;" kind:function line:136 language:C typeref:typename:tree * file: signature:(int tok) roles:def extras:fileScope end:149 +parse parse.c /^parse(void)$/;" kind:function line:47 language:C typeref:typename:int signature:(void) roles:def end:66 +parse.c parse.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:550 epoch:1659462012 +pc exec.h /^ int pc; \/* code[pc] is the next instruction *\/$/;" kind:member line:48 language:C++ scope:struct:thread typeref:typename:int access:public roles:def end:48 +pc rc.h /^ int pc; \/* pc of start of function *\/$/;" kind:member line:121 language:C++ scope:struct:var typeref:typename:int access:public roles:def end:121 +pchr io.c /^pchr(io *b, int c)$/;" kind:function line:65 language:C typeref:typename:void signature:(io * b,int c) roles:def end:70 +pcmd pcmd.c /^pcmd(io *f, tree *t)$/;" kind:function line:28 language:C typeref:typename:void signature:(io * f,tree * t) roles:def end:169 +pcmd.c pcmd.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:169 epoch:1659459892 +pdec io.c /^pdec(io *f, int n)$/;" kind:function line:169 language:C typeref:typename:void signature:(io * f,int n) roles:def end:188 +pdeglob pcmd.c /^pdeglob(io *f, char *s)$/;" kind:function line:10 language:C typeref:typename:void file: signature:(io * f,char * s) roles:def extras:fileScope end:17 +peekc rc.h /^ int peekc;$/;" kind:member line:90 language:C++ scope:struct:lexer typeref:typename:int access:public roles:def end:90 +pfln subr.c /^pfln(io *fd, char *file, int line)$/;" kind:function line:33 language:C typeref:typename:void signature:(io * fd,char * file,int line) roles:def end:41 +pfmt io.c /^pfmt(io *f, char *fmt, ...)$/;" kind:function line:56 language:C typeref:typename:void signature:(io * f,char * fmt,...) roles:def end:62 +pfnc pfnc.c /^pfnc(io *f, thread *t)$/;" kind:function line:68 language:C typeref:typename:void signature:(io * f,thread * t) roles:def end:78 +pfnc.c pfnc.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:78 epoch:1659459892 +pfun pfnc.c /^pfun(io *f, void (*fn)(void))$/;" kind:function line:57 language:C typeref:typename:void signature:(io * f,void (* fn)(void)) roles:def end:65 +pid exec.h /^ int pid; \/* process for Xpipewait to wait for *\/$/;" kind:member line:56 language:C++ scope:struct:thread typeref:typename:int access:public roles:def end:56 +pipe rc.h /^#undef pipe /;" kind:macro line:41 language:C++ roles:undef extras:reference +plan9.c plan9.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:494 epoch:1659459892 +poct io.c /^poct(io *f, unsigned n)$/;" kind:function line:191 language:C typeref:typename:void signature:(io * f,unsigned n) roles:def end:196 +poplist exec.c /^poplist(void)$/;" kind:function line:142 language:C typeref:typename:void signature:(void) roles:def end:145 +popthread exec.c /^popthread(void)$/;" kind:function line:44 language:C typeref:typename:void file: signature:(void) roles:def extras:fileScope end:55 +popword exec.c /^popword(void)$/;" kind:function line:116 language:C typeref:typename:void signature:(void) roles:def end:119 +pprompt exec.c /^pprompt(void)$/;" kind:function line:1051 language:C typeref:typename:void signature:(void) roles:def end:1066 +pptr io.c /^pptr(io *f, void *p)$/;" kind:function line:148 language:C typeref:typename:void signature:(io * f,void * p) roles:def end:158 +pquo io.c /^pquo(io *f, char *s)$/;" kind:function line:126 language:C typeref:typename:void signature:(io * f,char * s) roles:def end:135 +prolog rc.h /^ char *prolog;$/;" kind:member line:87 language:C++ scope:struct:lexer typeref:typename:char * access:public roles:def end:87 +promptstr exec.c /^static char *promptstr;$/;" kind:variable line:1007 language:C typeref:typename:char * file: roles:def extras:fileScope end:1007 +pstr io.c /^pstr(io *f, char *s)$/;" kind:function line:161 language:C typeref:typename:void signature:(io * f,char * s) roles:def end:166 +pstrs here.c /^pstrs(io *f, word *a)$/;" kind:function line:127 language:C typeref:typename:void signature:(io * f,word * a) roles:def end:137 +psubst here.c /^psubst(io *f, unsigned char *s)$/;" kind:function line:75 language:C typeref:typename:void signature:(io * f,unsigned char * s) roles:def end:124 +pushlist exec.c /^pushlist(void)$/;" kind:function line:122 language:C typeref:typename:void signature:(void) roles:def end:128 +pushredir exec.c /^pushredir(int type, int from, int to)$/;" kind:function line:156 language:C typeref:typename:void signature:(int type,int from,int to) roles:def end:164 +pushword exec.c /^pushword(char *s)$/;" kind:function line:83 language:C typeref:typename:word * signature:(char * s) roles:def end:86 +pval io.c /^pval(io *f, word *a)$/;" kind:function line:199 language:C typeref:typename:void signature:(io * f,word * a) roles:def end:209 +pwrd io.c /^pwrd(io *f, char *s)$/;" kind:function line:138 language:C typeref:typename:void signature:(io * f,char * s) roles:def end:145 +qflag rc.h /^ char qflag;$/;" kind:member line:101 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def end:101 +quoted rc.h /^ char quoted;$/;" kind:member line:51 language:C++ scope:struct:tree typeref:typename:char access:public roles:def end:51 +rc syn.y /^rc: { return 1;}$/;" kind:label line:24 language:YACC roles:def +rc.h code.c /^#include "rc.h"/;" kind:header line:1 language:C roles:local extras:reference +rc.h exec.c /^#include "rc.h"/;" kind:header line:1 language:C roles:local extras:reference +rc.h getflags.c /^#include "rc.h"/;" kind:header line:1 language:C roles:local extras:reference +rc.h glob.c /^#include "rc.h"/;" kind:header line:1 language:C roles:local extras:reference +rc.h havefork.c /^#include "rc.h"/;" kind:header line:1 language:C roles:local extras:reference +rc.h here.c /^#include "rc.h"/;" kind:header line:1 language:C roles:local extras:reference +rc.h io.c /^#include "rc.h"/;" kind:header line:1 language:C roles:local extras:reference +rc.h lex.c /^#include "rc.h"/;" kind:header line:1 language:C roles:local extras:reference +rc.h parse.c /^#include "rc.h"/;" kind:header line:1 language:C roles:local extras:reference +rc.h pcmd.c /^#include "rc.h"/;" kind:header line:1 language:C roles:local extras:reference +rc.h pfnc.c /^#include "rc.h"/;" kind:header line:1 language:C roles:local extras:reference +rc.h plan9.c /^#include "rc.h"/;" kind:header line:6 language:C roles:local extras:reference +rc.h rc.h 1;" kind:file line:1 language:C++ roles:def extras:inputFile end:170 epoch:1659461111 +rc.h simple.c /^#include "rc.h"/;" kind:header line:4 language:C roles:local extras:reference +rc.h subr.c /^#include "rc.h"/;" kind:header line:1 language:C roles:local extras:reference +rc.h syn.y /^#include "rc.h"/;" kind:header line:13 language:C roles:local extras:reference,guest +rc.h trap.c /^#include "rc.h"/;" kind:header line:1 language:C roles:local extras:reference +rc.h tree.c /^#include "rc.h"/;" kind:header line:1 language:C roles:local extras:reference +rc.h unix.c /^#include "rc.h"/;" kind:header line:6 language:C roles:local extras:reference +rc.h var.c /^#include "rc.h"/;" kind:header line:1 language:C roles:local extras:reference +rc.h y.tab.c /^#include "rc.h"/;" kind:header line:29 language:C roles:local extras:reference +rchr io.c /^rchr(io *b)$/;" kind:function line:73 language:C typeref:typename:int signature:(io * b) roles:def end:78 +readdir plan9.c /^struct readdir {$/;" kind:struct line:276 language:C file: roles:def extras:fileScope end:280 +readdir plan9.c /^typedef struct readdir readdir;$/;" kind:typedef line:275 language:C typeref:struct:readdir file: roles:def extras:fileScope +readdir::dbuf plan9.c /^ Dir *dbuf;$/;" kind:member line:277 language:C scope:struct:readdir typeref:typename:Dir * file: access:public roles:def extras:fileScope,qualified end:277 +readdir::fd plan9.c /^ int fd;$/;" kind:member line:279 language:C scope:struct:readdir typeref:typename:int file: access:public roles:def extras:fileScope,qualified end:279 +readdir::i plan9.c /^ int i, n;$/;" kind:member line:278 language:C scope:struct:readdir typeref:typename:int file: access:public roles:def extras:fileScope,qualified end:278 +readdir::n plan9.c /^ int i, n;$/;" kind:member line:278 language:C scope:struct:readdir typeref:typename:int file: access:public roles:def extras:fileScope,qualified end:278 +readhere here.c /^readhere(io *in)$/;" kind:function line:64 language:C typeref:typename:void signature:(io * in) roles:def end:72 +readhere1 here.c /^readhere1(tree *tag, io *in)$/;" kind:function line:10 language:C typeref:typename:char * file: signature:(tree * tag,io * in) roles:def extras:fileScope end:44 +reason getflags.c /^static int reason;$/;" kind:variable line:13 language:C typeref:typename:int file: roles:def extras:fileScope end:13 +redir exec.h /^ redir *redir; \/* redirection stack *\/$/;" kind:member line:51 language:C++ scope:struct:thread typeref:typename:redir * access:public roles:def end:51 +redir exec.h /^struct redir{$/;" kind:struct line:32 language:C++ roles:def end:36 +redir rc.h /^typedef struct redir redir;$/;" kind:typedef line:37 language:C++ typeref:struct:redir roles:def +redir::from exec.h /^ int from, to; \/* what to do it to *\/$/;" kind:member line:34 language:C++ scope:struct:redir typeref:typename:int access:public roles:def extras:qualified end:34 +redir::next exec.h /^ redir *next; \/* what else to do (reverse order) *\/$/;" kind:member line:35 language:C++ scope:struct:redir typeref:typename:redir * access:public roles:def extras:qualified end:35 +redir::to exec.h /^ int from, to; \/* what to do it to *\/$/;" kind:member line:34 language:C++ scope:struct:redir typeref:typename:int access:public roles:def extras:qualified end:34 +redir::type exec.h /^ int type; \/* what to do *\/$/;" kind:member line:33 language:C++ scope:struct:redir typeref:typename:int access:public roles:def extras:qualified end:33 +ret exec.h /^ thread *ret; \/* who continues when this finishes *\/$/;" kind:member line:58 language:C++ scope:struct:thread typeref:typename:thread * access:public roles:def end:58 +reverse getflags.c /^reverse(char **p, char **q)$/;" kind:function line:78 language:C typeref:typename:void file: signature:(char ** p,char ** q) roles:def extras:fileScope end:82 +rstr io.c /^rstr(io *b, char *stop)$/;" kind:function line:81 language:C typeref:typename:char * signature:(io * b,char * stop) roles:def end:123 +rtype rc.h /^ int rtype, fd0, fd1; \/* details of REDIR PIPE DUP tokens *\/$/;" kind:member line:48 language:C++ scope:struct:tree typeref:typename:int access:public roles:def end:48 +runq exec.c /^thread *runq;$/;" kind:variable line:10 language:C typeref:typename:thread * roles:def end:10 +s rc.h /^ char *s;$/;" kind:member line:77 language:C++ scope:union:code typeref:typename:char * access:public roles:def end:77 +scanflag getflags.c /^scanflag(int c, char *f)$/;" kind:function line:85 language:C typeref:typename:int file: signature:(int c,char * f) roles:def extras:fileScope end:116 +setstatus exec.c /^setstatus(char *s)$/;" kind:function line:1108 language:C typeref:typename:void signature:(char * s) roles:def end:1111 +setvar var.c /^setvar(char *name, word *val)$/;" kind:function line:96 language:C typeref:typename:void signature:(char * name,word * val) roles:def end:102 +shuffleredir exec.c /^shuffleredir(void)$/;" kind:function line:204 language:C typeref:typename:void signature:(void) roles:def end:216 +sighandler unix.c /^sighandler(int sig)$/;" kind:function line:186 language:C typeref:typename:void file: signature:(int sig) roles:def extras:fileScope end:190 +signal.h rc.h /^#include /;" kind:header line:18 language:C++ roles:system extras:reference +simple.c simple.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:537 epoch:1659461225 +simplemung tree.c /^simplemung(tree *t)$/;" kind:function line:131 language:C typeref:typename:tree * signature:(tree * t) roles:def end:146 +skipnl lex.c /^skipnl(void)$/;" kind:function line:154 language:C typeref:typename:void signature:(void) roles:def end:164 +skipwhite lex.c /^skipwhite(void)$/;" kind:function line:130 language:C typeref:typename:void file: signature:(void) roles:def extras:fileScope end:151 +srcfile exec.c /^srcfile(thread *p)$/;" kind:function line:1069 language:C typeref:typename:char * signature:(thread * p) roles:def end:1072 +start exec.c /^start(code *c, int pc, var *local, redir *redir)$/;" kind:function line:17 language:C typeref:typename:void signature:(code * c,int pc,var * local,redir * redir) roles:def end:32 +startfunc exec.c /^startfunc(var *func, word *starval, var *local, redir *redir)$/;" kind:function line:35 language:C typeref:typename:void signature:(var * func,word * starval,var * local,redir * redir) roles:def end:41 +startredir exec.h /^ redir *startredir; \/* redir inheritance point *\/$/;" kind:member line:52 language:C++ scope:struct:thread typeref:typename:redir * access:public roles:def end:52 +status exec.h /^ char *status; \/* status for Xpipewait *\/$/;" kind:member line:57 language:C++ scope:struct:thread typeref:typename:char * access:public roles:def end:57 +stdarg.h rc.h /^#include /;" kind:header line:15 language:C++ roles:system extras:reference +stdlib.h rc.h /^#include /;" kind:header line:14 language:C++ roles:system extras:reference +str rc.h /^ char *str;$/;" kind:member line:53 language:C++ scope:struct:tree typeref:typename:char * access:public roles:def end:53 +string.h rc.h /^#include /;" kind:header line:17 language:C++ roles:system extras:reference +stuffdot code.c /^stuffdot(int a)$/;" kind:function line:31 language:C typeref:typename:void signature:(int a) roles:def end:36 +subr.c subr.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:74 epoch:1659459892 +subwords exec.c /^subwords(word *val, int len, word *sub, word *a)$/;" kind:function line:842 language:C typeref:typename:word * file: signature:(word * val,int len,word * sub,word * a) roles:def extras:fileScope end:871 +syn.y syn.y 1;" kind:file line:1 language:YACC roles:def extras:inputFile end:92 epoch:1659462178 +syntax parse.c /^syntax(int tok)$/;" kind:function line:39 language:C typeref:typename:void file: signature:(int tok) roles:def extras:fileScope end:44 +sys/wait.h unix.c /^#include /;" kind:header line:19 language:C roles:system extras:reference +syssigname plan9.c /^static char *syssigname[] = {$/;" kind:variable line:38 language:C typeref:typename:char * [] file: roles:def extras:fileScope end:48 +tabs pcmd.c /^tabs(void)$/;" kind:function line:22 language:C typeref:typename:char * file: signature:(void) roles:def extras:fileScope end:25 +tail here.c /^static tree *head, *tail;$/;" kind:variable line:46 language:C typeref:typename:tree * file: roles:def extras:fileScope end:46 +test.rc test.rc 1;" kind:file line:1 language:WindRes roles:def extras:inputFile end:93 epoch:1659461757 +thread exec.h /^struct thread{$/;" kind:struct line:46 language:C++ roles:def end:59 +thread rc.h /^typedef struct thread thread;$/;" kind:typedef line:38 language:C++ typeref:struct:thread roles:def +thread::argv exec.h /^ list *argv; \/* argument stack *\/$/;" kind:member line:50 language:C++ scope:struct:thread typeref:typename:list * access:public roles:def extras:qualified end:50 +thread::code exec.h /^ code *code; \/* code for this thread *\/$/;" kind:member line:47 language:C++ scope:struct:thread typeref:typename:code * access:public roles:def extras:qualified end:47 +thread::iflag exec.h /^ int iflag; \/* interactive? *\/$/;" kind:member line:55 language:C++ scope:struct:thread typeref:typename:int access:public roles:def extras:qualified end:55 +thread::lex exec.h /^ lexer *lex; \/* lexer for Xrdcmds *\/$/;" kind:member line:54 language:C++ scope:struct:thread typeref:typename:lexer * access:public roles:def extras:qualified end:54 +thread::line exec.h /^ int line; \/* source code line for Xsrcline *\/$/;" kind:member line:49 language:C++ scope:struct:thread typeref:typename:int access:public roles:def extras:qualified end:49 +thread::local exec.h /^ var *local; \/* list of local variables *\/$/;" kind:member line:53 language:C++ scope:struct:thread typeref:typename:var * access:public roles:def extras:qualified end:53 +thread::pc exec.h /^ int pc; \/* code[pc] is the next instruction *\/$/;" kind:member line:48 language:C++ scope:struct:thread typeref:typename:int access:public roles:def extras:qualified end:48 +thread::pid exec.h /^ int pid; \/* process for Xpipewait to wait for *\/$/;" kind:member line:56 language:C++ scope:struct:thread typeref:typename:int access:public roles:def extras:qualified end:56 +thread::redir exec.h /^ redir *redir; \/* redirection stack *\/$/;" kind:member line:51 language:C++ scope:struct:thread typeref:typename:redir * access:public roles:def extras:qualified end:51 +thread::ret exec.h /^ thread *ret; \/* who continues when this finishes *\/$/;" kind:member line:58 language:C++ scope:struct:thread typeref:typename:thread * access:public roles:def extras:qualified end:58 +thread::startredir exec.h /^ redir *startredir; \/* redir inheritance point *\/$/;" kind:member line:52 language:C++ scope:struct:thread typeref:typename:redir * access:public roles:def extras:qualified end:52 +thread::status exec.h /^ char *status; \/* status for Xpipewait *\/$/;" kind:member line:57 language:C++ scope:struct:thread typeref:typename:char * access:public roles:def extras:qualified end:57 +threebyte rc.h /^#define threebyte(/;" kind:macro line:152 language:C++ signature:(c) roles:def end:152 +to exec.h /^ int from, to; \/* what to do it to *\/$/;" kind:member line:34 language:C++ scope:struct:redir typeref:typename:int access:public roles:def end:34 +tok rc.h /^ char tok[NTOK];$/;" kind:member line:103 language:C++ scope:struct:lexer typeref:typename:char[] access:public roles:def end:103 +token tree.c /^token(char *str, int type)$/;" kind:function line:184 language:C typeref:typename:tree * signature:(char * str,int type) roles:def end:190 +trap trap.c /^int trap[NSIG];$/;" kind:variable line:7 language:C typeref:typename:int[] roles:def end:7 +trap.c trap.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:34 epoch:1659459892 +tree rc.h /^struct tree{$/;" kind:struct line:46 language:C++ roles:def end:56 +tree rc.h /^typedef struct tree tree;$/;" kind:typedef line:30 language:C++ typeref:struct:tree roles:def +tree syn.y /^ struct tree *tree;$/;" kind:member line:17 language:C scope:union:__anon10643646010a typeref:struct:tree * file: access:public roles:def extras:fileScope,guest end:17 +tree y.tab.c /^ struct tree *tree;$/;" kind:member line:34 language:C scope:union:__anond9bd93f4010a typeref:struct:tree * file: access:public roles:def extras:fileScope end:34 +tree y.tab.h /^ struct tree *tree;$/;" kind:member line:29 language:C++ scope:union:__anond9bd93f9010a typeref:struct:tree * access:public roles:def end:29 +tree.c tree.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:190 epoch:1659459892 +tree1 tree.c /^tree1(int type, tree *c0)$/;" kind:function line:55 language:C typeref:typename:tree * signature:(int type,tree * c0) roles:def end:58 +tree2 tree.c /^tree2(int type, tree *c0, tree *c1)$/;" kind:function line:61 language:C typeref:typename:tree * signature:(int type,tree * c0,tree * c1) roles:def end:64 +tree3 tree.c /^tree3(int type, tree *c0, tree *c1, tree *c2)$/;" kind:function line:67 language:C typeref:typename:tree * signature:(int type,tree * c0,tree * c1,tree * c2) roles:def end:89 +tree::child rc.h /^ tree *child[3];$/;" kind:member line:54 language:C++ scope:struct:tree typeref:typename:tree * [3] access:public roles:def extras:qualified end:54 +tree::fd0 rc.h /^ int rtype, fd0, fd1; \/* details of REDIR PIPE DUP tokens *\/$/;" kind:member line:48 language:C++ scope:struct:tree typeref:typename:int access:public roles:def extras:qualified end:48 +tree::fd1 rc.h /^ int rtype, fd0, fd1; \/* details of REDIR PIPE DUP tokens *\/$/;" kind:member line:48 language:C++ scope:struct:tree typeref:typename:int access:public roles:def extras:qualified end:48 +tree::glob rc.h /^ char glob; \/* 0=string, 1=glob, 2=pattern see globprop() and noglobs() *\/$/;" kind:member line:50 language:C++ scope:struct:tree typeref:typename:char access:public roles:def extras:qualified end:50 +tree::iskw rc.h /^ char iskw;$/;" kind:member line:52 language:C++ scope:struct:tree typeref:typename:char access:public roles:def extras:qualified end:52 +tree::line rc.h /^ int line;$/;" kind:member line:49 language:C++ scope:struct:tree typeref:typename:int access:public roles:def extras:qualified end:49 +tree::next rc.h /^ tree *next;$/;" kind:member line:55 language:C++ scope:struct:tree typeref:typename:tree * access:public roles:def extras:qualified end:55 +tree::quoted rc.h /^ char quoted;$/;" kind:member line:51 language:C++ scope:struct:tree typeref:typename:char access:public roles:def extras:qualified end:51 +tree::rtype rc.h /^ int rtype, fd0, fd1; \/* details of REDIR PIPE DUP tokens *\/$/;" kind:member line:48 language:C++ scope:struct:tree typeref:typename:int access:public roles:def extras:qualified end:48 +tree::str rc.h /^ char *str;$/;" kind:member line:53 language:C++ scope:struct:tree typeref:typename:char * access:public roles:def extras:qualified end:53 +tree::type rc.h /^ int type;$/;" kind:member line:47 language:C++ scope:struct:tree typeref:typename:int access:public roles:def extras:qualified end:47 +treefree tree.c /^static tree *treefree, *treenodes;$/;" kind:variable line:9 language:C typeref:typename:tree * file: roles:def extras:fileScope end:9 +treenodes tree.c /^static tree *treefree, *treenodes;$/;" kind:variable line:9 language:C typeref:typename:tree * file: roles:def extras:fileScope end:9 +trimdirs plan9.c /^trimdirs(Dir *d, int nd)$/;" kind:function line:298 language:C typeref:typename:int file: signature:(Dir * d,int nd) roles:def extras:fileScope end:306 +truestatus exec.c /^truestatus(void)$/;" kind:function line:1131 language:C typeref:typename:int signature:(void) roles:def end:1138 +turfstack exec.c /^turfstack(var *local)$/;" kind:function line:188 language:C typeref:typename:void signature:(var * local) roles:def end:201 +twobyte rc.h /^#define twobyte(/;" kind:macro line:151 language:C++ signature:(c) roles:def end:151 +type exec.h /^ int type; \/* what to do *\/$/;" kind:member line:33 language:C++ scope:struct:redir typeref:typename:int access:public roles:def end:33 +type rc.h /^ int type;$/;" kind:member line:47 language:C++ scope:struct:tree typeref:typename:int access:public roles:def end:47 +type var.c /^ int type;$/;" kind:member line:18 language:C scope:struct:kw typeref:typename:int file: access:public roles:def extras:fileScope end:18 +u.h rc.h /^#include /;" kind:header line:8 language:C++ roles:system extras:reference +unicode glob.c /^unicode(char *p)$/;" kind:function line:168 language:C typeref:typename:int file: signature:(char * p) roles:def extras:fileScope end:185 +unistd.h rc.h /^#include /;" kind:header line:16 language:C++ roles:system extras:reference +unix.c unix.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:424 epoch:1659461425 +updenvlocal plan9.c /^updenvlocal(var *v)$/;" kind:function line:240 language:C typeref:typename:void file: signature:(var * v) roles:def extras:fileScope end:246 +usage getflags.c /^usage(char *tail)$/;" kind:function line:119 language:C typeref:typename:void signature:(char * tail) roles:def end:210 +val rc.h /^ word *val; \/* value *\/$/;" kind:member line:119 language:C++ scope:struct:var typeref:typename:word * access:public roles:def end:119 +var rc.h /^struct var{$/;" kind:struct line:117 language:C++ roles:def end:125 +var rc.h /^typedef struct var var;$/;" kind:typedef line:34 language:C++ typeref:struct:var roles:def +var.c var.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:109 epoch:1659459892 +var::changed rc.h /^ char changed;$/;" kind:member line:123 language:C++ scope:struct:var typeref:typename:char access:public roles:def extras:qualified end:123 +var::fn rc.h /^ code *fn; \/* pointer to function's code vector *\/$/;" kind:member line:120 language:C++ scope:struct:var typeref:typename:code * access:public roles:def extras:qualified end:120 +var::fnchanged rc.h /^ char fnchanged;$/;" kind:member line:122 language:C++ scope:struct:var typeref:typename:char access:public roles:def extras:qualified end:122 +var::name rc.h /^ char name[];$/;" kind:member line:124 language:C++ scope:struct:var typeref:typename:char[] access:public roles:def extras:qualified end:124 +var::next rc.h /^ var *next; \/* next on hash or local list *\/$/;" kind:member line:118 language:C++ scope:struct:var typeref:typename:var * access:public roles:def extras:qualified end:118 +var::pc rc.h /^ int pc; \/* pc of start of function *\/$/;" kind:member line:121 language:C++ scope:struct:var typeref:typename:int access:public roles:def extras:qualified end:121 +var::val rc.h /^ word *val; \/* value *\/$/;" kind:member line:119 language:C++ scope:struct:var typeref:typename:word * access:public roles:def extras:qualified end:119 +vlook var.c /^vlook(char *name)$/;" kind:function line:86 language:C typeref:typename:var * signature:(char * name) roles:def end:93 +vpfmt io.c /^vpfmt(io *f, char *fmt, va_list ap)$/;" kind:function line:11 language:C typeref:typename:void signature:(io * f,char * fmt,va_list ap) roles:def end:53 +wait unix.c /^#undef wait$/;" kind:macro line:12 language:C file: roles:undef extras:fileScope,reference +waitpid unix.c /^#undef waitpid$/;" kind:macro line:13 language:C file: roles:undef extras:fileScope,reference +waitpids havefork.c /^static int *waitpids;$/;" kind:variable line:7 language:C typeref:typename:int * file: roles:def extras:fileScope end:7 +word exec.h /^ char *word;$/;" kind:member line:23 language:C++ scope:struct:word typeref:typename:char * access:public roles:def end:23 +word exec.h /^struct word{$/;" kind:struct line:22 language:C++ roles:def end:25 +word rc.h /^typedef struct word word;$/;" kind:typedef line:31 language:C++ typeref:struct:word roles:def +word1 parse.c /^word1(int tok, int *ptok)$/;" kind:function line:448 language:C typeref:typename:tree * file: signature:(int tok,int * ptok) roles:def extras:fileScope end:523 +word::next exec.h /^ word *next;$/;" kind:member line:24 language:C++ scope:struct:word typeref:typename:word * access:public roles:def extras:qualified end:24 +word::word exec.h /^ char *word;$/;" kind:member line:23 language:C++ scope:struct:word typeref:typename:char * access:public roles:def extras:qualified end:23 +wordchr lex.c /^wordchr(int c)$/;" kind:function line:12 language:C typeref:typename:int signature:(int c) roles:def end:15 +words exec.h /^ word *words;$/;" kind:member line:27 language:C++ scope:struct:list typeref:typename:word * access:public roles:def end:27 +words parse.c /^words(int tok, int *ptok)$/;" kind:function line:384 language:C typeref:typename:tree * file: signature:(int tok,int * ptok) roles:def extras:fileScope end:397 +xbyte rc.h /^#define xbyte(/;" kind:macro line:154 language:C++ signature:(c) roles:def end:154 +y.debug y.tab.c /^#include "y.debug"/;" kind:header line:203 language:C roles:local extras:reference +y.tab.c y.tab.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:621 epoch:1659462189 +y.tab.h rc.h /^#include "y.tab.h"/;" kind:header line:28 language:C++ roles:local extras:reference +y.tab.h y.tab.h 1;" kind:file line:1 language:C++ roles:def extras:inputFile end:31 epoch:1659462189 +yyact y.tab.c /^static const short yyact[] =$/;" kind:variable line:55 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:95 +yychk y.tab.c /^static const short yychk[] =$/;" kind:variable line:139 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:153 +yyclearin y.tab.c /^#define yyclearin /;" kind:macro line:199 language:C file: roles:def extras:fileScope end:199 +yydebug y.tab.c /^#define yydebug /;" kind:macro line:205 language:C file: roles:def extras:fileScope end:205 +yydef y.tab.c /^static const short yydef[] =$/;" kind:variable line:154 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:168 +yyerrflag y.tab.c /^#define yyerrflag /;" kind:macro line:213 language:C file: roles:def extras:fileScope end:213 +yyerrflag y.tab.c /^int yyerrflag = 0; \/* error recovery flag *\/$/;" kind:variable line:218 language:C typeref:typename:int roles:def end:218 +yyerrok y.tab.c /^#define yyerrok /;" kind:macro line:200 language:C file: roles:def extras:fileScope end:200 +yyerror lex.c /^yyerror(char *m)$/;" kind:function line:420 language:C typeref:typename:void signature:(char * m) roles:def end:435 +yyexca y.tab.c /^static const short yyexca[] =$/;" kind:variable line:44 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:51 +yyjmp parse.c /^static jmp_buf yyjmp;$/;" kind:variable line:20 language:C typeref:typename:jmp_buf file: roles:def extras:fileScope end:20 +yylex lex.c /^yylex(void)$/;" kind:function line:214 language:C typeref:typename:int signature:(void) roles:def end:417 +yylex1 y.tab.c /^yylex1(struct Yyarg *yyarg)$/;" kind:function line:250 language:C typeref:typename:long file: signature:(struct Yyarg * yyarg) roles:def extras:fileScope end:294 +yylval y.tab.c /^#define yylval /;" kind:macro line:215 language:C file: roles:def extras:fileScope end:215 +yylval y.tab.c /^YYSTYPE yylval;$/;" kind:variable line:40 language:C typeref:typename:YYSTYPE roles:def end:40 +yynerrs y.tab.c /^#define yynerrs /;" kind:macro line:212 language:C file: roles:def extras:fileScope end:212 +yynerrs y.tab.c /^int yynerrs = 0; \/* number of errors *\/$/;" kind:variable line:217 language:C typeref:typename:int roles:def end:217 +yypact y.tab.c /^static const short yypact[] =$/;" kind:variable line:96 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:110 +yyparse y.tab.c /^yyparse(struct Yyarg *yyarg)$/;" kind:function line:298 language:C typeref:typename:int signature:(struct Yyarg * yyarg) roles:def end:621 +yyparse::__anond9bd93f40208::yys y.tab.c /^ int yys;$/;" kind:member line:306 language:C scope:struct:yyparse::__anond9bd93f40208 typeref:typename:int file: access:public roles:def extras:fileScope,qualified end:306 +yyparse::__anond9bd93f40208::yyv y.tab.c /^ YYSTYPE yyv;$/;" kind:member line:305 language:C scope:struct:yyparse::__anond9bd93f40208 typeref:typename:YYSTYPE file: access:public roles:def extras:fileScope,qualified end:305 +yypgo y.tab.c /^static const short yypgo[] =$/;" kind:variable line:111 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:116 +yyr1 y.tab.c /^static const short yyr1[] =$/;" kind:variable line:117 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:127 +yyr2 y.tab.c /^static const short yyr2[] =$/;" kind:variable line:128 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:138 +yyredir parse.c /^yyredir(int tok, int *ptok)$/;" kind:function line:171 language:C typeref:typename:tree * file: signature:(int tok,int * ptok) roles:def extras:fileScope end:193 +yys y.tab.c /^ int yys;$/;" kind:member line:306 language:C scope:struct:yyparse::__anond9bd93f40208 typeref:typename:int file: access:public roles:def extras:fileScope end:306 +yystates y.tab.c /^static const char* yystates[1]; \/* for debugging *\/$/;" kind:variable line:207 language:C typeref:typename:const char * [1] file: roles:def extras:fileScope end:207 +yystatname y.tab.c /^yystatname(int yys)$/;" kind:function line:237 language:C typeref:typename:const char * file: signature:(int yys) roles:def extras:fileScope end:246 +yytok1 y.tab.c /^static const short yytok1[] =$/;" kind:variable line:169 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:184 +yytok2 y.tab.c /^static const short yytok2[] =$/;" kind:variable line:185 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:190 +yytok3 y.tab.c /^static const long yytok3[] =$/;" kind:variable line:191 language:C typeref:typename:const long[] file: roles:def extras:fileScope end:194 +yytokname y.tab.c /^yytokname(int yyc)$/;" kind:function line:225 language:C typeref:typename:const char * file: signature:(int yyc) roles:def extras:fileScope end:234 +yytoknames y.tab.c /^static const char* yytoknames[1]; \/* for debugging *\/$/;" kind:variable line:206 language:C typeref:typename:const char * [1] file: roles:def extras:fileScope end:206 +yyv y.tab.c /^ YYSTYPE yyv;$/;" kind:member line:305 language:C scope:struct:yyparse::__anond9bd93f40208 typeref:typename:YYSTYPE file: access:public roles:def extras:fileScope end:305 +yyval y.tab.c /^#define yyval /;" kind:macro line:214 language:C file: roles:def extras:fileScope end:214 +yyval y.tab.c /^YYSTYPE yyval;$/;" kind:variable line:41 language:C typeref:typename:YYSTYPE roles:def end:41 +yyword parse.c /^yyword(int tok, int *ptok, int eqok)$/;" kind:function line:400 language:C typeref:typename:tree * file: signature:(int tok,int * ptok,int eqok) roles:def extras:fileScope end:445 diff --git a/src/cmd/rc/trap.c b/src/cmd/rc/trap.c index a572cac370..498218ab4c 100644 --- a/src/cmd/rc/trap.c +++ b/src/cmd/rc/trap.c @@ -2,27 +2,24 @@ #include "exec.h" #include "fns.h" #include "io.h" -extern char *Signame[]; + +int ntrap; +int trap[NSIG]; void dotrap(void) { int i; - struct var *trapreq; - struct word *starval; + var *trapreq; + word *starval; starval = vlook("*")->val; - while(ntrap) for(i = 0;i!=NSIG;i++) while(trap[i]){ + while(ntrap) for(i = 0;ifn){ - start(trapreq->fn, trapreq->pc, (struct var *)0); - runq->local = newvar(strdup("*"), runq->local); - runq->local->val = copywords(starval, (struct word *)0); - runq->local->changed = 1; - runq->redir = runq->startredir = 0; - } + if(trapreq->fn) + startfunc(trapreq, copywords(starval, (word*)0), (var*)0, (redir*)0); else if(i==SIGINT || i==SIGQUIT){ /* * run the stack down until we uncover the @@ -32,6 +29,6 @@ dotrap(void) */ while(!runq->iflag) Xreturn(); } - else Exit(getstatus()); + else Exit(); } } diff --git a/src/cmd/rc/tree.c b/src/cmd/rc/tree.c index 2c3ff6bc71..d3909b6399 100644 --- a/src/cmd/rc/tree.c +++ b/src/cmd/rc/tree.c @@ -1,20 +1,29 @@ #include "rc.h" -#include "exec.h" #include "io.h" #include "fns.h" -tree *treenodes; + /* * create and clear a new tree node, and add it * to the node list. */ +static tree *treefree, *treenodes; tree* newtree(void) { - tree *t = new(tree); + tree *t; + + t = treefree; + if(t==0) + t = new(tree); + else + treefree = t->next; + t->quoted = 0; + t->glob = 0; t->iskw = 0; t->str = 0; t->child[0] = t->child[1] = t->child[2] = 0; + t->line = lex->line; t->next = treenodes; treenodes = t; return t; @@ -23,12 +32,21 @@ newtree(void) void freenodes(void) { - tree *t, *u; - for(t = treenodes;t;t = u){ - u = t->next; - if(t->str) - efree(t->str); - efree((char *)t); + tree *t; + + t = treenodes; + while(t){ + if(t->str){ + free(t->str); + t->str = 0; + } + t->child[0] = t->child[1] = t->child[2] = 0; + if(t->next==0){ + t->next = treefree; + treefree = treenodes; + break; + } + t = t->next; } treenodes = 0; } @@ -60,6 +78,13 @@ tree3(int type, tree *c0, tree *c1, tree *c2) t->child[0] = c0; t->child[1] = c1; t->child[2] = c2; + + if(c0) + t->line = c0->line; + else if(c1) + t->line = c1->line; + else if(c2) + t->line = c2->line; return t; } @@ -97,21 +122,18 @@ epimung(tree *comp, tree *epi) p->child[1] = comp; return epi; } + /* * Add a SIMPLE node at the root of t and percolate all the redirections * up to the root. */ - tree* simplemung(tree *t) { tree *u; - struct io *s; + t = tree1(SIMPLE, t); - s = openstr(); - pfmt(s, "%t", t); - t->str = strdup(s->strp); - closeio(s); + t->str = fnstr(t); for(u = t->child[0];u->type==ARGLIST;u = u->child[0]){ if(u->child[1]->type==DUP || u->child[1]->type==REDIR){ @@ -123,24 +145,46 @@ simplemung(tree *t) return t; } +char* +fnstr(tree *t) +{ + io *f = openiostr(); + pfmt(f, "%t", t); + return closeiostr(f); +} + tree* -token(char *str, int type) +globprop(tree *t) { - tree *t = newtree(); - t->type = type; - t->str = strdup(str); + tree *c0 = t->child[0]; + tree *c1 = t->child[1]; + if(c1==0){ + while(c0 && c0->type==WORDS){ + c1 = c0->child[1]; + if(c1 && c1->glob){ + c1->glob=2; + t->glob=1; + } + c0 = c0->child[0]; + } + } else { + if(c0->glob){ + c0->glob=2; + t->glob=1; + } + if(c1->glob){ + c1->glob=2; + t->glob=1; + } + } return t; } -void -freetree(tree *p) +tree* +token(char *str, int type) { - if(p==0) - return; - freetree(p->child[0]); - freetree(p->child[1]); - freetree(p->child[2]); - if(p->str) - efree(p->str); - efree((char *)p); + tree *t = newtree(); + t->str = estrdup(str); + t->type = type; + return t; } diff --git a/src/cmd/rc/unix.c b/src/cmd/rc/unix.c new file mode 100644 index 0000000000..8872b08215 --- /dev/null +++ b/src/cmd/rc/unix.c @@ -0,0 +1,424 @@ +/* + * Unix versions of system-specific functions + * By convention, exported routines herein have names beginning with an + * upper case letter. + */ +#include "rc.h" +#include "exec.h" +#include "io.h" +#include "fns.h" +#include "getflags.h" + +#undef wait +#undef waitpid + +#include +#include +#include +#include +#include + +static void execfinit(void); + +builtin Builtin[] = { + "cd", execcd, + "whatis", execwhatis, + "eval", execeval, + "exec", execexec, /* but with popword first */ + "exit", execexit, + "shift", execshift, + "wait", execwait, + ".", execdot, + "flag", execflag, + "finit", execfinit, + 0 +}; + +char Rcmain[PATH_MAX]; +char Fdprefix[] = "/dev/fd/"; + +char *Signame[NSIG]; + +#define SEP '\1' +extern char **environ; +static char **envp; + +static void +Xrdfn(void) +{ + char *s; + int len; + + for(;*envp;envp++){ + for(s=*envp;*s && *s!='(' && *s!='=';s++); + switch(*s){ + case '(': /* Bourne again */ + if(strncmp(s, "()fn ", 5)!=0) + continue; + s=estrdup(s+2); + len=strlen(s); + s[len++]='\n'; + envp++; + runq->pc--; /* re-execute */ + execcmds(openiocore(s, len), estrdup("*environ*"), runq->local, runq->redir); + runq->lex->qflag = 1; + return; + default: + continue; + } + } +} + +static void +execfinit(void) +{ + static union code rdfns[5]; + if(rdfns[0].i==0){ + rdfns[0].i = 1; + rdfns[1].s = "*rdfns*"; + rdfns[2].f = Xrdfn; + rdfns[3].f = Xreturn; + rdfns[4].f = 0; + } + poplist(); + envp=environ; + start(rdfns, 2, runq->local, runq->redir); +} + +static int +cmpenv(const void *aa, const void *ab) +{ + return strcmp(*(char**)aa, *(char**)ab); +} + +static char** +mkenv(void) +{ + char **env, **ep, *p, *q; + struct var **h, *v; + struct word *a; + int nvar = 0, nchr = 0, sep; + + /* + * Slightly kludgy loops look at locals then globals. + * locals no longer exist - geoff + */ + for(h = gvar-1; h != &gvar[NVAR]; h++) + for(v = h >= gvar? *h: runq->local; v ;v = v->next){ + if((v==vlook(v->name)) && v->val){ + nvar++; + nchr+=strlen(v->name)+1; + for(a = v->val;a;a = a->next) + nchr+=strlen(a->word)+1; + } + if(v->fn){ + nvar++; + nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8; + } + } + env = (char **)emalloc((nvar+1)*sizeof(char *)+nchr); + ep = env; + p = (char *)&env[nvar+1]; + for(h = gvar-1; h != &gvar[NVAR]; h++) + for(v = h >= gvar? *h: runq->local;v;v = v->next){ + if((v==vlook(v->name)) && v->val){ + *ep++=p; + q = v->name; + while(*q) *p++=*q++; + sep='='; + for(a = v->val;a;a = a->next){ + *p++=sep; + sep = SEP; + q = a->word; + while(*q) *p++=*q++; + } + *p++='\0'; + } + if(v->fn){ + *ep++=p; + *p++='#'; *p++='('; *p++=')'; /* to fool Bourne */ + *p++='f'; *p++='n'; *p++=' '; + q = v->name; + while(*q) *p++=*q++; + *p++=' '; + q = v->fn[v->pc-1].s; + while(*q) *p++=*q++; + *p++='\0'; + } + } + *ep = 0; + qsort((void *)env, nvar, sizeof ep[0], cmpenv); + return env; +} + +static word* +envval(char *s) +{ + char *t, c; + word *v; + for(t=s;*t&&*t!=SEP;t++); + c=*t; + *t='\0'; + v=newword(s, c=='\0'?(word*)0:envval(t+1)); + *t=c; + return v; +} + +void +Vinit(void) +{ + char *s; + + for(envp=environ;*envp;envp++){ + for(s=*envp;*s && *s!='(' && *s!='=';s++); + switch(*s){ + case '=': + *s='\0'; + setvar(*envp, envval(s+1)); + *s='='; + break; + default: continue; + } + } +} + +static void +sighandler(int sig) +{ + trap[sig]++; + ntrap++; +} + +void +Trapinit(void) +{ + int i; + + Signame[0] = "sigexit"; + +#ifdef SIGINT + Signame[SIGINT] = "sigint"; +#endif +#ifdef SIGTERM + Signame[SIGTERM] = "sigterm"; +#endif +#ifdef SIGHUP + Signame[SIGHUP] = "sighup"; +#endif +#ifdef SIGQUIT + Signame[SIGQUIT] = "sigquit"; +#endif +#ifdef SIGPIPE + Signame[SIGPIPE] = "sigpipe"; +#endif +#ifdef SIGUSR1 + Signame[SIGUSR1] = "sigusr1"; +#endif +#ifdef SIGUSR2 + Signame[SIGUSR2] = "sigusr2"; +#endif +#ifdef SIGBUS + Signame[SIGBUS] = "sigbus"; +#endif +#ifdef SIGWINCH + Signame[SIGWINCH] = "sigwinch"; +#endif + + for(i=1; i= 0 && !havewaitpid(pid)) + return 0; + while((wpid = wait(&status))!=-1){ + delwaitpid(wpid); + inttoascii(num, WIFSIGNALED(status)?WTERMSIG(status)+1000:WEXITSTATUS(status)); + if(wpid==pid){ + setstatus(num); + return 0; + } + for(p = runq->ret;p;p = p->ret) + if(p->pid==wpid){ + p->pid=-1; + p->status = estrdup(num); + break; + } + } + if(Eintr()) return -1; + return 0; +} + +static char **nextenv; + +void +Updenv(void) +{ + if(nextenv){ + free(nextenv); + nextenv = NULL; + } + if(err) + flushio(err); +} + +void +Exec(char **argv) +{ + if(nextenv==NULL) nextenv=mkenv(); + execve(argv[0], argv+1, nextenv); +} + +int +Fork(void) +{ + Updenv(); + return fork(); +} + +void* +Opendir(char *name) +{ + return opendir(name); +} + +char* +Readdir(void *arg, int onlydirs) +{ + DIR *rd = arg; + struct dirent *ent = readdir(rd); + if(ent == NULL) + return 0; + return ent->d_name; +} + +void +Closedir(void *arg) +{ + DIR *rd = arg; + closedir(rd); +} + +long +Write(int fd, void *buf, long cnt) +{ + return write(fd, buf, cnt); +} + +long +Read(int fd, void *buf, long cnt) +{ + return read(fd, buf, cnt); +} + +long +Seek(int fd, long cnt, long whence) +{ + return lseek(fd, cnt, whence); +} + +int +Executable(char *file) +{ + return access(file, 01)==0; +} + +int +Open(char *file, int mode) +{ + static int tab[] = {O_RDONLY,O_WRONLY,O_RDWR,O_RDONLY}; + int fd = open(file, tab[mode&3]); + if(fd >= 0 && mode == 3) + unlink(file); + return fd; +} + +void +Close(int fd) +{ + close(fd); +} + +int +Creat(char *file) +{ + return creat(file, 0666L); +} + +int +Dup(int a, int b) +{ + return dup2(a, b); +} + +int +Dup1(int a) +{ + return dup(a, 0); +} + +void +Exit(void) +{ + Updenv(); + exit(truestatus()?0:1); +} + +int +Eintr(void) +{ + return errno==EINTR; +} + +void +Noerror(void) +{ + errno=0; +} + +int +Isatty(int fd) +{ + return isatty(fd); +} + +void +Abort(void) +{ + abort(); +} + +int +Chdir(char *dir) +{ + return chdir(dir); +} + +void +Prompt(char *s) +{ + pstr(err, s); + flushio(err); +} diff --git a/src/cmd/rc/unixcrap.c b/src/cmd/rc/unixcrap.c deleted file mode 100644 index 0b91563548..0000000000 --- a/src/cmd/rc/unixcrap.c +++ /dev/null @@ -1,242 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "rc.h" -#include "exec.h" -#include "io.h" -#include "fns.h" -#include "getflags.h" - -extern char **mkargv(word*); -extern int mapfd(int); - -static char *eargs = "cdflmnstuv"; -static int rlx[] = { - RLIMIT_CORE, - RLIMIT_DATA, - RLIMIT_FSIZE, -#ifdef RLIMIT_MEMLOCK - RLIMIT_MEMLOCK, -#else - 0, -#endif -#ifdef RLIMIT_RSS - RLIMIT_RSS, -#else - 0, -#endif - RLIMIT_NOFILE, - RLIMIT_STACK, - RLIMIT_CPU, -#ifdef RLIMIT_NPROC - RLIMIT_NPROC, -#else - 0, -#endif -#ifdef RLIMIT_RSS - RLIMIT_RSS, -#else - 0, -#endif -}; - -static void -eusage(void) -{ - fprint(mapfd(2), "usage: ulimit [-SHa%s [limit]]\n", eargs); -} - -#define Notset -4 -#define Unlimited -3 -#define Hard -2 -#define Soft -1 - -void -execulimit(void) -{ - rlim_t n; - int fd, argc, sethard, setsoft, limit; - int flag[256]; - char **argv, **oargv, *p; - char *argv0; - struct rlimit rl; - - argv0 = nil; - setstatus(""); - oargv = mkargv(runq->argv->words); - argv = oargv+1; - for(argc=0; argv[argc]; argc++) - ; - - memset(flag, 0, sizeof flag); - ARGBEGIN{ - default: - if(strchr(eargs, ARGC()) == nil){ - eusage(); - return; - } - case 'S': - case 'H': - case 'a': - flag[ARGC()] = 1; - break; - }ARGEND - - if(argc > 1){ - eusage(); - goto out; - } - - fd = mapfd(1); - - sethard = 1; - setsoft = 1; - if(flag['S'] && flag['H']) - ; - else if(flag['S']) - sethard = 0; - else if(flag['H']) - setsoft = 0; - - limit = Notset; - if(argc>0){ - if(strcmp(argv[0], "unlimited") == 0) - limit = Unlimited; - else if(strcmp(argv[0], "hard") == 0) - limit = Hard; - else if(strcmp(argv[0], "soft") == 0) - limit = Soft; - else if((limit = strtol(argv[0], &p, 0)) < 0 || *p != 0){ - eusage(); - goto out; - } - } - if(flag['a']){ - for(p=eargs; *p; p++){ - getrlimit(rlx[p-eargs], &rl); - n = flag['H'] ? rl.rlim_max : rl.rlim_cur; - if(n == RLIM_INFINITY) - fprint(fd, "ulimit -%c unlimited\n", *p); - else - fprint(fd, "ulimit -%c %llud\n", *p, (uvlong)n); - } - goto out; - } - for(p=eargs; *p; p++){ - if(flag[(uchar)*p]){ - n = 0; - getrlimit(rlx[p-eargs], &rl); - switch(limit){ - case Notset: - n = flag['H'] ? rl.rlim_max : rl.rlim_cur; - if(n == RLIM_INFINITY) - fprint(fd, "ulimit -%c unlimited\n", *p); - else - fprint(fd, "ulimit -%c %llud\n", *p, (uvlong)n); - break; - case Hard: - n = rl.rlim_max; - goto set; - case Soft: - n = rl.rlim_cur; - goto set; - case Unlimited: - n = RLIM_INFINITY; - goto set; - default: - n = limit; - set: - if(setsoft) - rl.rlim_cur = n; - if(sethard) - rl.rlim_max = n; - if(setrlimit(rlx[p-eargs], &rl) < 0) - fprint(mapfd(2), "setrlimit: %r\n"); - } - } - } - -out: - free(oargv); - poplist(); - flush(err); -} - -void -execumask(void) -{ - int n, argc; - char **argv, **oargv, *p; - char *argv0; - - argv0 = nil; - setstatus(""); - oargv = mkargv(runq->argv->words); - argv = oargv+1; - for(argc=0; argv[argc]; argc++) - ; - - ARGBEGIN{ - default: - usage: - fprint(mapfd(2), "usage: umask [mode]\n"); - goto out; - }ARGEND - - if(argc > 1) - goto usage; - - if(argc == 1){ - n = strtol(argv[0], &p, 8); - if(*p != 0 || p == argv[0]) - goto usage; - umask(n); - goto out; - } - - n = umask(0); - umask(n); - if(n < 0){ - fprint(mapfd(2), "umask: %r\n"); - goto out; - } - - fprint(mapfd(1), "umask %03o\n", n); - -out: - free(oargv); - poplist(); - flush(err); -} - -/* - * Cope with non-blocking read. - */ -long -readnb(int fd, char *buf, long cnt) -{ - int n, didreset; - int flgs; - - didreset = 0; -again: - n = read(fd, buf, cnt); - if(n == -1) - if(errno == EAGAIN){ - if(!didreset){ - if((flgs = fcntl(fd, F_GETFL, 0)) == -1) - return -1; - flgs &= ~O_NONBLOCK; - if(fcntl(fd, F_SETFL, flgs) == -1) - return -1; - didreset = 1; - } - goto again; - } - - return n; -} diff --git a/src/cmd/rc/var.c b/src/cmd/rc/var.c index 2564ba2f75..73b01fa5ec 100644 --- a/src/cmd/rc/var.c +++ b/src/cmd/rc/var.c @@ -2,6 +2,8 @@ #include "exec.h" #include "fns.h" +var *gvar[NVAR]; + int hash(char *s, int n) { @@ -57,13 +59,27 @@ klook(char *name) return t; } +var* +newvar(char *name, var *next) +{ + int n = strlen(name)+1; + var *v = emalloc(sizeof(var)+n); + memmove(v->name, name, n); + v->next = next; + v->val = 0; + v->fn = 0; + v->changed = 0; + v->fnchanged = 0; + return v; +} + var* gvlook(char *name) { int h = hash(name, NVAR); var *v; for(v = gvar[h];v;v = v->next) if(strcmp(v->name, name)==0) return v; - return gvar[h] = newvar(strdup(name), gvar[h]); + return gvar[h] = newvar(name, gvar[h]); } var* @@ -76,98 +92,18 @@ vlook(char *name) return gvlook(name); } -void -_setvar(char *name, word *val, int callfn) -{ - struct var *v = vlook(name); - freewords(v->val); - v->val=val; - v->changed=1; - if(callfn && v->changefn) - v->changefn(v); -} - void setvar(char *name, word *val) { - _setvar(name, val, 1); -} - -void -bigpath(var *v) -{ - /* convert $PATH to $path */ - char *p, *q; - word **l, *w; - - if(v->val == nil){ - _setvar("path", nil, 0); - return; - } - p = v->val->word; - w = nil; - l = &w; - /* - * Doesn't handle escaped colon nonsense. - */ - if(p[0] == 0) - p = nil; - while(p){ - q = strchr(p, ':'); - if(q) - *q = 0; - *l = newword(p[0] ? p : ".", nil); - l = &(*l)->next; - if(q){ - *q = ':'; - p = q+1; - }else - p = nil; - } - _setvar("path", w, 0); -} - -char* -list2strcolon(word *words) -{ - char *value, *s, *t; - int len = 0; - word *ap; - for(ap = words;ap;ap = ap->next) - len+=1+strlen(ap->word); - value = emalloc(len+1); - s = value; - for(ap = words;ap;ap = ap->next){ - for(t = ap->word;*t;) *s++=*t++; - *s++=':'; - } - if(s==value) - *s='\0'; - else s[-1]='\0'; - return value; -} -void -littlepath(var *v) -{ - /* convert $path to $PATH */ - char *p; - word *w; - - p = list2strcolon(v->val); - w = new(word); - w->word = p; - w->next = nil; - _setvar("PATH", w, 1); /* 1: recompute $path to expose colon problems */ + var *v = vlook(name); + freewords(v->val); + v->val = val; + v->changed = 1; } void -pathinit(void) +freevar(var *v) { - var *v; - - v = gvlook("path"); - v->changefn = littlepath; - v = gvlook("PATH"); - v->changefn = bigpath; - bigpath(v); + freewords(v->val); + free(v); }