From 90316f687e7d956a16d58595ea698dfc9c2fd0c7 Mon Sep 17 00:00:00 2001 From: grobe0ba Date: Tue, 2 Aug 2022 11:40:11 -0500 Subject: [PATCH] rc: import latest from 9front Includes work to increase portability on *nix systems by cinap_lenrek, some extensions to the syntax, and multiple bug fixes to: - lexer/interpreter - globber - heredoc and much more. --- rcmain | 47 +- src/cmd/rc/Makefile | 51 ++ src/cmd/rc/code.c | 412 +++++++++------- src/cmd/rc/exec.c | 1040 ++++++++++++++++++++++----------------- src/cmd/rc/exec.h | 100 ++-- src/cmd/rc/fmtquote.c | 40 +- src/cmd/rc/fns.h | 140 +++--- src/cmd/rc/getflags.c | 201 ++++---- src/cmd/rc/getflags.h | 8 +- src/cmd/rc/glob.c | 393 ++++++++------- src/cmd/rc/havefork.c | 304 +++++------- src/cmd/rc/haventfork.c | 87 ++-- src/cmd/rc/here.c | 170 +++---- src/cmd/rc/io.c | 349 ++++++------- src/cmd/rc/io.h | 55 +-- src/cmd/rc/lex.c | 398 ++++++++------- src/cmd/rc/mkfile | 28 +- src/cmd/rc/parse.c | 203 ++++---- src/cmd/rc/pcmd.c | 256 +++------- src/cmd/rc/pfnc.c | 92 ++-- src/cmd/rc/plan9ish.c | 474 +++++++++--------- src/cmd/rc/rc.h | 216 ++++---- src/cmd/rc/rcmain.plan9 | 41 ++ src/cmd/rc/rcmain.unix | 38 ++ src/cmd/rc/simple.c | 538 ++++++++++---------- src/cmd/rc/subr.c | 79 ++- src/cmd/rc/syn.y | 35 +- src/cmd/rc/tags | 897 +++++++++++++++++++++++++++++++++ src/cmd/rc/trap.c | 53 +- src/cmd/rc/tree.c | 156 +++--- src/cmd/rc/unix.c | 425 ++++++++++++++++ src/cmd/rc/unixcrap.c | 94 ++-- src/cmd/rc/var.c | 122 +++-- 33 files changed, 4554 insertions(+), 2988 deletions(-) create mode 100644 src/cmd/rc/Makefile create mode 100644 src/cmd/rc/rcmain.plan9 create mode 100644 src/cmd/rc/rcmain.unix create mode 100644 src/cmd/rc/tags create mode 100644 src/cmd/rc/unix.c 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/Makefile b/src/cmd/rc/Makefile new file mode 100644 index 0000000000..0abe5bc6dd --- /dev/null +++ b/src/cmd/rc/Makefile @@ -0,0 +1,51 @@ +TARG=rc + +OFILES=\ + code.o\ + exec.o\ + getflags.o\ + glob.o\ + here.o\ + io.o\ + lex.o\ + pcmd.o\ + pfnc.o\ + simple.o\ + subr.o\ + trap.o\ + tree.o\ + var.o\ + havefork.o\ + unix.o\ + syn.o\ + +HFILES=rc.h\ + y.tab.h\ + io.h\ + exec.h\ + fns.h\ + getflags.h\ + +YFILES=syn.y +YFLAGS=-d + +PREFIX=/usr/local + +all: $(TARG) + +install: $(TARG) rcmain.unix + cp $(TARG) $(PREFIX)/bin/ + cp rcmain.unix $(PREFIX)/lib/rcmain + +$(TARG): $(OFILES) + $(CC) $(CFLAGS) $(LDFLAGS) -o $(TARG) $(OFILES) + +y.tab.h: syn.c + +unix.o: unix.c + $(CC) $(CFLAGS) '-DPREFIX="$(PREFIX)"' -c unix.c + +$(OFILES): $(HFILES) + +clean: + rm -f $(OFILES) $(TARG) syn.c y.tab.? y.debug diff --git a/src/cmd/rc/code.c b/src/cmd/rc/code.c index 208476ae3e..aec333682e 100644 --- a/src/cmd/rc/code.c +++ b/src/cmd/rc/code.c @@ -3,37 +3,34 @@ #include "exec.h" #include "fns.h" #include "getflags.h" -#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++) +#define c0 t->child[0] +#define c1 t->child[1] +#define c2 t->child[2] +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*); -code *codecopy(code*); -void codefree(code*); +void outcode(tree *, int); +void codeswitch(tree *, int); +int iscase(tree *); +code *codecopy(code *); +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; } void stuffdot(int a) { - if(a<0 || codep<=a) + if(a < 0 || codep <= a) panic("Bad address %d in stuffdot", a); codebuf[a].i = codep; } @@ -41,93 +38,122 @@ 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]); - codep = 0; - emiti(0); /* reference count */ - outcode(t, flag['e']?1:0); + ncode = 100; + codebuf = emalloc(ncode * sizeof codebuf[0]); + codep = 0; + codeline = 0; /* force source */ + emiti(0); /* reference count */ + 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) + if(t == 0) return; - if(t->type!=NOT && t->type!=';') - runq->iflast = 0; + if(t->type != NOT && t->type != ';') + 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; + 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 +167,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); @@ -166,27 +201,26 @@ outcode(tree *t, int eflag) emitf(Xbang); break; case PCMD: - case BRACE: - outcode(c0, eflag); - break; + case BRACE: outcode(c0, 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); - } - else + }else emitf(Xdelfn); break; case IF: @@ -198,7 +232,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); @@ -212,9 +246,7 @@ outcode(tree *t, int eflag) outcode(c1, eflag); stuffdot(p); break; - case PAREN: - outcode(c0, eflag); - break; + case PAREN: outcode(c0, eflag); break; case SIMPLE: emitf(Xmark); outcode(c0, eflag); @@ -224,24 +256,22 @@ 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; - case SWITCH: - codeswitch(t, eflag); - break; + case SWITCH: codeswitch(t, 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); @@ -249,8 +279,8 @@ outcode(tree *t, int eflag) case WHILE: q = codep; outcode(c0, 0); - if(q==codep) - emitf(Xsettrue); /* empty condition == while(true) */ + if(q == codep) + emitf(Xsettrue); /* empty condition == while(true) */ emitf(Xtrue); p = emiti(0); outcode(c1, eflag); @@ -266,16 +296,15 @@ outcode(tree *t, int eflag) emitf(Xmark); if(c1){ outcode(c1, eflag); - emitf(Xglob); - } - else{ + }else{ emitf(Xmark); emitf(Xword); - emits(strdup("*")); + emits(estrdup("*")); emitf(Xdol); } - emitf(Xmark); /* dummy value for Xlocal */ + emitf(Xmark); /* dummy value for Xlocal */ emitf(Xmark); + noglobs(c0, 0); outcode(c0, eflag); emitf(Xlocal); p = emitf(Xfor); @@ -288,15 +317,15 @@ 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){ + if(t->rtype == DUPFD){ emitf(Xdup); emiti(t->fd0); emiti(t->fd1); - } - else{ + }else{ emitf(Xclose); emiti(t->fd0); } @@ -306,32 +335,26 @@ 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); - break; - case WRITE: - emitf(Xwrite); - break; - case READ: + case APPEND: emitf(Xappend); break; + case WRITE: emitf(Xwrite); break; + case READ: emitf(Xread); break; + case RDWR: emitf(Xrdwr); break; case HERE: - emitf(Xread); - break; - case RDWR: - emitf(Xrdwr); + emitf(c0->quoted ? Xhereq : Xhere); + emits(t->str); + t->str = 0; /* passed ownership */ break; } emiti(t->fd0); @@ -340,53 +363,54 @@ outcode(tree *t, int eflag) break; case '=': tt = t; - for(;t && t->type=='=';t = c2); - if(t){ - for(t = tt;t->type=='=';t = c2){ + for(; t && t->type == '='; t = c2) + ; + 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); - } - else{ - for(t = tt;t;t = c2){ + outcode(t, eflag); /* gen. code for cmd */ + for(t = tt; t->type == '='; t = c2) emitf(Xunlocal); /* pop var */ + }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 */ + t = tt; /* so tests below will work */ break; case PIPE: 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->type!=NOT && t->type!=';') - runq->iflast = t->type==IF; - else if(c0) runq->iflast = c0->type==IF; + if(t->glob == 1) + emitf(Xglob); + if(t->type != NOT && t->type != ';') + lex->iflast = t->type == IF; + else if(c0) + lex->iflast = c0->type == IF; } /* * switch code looks like this: @@ -412,39 +436,42 @@ outcode(tree *t, int eflag) void codeswitch(tree *t, int eflag) { - int leave; /* patch jump address to leave switch */ - int out; /* jump here to leave switch */ - int nextcase; /* patch jump address to next case */ + int leave; /* patch jump address to leave switch */ + int out; /* jump here to leave switch */ + int nextcase; /* patch jump address to next case */ tree *tt; - if(c1->child[0]==nil - || c1->child[0]->type!=';' - || !iscase(c1->child[0]->child[0])){ + if(c1->child[0] == 0 || c1->child[0]->type != ';' || !iscase(c1->child[0]->child[0])){ yyerror("case missing in switch"); return; } emitf(Xmark); outcode(c0, eflag); + emitf(Xqw); emitf(Xjump); nextcase = emiti(0); - out = emitf(Xjump); - leave = emiti(0); + out = emitf(Xjump); + leave = emiti(0); stuffdot(nextcase); t = c1->child[0]; - while(t->type==';'){ + 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; + t = tt; for(;;){ - if(t->type==';'){ - if(iscase(c0)) break; + if(t->type == ';'){ + if(iscase(c0)) + break; outcode(c0, eflag); t = c1; - } - else{ - if(!iscase(t)) outcode(t, eflag); + }else{ + if(!iscase(t)) + outcode(t, eflag); break; } } @@ -459,13 +486,14 @@ codeswitch(tree *t, int eflag) int iscase(tree *t) { - if(t->type!=SIMPLE) + if(t->type != SIMPLE) return 0; - do t = c0; while(t->type==ARGLIST); - return t->type==WORD && !t->quoted && strcmp(t->str, "case")==0; + do t = c0; + while(t->type == ARGLIST); + return t->type == WORD && !t->quoted && strcmp(t->str, "case") == 0; } -code* +code * codecopy(code *cp) { cp[0].i++; @@ -476,21 +504,27 @@ void codefree(code *cp) { code *p; - if(--cp[0].i!=0) + if(--cp[0].i != 0) return; - for(p = cp+1;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==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==Xfn){ - efree(p[2].s); - p+=2; + 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 == Xhere || p->f == Xhereq) + free(p[1].s), p += 2; + else if(p->f == Xword) + free((++p)->s); + else if(p->f == Xfn){ + 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..b4d5cdecf2 100644 --- a/src/cmd/rc/exec.c +++ b/src/cmd/rc/exec.c @@ -3,193 +3,292 @@ #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, redir *redir) +{ + thread *p = new(thread); + p->code = codecopy(c); + p->line = 0; + p->pc = pc; + p->argv = 0; + p->redir = p->startredir = redir; + p->lex = 0; + p->local = local; + p->iflag = 0; + p->pid = 0; + p->status = 0; + p->ret = runq; + runq = p; +} void -start(code *c, int pc, var *local) +startfunc(var *func, word *starval, var *local, redir *redir) { - struct thread *p = new(struct thread); + start(func->fn, func->pc, local, redir); + runq->local = newvar("*", runq->local); + runq->local->val = starval; + runq->local->changed = 1; +} - p->code = codecopy(c); - p->pc = pc; - p->argv = 0; - p->redir = p->startredir = runq?runq->redir:0; - p->local = local; - p->cmdfile = 0; - p->cmdfd = 0; - p->eof = 0; - p->iflag = 0; - p->lineno = 1; - p->ret = runq; - runq = p; +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) +word * +Newword(char *s, word *next) { word *p = new(word); - p->word = strdup(wd); + 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) { - if(runq->argv==0) + 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; - if(runq->argv==0) + while((p = w) != 0){ + w = w->next; + free(Freeword(p)); + } +} +char * +Popword(void) +{ + word *p; + if(runq->argv == 0) panic("popword but no argv!", 0); p = runq->argv->words; - if(p==0) + 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; + list *p = new(list); + 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) + 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 count(word *w) { int n; - for(n = 0;w;n++) w = w->next; + for(n = 0; w; n++) w = w->next; return n; } void pushredir(int type, int from, int to) { - redir * rp = new(redir); - rp->type = type; - rp->from = from; - rp->to = to; - rp->next = runq->redir; + redir *rp = new(redir); + rp->type = type; + rp->from = from; + rp->to = to; + rp->next = runq->redir; 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); - if(argc==-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]=='-') + if(argv[0][0] == '-') flag['l'] = flagset; 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); + else if(flag['i'] == 0 && argc == 1 && Isatty(0)) + flag['i'] = flagset; + 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("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(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 +299,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,31 +307,31 @@ 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 + * Xfalse{...} execute {}if false + * 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 * Xmatch(pat, str) match pattern, set status * Xpipe[i j]{... Xreturn}{... Xreturn} construct a pipe between 2 new threads, * wait for both - * Xpipefd[type]{... Xreturn} connect {} to pipe (input or output, + * 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 - * Xsubshell{... Xexit} execute {} in a subshell and wait - * Xtrue{...} execute {} if true + * 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 * Xword[string] push string * Xwrite(file)[fd] open file to write @@ -242,26 +341,20 @@ void Xappend(void) { char *file; - int f; + int fd; + switch(count(runq->argv->words)){ - default: - Xerror1(">> requires singleton"); - return; - case 0: - Xerror1(">> requires file"); - return; - case 1: - break; + default: Xerror1(">> requires singleton"); return; + case 0: Xerror1(">> requires file"); return; + case 1: 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(); } @@ -274,59 +367,56 @@ Xsettrue(void) void Xbang(void) { - setstatus(truestatus()?"false":""); + setstatus(truestatus() ? "false" : ""); } void Xclose(void) { - pushredir(RCLOSE, runq->code[runq->pc].i, 0); - runq->pc++; + pushredir(RCLOSE, runq->code[runq->pc++].i, 0); } void Xdup(void) { - pushredir(RDUP, runq->code[runq->pc].i, runq->code[runq->pc+1].i); - runq->pc+=2; + pushredir(RDUP, runq->code[runq->pc].i, runq->code[runq->pc + 1].i); + runq->pc += 2; } 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"); + + if(getpid() == mypid && !beenhere){ + 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 Xfalse(void) { - if(truestatus()) runq->pc = runq->code[runq->pc].i; - else runq->pc++; + if(truestatus()) + runq->pc = runq->code[runq->pc].i; + else + runq->pc++; } -int ifnot; /* dynamic if not flag */ +int ifnot; /* dynamic if not flag */ void Xifnot(void) @@ -356,103 +446,166 @@ Xpopm(void) } void -Xread(void) +Xpush(void) { - char *file; - int f; - switch(count(runq->argv->words)){ - default: - Xerror1("< requires singleton\n"); + 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; - case 0: - Xerror1("< requires file\n"); + } + 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; - case 1: - break; } - file = runq->argv->words->word; - if((f = open(file, 0))<0){ - pfmt(err, "%s: ", file); - Xerror("can't open"); + 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; } - pushredir(ROPEN, f, runq->code[runq->pc].i); - runq->pc++; - poplist(); + 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 -Xrdwr(void) +Xread(void) { char *file; - int f; + int fd; switch(count(runq->argv->words)){ - default: - Xerror1("<> requires singleton\n"); - return; - case 0: - Xerror1("<> requires file\n"); - return; - case 1: - break; + default: Xerror1("< requires singleton"); return; + case 0: 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, 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(); } void -turfredir(void) +Xrdwr(void) { - while(runq->redir!=runq->startredir) - Xpopredir(); + char *file; + int fd; + + switch(count(runq->argv->words)){ + default: Xerror1("<> requires singleton"); return; + case 0: Xerror1("<> requires file"); return; + case 1: break; + } + file = runq->argv->words->word; + if((fd = Open(file, 2)) < 0){ + Xerror3("<> can't open", file, Errstr()); + return; + } + pushredir(ROPEN, fd, runq->code[runq->pc++].i); + poplist(); } void Xpopredir(void) { - struct redir *rp = runq->redir; - if(rp==0) - panic("turfredir null!", 0); + redir *rp = runq->redir; + + if(rp == 0) + panic("Xpopredir null!", 0); runq->redir = rp->next; - if(rp->type==ROPEN) - close(rp->from); - efree((char *)rp); + if(rp->type == ROPEN) + 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); - if(runq==0) - Exit(getstatus()); + while(runq->redir != runq->startredir) Xpopredir(); + popthread(); + if(runq == 0) + Exit(); } void Xtrue(void) { - if(truestatus()) runq->pc++; - else runq->pc = runq->code[runq->pc].i; + if(truestatus()) + runq->pc++; + else + runq->pc = runq->code[runq->pc].i; } void Xif(void) { ifnot = 1; - if(truestatus()) runq->pc++; - else runq->pc = runq->code[runq->pc].i; + if(truestatus()) + runq->pc++; + else + runq->pc = runq->code[runq->pc].i; } void @@ -471,61 +624,35 @@ void Xwrite(void) { char *file; - int f; + int fd; + switch(count(runq->argv->words)){ - default: - Xerror1("> requires singleton\n"); - return; - case 0: - Xerror1("> requires file\n"); - return; - case 1: - break; + default: Xerror1("> requires singleton"); return; + case 0: 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"); - for(p = runq->argv->next->words;p;p = p->next) - if(match(subject, p->word, '\0')){ + s = runq->argv->words->word; + for(p = runq->argv->next->words; p; p = p->next) + if(match(s, p->word, '\0')){ setstatus(""); break; } - efree(subject); poplist(); poplist(); } @@ -536,14 +663,14 @@ Xcase(void) word *p; char *s; int ok = 0; - s = list2str(runq->argv->next->words); - for(p = runq->argv->words;p;p = p->next){ + + 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 +678,26 @@ 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; } @@ -574,12 +708,12 @@ Xconc(void) word *rp = runq->argv->next->words; word *vp = runq->argv->next->next->words; int lc = count(lp), rc = count(rp); - if(lc!=0 || rc!=0){ - if(lc==0 || rc==0){ + if(lc != 0 || rc != 0){ + if(lc == 0 || rc == 0){ Xerror1("null list in concatenation"); return; } - if(lc!=1 && rc!=1 && lc!=rc){ + if(lc != 1 && rc != 1 && lc != rc){ Xerror1("mismatched list lengths in concatenation"); return; } @@ -594,32 +728,27 @@ void Xassign(void) { var *v; - if(count(runq->argv->words)!=1){ - Xerror1("variable name not singleton!"); + + if(count(runq->argv->words) != 1){ + 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* +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); + + for(end = &v; a; a = a->next, end = &(*end)->next) *end = newword(a->word, 0); *end = tail; return v; } @@ -630,20 +759,20 @@ Xdol(void) word *a, *star; char *s, *t; int n; - if(count(runq->argv->words)!=1){ - Xerror1("variable name not singleton!"); + + if(count(runq->argv->words) != 1){ + Xerror1("$ variable name not singleton!"); return; } - s = runq->argv->words->word; - deglob(s); n = 0; - for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'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) + if(n == 0 || *t) a = copywords(vlook(s)->val, a); else{ star = vlook("*")->val; - if(star && 1<=n && n<=count(star)){ + if(star && 1 <= n && n <= count(star)){ while(--n) star = star->next; a = newword(star->word, a); } @@ -653,85 +782,77 @@ 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; + v = 0; end = &v; while(n-- > 0){ *end = newword(a->word, 0); - end = &(*end)->next; - a = a->next; + end = &(*end)->next; + a = a->next; } *end = tail; 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') - n = n*10+ *s++ -'0'; + while('0' <= *s && *s <= '9') n = n * 10 + *s++ - '0'; if(*s == '-'){ if(*++s == 0) m = len - n; else{ - while('0'<=*s && *s<='9') - m = m*10+ *s++ -'0'; + while('0' <= *s && *s <= '9') m = m * 10 + *s++ - '0'; m -= n; } } - if(n<1 || n>len || m<0) + if(n < 1 || n > len || m < 0) return a; - if(n+m>len) - m = len-n; - while(--n > 0) - val = val->next; - return copynwords(val, a, m+1); + if(n + m > len) + m = len - n; + while(--n > 0) val = val->next; + return copynwords(val, a, m + 1); } void @@ -739,12 +860,12 @@ Xsub(void) { word *a, *v; char *s; - if(count(runq->argv->next->words)!=1){ - Xerror1("variable name not singleton!"); + + if(count(runq->argv->next->words) != 1){ + 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,24 +878,22 @@ 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!"); + + if(count(runq->argv->words) != 1){ + Xerror1("$# variable name not singleton!"); return; } - s = runq->argv->words->word; - deglob(s); n = 0; - for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0'; - if(n==0 || *t){ + 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; inttoascii(num, count(a)); - } - else{ + }else{ a = vlook("*")->val; - inttoascii(num, a && 1<=n && n<=count(a)?1:0); + inttoascii(num, a && 1 <= n && n <= count(a) ? 1 : 0); } poplist(); pushword(num); @@ -783,42 +902,26 @@ Xcount(void) void Xlocal(void) { - if(count(runq->argv->words)!=1){ - Xerror1("variable name must be singleton\n"); + if(count(runq->argv->words) != 1){ + 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; - if(v==0) + var *hid, *v = runq->local; + if(v == 0) panic("Xunlocal: no locals!", 0); - runq->local = v->next; - hid = vlook(v->name); + 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 +929,16 @@ Xfn(void) { var *v; word *a; - int end; - end = runq->code[runq->pc].i; - for(a = runq->argv->words;a;a = a->next){ + 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->fn = codecopy(runq->code); + v->pc = pc + 2; v->fnchanged = 1; } - runq->pc = end; poplist(); } @@ -845,151 +947,196 @@ Xdelfn(void) { var *v; word *a; - for(a = runq->argv->words;a;a = a->next){ + for(a = runq->argv->words; a; a = a->next){ v = gvlook(a->word); if(v->fn) codefree(v->fn); - v->fn = 0; + v->fn = 0; v->fnchanged = 1; } 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); - runq->pid=-1; - setstatus(concstatus(getstatus(), status)); + 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(), 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="% "; + 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 */ + --p->pc; /* go back for next command */ } + }else{ + 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); } - else{ - ntrap = 0; /* avoid double-interrupts during blocked writes */ - --p->pc; /* re-execute Xrdcmds after codebuf runs */ - start(codebuf, 1, runq->local); - } + 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* +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) { var *status = vlook("status"); - return status->val?status->val->word:""; + return status->val ? status->val->word : ""; } int truestatus(void) { char *s; - for(s = getstatus();*s;s++) - if(*s!='|' && *s!='0') + for(s = getstatus(); *s; s++) + if(*s != '|' && *s != '0') return 0; 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; + }else{ + 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 +1144,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..929c548038 100644 --- a/src/cmd/rc/exec.h +++ b/src/cmd/rc/exec.h @@ -2,75 +2,85 @@ * 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 Xerror1(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 */ -struct word{ +struct word { char *word; word *next; }; -struct list{ +struct list { word *words; 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) */ + +struct redir { + 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); */ -struct thread{ - union 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 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 */ +#define ROPEN 1 /* dup2(from, to); close(from); */ +#define RDUP 2 /* dup2(from, to); */ +#define RCLOSE 3 /* close(from); */ +void shuffleredir(void); + +struct thread { + code *code; /* code for this thread */ + int pc; /* code[pc] is the next instruction */ + 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 pid; /* process for Xpipewait to wait for */ + char *status; /* status for Xpipewait */ + thread *ret; /* who continues when this finishes */ }; -thread *runq; -code *codecopy(code*); -code *codebuf; /* compiler output */ -int ntrap; /* number of outstanding traps */ -int trap[NSIG]; /* number of outstanding traps per type */ -struct builtin{ +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 *); +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 index e6b91e34b3..3446ddc76a 100644 --- a/src/cmd/rc/fmtquote.c +++ b/src/cmd/rc/fmtquote.c @@ -36,37 +36,37 @@ __quotesetup(char *s, int nin, int nout, Quoteinfo *q, int sharp) { int c; - q->quoted = 0; + q->quoted = 0; q->nbytesout = 0; q->nrunesout = 0; - q->nbytesin = 0; - q->nrunesin = 0; - if(sharp || nin==0 || *s=='\0'){ + q->nbytesin = 0; + q->nrunesin = 0; + if(sharp || nin == 0 || *s == '\0'){ if(nout < 2) return; - q->quoted = 1; + q->quoted = 1; q->nbytesout = 2; q->nrunesout = 2; } - for(; nin!=0; nin-=1){ + for(; nin != 0; nin -= 1){ c = *s; if(c == '\0') break; - if(q->nrunesout+1 > nout) + if(q->nrunesout + 1 > nout) break; - if((c <= L' ') || (c == L'\'') || (doquote!=nil && doquote(c))){ + if((c <= L' ') || (c == L'\'') || (doquote != nil && doquote(c))){ if(!q->quoted){ - if(1+q->nrunesout+1+1 > nout) /* no room for quotes */ + if(1 + q->nrunesout + 1 + 1 > nout) /* no room for quotes */ break; - q->nrunesout += 2; /* include quotes */ - q->nbytesout += 2; /* include quotes */ + q->nrunesout += 2; /* include quotes */ + q->nbytesout += 2; /* include quotes */ q->quoted = 1; } - if(c == '\'') { + if(c == '\''){ q->nbytesout++; - q->nrunesout++; /* quotes reproduce as two characters */ + q->nrunesout++; /* quotes reproduce as two characters */ } } @@ -89,10 +89,10 @@ qstrfmt(char *sin, Quoteinfo *q, Fmt *f) ulong fl; int nc, w; - m = sin; + m = sin; me = m + q->nbytesin; - w = f->width; + w = f->width; fl = f->flags; if(!(fl & FmtLeft) && __fmtpad(f, w - q->nbytesout) < 0) return -1; @@ -100,7 +100,7 @@ qstrfmt(char *sin, Quoteinfo *q, Fmt *f) s = f->stop; FMTCHAR(f, t, s, '\''); for(nc = q->nrunesin; nc > 0; nc--){ - r = *(uchar*)m++; + r = *(uchar *)m++; FMTCHAR(f, t, s, r); if(r == '\'') FMTCHAR(f, t, s, r); @@ -121,17 +121,17 @@ __quotestrfmt(int runesin, Fmt *f) char *s; Quoteinfo q; - f->flags &= ~FmtPrec; /* ignored for %q %Q, so disable for %s %S in easy case */ + 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 */ + outlen = 0x7FFFFFFF; /* if we can flush, no output limit */ else - outlen = (char*)f->stop - (char*)f->to; + outlen = (char *)f->stop - (char *)f->to; - __quotesetup(s, -1, outlen, &q, f->flags&FmtSharp); + __quotesetup(s, -1, outlen, &q, f->flags & FmtSharp); if(!q.quoted) return __fmtcpy(f, s, q.nrunesin, q.nbytesin); diff --git a/src/cmd/rc/fns.h b/src/cmd/rc/fns.h index 5721d61757..ca7f89664c 100644 --- a/src/cmd/rc/fns.h +++ b/src/cmd/rc/fns.h @@ -1,68 +1,72 @@ -void Abort(void); -void Closedir(int); -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*); -int Isatty(int); -void Memcpy(char*, char*, long); -void Noerror(void); -int Opendir(char*); -long Read(int, char*, long); -int Readdir(int, char*, int); -long Seek(int, long, long); -void Trapinit(void); -void Unlink(char*); -void Updenv(void); -void Vinit(void); -int Waitfor(int, int); -long Write(int, char*, long); -void addwaitpid(int); -int advance(void); -int back(int); -void cleanhere(char*); -void codefree(code*); -int compile(tree*); -char * list2str(word*); -int count(word*); -void deglob(char*); -void delwaitpid(int); -void dotrap(void); -void freenodes(void); -void freewords(word*); -void globlist(void); -int havewaitpid(int); -int idchr(int); -void inttoascii(char*, long); -void kinit(void); -int mapfd(int); -int match(char*, char*, int); -int matchfn(char*, char*); -char** mkargv(word*); -void clearwaitpids(void); -void panic(char*, int); -void pathinit(void); -void poplist(void); -void popword(void); -void pprompt(void); -void pushlist(void); -void pushredir(int, int, int); -void pushword(char*); -void readhere(void); -word* searchpath(char*); -void setstatus(char*); -void setvar(char*, word*); -void skipnl(void); -void start(code*, int, var*); -int truestatus(void); -void usage(char*); -int wordchr(int); -void yyerror(char*); -int yylex(void); -int yyparse(void); -int parse(void); +void Abort(void); +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 Exec(char**); +void Exit(void); +char* Errstr(void); +char* Freeword(word*); +int Fork(void); +char* Getstatus(void); +int Isatty(int); +word* Newword(char*, word*); +void Noerror(void); +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 Updenv(void); +void Vinit(void); +int Waitfor(int); +long Write(int, void*, long); +void addwaitpid(int); +void clearwaitpids(void); +void codefree(code*); +int compile(tree*); +int count(word*); +char* deglob(char*); +void delwaitpid(int); +void dotrap(void); +void freenodes(void); +void freewords(word*); +void globword(word*); +int havewaitpid(int); +int idchr(int); +void inttoascii(char*, int); +void kinit(void); +int mapfd(int); +int match(char*, char*, int); +char* makepath(char*, char*); +void panic(char*, int); +void pathinit(); +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); +word* pushword(char*); +void readhere(io*); +void heredoc(tree*); +void setstatus(char*); +void skipnl(void); +void start(code*, int, var*, redir*); +int truestatus(void); +void usage(char*); +int wordchr(int); +void yyerror(char*); +int yylex(void); +int yyparse(void); diff --git a/src/cmd/rc/getflags.c b/src/cmd/rc/getflags.c index 09f6e3a71e..b1e3ff09f1 100644 --- a/src/cmd/rc/getflags.c +++ b/src/cmd/rc/getflags.c @@ -1,84 +1,74 @@ -/*% 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**); -static int scanflag(int, char*); -static void errn(char*, int); -static void errs(char*); +static char *flagarg = ""; +static void reverse(char **, char **); +static int scanflag(int, char *); +static void errn(char *, int); +static void errs(char *); static void errc(int); static int reason; -#define RESET 1 -#define FEWARGS 2 -#define FLAGSYN 3 -#define BADFLAG 4 +#define RESET 1 +#define FEWARGS 2 +#define FLAGSYN 3 +#define BADFLAG 4 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) + 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) + while(i != argc){ + if(argv[i][0] != '-' || argv[i][1] == '\0'){ + if(stop) /* always true in rc */ return argc; i++; continue; } - s = argv[i]+1; + s = argv[i] + 1; while(*s){ - c=*s++; + c = *s++; count = scanflag(c, flags); - if(count==-1) + if(count == -1) + return -1; + if(flag[c]){ + reason = RESET; + badflag = c; return -1; - if(flag[c]){ reason = RESET; badflag = c; return -1; } - if(count==0){ + } + if(count == 0){ flag[c] = flagset; - if(*s=='\0'){ - for(j = i+1;j<=argc;j++) - argv[j-1] = argv[j]; + if(*s == '\0'){ + for(j = i + 1; j <= argc; j++) argv[j - 1] = argv[j]; --argc; } - } - else{ - if(*s=='\0'){ - for(j = i+1;j<=argc;j++) - argv[j-1] = argv[j]; + }else{ + if(*s == '\0'){ + for(j = i + 1; j <= argc; j++) argv[j - 1] = argv[j]; --argc; s = argv[i]; } - if(argc-inext) n++; - list = (char **)emalloc(n*sizeof(char *)); - for(a = left,n = 0;a!=right;a = a->next,n++) list[n] = a->word; + for(a = left; a != right; a = a->next) n++; + list = (char **)emalloc(n * sizeof(char *)); + 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); + for(a = left, n = 0; a != right; a = a->next, n++) a->word = list[n]; + 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]!='.') + if(*p != *q) return 0; - return match(s, p, '/'); + 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)){ - if(*p!=GLOB){ - if(!equtf(p, s)) return 0; - } - else switch(*++p){ - case GLOB: - if(*s!=GLOB) - return 0; - break; - case '*': - for(;;){ - if(match(s, nextutf(p), stop)) return 1; - if(!*s) - break; - s = nextutf(s); - } - return 0; - case '?': - if(*s=='\0') + + for(; *p != stop && *p != '\0'; s = nextutf(s), p = nextutf(p)){ + if(*p != GLOB){ + if(!equtf(p, s)) return 0; - break; - case '[': - if(*s=='\0') + }else + switch(*++p){ + case GLOB: + if(*s != GLOB) + return 0; + break; + case '*': + for(;;){ + if(match(s, nextutf(p), stop)) + return 1; + if(!*s) + break; + s = nextutf(s); + } return 0; - c = unicode(s); - p++; - compl=*p=='~'; - if(compl) + case '?': + if(*s == '\0') + return 0; + break; + case '[': + if(*s == '\0') + return 0; + c = unicode(s); p++; - hit = 0; - while(*p!=']'){ - if(*p=='\0') - return 0; /* syntax error */ - lo = unicode(p); - p = nextutf(p); - if(*p!='-') - hi = lo; - else{ + compl = *p == '~'; + if(compl ) p++; - if(*p=='\0') - return 0; /* syntax error */ - hi = unicode(p); - p = nextutf(p); - if(hinext); - 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; } + return *s == '\0'; } diff --git a/src/cmd/rc/havefork.c b/src/cmd/rc/havefork.c index 63f83354d3..d623184c8f 100644 --- a/src/cmd/rc/havefork.c +++ b/src/cmd/rc/havefork.c @@ -1,68 +1,62 @@ -#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 < nwaitpids; r++) + if(waitpids[r] != pid) + waitpids[w++] = waitpids[r]; + nwaitpids = w; +} + +void +clearwaitpids(void) +{ + nwaitpids = 0; +} + +int +havewaitpid(int pid) +{ + int i; + + for(i = 0; i < nwaitpids; i++) + if(waitpids[i] == pid) + return 1; + return 0; +} void Xasync(void) { - int null = open("/dev/null", 0); - int tty; int pid; char npid[10]; - if(null<0){ - Xerror("Can't open /dev/null\n"); - return; - } - switch(pid = rfork(RFFDG|RFPROC|RFNOTEG)){ - case -1: - close(null); - Xerror("try again"); - break; + + switch(pid = Fork()){ + case -1: Xerror2("try again", Errstr()); break; case 0: clearwaitpids(); - /* - * I don't know what the right thing to do here is, - * so this is all experimentally determined. - * If we just dup /dev/null onto 0, then running - * ssh foo & will reopen /dev/tty, try to read a password, - * get a signal, and repeat, in a tight loop, forever. - * Arguably this is a bug in ssh (it behaves the same - * way under bash as under rc) but I'm fixing it here - * anyway. If we dissociate the process from the tty, - * then it won't be able to open /dev/tty ever again. - * The SIG_IGN on SIGTTOU makes writing the tty - * (via fd 1 or 2, for example) succeed even though - * our pgrp is not the terminal's controlling pgrp. - */ - if((tty = open("/dev/tty", OREAD)) >= 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 +67,32 @@ 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"); + + if(pipe(pfd) < 0){ + Xerror2("can't get pipe", Errstr()); return; } - switch(forkid = fork()){ - case -1: - Xerror("try again"); - break; + switch(pid = Fork()){ + case -1: 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->pc = p->code[pc + 1].i; + p->pid = pid; break; } } @@ -107,75 +100,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:""; - if(pipe(pfd)<0){ - Xerror("can't make pipe"); + int pid, pfd[2]; + char *s, *split; + word *end, **link; + io *f; + + if(pipe(pfd) < 0){ + 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,72 +152,41 @@ 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; - - r = &fd[0]; - w = &fd[1]; - switch(p->code[pc].i){ - case READ: - w = nil; - break; - case WRITE: - r = nil; - } + int sidefd, mainfd; - if(r){ - if(pipe(pfd)<0){ - Xerror("can't get pipe"); - return; - } - r->sidefd = pfd[PWR]; - r->mainfd = pfd[PRD]; + if(pipe(pfd) < 0){ + Xerror2("can't get pipe", Errstr()); + return; } - if(w){ - if(pipe(pfd)<0){ - Xerror("can't get pipe"); - return; - } - w->sidefd = pfd[PRD]; - w->mainfd = pfd[PWR]; + if(p->code[pc].i == READ){ + sidefd = pfd[PWR]; + mainfd = pfd[PRD]; + }else{ + sidefd = pfd[PRD]; + mainfd = pfd[PWR]; } - switch(pid = fork()){ - case -1: - Xerror("try again"); - break; + switch(pid = Fork()){ + case -1: 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); - } - p->pc = p->code[pc+1].i; + 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 +195,18 @@ void Xsubshell(void) { int pid; - switch(pid = fork()){ - case -1: - Xerror("try again"); - break; + + switch(pid = Fork()){ + case -1: 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 +216,14 @@ int execforkexec(void) { int pid; - int n; - char buf[ERRMAX]; - switch(pid = fork()){ - case -1: - return -1; + 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 index fc8f7608ec..c5be5de5aa 100644 --- a/src/cmd/rc/haventfork.c +++ b/src/cmd/rc/haventfork.c @@ -13,9 +13,9 @@ rcargv(char *s) char **argv; word *p; - p = vlook("*")->val; - argv = malloc((count(p)+6)*sizeof(char*)); - argc = 0; + p = vlook("*")->val; + argv = malloc((count(p) + 6) * sizeof(char *)); + argc = 0; argv[argc++] = argv0; if(flag['e']) argv[argc++] = "-Se"; @@ -23,8 +23,7 @@ rcargv(char *s) argv[argc++] = "-S"; argv[argc++] = "-c"; argv[argc++] = s; - for(p = vlook("*")->val; p; p = p->next) - argv[argc++] = p->word; + for(p = vlook("*")->val; p; p = p->next) argv[argc++] = p->word; argv[argc] = 0; return argv; } @@ -38,10 +37,10 @@ Xasync(void) Updenv(); argv = rcargv(runq->code[runq->pc].s); - pid = ForkExecute(argv0, argv, -1, 1, 2); + pid = ForkExecute(argv0, argv, -1, 1, 2); free(argv); - if(pid == 0) { + if(pid == 0){ Xerror("proc failed"); return; } @@ -56,15 +55,15 @@ Xbackq(void) { char wd[8193], **argv; int c; - char *s, *ewd=&wd[8192], *stop; + 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){ + stop = ifs->val ? ifs->val->word : ""; + if(pipe(pfd) < 0){ Xerror("can't make pipe"); return; } @@ -72,12 +71,12 @@ Xbackq(void) Updenv(); argv = rcargv(runq->code[runq->pc].s); - pid = ForkExecute(argv0, argv, -1, pfd[1], 2); + pid = ForkExecute(argv0, argv, -1, pfd[1], 2); free(argv); close(pfd[1]); - if(pid == 0) { + if(pid == 0){ Xerror("proc failed"); close(pfd[0]); return; @@ -86,28 +85,28 @@ Xbackq(void) 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; + 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; + }else + *s++ = c; } - if(s!=wd){ - *s='\0'; - v=newword(wd, v); + 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; + nextv = v->next; + v->next = runq->argv->words; + runq->argv->words = v; + v = nextv; } runq->pc++; } @@ -115,34 +114,34 @@ Xbackq(void) void Xpipe(void) { - thread *p=runq; - int pc=p->pc, pid; - int rfd=p->code[pc+1].i; + thread *p = runq; + int pc = p->pc, pid; + int rfd = p->code[pc + 1].i; int pfd[2]; char **argv; - if(pipe(pfd)<0){ + 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); + argv = rcargv(runq->code[pc + 2].s); + pid = ForkExecute(argv0, argv, 0, pfd[1], 2); free(argv); close(pfd[1]); - if(pid == 0) { + if(pid == 0){ Xerror("proc failed"); close(pfd[0]); return; } - start(p->code, pc+4, runq->local); + start(p->code, pc + 4, runq->local); pushredir(ROPEN, pfd[0], rfd); - p->pc=p->code[pc+3].i; - p->pid=pid; + p->pc = p->code[pc + 3].i; + p->pid = pid; } void @@ -160,10 +159,10 @@ Xsubshell(void) Updenv(); argv = rcargv(runq->code[runq->pc].s); - pid = ForkExecute(argv0, argv, -1, 1, 2); + pid = ForkExecute(argv0, argv, -1, 1, 2); free(argv); - if(pid < 0) { + if(pid < 0){ Xerror("proc failed"); return; } @@ -184,21 +183,21 @@ execforkexec(void) word *path; int pid; - if(runq->argv->words==0) + if(runq->argv->words == 0) return -1; argv = mkargv(runq->argv->words); - for(path = searchpath(runq->argv->words->word);path;path = path->next){ + 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; diff --git a/src/cmd/rc/here.c b/src/cmd/rc/here.c index 17c6245813..c12e61b7f5 100644 --- a/src/cmd/rc/here.c +++ b/src/cmd/rc/here.c @@ -2,133 +2,117 @@ #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 pstrs(io*, word*); -void -hexnum(char *p, int n) +void psubst(io *, unsigned char *); +void pstrs(io *, word *); + +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); } -tree* -heredoc(tree *tag) +static tree *head, *tail; + +void +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; + } + 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; } -/* - * 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(*s != '$'){ + if(0xa0 <= *s && *s <= 0xf5){ pchr(f, *s++); - if(*s=='\0') + if(*s == '\0') break; - } - else if(0xf6<=(*s&0xff) && (*s&0xff)<=0xf7){ + }else if(0xf6 <= *s && *s <= 0xf7){ pchr(f, *s++); - if(*s=='\0') + if(*s == '\0') break; pchr(f, *s++); - if(*s=='\0') + if(*s == '\0') break; } pchr(f, *s++); - } - else{ - t=++s; - if(*t=='$') + }else{ + t = ++s; + if(*t == '$') pchr(f, *t++); else{ while(*t && idchr(*t)) t++; - savec=*t; - *t='\0'; - n = 0; - for(u = s;*u && '0'<=*u && *u<='9';u++) n = n*10+*u-'0'; - if(n && *u=='\0'){ + savec = *t; + *t = '\0'; + n = 0; + for(u = s; *u && '0' <= *u && *u <= '9'; u++) n = n * 10 + *u - '0'; + if(n && *u == '\0'){ star = vlook("*")->val; - if(star && 1<=n && n<=count(star)){ + if(star && 1 <= n && n <= count(star)){ while(--n) star = star->next; pstr(f, star->word); } - } - else - pstrs(f, vlook(s)->val); + }else + pstrs(f, vlook((char *)s)->val); *t = savec; - if(savec=='^') + if(savec == '^') t++; } s = t; diff --git a/src/cmd/rc/io.c b/src/cmd/rc/io.c index 907ba86fbf..7efd9bb6b1 100644 --- a/src/cmd/rc/io.c +++ b/src/cmd/rc/io.c @@ -1,91 +1,117 @@ -#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!='%') - pchr(f, *fmt); - else switch(*++fmt){ - case '\0': - va_end(ap); - return; - case 'c': - pchr(f, va_arg(ap, int)); - break; - case 'd': - pdec(f, va_arg(ap, int)); - break; - case 'o': - poct(f, va_arg(ap, unsigned)); - break; - case 'p': - pptr(f, va_arg(ap, void*)); - break; - case 'Q': - pquo(f, va_arg(ap, char *)); - break; - 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 *)); - break; - default: + for(; *fmt; fmt++){ + if(*fmt != '%'){ pchr(f, *fmt); + continue; + } + if(*++fmt == '\0') /* "blah%"? */ break; + switch(*fmt){ + case 'c': pchr(f, va_arg(ap, int)); break; + case 'd': pdec(f, va_arg(ap, int)); break; + case 'o': poct(f, va_arg(ap, unsigned)); break; + case 'p': pptr(f, va_arg(ap, void *)); break; + case 'Q': pquo(f, va_arg(ap, char *)); break; + case 'q': pwrd(f, va_arg(ap, char *)); break; + case 's': pstr(f, va_arg(ap, char *)); break; + case 't': pcmd(f, va_arg(ap, tree *)); break; + case 'v': 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++) - if(*s=='\'') - pfmt(f, "''"); - else pchr(f, *s); + for(; *s; s++){ + if(*s == '\'') + pchr(f, *s); + pchr(f, *s); + } pchr(f, '\''); } @@ -93,181 +119,168 @@ void pwrd(io *f, char *s) { char *t; - for(t = s;*t;t++) if(!wordchr(*t)) break; - if(t==s || *t) + for(t = s; *t; t++) + if(*t >= 0 && (*t <= ' ' || strchr("`^#*[]=|\\?${}()'<>&;", *t))) + break; + if(t == s || *t) pquo(f, s); - else pstr(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 pstr(io *f, char *s) { - if(s==0) - s="(null)"; + if(s == 0) + s = "(null)"; while(*s) pchr(f, *s++); } void pdec(io *f, int n) { - if(n<0){ - if(n!=INT_MIN){ + if(n < 0){ + 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'); + pdec(f, n / 10); + pchr(f, n % 10 + '1'); return; } - if(n>9) - pdec(f, n/10); - pchr(f, n%10+'0'); + if(n > 9) + pdec(f, n / 10); + pchr(f, n % 10 + '0'); } void poct(io *f, unsigned n) { - if(n>7) - poct(f, n>>3); - pchr(f, (n&7)+'0'); + if(n > 7) + poct(f, n >> 3); + pchr(f, (n & 7) + '0'); } 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; } -io* -openstr(void) +/* + * Use a open file descriptor for reading. + */ +io * +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) +io * +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; - else{ - io->bufp = io->ebuf = io->buf; - Seek(io->fd, 0L, 0); + 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{ + 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) + 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..a98b5717af 100644 --- a/src/cmd/rc/io.h +++ b/src/cmd/rc/io.h @@ -1,31 +1,28 @@ -/* - * 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{ +#define EOF (-1) + +struct io { int fd; - char *bufp, *ebuf, *strp, buf[NBUF]; + unsigned char *buf, *bufp, *ebuf; + io *next; }; -io *err; -io *openfd(int), *openstr(void), *opencore(char *, int); -int emptybuf(io*); -void pchr(io*, int); -int rchr(io*); -void closeio(io*); -void flush(io*); -int fullbuf(io*, int); -void pdec(io*, int); -void poct(io*, unsigned); -void pptr(io*, void*); -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 pfnc(io*, thread*); -void pfmt(io*, char*, ...); + +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 *); +int emptyiobuf(io *); +void flushio(io *); +void pdec(io *, int); +void poct(io *, unsigned); +void pptr(io *, void *); +void pquo(io *, char *); +void pwrd(io *, char *); +void pstr(io *, char *); +void pcmd(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..75ed4dd03f 100644 --- a/src/cmd/rc/lex.c +++ b/src/cmd/rc/lex.c @@ -1,14 +1,17 @@ #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) { - return !strchr("\n \t#;&|^$=`'{}()<>", c) && c!=EOF; + return !strchr("\n \t#;&|^$=`'{}()<>", c) && c != EOF; } int @@ -19,115 +22,131 @@ idchr(int c) * return 'a'<=c && c<='z' || 'A'<=c && c<='Z' || '0'<=c && c<='9' * || c=='_' || c=='*'; */ - return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", 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; - c='\\'; + c = ' '; + }else{ + 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; + if(c == '#'){ + lex->incomm = 1; for(;;){ c = nextc(); - if(c=='\n' || c==EOF) { - incomm = 0; + if(c == '\n' || c == EOF){ + lex->incomm = 0; break; } advance(); } } - if(c==' ' || c=='\t') { - skipped = 1; + if(c == ' ' || c == '\t') advance(); - } else - return skipped; + return; } } @@ -138,63 +157,69 @@ skipnl(void) for(;;){ skipwhite(); c = nextc(); - if(c!='\n') + if(c != '\n') return; advance(); } } -int +static int nextis(int c) { - if(nextc()==c){ + if(nextc() == c){ advance(); return 1; } return 0; } -char* +static char * addtok(char *p, int val) { - if(p==0) + 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; } - *p++=val; + *p++ = 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(); - char *w = tok; + 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,28 +227,27 @@ 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(d=='('){ + if(lex->lastword){ + lex->lastword = 0; + if(d == '('){ advance(); - strcpy(tok, "("); + strcpy(tok, "( [SUB]"); return SUB; } - if(wordchr(d) || d=='\'' || d=='`' || d=='$' || d=='"'){ + if(wordchr(d) || d == '\'' || d == '`' || d == '$' || d == '"'){ strcpy(tok, "^"); 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 ']' @@ -263,134 +285,150 @@ yylex(void) * digit: '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' * some possibilities are nonsensical and get a message. */ - *w++=c; - t = newtree(); + *w++ = c; + t = newtree(); switch(c){ case '|': t->type = PIPE; - t->fd0 = 1; - t->fd1 = 0; + t->fd0 = 1; + t->fd1 = 0; break; case '>': t->type = REDIR; if(nextis(c)){ t->rtype = APPEND; - *w++=c; - } - else t->rtype = WRITE; + *w++ = c; + }else + t->rtype = WRITE; t->fd0 = 1; break; case '<': t->type = REDIR; if(nextis(c)){ t->rtype = HERE; - *w++=c; - } else if (nextis('>')){ + *w++ = c; + }else if(nextis('>')){ t->rtype = RDWR; - *w++=c; - } else t->rtype = READ; + *w++ = c; + }else + t->rtype = READ; t->fd0 = 0; break; } if(nextis('[')){ - *w++='['; - c = advance(); - *w++=c; - if(c<'0' || '9'type==PIPE?"pipe syntax" - :"redirection syntax"); + yyerror(t->type == PIPE ? "pipe syntax" : "redirection syntax"); return EOF; } t->fd0 = 0; - do{ - t->fd0 = t->fd0*10+c-'0'; - *w++=c; - c = advance(); - }while('0'<=c && c<='9'); - if(c=='='){ - *w++='='; - if(t->type==REDIR) + do { + t->fd0 = t->fd0 * 10 + c - '0'; + *w++ = c; + c = advance(); + }while('0' <= c && c <= '9'); + if(c == '='){ + *w++ = '='; + if(t->type == REDIR) t->type = DUP; c = advance(); - if('0'<=c && c<='9'){ + if('0' <= c && c <= '9'){ t->rtype = DUPFD; - t->fd1 = t->fd0; - t->fd0 = 0; - do{ - t->fd0 = t->fd0*10+c-'0'; - *w++=c; - c = advance(); - }while('0'<=c && c<='9'); - } - else{ - if(t->type==PIPE) + t->fd1 = t->fd0; + t->fd0 = 0; + do { + t->fd0 = t->fd0 * 10 + c - '0'; + *w++ = c; + c = advance(); + }while('0' <= c && c <= '9'); + }else{ + if(t->type == PIPE) goto RedirErr; t->rtype = CLOSE; } } - if(c!=']' - || t->type==DUP && (t->rtype==HERE || t->rtype==APPEND)) + if(c != ']' || t->type == DUP && (t->rtype == HERE || t->rtype == APPEND)) goto RedirErr; - *w++=']'; + *w++ = ']'; } - *w='\0'; + *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) + if(c == EOF) break; - if(c=='\''){ - if(nextc()!='\'') + if(c == '\''){ + if(nextc() != '\'') break; advance(); } w = addutf(w, c); } - if(w!=0) - *w='\0'; - t = token(tok, WORD); - t->quoted = 1; + if(w != 0) + *w = '\0'; + t = token(tok, WORD); + t->quoted = 1; yylval.tree = t; return t->type; } if(!wordchr(c)){ - lastdol = 0; - tok[0] = c; - tok[1]='\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) - w = addtok(w, 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; - if(w!=0) - *w='\0'; + lex->lastword = 1; + lex->lastdol = 0; + if(w != 0) + *w = '\0'; t = klook(tok); - if(t->type!=WORD) - lastword = 0; - t->quoted = 0; + if(t->type != WORD) + 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..de15c6aa5b 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,38 @@ 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\ + 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/parse.c b/src/cmd/rc/parse.c index a9cf497a7a..faa3960b46 100644 --- a/src/cmd/rc/parse.c +++ b/src/cmd/rc/parse.c @@ -2,36 +2,34 @@ #include "io.h" #include "fns.h" -static tree* body(int tok, int *ptok); -static tree* brace(int tok); -static tree* cmd(int tok, int *ptok); -static tree* cmd2(int tok, int *ptok); -static tree* cmd3(int tok, int *ptok); -static tree* cmds(int tok, int *ptok, int nlok); -static tree* epilog(int tok, int *ptok); -static int iswordtok(int tok); -static tree* line(int tok, int *ptok); -static tree* paren(int tok); -static tree* yyredir(int tok, int *ptok); -static tree* yyword(int tok, int *ptok, int eqok); -static tree* word1(int tok, int *ptok); -static tree* words(int tok, int *ptok); +static tree *body(int tok, int *ptok); +static tree *brace(int tok); +static tree *cmd(int tok, int *ptok); +static tree *cmd2(int tok, int *ptok); +static tree *cmd3(int tok, int *ptok); +static tree *cmds(int tok, int *ptok, int nlok); +static tree *epilog(int tok, int *ptok); +static int iswordtok(int tok); +static tree *line(int tok, int *ptok); +static tree *paren(int tok); +static tree *yyredir(int tok, int *ptok); +static tree *yyword(int tok, int *ptok, int eqok); +static tree *word1(int tok, int *ptok); +static tree *words(int tok, int *ptok); static jmp_buf yyjmp; static int dropnl(int tok) { - while(tok == ' ' || tok == '\n') - tok = yylex(); + while(tok == ' ' || tok == '\n') tok = yylex(); return tok; } static int dropsp(int tok) { - while(tok == ' ') - tok = yylex(); + while(tok == ' ') tok = yylex(); return tok; } @@ -65,19 +63,19 @@ parse(void) return !compile(t); } -static tree* +static tree * line(int tok, int *ptok) { return cmds(tok, ptok, 0); } -static tree* +static tree * body(int tok, int *ptok) { return cmds(tok, ptok, 1); } -static tree* +static tree * cmds(int tok, int *ptok, int nlok) { tree *t, **last, *t2; @@ -92,20 +90,20 @@ cmds(int tok, int *ptok, int nlok) // cmdsan: cmdsa // | cmd '\n' - t = nil; + t = nil; last = nil; - for(;;) { + for(;;){ t2 = cmd(tok, &tok); if(tok == '&') t2 = tree1('&', t2); - if(t2 != nil) { + if(t2 != nil){ // slot into list t - if(last == nil) { - t = t2; + if(last == nil){ + t = t2; last = &t; - } else { + }else{ *last = tree2(';', *last, t2); - last = &(*last)->child[1]; + last = &(*last)->child[1]; } } if(tok != ';' && tok != '&' && (!nlok || tok != '\n')) @@ -116,7 +114,7 @@ cmds(int tok, int *ptok, int nlok) return t; } -static tree* +static tree * brace(int tok) { tree *t; @@ -132,7 +130,7 @@ brace(int tok) return tree1(BRACE, t); } -static tree* +static tree * paren(int tok) { tree *t; @@ -148,7 +146,7 @@ paren(int tok) return tree1(PCMD, t); } -static tree* +static tree * epilog(int tok, int *ptok) { tree *t, *r; @@ -156,18 +154,18 @@ epilog(int tok, int *ptok) // epilog: {$$=0;} // | redir epilog {$$=mung2($1, $1->child[0], $2);} - if(tok != REDIR && tok != DUP) { + if(tok != REDIR && tok != DUP){ *ptok = tok; return nil; } - r = yyredir(tok, &tok); - t = epilog(tok, &tok); + r = yyredir(tok, &tok); + t = epilog(tok, &tok); *ptok = tok; return mung2(r, r->child[0], t); } -static tree* +static tree * yyredir(int tok, int *ptok) { tree *r, *w; @@ -175,24 +173,23 @@ yyredir(int tok, int *ptok) // redir: REDIR word {$$=mung1($1, $1->rtype==HERE?heredoc($2):$2);} // | DUP - switch(tok) { - default: - syntax(tok); + switch(tok){ + default: syntax(tok); case DUP: - r = yylval.tree; + r = yylval.tree; *ptok = dropsp(yylex()); break; case REDIR: - r = yylval.tree; - w = yyword(yylex(), &tok, 1); + r = yylval.tree; + w = yyword(yylex(), &tok, 1); *ptok = dropsp(tok); - r = mung1(r, r->rtype==HERE?heredoc(w):w); + r = mung1(r, r->rtype == HERE ? heredoc(w) : w); break; } return r; } -static tree* +static tree * cmd(int tok, int *ptok) { int op; @@ -202,8 +199,8 @@ cmd(int tok, int *ptok) // | cmd OROR cmd {$$=tree2(OROR, $1, $3);} tok = dropsp(tok); - t1 = cmd2(tok, &tok); - while(tok == ANDAND || tok == OROR) { + t1 = cmd2(tok, &tok); + while(tok == ANDAND || tok == OROR){ op = tok; t2 = cmd2(dropnl(yylex()), &tok); t1 = tree2(op, t1, t2); @@ -212,14 +209,14 @@ cmd(int tok, int *ptok) return t1; } -static tree* +static tree * cmd2(int tok, int *ptok) { tree *t1, *t2, *t3; // | cmd PIPE cmd {$$=mung2($2, $1, $3);} t1 = cmd3(tok, &tok); - while(tok == PIPE) { + while(tok == PIPE){ t2 = yylval.tree; t3 = cmd3(dropnl(yylex()), &tok); t1 = mung2(t2, t1, t3); @@ -228,25 +225,23 @@ cmd2(int tok, int *ptok) return t1; } -static tree* +static tree * cmd3(int tok, int *ptok) { tree *t1, *t2, *t3, *t4; tok = dropsp(tok); - switch(tok) { + switch(tok){ case ';': case '&': - case '\n': - *ptok = tok; - return nil; + case '\n': *ptok = tok; return nil; case IF: - // | IF paren {skipnl();} cmd {$$=mung2($1, $2, $4);} - // | IF NOT {skipnl();} cmd {$$=mung1($2, $4);} - t1 = yylval.tree; + // | IF paren {skipnl();}cmd {$$=mung2($1, $2, $4);} + // | IF NOT {skipnl();}cmd {$$=mung1($2, $4);} + t1 = yylval.tree; tok = dropsp(yylex()); - if(tok == NOT) { + if(tok == NOT){ t1 = yylval.tree; t2 = cmd(dropnl(yylex()), ptok); return mung1(t1, t2); @@ -256,21 +251,18 @@ cmd3(int tok, int *ptok) return mung2(t1, t2, t3); case FOR: - // | FOR '(' word IN words ')' {skipnl();} cmd + // | FOR '(' word IN words ')' {skipnl();}cmd // {$$=mung3($1, $3, $5 ? $5 : tree1(PAREN, $5), $8);} - // | FOR '(' word ')' {skipnl();} cmd + // | FOR '(' word ')' {skipnl();}cmd // {$$=mung3($1, $3, (tree *)0, $6);} - t1 = yylval.tree; + t1 = yylval.tree; tok = dropsp(yylex()); if(tok != '(') syntax(tok); t2 = yyword(yylex(), &tok, 1); - switch(tok) { - default: - syntax(tok); - case ')': - t3 = nil; - break; + switch(tok){ + default: syntax(tok); + case ')': t3 = nil; break; case IN: t3 = words(yylex(), &tok); if(t3 == nil) @@ -283,7 +275,7 @@ cmd3(int tok, int *ptok) return mung3(t1, t2, t3, t4); case WHILE: - // | WHILE paren {skipnl();} cmd + // | WHILE paren {skipnl();}cmd // {$$=mung2($1, $2, $4);} t1 = yylval.tree; t2 = paren(yylex()); @@ -291,11 +283,11 @@ cmd3(int tok, int *ptok) return mung2(t1, t2, t3); case SWITCH: - // | SWITCH word {skipnl();} brace + // | SWITCH word {skipnl();}brace // {$$=tree2(SWITCH, $2, $4);} - t1 = yyword(yylex(), &tok, 1); - tok = dropnl(tok); // doesn't work in yacc grammar but works here! - t2 = brace(tok); + t1 = yyword(yylex(), &tok, 1); + tok = dropnl(tok); // doesn't work in yacc grammar but works here! + t2 = brace(tok); *ptok = dropsp(yylex()); return tree2(SWITCH, t1, t2); @@ -303,11 +295,11 @@ cmd3(int tok, int *ptok) // | FN words brace {$$=tree2(FN, $2, $3);} // | FN words {$$=tree1(FN, $2);} t1 = words(yylex(), &tok); - if(tok != '{') { + if(tok != '{'){ *ptok = tok; return tree1(FN, t1); } - t2 = brace(tok); + t2 = brace(tok); *ptok = dropsp(yylex()); return tree2(FN, t1, t2); @@ -322,27 +314,27 @@ cmd3(int tok, int *ptok) case SUBSHELL: // | BANG cmd {$$=mung1($1, $2);} // | SUBSHELL cmd {$$=mung1($1, $2);} - // Note: cmd2: ! x | y is !{x | y} not {!x} | y. + // Note: cmd2: ! x | y is !{x | y}not {!x} | y. t1 = yylval.tree; return mung1(t1, cmd2(yylex(), ptok)); case REDIR: case DUP: // | redir cmd %prec BANG {$$=mung2($1, $1->child[0], $2);} - // Note: cmd2: {>x echo a | tr a-z A-Z} writes A to x. + // Note: cmd2: {>x echo a | tr a-z A-Z}writes A to x. t1 = yyredir(tok, &tok); t2 = cmd2(tok, ptok); return mung2(t1, t1->child[0], t2); case '{': // | brace epilog {$$=epimung($1, $2);} - t1 = brace(tok); + t1 = brace(tok); tok = dropsp(yylex()); - t2 = epilog(tok, ptok); + t2 = epilog(tok, ptok); return epimung(t1, t2); } - if(!iswordtok(tok)) { + if(!iswordtok(tok)){ *ptok = tok; return nil; } @@ -356,9 +348,9 @@ cmd3(int tok, int *ptok) // Except NOT, but disallowing that in yacc was likely a mistake anyway: // there's no ambiguity in not=1 or not x y z. t1 = yyword(tok, &tok, 0); - if(tok == '=') { + if(tok == '='){ // assignment - // Note: cmd2: {x=1 true | echo $x} echoes 1. + // Note: cmd2: {x=1 true | echo $x}echoes 1. t1 = tree2('=', t1, yyword(yylex(), &tok, 1)); t2 = cmd2(tok, ptok); return mung3(t1, t1->child[0], t1->child[1], t2); @@ -367,12 +359,12 @@ cmd3(int tok, int *ptok) // simple: first // | simple word {$$=tree2(ARGLIST, $1, $2);} // | simple redir {$$=tree2(ARGLIST, $1, $2);} - for(;;) { - if(tok == REDIR || tok == DUP) { + for(;;){ + if(tok == REDIR || tok == DUP){ t1 = tree2(ARGLIST, t1, yyredir(tok, &tok)); - } else if(iswordtok(tok)) { + }else if(iswordtok(tok)){ t1 = tree2(ARGLIST, t1, yyword(tok, &tok, 1)); - } else { + }else{ break; } } @@ -380,7 +372,7 @@ cmd3(int tok, int *ptok) return simplemung(t1); } -static tree* +static tree * words(int tok, int *ptok) { tree *t; @@ -388,15 +380,14 @@ words(int tok, int *ptok) // words: {$$=(tree*)0;} // | words word {$$=tree2(WORDS, $1, $2);} - t = nil; + t = nil; tok = dropsp(tok); - while(iswordtok(tok)) - t = tree2(WORDS, t, yyword(tok, &tok, 1)); + while(iswordtok(tok)) t = tree2(WORDS, t, yyword(tok, &tok, 1)); *ptok = tok; return t; } -static tree* +static tree * yyword(int tok, int *ptok, int eqok) { tree *t; @@ -424,8 +415,8 @@ yyword(int tok, int *ptok, int eqok) t = word1(tok, &tok); if(tok == '=' && !eqok) goto out; - for(;;) { - if(iswordtok(tok)) { + for(;;){ + if(iswordtok(tok)){ // No free carats around parens. if(t->type == PAREN || tok == '(') syntax(tok); @@ -433,7 +424,7 @@ yyword(int tok, int *ptok, int eqok) continue; } tok = dropsp(tok); - if(tok == '^') { + if(tok == '^'){ t = tree2('^', t, word1(yylex(), &tok)); continue; } @@ -444,15 +435,14 @@ yyword(int tok, int *ptok, int eqok) return t; } -static tree* +static tree * word1(int tok, int *ptok) { tree *w, *sub, *t; tok = dropsp(tok); - switch(tok) { - default: - syntax(tok); + switch(tok){ + default: syntax(tok); case WORD: case FOR: @@ -467,20 +457,18 @@ word1(int tok, int *ptok) case FN: // | WORD // keyword: FOR|IN|WHILE|IF|NOT|TWIDDLE|BANG|SUBSHELL|SWITCH|FN - t = yylval.tree; + t = yylval.tree; t->type = WORD; - *ptok = yylex(); + *ptok = yylex(); return t; - case '=': - *ptok = yylex(); - return token("=", WORD); + case '=': *ptok = yylex(); return token("=", WORD); case '$': // comword: '$' word1 {$$=tree1('$', $2);} // | '$' word1 SUB words ')' {$$=tree2(SUB, $2, $4);} w = word1(yylex(), &tok); - if(tok == '(') { + if(tok == '('){ sub = words(yylex(), &tok); if(tok != ')') syntax(tok); @@ -500,7 +488,7 @@ word1(int tok, int *ptok) case '`': // | '`' brace {$$=tree1('`', $2);} - t = tree1('`', brace(yylex())); + t = tree1('`', brace(yylex())); *ptok = yylex(); return t; @@ -514,10 +502,10 @@ word1(int tok, int *ptok) case REDIRW: // | REDIRW brace {$$=mung1($1, $2); $$->type=PIPEFD;} - t = yylval.tree; - t = mung1(t, brace(yylex())); + t = yylval.tree; + t = mung1(t, brace(yylex())); t->type = PIPEFD; - *ptok = yylex(); + *ptok = yylex(); return t; } } @@ -525,7 +513,7 @@ word1(int tok, int *ptok) static int iswordtok(int tok) { - switch(tok) { + switch(tok){ case FOR: case IN: case WHILE: @@ -543,8 +531,7 @@ iswordtok(int tok) case '`': case '(': case REDIRW: - case '=': - return 1; + case '=': return 1; } return 0; } diff --git a/src/cmd/rc/pcmd.c b/src/cmd/rc/pcmd.c index cae8473799..5f25731ad7 100644 --- a/src/cmd/rc/pcmd.c +++ b/src/cmd/rc/pcmd.c @@ -1,85 +1,82 @@ #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 +#define c0 t->child[0] +#define c1 t->child[1] +#define c2 t->child[2] + +static void pdeglob(io *f, char *s) { while(*s){ - if(*s==GLOB) + if(*s == GLOB) s++; pchr(f, *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) { - if(t==0) + if(t == 0) return; switch(t->type){ - default: pfmt(f, "bad %d %p %p %p", t->type, c0, c1, c2); - break; - case '$': pfmt(f, "$%t", c0); - break; - case '"': pfmt(f, "$\"%t", c0); - break; - case '&': pfmt(f, "%t&", c0); - break; - case '^': pfmt(f, "%t^%t", c0, c1); - break; - case '`': pfmt(f, "`%t", c0); - break; - case ANDAND: pfmt(f, "%t && %t", c0, c1); - break; - case BANG: pfmt(f, "! %t", c0); - break; - case BRACE: pfmt(f, "{%t}", c0); - break; - case COUNT: pfmt(f, "$#%t", c0); - break; - case FN: pfmt(f, "fn %t %t", c0, c1); - break; - case IF: pfmt(f, "if%t%t", c0, c1); - break; - case NOT: pfmt(f, "if not %t", c0); - break; - case OROR: pfmt(f, "%t || %t", c0, c1); - break; + default: pfmt(f, "bad %d %p %p %p", t->type, c0, c1, c2); break; + case '$': pfmt(f, "$%t", c0); break; + case '"': pfmt(f, "$\"%t", c0); break; + case '&': pfmt(f, "%t&", c0); break; + case '^': pfmt(f, "%t^%t", c0, c1); break; + 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: + ntab++; + pfmt(f, "{\n%s%t", tabs(), c0); + ntab--; + pfmt(f, "\n%s}", tabs()); + break; + case COUNT: pfmt(f, "$#%t", c0); break; + case FN: pfmt(f, "fn %t %t", c0, c1); break; + case IF: pfmt(f, "if%t%t", c0, c1); break; + case NOT: pfmt(f, "if not %t", c0); break; + case OROR: pfmt(f, "%t || %t", c0, c1); break; case PCMD: - case PAREN: pfmt(f, "(%t)", c0); - break; - case SUB: pfmt(f, "$%t(%t)", c0, c1); - break; - case SIMPLE: pfmt(f, "%t", c0); - break; - case SUBSHELL: pfmt(f, "@ %t", c0); - break; - case SWITCH: pfmt(f, "switch %t %t", c0, c1); - break; - case TWIDDLE: pfmt(f, "~ %t %t", c0, c1); - break; - case WHILE: pfmt(f, "while %t%t", c0, c1); - break; + case PAREN: pfmt(f, "(%t)", c0); break; + case SUB: pfmt(f, "$%t(%t)", c0, c1); break; + case SIMPLE: pfmt(f, "%t", c0); break; + case SUBSHELL: pfmt(f, "@ %t", c0); break; + case SWITCH: pfmt(f, "switch %t %t", c0, c1); break; + case TWIDDLE: pfmt(f, "~ %t %t", c0, c1); break; + case WHILE: pfmt(f, "while %t%t", c0, c1); break; case ARGLIST: - if(c0==0) + if(c0 == 0) pfmt(f, "%t", c1); - else if(c1==0) + else if(c1 == 0) pfmt(f, "%t", c0); else pfmt(f, "%t %t", c0, c1); break; case ';': if(c0){ - if(c1) - pfmt(f, "%t%c%t", c0, nl, c1); - else pfmt(f, "%t", c0); - } - else pfmt(f, "%t", c1); + 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; case WORDS: if(c0) @@ -95,10 +92,11 @@ pcmd(io *f, tree *t) case WORD: if(t->quoted) pfmt(f, "%Q", t->str); - else pdeglob(f, t->str); + else + pdeglob(f, t->str); break; case DUP: - if(t->rtype==DUPFD) + 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); @@ -106,27 +104,31 @@ 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: pchr(f, '<'); - if(t->rtype==RDWR) + if(t->rtype == RDWR) pchr(f, '>'); - if(t->fd0!=0) + if(t->fd0 != 0) pfmt(f, "[%d]", t->fd0); break; - case APPEND: - pchr(f, '>'); + case APPEND: pchr(f, '>'); case WRITE: pchr(f, '>'); - if(t->fd0!=1) + if(t->fd0 != 1) pfmt(f, "[%d]", t->fd0); 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 '=': @@ -136,130 +138,12 @@ pcmd(io *f, tree *t) break; case PIPE: pfmt(f, "%t|", c0); - if(t->fd1==0){ - if(t->fd0!=1) + if(t->fd1 == 0){ + if(t->fd0 != 1) pfmt(f, "[%d]", t->fd0); - } - else pfmt(f, "[%d=%d]", t->fd0, t->fd1); + }else + pfmt(f, "[%d=%d]", t->fd0, t->fd1); pfmt(f, "%t", c1); 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..945d952331 100644 --- a/src/cmd/rc/pfnc.c +++ b/src/cmd/rc/pfnc.c @@ -2,70 +2,44 @@ #include "exec.h" #include "io.h" #include "fns.h" -struct{ +struct { void (*f)(void); char *name; -}fname[] = { - Xappend, "Xappend", - Xasync, "Xasync", - Xbang, "Xbang", - Xclose, "Xclose", - Xdup, "Xdup", - Xeflag, "Xeflag", - Xexit, "Xexit", - Xfalse, "Xfalse", - Xifnot, "Xifnot", - Xjump, "Xjump", - Xmark, "Xmark", - Xpopm, "Xpopm", - Xrdwr, "Xrdwr", - Xread, "Xread", - Xreturn, "Xreturn", - Xtrue, "Xtrue", - Xif, "Xif", - Xwastrue, "Xwastrue", - Xword, "Xword", - Xwrite, "Xwrite", - Xmatch, "Xmatch", - Xcase, "Xcase", - Xconc, "Xconc", - Xassign, "Xassign", - Xdol, "Xdol", - Xcount, "Xcount", - Xlocal, "Xlocal", - Xunlocal, "Xunlocal", - Xfn, "Xfn", - Xdelfn, "Xdelfn", - Xpipe, "Xpipe", - Xpipewait, "Xpipewait", - 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", -0}; +}fname[] = {Xappend, "Xappend", Xasync, "Xasync", Xbang, "Xbang", Xclose, + "Xclose", Xdup, "Xdup", Xeflag, "Xeflag", Xexit, "Xexit", + Xfalse, "Xfalse", Xifnot, "Xifnot", Xjump, "Xjump", Xmark, + "Xmark", Xpopm, "Xpopm", Xpush, "Xpush", Xrdwr, "Xrdwr", + Xread, "Xread", Xhere, "Xhere", Xhereq, "Xhereq", Xreturn, + "Xreturn", Xtrue, "Xtrue", Xif, "Xif", Xwastrue, "Xwastrue", + Xword, "Xword", Xwrite, "Xwrite", Xmatch, "Xmatch", Xcase, + "Xcase", Xconc, "Xconc", Xassign, "Xassign", Xdol, "Xdol", + Xcount, "Xcount", Xlocal, "Xlocal", Xunlocal, "Xunlocal", Xfn, + "Xfn", Xdelfn, "Xdelfn", Xpipe, "Xpipe", Xpipewait, "Xpipewait", + Xpopredir, "Xpopredir", Xrdcmds, "Xrdcmds", Xbackq, "Xbackq", Xpipefd, + "Xpipefd", Xsubshell, "Xsubshell", Xfor, "Xfor", Xglob, "Xglob", + Xsimple, "Xsimple", 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; + for(i = 0; fname[i].f; i++) + if(fname[i].f == fn){ + pstr(f, fname[i].name); + return; + } + pfmt(f, "%p", fn); +} + +void +pfnc(io *f, thread *t) +{ 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; - } - 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); + + 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/plan9ish.c b/src/cmd/rc/plan9ish.c index d52def7d0f..77f65d261f 100644 --- a/src/cmd/rc/plan9ish.c +++ b/src/cmd/rc/plan9ish.c @@ -8,29 +8,18 @@ #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* +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/"; +char Fdprefix[] = "/dev/fd/"; long readnb(int, char *, long); void execfinit(void); void execbind(void); @@ -38,22 +27,11 @@ 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 -}; +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) @@ -62,30 +40,20 @@ execrfork(void) char *s; switch(count(runq->argv->words)){ - case 1: - arg = RFENVG|RFNOTEG|RFNAMEG; - break; + 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; - } + 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: @@ -94,66 +62,69 @@ execrfork(void) poplist(); return; } - if(rfork(arg)==-1){ + if(rfork(arg) == -1){ pfmt(err, "rc: %s failed\n", runq->argv->words->word); setstatus("rfork failed"); - } - else + }else setstatus(""); poplist(); } - - -#define SEP '\1' +#define SEP '\1' char **environp; -struct word *enval(s) +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; + 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){ +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++); + 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); */ + /* pfmt(err, "rc: odd environment %q?\n", *env); */ break; case '=': - *s='\0'; - setvar(*env, enval(s+1)); - *s='='; - break; - case '(': /* ignore functions for now */ + *s = '\0'; + setvar(*env, enval(s + 1)); + *s = '='; break; + case '(': /* ignore functions for now */ break; } } } char **envp; -void Xrdfn(void){ +void +Xrdfn(void) +{ char *p; register char *s; register int len; - for(;*envp;envp++){ + for(; *envp; envp++){ s = *envp; if(strncmp(s, "fn#", 3) == 0){ p = strchr(s, '='); if(p == nil) continue; - *p = ' '; + *p = ' '; s[2] = ' '; - len = strlen(s); + len = strlen(s); execcmds(opencore(s, len)); s[len] = '\0'; return; @@ -180,21 +151,25 @@ void Xrdfn(void){ Xreturn(); } union code rdfns[4]; -void execfinit(void){ - static int first=1; +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; + rdfns[0].i = 1; + rdfns[1].f = Xrdfn; + rdfns[2].f = Xjump; + rdfns[3].i = 1; + first = 0; } Xpopm(); - envp=environp; + envp = environp; start(rdfns, 1, runq->local); } extern int mapfd(int); -int Waitfor(int pid, int unused0){ +int +Waitfor(int pid, int unused0) +{ thread *p; Waitmsg *w; char errbuf[ERRMAX]; @@ -203,7 +178,7 @@ int Waitfor(int pid, int unused0){ return 0; while((w = wait()) != nil){ delwaitpid(w->pid); - if(w->pid==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); @@ -212,24 +187,26 @@ int Waitfor(int pid, int unused0){ } 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; + 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; + if(strcmp(errbuf, "interrupted") == 0) + return -1; return 0; } -char **mkargv(word *a) +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; + 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; } /* @@ -283,47 +260,50 @@ void Updenv(void){ int cmpenv(const void *a, const void *b) { - return strcmp(*(char**)a, *(char**)b); + return strcmp(*(char **)a, *(char **)b); } -char **mkenv(){ +char ** +mkenv() +{ register char **env, **ep, *p, *q; register struct var **h, *v; register struct word *a; - register int nvar=0, nchr=0, sep; + 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++; + 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; } - *p++='\0'; } - if(v->fn){ - *ep++=p; + 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++=' '; @@ -331,81 +311,89 @@ char **mkenv(){ 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'; + *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; + *ep = 0; qsort((char *)env, nvar, sizeof ep[0], cmpenv); return env; } -void Updenv(void){} -void Execute(word *args, word *path) +void +Updenv(void) { - char **argv=mkargv(args); - char **env=mkenv(); +} +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){ + 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){ + if(nc + strlen(argv[1]) < 1024){ strcat(file, argv[1]); - execve(file, argv+1, env); - } - else werrstr("command name too long"); + 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) +#define NDIR 256 /* shoud be a better way */ +int +Globsize(char *p) { - ulong isglob=0, globlen=NDIR+1; - for(;*p;p++){ - if(*p==GLOB){ + ulong isglob = 0, globlen = NDIR + 1; + for(; *p; p++){ + if(*p == GLOB){ p++; - if(*p!=GLOB) isglob++; - globlen+=*p=='*'?NDIR:1; - } - else + 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; + return isglob ? globlen : 0; +} +#define NFD 50 +#define NDBUF 32 +struct { + Dir *dbuf; + int i; + int n; }dir[NFD]; -int Opendir(char *name) +int +Opendir(char *name) { Dir *db; int f; - f=open(name, 0); - if(f==-1) + f = open(name, 0); + if(f == -1) return f; db = dirfstat(f); - if(db!=nil && (db->mode&DMDIR)){ - if(fmode & DMDIR)){ + if(f < NFD){ + dir[f].i = 0; + dir[f].n = 0; } free(db); return f; @@ -414,35 +402,38 @@ int Opendir(char *name) close(f); return -1; } -int Readdir(int f, char *p, int onlydirs) +int +Readdir(int f, char *p, int onlydirs) { int n; - USED(onlydirs); /* only advisory */ + USED(onlydirs); /* only advisory */ - if(f<0 || f>=NFD) + if(f < 0 || f >= NFD) return 0; - if(dir[f].i==dir[f].n){ /* read */ + 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; + 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; + dir[f].n = 0; + dir[f].i = 0; } - if(dir[f].i==dir[f].n) + 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= 0 && f < NFD){ free(dir[f].dbuf); - dir[f].i=0; - dir[f].n=0; - dir[f].dbuf=0; + dir[f].i = 0; + dir[f].n = 0; + dir[f].dbuf = 0; } close(f); } @@ -451,11 +442,11 @@ void notifyf(void *unused0, 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){ + for(i = 0; syssigname[i]; i++) + if(strncmp(s, syssigname[i], strlen(syssigname[i])) == 0){ + if(strncmp(s, "sys: ", 5) != 0){ if(kidpid && !interrupted){ - interrupted=1; + interrupted = 1; postnote(PNGROUP, kidpid, s); } interrupted = 1; @@ -463,92 +454,117 @@ notifyf(void *unused0, char *s) goto Out; } if(strcmp(s, "sys: window size change") != 0) - if(strcmp(s, "sys: write on closed pipe") != 0) - if(strcmp(s, "sys: child") != 0) - pfmt(err, "rc: note: %s\n", s); + if(strcmp(s, "sys: write on closed pipe") != 0) + if(strcmp(s, "sys: child") != 0) + pfmt(err, "rc: note: %s\n", s); noted(NDFLT); return; Out: - if(strcmp(s, "interrupt")!=0 || trap[i]==0){ + if(strcmp(s, "interrupt") != 0 || trap[i] == 0){ trap[i]++; ntrap++; } - if(ntrap>=32){ /* rc is probably in a trap loop */ + if(ntrap >= 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){ +void +Trapinit(void) +{ notify(notifyf); } -void Unlink(char *name) +void +Unlink(char *name) { remove(name); } -long Write(int fd, char *buf, long cnt) +long +Write(int fd, char *buf, long cnt) { return write(fd, buf, (long)cnt); } -long Read(int fd, char *buf, long cnt) +long +Read(int fd, char *buf, long cnt) { int i; i = readnb(fd, buf, cnt); - if(ntrap) dotrap(); + if(ntrap) + dotrap(); return i; } -long Seek(int fd, long cnt, long whence) +long +Seek(int fd, long cnt, long whence) { return seek(fd, cnt, whence); } -int Executable(char *file) +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); + if(statbuf == nil) + return 0; + ret = ((statbuf->mode & 0111) != 0 && (statbuf->mode & DMDIR) == 0); free(statbuf); return ret; } -int Creat(char *file) +int +Creat(char *file) { return create(file, 1, 0666L); } -int Dup(int a, int b){ +int +Dup(int a, int b) +{ return dup(a, b); } -int Dup1(int a){ +int +Dup1(int a) +{ return dup(a, -1); } -void Exit(char *stat) +void +Exit(char *stat) { Updenv(); setstatus(stat); - exits(truestatus()?"":getstatus()); + exits(truestatus() ? "" : getstatus()); } -int Eintr(void){ +int +Eintr(void) +{ return interrupted; } -void Noerror(void){ - interrupted=0; +void +Noerror(void) +{ + interrupted = 0; } int -Isatty(int fd){ +Isatty(int fd) +{ return isatty(fd); } -void Abort(void){ +void +Abort(void) +{ pfmt(err, "aborting\n"); flush(err); Exit("aborting"); } -void Memcpy(char *a, char *b, long n) +void +Memcpy(char *a, char *b, long n) { memmove(a, b, (long)n); } -void *Malloc(ulong n){ +void * +Malloc(ulong n) +{ return malloc(n); } @@ -569,9 +585,9 @@ int nwaitpids; void addwaitpid(int pid) { - waitpids = realloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]); + waitpids = realloc(waitpids, (nwaitpids + 1) * sizeof waitpids[0]); if(waitpids == 0) - panic("Can't realloc %d waitpids", nwaitpids+1); + panic("Can't realloc %d waitpids", nwaitpids + 1); waitpids[nwaitpids++] = pid; } @@ -580,7 +596,7 @@ delwaitpid(int pid) { int r, w; - for(r=w=0; r #include -#undef NSIG -#undef SIGINT -#undef SIGQUIT -#define NSIG 32 -#define SIGINT 2 -#define SIGQUIT 3 -#endif -#ifdef V9 -#include -#include -#endif -#ifdef Sun +#define NSIG 32 +#define SIGINT 2 +#define SIGQUIT 3 +#else +#include +#include +#include +#include #include -#endif -#define YYMAXDEPTH 500 -#ifndef PAREN -#ifndef YYMAJOR -#include "x.tab.h" +#ifndef NSIG +#define NSIG 32 #endif #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 +#include +#define YYMAXDEPTH 500 +#ifndef PAREN +#include "y.tab.h" +#endif 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; -struct tree{ +#undef pipe + +#pragma incomplete word +#pragma incomplete io + +struct tree { int type; - int rtype, fd0, fd1; /* details of REDIR PIPE DUP tokens */ + 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; - int quoted; - int iskw; 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 *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 *); +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{ +union code { void (*f)(void); int i; char *s; }; -char *promptstr; -#define NTOK 8192 -char tok[NTOK]; -#define APPEND 1 -#define WRITE 2 -#define READ 3 -#define HERE 4 -#define DUPFD 5 -#define CLOSE 6 -#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*); + +#define NTOK 8192 + +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]; }; -var *vlook(char*), *gvlook(char*), *newvar(char*, var*); -#define NVAR 521 -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; +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 + +struct 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 */ + void (*changefn)(var *); + char fnchanged; + char changed; + char name[]; }; -int mypid; +var *vlook(char *), *gvlook(char *), *newvar(char *, var *); +void setvar(char *, word *), freevar(var *); + +#define NVAR 521 +extern var *gvar[NVAR]; /* hash for globals */ + +#define new(type) ((type *)emalloc(sizeof(type))) + +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. @@ -118,36 +144,28 @@ int mypid; * GLOB[...] matches anything in the brackets * GLOBGLOB matches GLOB */ -#define GLOB ((char)0x01) +#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 */ -extern int doprompt; /* is it time for a prompt? */ +#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. * 9th edition Unix doesn't care, the following defines * work on plan 9. */ -#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; +#define PRD 0 +#define PWR 1 +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..5ec290188c 100644 --- a/src/cmd/rc/simple.c +++ b/src/cmd/rc/simple.c @@ -6,149 +6,194 @@ #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++; - return c->f==Xexit; +exitnext(void) +{ + 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){ + 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; - } + if(strcmp(a->word, "builtin") == 0){ 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(); - } - else{ - flush(err); - Updenv(); /* necessary so changes don't go out again */ + /* does not return */ + }else{ 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){ doredir(rp->next); switch(rp->type){ case ROPEN: - if(rp->from!=rp->to){ + 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); - break; + case RDUP: Dup(rp->from, rp->to); break; + case RCLOSE: Close(rp->from); break; } } } -word* -searchpath(char *w) +word * +_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) { - popword(); /* "exec" */ - if(runq->argv->words==0){ - Xerror1("empty argument list"); + char **argv; + word *path; + + popword(); /* "exec" */ + if(runq->argv->words == 0){ + 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,41 +201,35 @@ 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; + 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); + if(cdpath == 0) + 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); - } - else + pfmt(err, "Can't cd %s: %s\n", a->word, Errstr()); + }else pfmt(err, "Can't cd -- $home empty\n"); break; } @@ -201,11 +240,9 @@ void execexit(void) { switch(count(runq->argv->words)){ - default: - pfmt(err, "Usage: exit [status]\nExiting anyway\n"); - case 2: - setstatus(runq->argv->words->next->word); - case 1: Xexit(); + default: pfmt(err, "Usage: exit [status]\nExiting anyway\n"); + case 2: setstatus(runq->argv->words->next->word); + case 1: Xexit(); } } @@ -221,175 +258,160 @@ execshift(void) setstatus("shift usage"); poplist(); return; - case 2: - n = atoi(runq->argv->words->next->word); - break; - case 1: - n = 1; - break; + case 2: n = atoi(runq->argv->words->next->word); break; + case 1: n = 1; 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); - star->val = a; + free(Freeword(star->val)); + star->val = a; star->changed = 1; } setstatus(""); 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) { redir *rp; - for(rp = runq->redir;rp;rp = rp->next){ + for(rp = runq->redir; rp; rp = rp->next){ switch(rp->type){ case RCLOSE: - if(rp->from==fd) - fd=-1; + if(rp->from == fd) + fd = -1; break; case RDUP: case ROPEN: - if(rp->to==fd) + if(rp->to == fd) fd = rp->from; break; } } 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; - if(strcmp(file, "/dev/stdin")==0){ /* for sun & ucb */ + 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 */ + fprint(2, "%s\n", file); fd = Dup1(0); - if(fd>=0) + if(fd >= 0) break; } + free(file); } - if(fd<0){ - pfmt(err, "%s: ", zero); - setstatus("can't open"); - Xerror(".: can't open"); + if(fd < 0){ + 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->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++; + runq->lex->qflag = qflag; + runq->iflag = iflag; + 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,83 +420,74 @@ 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; + val = runq->argv->words->next->next->word; + if(strlen(letter) == 1){ + if(strcmp(val, "+") == 0){ + flag[(unsigned char)letter[0]] = flagset; break; } - if(strcmp(val, "-")==0){ - flag[(uchar)letter[0]] = 0; + if(strcmp(val, "-") == 0){ + flag[(unsigned char)letter[0]] = 0; break; } } - default: - Xerror1("Usage: flag [letter] [+-]"); - return; + default: Xerror1("Usage: flag [letter] [+-]"); return; } poplist(); } void -execwhatis(void){ /* mildly wrong -- should fork before writing */ +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){ + if(a == 0){ Xerror1("Usage: whatis name ..."); return; } setstatus(""); - out->fd = mapfd(1); - out->bufp = out->buf; - out->ebuf = &out->buf[NBUF]; - out->strp = 0; - for(;a;a = a->next){ + out = openiofd(mapfd(1)); + for(; a; a = a->next){ v = vlook(a->word); if(v->val){ pfmt(out, "%s=", a->word); - if(v->val->next==0) + if(v->val->next == 0) pfmt(out, "%q\n", v->val->word); else{ - sep='('; - for(b = v->val;b && b->word;b = b->next){ + sep = '('; + for(b = v->val; b && b->word; b = b->next){ pfmt(out, "%c%q", sep, b->word); - sep=' '; + sep = ' '; } - pfmt(out, ")\n"); + pstr(out, ")\n"); } found = 1; - } - else + }else 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,24 +495,19 @@ execwhatis(void){ /* mildly wrong -- should fork before writing */ } } } + flushio(out); } poplist(); - flush(err); + free(closeiostr(out)); /* don't close fd */ } void execwait(void) { switch(count(runq->argv->words)){ - default: - Xerror1("Usage: wait [pid]"); - return; - case 2: - Waitfor(atoi(runq->argv->words->next->word), 0); - break; - case 1: - Waitfor(-1, 0); - break; + default: Xerror1("Usage: wait [pid]"); return; + case 2: Waitfor(atoi(runq->argv->words->next->word)); break; + case 1: Waitfor(-1); break; } poplist(); } diff --git a/src/cmd/rc/subr.c b/src/cmd/rc/subr.c index 47f7439e64..da09b41f0d 100644 --- a/src/cmd/rc/subr.c +++ b/src/cmd/rc/subr.c @@ -1,77 +1,74 @@ #include "rc.h" -#include "exec.h" #include "io.h" #include "fns.h" -char* +void * emalloc(long n) { - char *p = (char *)Malloc(n); - if(p==0) + 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) { - if(n<0){ - *bp++='-'; - n=-n; /* doesn't work for n==-inf */ + if(n < 0){ + *bp++ = '-'; + n = -n; /* doesn't work for n==-inf */ } - if(n/10) - iacvt(n/10); - *bp++=n%10+'0'; + if(n / 10) + iacvt(n / 10); + *bp++ = n % 10 + '0'; } void -inttoascii(char *s, long n) +inttoascii(char *s, int n) { bp = s; iacvt(n); - *bp='\0'; + *bp = '\0'; } 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..781bdf316a 100644 --- a/src/cmd/rc/syn.y +++ b/src/cmd/rc/syn.y @@ -1,5 +1,5 @@ %term FOR IN WHILE IF NOT TWIDDLE BANG SUBSHELL SWITCH FN -%term WORD REDIR REDIRW DUP PIPE SUB +%term WORD REDIR DUP PIPE SUB %term SIMPLE ARGLIST WORDS BRACE PAREN PCMD PIPEFD /* not used in syntax */ /* operator priorities -- lowest first */ %left IF WHILE FOR SWITCH ')' NOT @@ -19,10 +19,10 @@ %type line paren brace body cmdsa cmdsan assign epilog redir %type cmd simple first word comword keyword words %type NOT FOR IN WHILE IF TWIDDLE BANG SUBSHELL SWITCH FN -%type WORD REDIR REDIRW DUP PIPE +%type WORD REDIR DUP PIPE %% rc: { return 1;} -| line '\n' {return !compile($1);} +| line '\n' {readhere(lex->input); return !compile($1);} line: cmd | cmdsa line {$$=tree2(';', $1, $2);} body: cmd @@ -30,13 +30,13 @@ body: cmd cmdsa: cmd ';' | cmd '&' {$$=tree1('&', $1);} cmdsan: cmdsa -| cmd '\n' +| cmd '\n' {readhere(lex->input);} brace: '{' body '}' {$$=tree1(BRACE, $2);} paren: '(' body ')' {$$=tree1(PCMD, $2);} assign: first '=' word {$$=tree2('=', $1, $3);} epilog: {$$=0;} | redir epilog {$$=mung2($1, $1->child[0], $2);} -redir: REDIR word {$$=mung1($1, $1->rtype==HERE?heredoc($2):$2);} +redir: REDIR word {$$=mung1($1, $2); if($$->rtype==HERE) heredoc($$);} | DUP cmd: {$$=0;} | brace epilog {$$=epimung($1, $2);} @@ -45,7 +45,7 @@ cmd: {$$=0;} | IF NOT {skipnl();} cmd {$$=mung1($2, $4);} | FOR '(' word IN words ')' {skipnl();} cmd /* - * if ``words'' is nil, we need a tree element to distinguish between + * if ``words'' is nil, we need a tree element to distinguish between * for(i in ) and for(i), the former being a loop over the empty set * and the latter being the implicit argument loop. so if $5 is nil * (the empty set), we represent it as "()". don't parenthesize non-nil @@ -54,7 +54,7 @@ cmd: {$$=0;} */ {$$=mung3($1, $3, $5 ? $5 : tree1(PAREN, $5), $8);} | FOR '(' word ')' {skipnl();} cmd - {$$=mung3($1, $3, (struct tree *)0, $6);} + {$$=mung3($1, $3, (tree*)0, $6);} | WHILE paren {skipnl();} cmd {$$=mung2($1, $2, $4);} | SWITCH word {skipnl();} brace @@ -71,21 +71,22 @@ cmd: {$$=0;} | FN words brace {$$=tree2(FN, $2, $3);} | FN words {$$=tree1(FN, $2);} simple: first -| simple word {$$=tree2(ARGLIST, $1, $2);} -| simple redir {$$=tree2(ARGLIST, $1, $2);} -first: comword -| first '^' word {$$=tree2('^', $1, $3);} -word: keyword {lastword=1; $1->type=WORD;} +| simple word {$$=globprop(tree2(ARGLIST, $1, $2));} +| simple redir {$$=globprop(tree2(ARGLIST, $1, $2));} +first: comword +| first '^' word {$$=globprop(tree2('^', $1, $3));} +word: keyword {lex->lastword=1; $1->type=WORD;} | comword -| word '^' word {$$=tree2('^', $1, $3);} +| word '^' word {$$=globprop(tree2('^', $1, $3));} comword: '$' word {$$=tree1('$', $2);} | '$' word SUB words ')' {$$=tree2(SUB, $2, $4);} | '"' word {$$=tree1('"', $2);} | COUNT word {$$=tree1(COUNT, $2);} | WORD -| '`' brace {$$=tree1('`', $2);} -| '(' words ')' {$$=tree1(PAREN, $2);} -| REDIRW brace {$$=mung1($1, $2); $$->type=PIPEFD;} +| '`' brace {$$=tree2('`', (tree*)0, $2);} +| '`' word brace {$$=tree2('`', $2, $3);} +| '(' words ')' {$$=globprop(tree1(PAREN, $2));} +| REDIR brace {$$=mung1($1, $2); $$->type=PIPEFD;} keyword: FOR|IN|WHILE|IF|NOT|TWIDDLE|BANG|SUBSHELL|SWITCH|FN -words: {$$=(struct tree*)0;} +words: {$$=(tree*)0;} | words word {$$=tree2(WORDS, $1, $2);} diff --git a/src/cmd/rc/tags b/src/cmd/rc/tags new file mode 100644 index 0000000000..6af84a6798 --- /dev/null +++ b/src/cmd/rc/tags @@ -0,0 +1,897 @@ +!_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 +$(OFILES) Makefile /^$(OFILES): $(HFILES)$/;" kind:target line:48 language:Make roles:def end:49 +$(TARG) Makefile /^$(TARG): $(OFILES)$/;" kind:target line:40 language:Make roles:def end:42 +ANDAND x.tab.h /^#define ANDAND /;" kind:macro line:24 language:C++ roles:def end:24 +ANDAND y.tab.c /^#define ANDAND /;" kind:macro line:23 language:C file: roles:def extras:fileScope end:23 +ANDAND y.tab.h /^#define ANDAND /;" kind:macro line:23 language:C++ roles:def end:23 +APPEND rc.h /^#define APPEND /;" kind:macro line:107 language:C++ roles:def end:107 +ARGLIST x.tab.h /^#define ARGLIST /;" kind:macro line:18 language:C++ roles:def end:18 +ARGLIST y.tab.c /^#define ARGLIST /;" kind:macro line:17 language:C file: roles:def extras:fileScope end:17 +ARGLIST y.tab.h /^#define ARGLIST /;" kind:macro line:17 language:C++ roles:def end:17 +Abort plan9ish.c /^void Abort(void){$/;" kind:function line:542 language:C typeref:typename:void signature:(void) roles:def end:546 +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 x.tab.h /^#define BANG /;" kind:macro line:7 language:C++ roles:def end:7 +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 x.tab.h /^#define BRACE /;" kind:macro line:20 language:C++ roles:def end:20 +BRACE y.tab.c /^#define BRACE /;" kind:macro line:19 language:C file: roles:def extras:fileScope end:19 +BRACE y.tab.h /^#define BRACE /;" kind:macro line:19 language:C++ roles:def end:19 +Builtin plan9ish.c /^builtin Builtin[]={$/;" kind:variable line:41 language:C typeref:typename:builtin[] roles:def end:56 +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:112 language:C++ roles:def end:112 +COUNT x.tab.h /^#define COUNT /;" kind:macro line:26 language:C++ roles:def end:26 +COUNT y.tab.c /^#define COUNT /;" kind:macro line:25 language:C file: roles:def extras:fileScope end:25 +COUNT y.tab.h /^#define COUNT /;" kind:macro line:25 language:C++ roles:def end:25 +Chdir unix.c /^Chdir(char *dir)$/;" kind:function line:414 language:C typeref:typename:int signature:(char * dir) roles:def end:417 +Close unix.c /^Close(int fd)$/;" kind:function line:359 language:C typeref:typename:void signature:(int fd) roles:def end:362 +Closedir plan9ish.c /^void Closedir(int f){$/;" kind:function line:440 language:C typeref:typename:void signature:(int f) roles:def end:448 +Closedir unix.c /^Closedir(void *arg)$/;" kind:function line:318 language:C typeref:typename:void signature:(void * arg) roles:def end:322 +Creat plan9ish.c /^int Creat(char *file)$/;" kind:function line:516 language:C typeref:typename:int signature:(char * file) roles:def end:519 +Creat unix.c /^Creat(char *file)$/;" kind:function line:365 language:C typeref:typename:int signature:(char * file) roles:def end:368 +DUP x.tab.h /^#define DUP /;" kind:macro line:14 language:C++ roles:def end:14 +DUP y.tab.c /^#define DUP /;" kind:macro line:13 language:C file: roles:def extras:fileScope end:13 +DUP y.tab.h /^#define DUP /;" kind:macro line:13 language:C++ roles:def end:13 +DUPFD rc.h /^#define DUPFD /;" kind:macro line:111 language:C++ roles:def end:111 +Dup plan9ish.c /^int Dup(int a, int b){$/;" kind:function line:520 language:C typeref:typename:int signature:(int a,int b) roles:def end:522 +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 plan9ish.c /^int Dup1(int a){$/;" kind:function line:523 language:C typeref:typename:int signature:(int a) roles:def end:525 +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 plan9ish.c /^int Eintr(void){$/;" kind:function line:532 language:C typeref:typename:int signature:(void) roles:def end:534 +Eintr unix.c /^Eintr(void)$/;" kind:function line:390 language:C typeref:typename:int signature:(void) roles:def end:393 +Errstr unix.c /^Errstr(void)$/;" kind:function line:242 language:C typeref:typename:char * signature:(void) roles:def end:245 +Exec unix.c /^Exec(char **argv)$/;" kind:function line:288 language:C typeref:typename:void signature:(char ** argv) roles:def end:292 +Executable plan9ish.c /^int Executable(char *file)$/;" kind:function line:505 language:C typeref:typename:int signature:(char * file) roles:def end:515 +Executable unix.c /^Executable(char *file)$/;" kind:function line:343 language:C typeref:typename:int signature:(char * file) roles:def end:346 +Execute plan9ish.c /^void Execute(word *args, word *path)$/;" kind:function line:349 language:C typeref:typename:void signature:(word * args,word * path) roles:def end:374 +Exit plan9ish.c /^void Exit(char *stat)$/;" kind:function line:526 language:C typeref:typename:void signature:(char * stat) roles:def end:531 +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 x.tab.h /^#define FN /;" kind:macro line:10 language:C++ roles:def end:10 +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 x.tab.h /^#define FOR /;" kind:macro line:1 language:C++ roles:def end:1 +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 plan9ish.c /^char Fdprefix[]="\/dev\/fd\/";$/;" kind:variable line:33 language:C typeref:typename:char[] roles:def end:33 +Fdprefix unix.c /^char Fdprefix[] = "\/dev\/fd\/";$/;" kind:variable line:38 language:C typeref:typename:char[] roles:def end:38 +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:144 language:C++ roles:def end:144 +Getstatus exec.c /^Getstatus(void)$/;" kind:function line:1114 language:C typeref:typename:char * signature:(void) roles:def end:1123 +Globsize plan9ish.c /^int Globsize(char *p)$/;" kind:function line:376 language:C typeref:typename:int signature:(char * p) roles:def end:389 +HERE rc.h /^#define HERE /;" kind:macro line:110 language:C++ roles:def end:110 +HFILES Makefile /^HFILES=rc.h\\$/;" kind:macro line:22 language:Make roles:def +Hard unixcrap.c /^#define Hard /;" kind:macro line:55 language:C file: roles:def extras:fileScope end:55 +IF x.tab.h /^#define IF /;" kind:macro line:4 language:C++ roles:def end:4 +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 x.tab.h /^#define IN /;" kind:macro line:2 language:C++ roles:def end:2 +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 plan9ish.c /^Isatty(int fd){$/;" kind:function line:539 language:C typeref:typename:int signature:(int fd) roles:def end:541 +Isatty unix.c /^Isatty(int fd)$/;" kind:function line:402 language:C typeref:typename:int signature:(int fd) roles:def end:405 +Makefile Makefile 1;" kind:file line:1 language:Make roles:def extras:inputFile end:51 epoch:1658745928 +Malloc plan9ish.c /^void *Malloc(ulong n){$/;" kind:function line:551 language:C typeref:typename:void * signature:(ulong n) roles:def end:553 +Memcpy plan9ish.c /^void Memcpy(char *a, char *b, long n)$/;" kind:function line:547 language:C typeref:typename:void signature:(char * a,char * b,long n) roles:def end:550 +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 +NDBUF plan9ish.c /^#define NDBUF /;" kind:macro line:391 language:C file: roles:def extras:fileScope end:391 +NDIR plan9ish.c /^#define NDIR /;" kind:macro line:375 language:C file: roles:def extras:fileScope end:375 +NFD plan9ish.c /^#define NFD /;" kind:macro line:390 language:C file: roles:def extras:fileScope end:390 +NFLAG getflags.h /^#define NFLAG /;" kind:macro line:1 language:C++ roles:def end:1 +NKW var.c /^#define NKW /;" kind:macro line:13 language:C file: roles:def extras:fileScope end:13 +NOT x.tab.h /^#define NOT /;" kind:macro line:5 language:C++ roles:def end:5 +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:78 language:C++ roles:def end:78 +NVAR rc.h /^#define NVAR /;" kind:macro line:127 language:C++ roles:def end:127 +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 plan9ish.c /^void Noerror(void){$/;" kind:function line:535 language:C typeref:typename:void signature:(void) roles:def end:537 +Noerror unix.c /^Noerror(void)$/;" kind:function line:396 language:C typeref:typename:void signature:(void) roles:def end:399 +Notset unixcrap.c /^#define Notset /;" kind:macro line:53 language:C file: roles:def extras:fileScope end:53 +OFILES Makefile /^OFILES=\\$/;" kind:macro line:3 language:Make roles:def +OROR x.tab.h /^#define OROR /;" kind:macro line:25 language:C++ roles:def end:25 +OROR y.tab.c /^#define OROR /;" kind:macro line:24 language:C file: roles:def extras:fileScope end:24 +OROR y.tab.h /^#define OROR /;" kind:macro line:24 language:C++ roles:def end:24 +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 plan9ish.c /^int Opendir(char *name)$/;" kind:function line:397 language:C typeref:typename:int signature:(char * name) roles:def end:416 +Opendir unix.c /^Opendir(char *name)$/;" kind:function line:302 language:C typeref:typename:void * signature:(char * name) roles:def end:305 +PAREN x.tab.h /^#define PAREN /;" kind:macro line:21 language:C++ roles:def end:21 +PAREN y.tab.c /^#define PAREN /;" kind:macro line:20 language:C file: roles:def extras:fileScope end:20 +PAREN y.tab.h /^#define PAREN /;" kind:macro line:20 language:C++ roles:def end:20 +PCMD x.tab.h /^#define PCMD /;" kind:macro line:22 language:C++ roles:def end:22 +PCMD y.tab.c /^#define PCMD /;" kind:macro line:21 language:C file: roles:def extras:fileScope end:21 +PCMD y.tab.h /^#define PCMD /;" kind:macro line:21 language:C++ roles:def end:21 +PIPE x.tab.h /^#define PIPE /;" kind:macro line:15 language:C++ roles:def end:15 +PIPE y.tab.c /^#define PIPE /;" kind:macro line:14 language:C file: roles:def extras:fileScope end:14 +PIPE y.tab.h /^#define PIPE /;" kind:macro line:14 language:C++ roles:def end:14 +PIPEFD x.tab.h /^#define PIPEFD /;" kind:macro line:23 language:C++ roles:def end:23 +PIPEFD y.tab.c /^#define PIPEFD /;" kind:macro line:22 language:C file: roles:def extras:fileScope end:22 +PIPEFD y.tab.h /^#define PIPEFD /;" kind:macro line:22 language:C++ roles:def end:22 +PRD rc.h /^#define PRD /;" kind:macro line:165 language:C++ roles:def end:165 +PREFIX Makefile /^PREFIX=\/usr\/local$/;" kind:macro line:32 language:Make roles:def +PWR rc.h /^#define PWR /;" kind:macro line:166 language:C++ roles:def end:166 +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 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:113 language:C++ roles:def end:113 +READ rc.h /^#define READ /;" kind:macro line:109 language:C++ roles:def end:109 +REDIR x.tab.h /^#define REDIR /;" kind:macro line:12 language:C++ roles:def end:12 +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 x.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 plan9ish.c /^Rcmain(void)$/;" kind:function line:28 language:C typeref:typename:char * signature:(void) roles:def end:31 +Rcmain unix.c /^char Rcmain[PATH_MAX];$/;" kind:variable line:37 language:C typeref:typename:char[] roles:def end:37 +Read plan9ish.c /^long Read(int fd, char *buf, long cnt)$/;" kind:function line:493 language:C typeref:typename:long signature:(int fd,char * buf,long cnt) roles:def end:500 +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 plan9ish.c /^int Readdir(int f, char *p, int onlydirs)$/;" kind:function line:417 language:C typeref:typename:int signature:(int f,char * p,int onlydirs) roles:def end:439 +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 plan9ish.c /^#define SEP /;" kind:macro line:108 language:C file: roles:def extras:fileScope end:108 +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 x.tab.h /^#define SIMPLE /;" kind:macro line:17 language:C++ roles:def end:17 +SIMPLE y.tab.c /^#define SIMPLE /;" kind:macro line:16 language:C file: roles:def extras:fileScope end:16 +SIMPLE y.tab.h /^#define SIMPLE /;" kind:macro line:16 language:C++ roles:def end:16 +SUB x.tab.h /^#define SUB /;" kind:macro line:16 language:C++ roles:def end:16 +SUB y.tab.c /^#define SUB /;" kind:macro line:15 language:C file: roles:def extras:fileScope end:15 +SUB y.tab.h /^#define SUB /;" kind:macro line:15 language:C++ roles:def end:15 +SUBSHELL x.tab.h /^#define SUBSHELL /;" kind:macro line:8 language:C++ roles:def end:8 +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 x.tab.h /^#define SWITCH /;" kind:macro line:9 language:C++ roles:def end:9 +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 plan9ish.c /^long Seek(int fd, long cnt, long whence)$/;" kind:function line:501 language:C typeref:typename:long signature:(int fd,long cnt,long whence) roles:def end:504 +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:1104 language:C typeref:typename:void signature:(char * s) roles:def end:1107 +Signame plan9ish.c /^char *Signame[]={$/;" kind:variable line:11 language:C typeref:typename:char * [] roles:def end:15 +Signame unix.c /^char *Signame[NSIG];$/;" kind:variable line:40 language:C typeref:typename:char * [] roles:def end:40 +Soft unixcrap.c /^#define Soft /;" kind:macro line:56 language:C file: roles:def extras:fileScope end:56 +TARG Makefile /^TARG=rc$/;" kind:macro line:1 language:Make roles:def +TWIDDLE x.tab.h /^#define TWIDDLE /;" kind:macro line:6 language:C++ roles:def end:6 +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 plan9ish.c /^void Trapinit(void){$/;" kind:function line:482 language:C typeref:typename:void signature:(void) roles:def end:484 +Trapinit unix.c /^Trapinit(void)$/;" kind:function line:193 language:C typeref:typename:void signature:(void) roles:def end:239 +Unlimited unixcrap.c /^#define Unlimited /;" kind:macro line:54 language:C file: roles:def extras:fileScope end:54 +Unlink plan9ish.c /^void Unlink(char *name)$/;" kind:function line:485 language:C typeref:typename:void signature:(char * name) roles:def end:488 +Updenv plan9ish.c /^void Updenv(void){}$/;" kind:function line:348 language:C typeref:typename:void signature:(void) roles:def end:348 +Updenv unix.c /^Updenv(void)$/;" kind:function line:277 language:C typeref:typename:void signature:(void) roles:def end:285 +Vinit plan9ish.c /^void Vinit(void){$/;" kind:function line:122 language:C typeref:typename:void signature:(void) roles:def end:142 +Vinit unix.c /^Vinit(void)$/;" kind:function line:168 language:C typeref:typename:void signature:(void) roles:def end:183 +WHILE x.tab.h /^#define WHILE /;" kind:macro line:3 language:C++ roles:def end:3 +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 x.tab.h /^#define WORD /;" kind:macro line:11 language:C++ roles:def end:11 +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 x.tab.h /^#define WORDS /;" kind:macro line:19 language:C++ roles:def end:19 +WORDS y.tab.c /^#define WORDS /;" kind:macro line:18 language:C file: roles:def extras:fileScope end:18 +WORDS y.tab.h /^#define WORDS /;" kind:macro line:18 language:C++ roles:def end:18 +WRITE rc.h /^#define WRITE /;" kind:macro line:108 language:C++ roles:def end:108 +Waitfor plan9ish.c /^int Waitfor(int pid, int unused0){$/;" kind:function line:197 language:C typeref:typename:int signature:(int pid,int unused0) roles:def end:226 +Waitfor unix.c /^Waitfor(int pid)$/;" kind:function line:248 language:C typeref:typename:int signature:(int pid) roles:def end:272 +Write plan9ish.c /^long Write(int fd, char *buf, long cnt)$/;" kind:function line:489 language:C typeref:typename:long signature:(int fd,char * buf,long cnt) roles:def end:492 +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:340 language:C typeref:typename:void signature:(void) roles:def end:363 +Xassign exec.c /^Xassign(void)$/;" kind:function line:739 language:C typeref:typename:void signature:(void) roles:def end:752 +Xasync havefork.c /^Xasync(void)$/;" kind:function line:46 language:C typeref:typename:void signature:(void) roles:def end:67 +Xasync haventfork.c /^Xasync(void)$/;" kind:function line:33 language:C typeref:typename:void signature:(void) roles:def end:52 +Xbackq havefork.c /^Xbackq(void)$/;" kind:function line:109 language:C typeref:typename:void signature:(void) roles:def end:154 +Xbackq haventfork.c /^Xbackq(void)$/;" kind:function line:55 language:C typeref:typename:void signature:(void) roles:def end:113 +Xbang exec.c /^Xbang(void)$/;" kind:function line:372 language:C typeref:typename:void signature:(void) roles:def end:375 +Xcase exec.c /^Xcase(void)$/;" kind:function line:674 language:C typeref:typename:void signature:(void) roles:def end:692 +Xclose exec.c /^Xclose(void)$/;" kind:function line:378 language:C typeref:typename:void signature:(void) roles:def end:381 +Xconc exec.c /^Xconc(void)$/;" kind:function line:716 language:C typeref:typename:void signature:(void) roles:def end:736 +Xcount exec.c /^Xcount(void)$/;" kind:function line:894 language:C typeref:typename:void signature:(void) roles:def end:917 +Xdelfn exec.c /^Xdelfn(void)$/;" kind:function line:963 language:C typeref:typename:void signature:(void) roles:def end:975 +Xdol exec.c /^Xdol(void)$/;" kind:function line:769 language:C typeref:typename:void signature:(void) roles:def end:794 +Xdup exec.c /^Xdup(void)$/;" kind:function line:384 language:C typeref:typename:void signature:(void) roles:def end:388 +Xeflag exec.c /^Xeflag(void)$/;" kind:function line:391 language:C typeref:typename:void signature:(void) roles:def end:394 +Xerror1 exec.c /^Xerror1(char *s)$/;" kind:function line:1076 language:C typeref:typename:void signature:(char * s) roles:def end:1083 +Xerror2 exec.c /^Xerror2(char *s, char *e)$/;" kind:function line:1085 language:C typeref:typename:void signature:(char * s,char * e) roles:def end:1092 +Xerror3 exec.c /^Xerror3(char *s, char *m, char *e)$/;" kind:function line:1094 language:C typeref:typename:void signature:(char * s,char * m,char * e) roles:def end:1101 +Xexit exec.c /^Xexit(void)$/;" kind:function line:397 language:C typeref:typename:void signature:(void) roles:def end:412 +Xfalse exec.c /^Xfalse(void)$/;" kind:function line:415 language:C typeref:typename:void signature:(void) roles:def end:419 +Xfn exec.c /^Xfn(void)$/;" kind:function line:945 language:C typeref:typename:void signature:(void) roles:def end:960 +Xfor exec.c /^Xfor(void)$/;" kind:function line:1142 language:C typeref:typename:void signature:(void) roles:def end:1157 +Xglob exec.c /^Xglob(void)$/;" kind:function line:1160 language:C typeref:typename:void signature:(void) roles:def end:1168 +Xhere exec.c /^Xhere(void)$/;" kind:function line:486 language:C typeref:typename:void signature:(void) roles:def end:507 +Xhereq exec.c /^Xhereq(void)$/;" kind:function line:510 language:C typeref:typename:void signature:(void) roles:def end:529 +Xif exec.c /^Xif(void)$/;" kind:function line:612 language:C typeref:typename:void signature:(void) roles:def end:617 +Xifnot exec.c /^Xifnot(void)$/;" kind:function line:423 language:C typeref:typename:void signature:(void) roles:def end:429 +Xjump exec.c /^Xjump(void)$/;" kind:function line:432 language:C typeref:typename:void signature:(void) roles:def end:435 +Xlocal exec.c /^Xlocal(void)$/;" kind:function line:920 language:C typeref:typename:void signature:(void) roles:def end:930 +Xmark exec.c /^Xmark(void)$/;" kind:function line:438 language:C typeref:typename:void signature:(void) roles:def end:441 +Xmatch exec.c /^Xmatch(void)$/;" kind:function line:657 language:C typeref:typename:void signature:(void) roles:def end:671 +Xpipe havefork.c /^Xpipe(void)$/;" kind:function line:70 language:C typeref:typename:void signature:(void) roles:def end:102 +Xpipe haventfork.c /^Xpipe(void)$/;" kind:function line:116 language:C typeref:typename:void signature:(void) roles:def end:146 +Xpipefd havefork.c /^Xpipefd(void)$/;" kind:function line:157 language:C typeref:typename:void signature:(void) roles:def end:199 +Xpipefd haventfork.c /^Xpipefd(void)$/;" kind:function line:149 language:C typeref:typename:void signature:(void) roles:def end:152 +Xpipewait exec.c /^Xpipewait(void)$/;" kind:function line:994 language:C typeref:typename:void signature:(void) roles:def end:1006 +Xpopm exec.c /^Xpopm(void)$/;" kind:function line:444 language:C typeref:typename:void signature:(void) roles:def end:447 +Xpopredir exec.c /^Xpopredir(void)$/;" kind:function line:582 language:C typeref:typename:void signature:(void) roles:def end:592 +Xpush exec.c /^Xpush(void)$/;" kind:function line:450 language:C typeref:typename:void signature:(void) roles:def end:457 +Xqw exec.c /^Xqw(void)$/;" kind:function line:797 language:C typeref:typename:void signature:(void) roles:def end:824 +Xrdcmds exec.c /^Xrdcmds(void)$/;" kind:function line:1011 language:C typeref:typename:void signature:(void) roles:def end:1049 +Xrdfn plan9ish.c /^void Xrdfn(void){$/;" kind:function line:144 language:C typeref:typename:void signature:(void) roles:def end:181 +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:557 language:C typeref:typename:void signature:(void) roles:def end:579 +Xread exec.c /^Xread(void)$/;" kind:function line:532 language:C typeref:typename:void signature:(void) roles:def end:554 +Xreturn exec.c /^Xreturn(void)$/;" kind:function line:595 language:C typeref:typename:void signature:(void) roles:def end:602 +Xsettrue exec.c /^Xsettrue(void)$/;" kind:function line:366 language:C typeref:typename:void signature:(void) roles:def end:369 +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:1171 language:C typeref:typename:void signature:(void) roles:def end:1174 +Xsub exec.c /^Xsub(void)$/;" kind:function line:875 language:C typeref:typename:void signature:(void) roles:def end:891 +Xsubshell havefork.c /^Xsubshell(void)$/;" kind:function line:202 language:C typeref:typename:void signature:(void) roles:def end:222 +Xsubshell haventfork.c /^Xsubshell(void)$/;" kind:function line:155 language:C typeref:typename:void signature:(void) roles:def end:173 +Xtrue exec.c /^Xtrue(void)$/;" kind:function line:605 language:C typeref:typename:void signature:(void) roles:def end:609 +Xunlocal exec.c /^Xunlocal(void)$/;" kind:function line:933 language:C typeref:typename:void signature:(void) roles:def end:942 +Xwastrue exec.c /^Xwastrue(void)$/;" kind:function line:620 language:C typeref:typename:void signature:(void) roles:def end:623 +Xword exec.c /^Xword(void)$/;" kind:function line:626 language:C typeref:typename:void signature:(void) roles:def end:629 +Xwrite exec.c /^Xwrite(void)$/;" kind:function line:632 language:C typeref:typename:void signature:(void) roles:def end:654 +YFILES Makefile /^YFILES=syn.y$/;" kind:macro line:29 language:Make roles:def +YFLAGS Makefile /^YFLAGS=-d$/;" kind:macro line:30 language:Make roles:def +YYABORT y.tab.c /^#define YYABORT /;" kind:macro line:193 language:C file: roles:def extras:fileScope end:193 +YYACCEPT y.tab.c /^#define YYACCEPT /;" kind:macro line:192 language:C file: roles:def extras:fileScope end:192 +YYEOFCODE y.tab.c /^#define YYEOFCODE /;" kind:macro line:41 language:C file: roles:def extras:fileScope end:41 +YYERRCODE y.tab.c /^#define YYERRCODE /;" kind:macro line:42 language:C file: roles:def extras:fileScope end:42 +YYERROR y.tab.c /^#define YYERROR /;" kind:macro line:191 language:C file: roles:def extras:fileScope end:191 +YYFLAG y.tab.c /^#define YYFLAG /;" kind:macro line:190 language:C file: roles:def extras:fileScope end:190 +YYLAST y.tab.c /^#define YYLAST /;" kind:macro line:53 language:C file: roles:def extras:fileScope end:53 +YYMAXDEPTH rc.h /^#define YYMAXDEPTH /;" kind:macro line:26 language:C++ roles:def end:26 +YYMAXDEPTH y.tab.c /^#define YYMAXDEPTH /;" kind:macro line:37 language:C file: roles:def extras:fileScope end:37 +YYNPROD y.tab.c /^#define YYNPROD /;" kind:macro line:51 language:C file: roles:def extras:fileScope end:51 +YYPRIVATE y.tab.c /^#define YYPRIVATE /;" kind:macro line:52 language:C file: roles:def extras:fileScope end:52 +YYSTYPE x.tab.h /^} YYSTYPE;$/;" kind:typedef line:30 language:C++ typeref:union:__anon8cc35738010a roles:def +YYSTYPE y.tab.c /^} YYSTYPE;$/;" kind:typedef line:34 language:C typeref:union:__anond9bd93f4010a file: roles:def extras:fileScope +YYSTYPE y.tab.h /^} YYSTYPE;$/;" kind:typedef line:29 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 +__anon43e7b75e0108 plan9ish.c /^struct{$/;" kind:struct line:392 language:C file: roles:def extras:fileScope,anonymous end:396 +__anon43e7b75e0108::dbuf plan9ish.c /^ Dir *dbuf;$/;" kind:member line:393 language:C scope:struct:__anon43e7b75e0108 typeref:typename:Dir * file: access:public roles:def extras:fileScope,qualified end:393 +__anon43e7b75e0108::i plan9ish.c /^ int i;$/;" kind:member line:394 language:C scope:struct:__anon43e7b75e0108 typeref:typename:int file: access:public roles:def extras:fileScope,qualified end:394 +__anon43e7b75e0108::n plan9ish.c /^ int n;$/;" kind:member line:395 language:C scope:struct:__anon43e7b75e0108 typeref:typename:int file: access:public roles:def extras:fileScope,qualified end:395 +__anon7c9881ce0103 io.c /^enum {$/;" kind:enum line:6 language:C file: roles:def extras:fileScope,anonymous end:8 +__anon8cc35738010a x.tab.h /^typedef union {$/;" kind:union line:28 language:C++ roles:def extras:anonymous end:30 +__anon8cc35738010a::tree x.tab.h /^ struct tree *tree;$/;" kind:member line:29 language:C++ scope:union:__anon8cc35738010a typeref:struct:tree * access:public roles:def extras:qualified end:29 +__anond9bd93f4010a y.tab.c /^typedef union {$/;" kind:union line:32 language:C file: roles:def extras:fileScope,anonymous end:34 +__anond9bd93f4010a::tree y.tab.c /^ struct tree *tree;$/;" kind:member line:33 language:C scope:union:__anond9bd93f4010a typeref:struct:tree * file: access:public roles:def extras:fileScope,qualified end:33 +__anond9bd93f40208 y.tab.c /^ {$/;" kind:struct line:299 language:C scope:function:yyparse file: roles:def extras:fileScope,anonymous end:302 +__anond9bd93f9010a y.tab.h /^typedef union {$/;" kind:union line:27 language:C++ roles:def extras:anonymous end:29 +__anond9bd93f9010a::tree y.tab.h /^ struct tree *tree;$/;" kind:member line:28 language:C++ scope:union:__anond9bd93f9010a typeref:struct:tree * access:public roles:def extras:qualified end:28 +__needsquotes fmtquote.c /^__needsquotes(char *s, int *quotelenp)$/;" kind:function line:154 language:C typeref:typename:int signature:(char * s,int * quotelenp) roles:def end:162 +__quotesetup fmtquote.c /^__quotesetup(char *s, int nin, int nout, Quoteinfo *q, int sharp)$/;" kind:function line:35 language:C typeref:typename:void signature:(char * s,int nin,int nout,Quoteinfo * q,int sharp) roles:def end:82 +__quotestrfmt fmtquote.c /^__quotestrfmt(int runesin, Fmt *f)$/;" kind:function line:118 language:C typeref:typename:int signature:(int runesin,Fmt * f) roles:def end:139 +_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 +_setvar var.c /^_setvar(char *name, word *val, int callfn)$/;" kind:function line:80 language:C typeref:typename:void signature:(char * name,word * val,int callfn) roles:def end:88 +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 +addwaitpid plan9ish.c /^addwaitpid(int pid)$/;" kind:function line:570 language:C typeref:typename:void signature:(int pid) roles:def end:576 +advance lex.c /^advance(void)$/;" kind:function line:119 language:C typeref:typename:int file: signature:(void) roles:def extras:fileScope end:127 +all Makefile /^all: $(TARG)$/;" kind:target line:34 language:Make roles:def end:35 +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 +bigpath var.c /^bigpath(var *v)$/;" kind:function line:97 language:C typeref:typename:void signature:(var * v) roles:def end:128 +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:121 language:C++ scope:struct:var typeref:typename:char access:public roles:def end:121 +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:52 language:C++ scope:struct:tree typeref:typename:tree * [3] access:public roles:def end:52 +clean Makefile /^clean:$/;" kind:target line:50 language:Make roles:def end:51 +clearwaitpids havefork.c /^clearwaitpids(void)$/;" kind:function line:29 language:C typeref:typename:void signature:(void) roles:def end:32 +clearwaitpids plan9ish.c /^clearwaitpids(void)$/;" kind:function line:590 language:C typeref:typename:void signature:(void) roles:def end:593 +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 plan9ish.c /^cmpenv(const void *a, const void *b)$/;" kind:function line:284 language:C typeref:typename:int signature:(const void * a,const void * b) roles:def end:287 +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:72 language:C++ roles:def end:76 +code.c code.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:547 epoch:1658745928 +code::f rc.h /^ void (*f)(void);$/;" kind:member line:73 language:C++ scope:union:code typeref:typename:void (*)(void) access:public roles:def extras:qualified end:73 +code::i rc.h /^ int i;$/;" kind:member line:74 language:C++ scope:union:code typeref:typename:int access:public roles:def extras:qualified end:74 +code::s rc.h /^ char *s;$/;" kind:member line:75 language:C++ scope:union:code typeref:typename:char * access:public roles:def extras:qualified end:75 +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:695 language:C typeref:typename:word * file: signature:(word * lp,word * rp,word * tail) roles:def extras:fileScope end:713 +concstatus exec.c /^concstatus(char *s, char *t)$/;" kind:function line:978 language:C typeref:typename:char * file: signature:(char * s,char * t) roles:def extras:fileScope end:991 +copynwords exec.c /^copynwords(word *a, word *tail, int n)$/;" kind:function line:827 language:C typeref:typename:word * file: signature:(word * a,word * tail,int n) roles:def extras:fileScope end:840 +copywords exec.c /^copywords(word *a, word *tail)$/;" kind:function line:758 language:C typeref:typename:word * signature:(word * a,word * tail) roles:def end:766 +count exec.c /^count(word *w)$/;" kind:function line:148 language:C typeref:typename:int signature:(word * w) roles:def end:153 +dbuf plan9ish.c /^ Dir *dbuf;$/;" kind:member line:393 language:C scope:struct:__anon43e7b75e0108 typeref:typename:Dir * file: access:public roles:def extras:fileScope end:393 +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 +delwaitpid plan9ish.c /^delwaitpid(int pid)$/;" kind:function line:579 language:C typeref:typename:void signature:(int pid) roles:def end:587 +dir plan9ish.c /^}dir[NFD];$/;" kind:variable line:396 language:C typeref:struct:__anon43e7b75e0108[] roles:def end:396 +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 +eargs unixcrap.c /^static char *eargs = "cdflmnstuv";$/;" kind:variable line:17 language:C typeref:typename:char * file: roles:def extras:fileScope end:17 +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 +enval plan9ish.c /^struct word *enval(s)$/;" kind:function line:110 language:C signature:(s) roles:def end:121 +environ exec.c /^char **environ;$/;" kind:variable line:11 language:C typeref:typename:char ** roles:def end:11 +environp plan9ish.c /^char **environp;$/;" kind:variable line:109 language:C typeref:typename:char ** roles:def end:109 +envp plan9ish.c /^char **envp;$/;" kind:variable line:143 language:C typeref:typename:char ** roles:def end:143 +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:92 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def end:92 +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:86 language:C++ scope:struct:lexer typeref:typename:char * access:public roles:def end:86 +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 +errno.h unixcrap.c /^#include /;" kind:header line:5 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 +eusage unixcrap.c /^eusage(void)$/;" kind:function line:48 language:C typeref:typename:void file: signature:(void) roles:def extras:fileScope end:51 +exec.c exec.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:1174 epoch:1658749971 +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:1658745928 +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 haventfork.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 plan9ish.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 unixcrap.c /^#include "exec.h"/;" kind:header line:9 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:433 +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 plan9ish.c /^void execfinit(void){$/;" kind:function line:183 language:C typeref:typename:void signature:(void) roles:def end:195 +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:436 language:C typeref:typename:void signature:(void) roles:def end:461 +execforkexec havefork.c /^execforkexec(void)$/;" kind:function line:225 language:C typeref:typename:int signature:(void) roles:def end:240 +execforkexec haventfork.c /^execforkexec(void)$/;" kind:function line:179 language:C typeref:typename:int signature:(void) roles:def end:211 +execfunc simple.c /^execfunc(var *func)$/;" kind:function line:197 language:C typeref:typename:void signature:(var * func) roles:def end:201 +execrfork plan9ish.c /^execrfork(void)$/;" kind:function line:59 language:C typeref:typename:void signature:(void) roles:def end:104 +execshift simple.c /^execshift(void)$/;" kind:function line:259 language:C typeref:typename:void signature:(void) roles:def end:286 +execulimit unixcrap.c /^execulimit(void)$/;" kind:function line:59 language:C typeref:typename:void signature:(void) roles:def end:167 +execumask unixcrap.c /^execumask(void)$/;" kind:function line:170 language:C typeref:typename:void signature:(void) roles:def end:214 +execwait simple.c /^execwait(void)$/;" kind:function line:524 language:C typeref:typename:void signature:(void) roles:def end:538 +execwhatis simple.c /^execwhatis(void){ \/* mildly wrong -- should fork before writing *\/$/;" kind:function line:464 language:C typeref:typename:void signature:(void) roles:def end:521 +exitcode plan9ish.c /^exitcode(char *msg)$/;" kind:function line:556 language:C typeref:typename:int signature:(char * msg) roles:def end:564 +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:73 language:C++ scope:union:code typeref:typename:void (*)(void) access:public roles:def end:73 +fcntl.h unix.c /^#include /;" kind:header line:16 language:C roles:system extras:reference +fcntl.h unixcrap.c /^#include /;" kind:header line:6 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 +fd0 rc.h /^ int rtype, fd0, fd1; \/* details of REDIR PIPE DUP tokens *\/$/;" kind:member line:46 language:C++ scope:struct:tree typeref:typename:int access:public roles:def end:46 +fd1 rc.h /^ int rtype, fd0, fd1; \/* details of REDIR PIPE DUP tokens *\/$/;" kind:member line:46 language:C++ scope:struct:tree typeref:typename:int access:public roles:def end:46 +file rc.h /^ char *file;$/;" kind:member line:82 language:C++ scope:struct:lexer typeref:typename:char * access:public roles:def end:82 +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 +fmt.h fmtquote.c /^#include "fmt.h"/;" kind:header line:16 language:C roles:local extras:reference +fmtdef.h fmtquote.c /^#include "fmtdef.h"/;" kind:header line:17 language:C roles:local extras:reference +fmtquote.c fmtquote.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:162 epoch:1658434441 +fn rc.h /^ code *fn; \/* pointer to function's code vector *\/$/;" kind:member line:118 language:C++ scope:struct:var typeref:typename:code * access:public roles:def end:118 +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:120 language:C++ scope:struct:var typeref:typename:char access:public roles:def end:120 +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:1658745928 +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 haventfork.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 plan9ish.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 unixcrap.c /^#include "fns.h"/;" kind:header line:11 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:29 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:151 language:C++ signature:(c) roles:def end:151 +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 +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:89 language:C++ scope:struct:lexer typeref:typename:int access:public roles:def end:89 +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:1658745928 +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:1658745928 +getflags.h havefork.c /^#include "getflags.h"/;" kind:header line:2 language:C roles:local extras:reference +getflags.h haventfork.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 plan9ish.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 +getflags.h unixcrap.c /^#include "getflags.h"/;" kind:header line:12 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:1125 language:C typeref:typename:char * signature:(void) roles:def end:1129 +glob rc.h /^ char glob; \/* 0=string, 1=glob, 2=pattern see globprop() and noglobs() *\/$/;" kind:member line:48 language:C++ scope:struct:tree typeref:typename:char access:public roles:def end:48 +glob.c glob.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:259 epoch:1658745928 +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 +gvlook var.c /^gvlook(char *name)$/;" kind:function line:61 language:C typeref:typename:var * signature:(char * name) roles:def end:67 +hash var.c /^hash(char *s, int n)$/;" kind:function line:6 language:C typeref:typename:int signature:(char * s,int n) roles:def end:12 +havefork haventfork.c /^int havefork = 0;$/;" kind:variable line:7 language:C typeref:typename:int roles:def end:7 +havefork.c havefork.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:240 epoch:1658745928 +haventfork.c haventfork.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:211 epoch:1658434441 +havewaitpid havefork.c /^havewaitpid(int pid)$/;" kind:function line:35 language:C typeref:typename:int signature:(int pid) roles:def end:43 +havewaitpid plan9ish.c /^havewaitpid(int pid)$/;" kind:function line:596 language:C typeref:typename:int signature:(int pid) roles:def end:604 +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:1658745928 +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:460 language:C typeref:typename:int file: signature:(char * tmp) roles:def extras:fileScope end:483 +i plan9ish.c /^ int i;$/;" kind:member line:394 language:C scope:struct:__anon43e7b75e0108 typeref:typename:int file: access:public roles:def extras:fileScope end:394 +i rc.h /^ int i;$/;" kind:member line:74 language:C++ scope:union:code typeref:typename:int access:public roles:def end:74 +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:97 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def end:97 +ifnot exec.c /^int ifnot; \/* dynamic if not flag *\/$/;" kind:variable line:420 language:C typeref:typename:int roles:def end:420 +incomm rc.h /^ char incomm;$/;" kind:member line:94 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def end:94 +input rc.h /^ io *input;$/;" kind:member line:81 language:C++ scope:struct:lexer typeref:typename:io * access:public roles:def end:81 +inquote rc.h /^ char inquote;$/;" kind:member line:93 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def end:93 +install Makefile /^install: $(TARG) rcmain.unix$/;" kind:target line:36 language:Make roles:def end:39 +interrupted plan9ish.c /^int interrupted = 0;$/;" kind:variable line:449 language:C typeref:typename:int roles:def end:449 +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:1658745928 +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 haventfork.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:1658745928 +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 plan9ish.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.h unixcrap.c /^#include "io.h"/;" kind:header line:10 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:50 language:C++ scope:struct:tree typeref:typename:char access:public roles:def end:50 +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:21 language:C typeref:typename:void signature:(int type,char * name) roles:def end:29 +kinit var.c /^kinit(void)$/;" kind:function line:32 language:C typeref:typename:void signature:(void) roles:def end:44 +klook var.c /^klook(char *name)$/;" kind:function line:47 language:C typeref:typename:tree * signature:(char * name) roles:def end:58 +kw var.c /^struct kw{$/;" kind:struct line:14 language:C file: roles:def extras:fileScope end:18 +kw var.c /^}*kw[NKW];$/;" kind:variable line:18 language:C typeref:struct:kw * [] roles:def end:18 +kw::name var.c /^ char *name;$/;" kind:member line:15 language:C scope:struct:kw typeref:typename:char * file: access:public roles:def extras:fileScope,qualified end:15 +kw::next var.c /^ struct kw *next;$/;" kind:member line:17 language:C scope:struct:kw typeref:struct:kw * file: access:public roles:def extras:fileScope,qualified end:17 +kw::type var.c /^ int type;$/;" kind:member line:16 language:C scope:struct:kw typeref:typename:int file: access:public roles:def extras:fileScope,qualified end:16 +lastc rc.h /^ int lastc;$/;" kind:member line:90 language:C++ scope:struct:lexer typeref:typename:int access:public roles:def end:90 +lastdol rc.h /^ char lastdol; \/* was the last token read '$' or '$#' or '"'? *\/$/;" kind:member line:96 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def end:96 +lastword rc.h /^ char lastword; \/* was the last token read a word or compound word terminator? *\/$/;" kind:member line:95 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def end:95 +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:1658745928 +lexer rc.h /^struct lexer{$/;" kind:struct line:80 language:C++ roles:def end:102 +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:92 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def extras:qualified end:92 +lexer::epilog rc.h /^ char *epilog;$/;" kind:member line:86 language:C++ scope:struct:lexer typeref:typename:char * access:public roles:def extras:qualified end:86 +lexer::file rc.h /^ char *file;$/;" kind:member line:82 language:C++ scope:struct:lexer typeref:typename:char * access:public roles:def extras:qualified end:82 +lexer::future rc.h /^ int future;$/;" kind:member line:89 language:C++ scope:struct:lexer typeref:typename:int access:public roles:def extras:qualified end:89 +lexer::iflast rc.h /^ char iflast; \/* static `if not' checking *\/$/;" kind:member line:97 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def extras:qualified end:97 +lexer::incomm rc.h /^ char incomm;$/;" kind:member line:94 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def extras:qualified end:94 +lexer::input rc.h /^ io *input;$/;" kind:member line:81 language:C++ scope:struct:lexer typeref:typename:io * access:public roles:def extras:qualified end:81 +lexer::inquote rc.h /^ char inquote;$/;" kind:member line:93 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def extras:qualified end:93 +lexer::lastc rc.h /^ int lastc;$/;" kind:member line:90 language:C++ scope:struct:lexer typeref:typename:int access:public roles:def extras:qualified end:90 +lexer::lastdol rc.h /^ char lastdol; \/* was the last token read '$' or '$#' or '"'? *\/$/;" kind:member line:96 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def extras:qualified end:96 +lexer::lastword rc.h /^ char lastword; \/* was the last token read a word or compound word terminator? *\/$/;" kind:member line:95 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def extras:qualified end:95 +lexer::line rc.h /^ int line;$/;" kind:member line:83 language:C++ scope:struct:lexer typeref:typename:int access:public roles:def extras:qualified end:83 +lexer::peekc rc.h /^ int peekc;$/;" kind:member line:88 language:C++ scope:struct:lexer typeref:typename:int access:public roles:def extras:qualified end:88 +lexer::prolog rc.h /^ char *prolog;$/;" kind:member line:85 language:C++ scope:struct:lexer typeref:typename:char * access:public roles:def extras:qualified end:85 +lexer::qflag rc.h /^ char qflag;$/;" kind:member line:99 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def extras:qualified end:99 +lexer::tok rc.h /^ char tok[NTOK];$/;" kind:member line:101 language:C++ scope:struct:lexer typeref:typename:char[] access:public roles:def extras:qualified end:101 +libc.h fmtquote.c /^#include /;" kind:header line:15 language:C roles:system extras:reference +libc.h rc.h /^#include /;" kind:header line:9 language:C++ roles:system extras:reference +libc.h unixcrap.c /^#include /;" kind:header line:7 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:47 language:C++ scope:struct:tree typeref:typename:int access:public roles:def end:47 +line rc.h /^ int line;$/;" kind:member line:83 language:C++ scope:struct:lexer typeref:typename:int access:public roles:def end:83 +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 +list2strcolon var.c /^list2strcolon(word *words)$/;" kind:function line:131 language:C typeref:typename:char * signature:(word * words) roles:def end:148 +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 +littlepath var.c /^littlepath(var *v)$/;" kind:function line:150 language:C typeref:typename:void signature:(var * v) roles:def end:161 +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:291 +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 plan9ish.c /^char **mkargv(word *a)$/;" kind:function line:227 language:C typeref:typename:char ** signature:(word * a) roles:def end:234 +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 plan9ish.c /^char **mkenv(){$/;" kind:function line:288 language:C typeref:typename:char ** signature:() roles:def end:347 +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 plan9ish.c /^ int n;$/;" kind:member line:395 language:C scope:struct:__anon43e7b75e0108 typeref:typename:int file: access:public roles:def extras:fileScope end:395 +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:122 language:C++ scope:struct:var typeref:typename:char[] access:public roles:def end:122 +name var.c /^ char *name;$/;" kind:member line:15 language:C scope:struct:kw typeref:typename:char * file: access:public roles:def extras:fileScope end:15 +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:130 language:C++ signature:(type) roles:def end:130 +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 +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:53 language:C++ scope:struct:tree typeref:typename:tree * access:public roles:def end:53 +next rc.h /^ var *next; \/* next on hash or local list *\/$/;" kind:member line:116 language:C++ scope:struct:var typeref:typename:var * access:public roles:def end:116 +next var.c /^ struct kw *next;$/;" kind:member line:17 language:C scope:struct:kw typeref:struct:kw * file: access:public roles:def extras:fileScope end:17 +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 plan9ish.c /^notifyf(void *unused0, char *s)$/;" kind:function line:451 language:C typeref:typename:void signature:(void * unused0,char * s) roles:def end:481 +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 +nwaitpids plan9ish.c /^int nwaitpids;$/;" kind:variable line:567 language:C typeref:typename:int roles:def end:567 +onebyte rc.h /^#define onebyte(/;" kind:macro line:148 language:C++ signature:(c) roles:def end:148 +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:1658434441 +pathinit var.c /^pathinit(void)$/;" kind:function line:164 language:C typeref:typename:void signature:(void) roles:def end:173 +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:119 language:C++ scope:struct:var typeref:typename:int access:public roles:def end:119 +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:1658745928 +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:88 language:C++ scope:struct:lexer typeref:typename:int access:public roles:def end:88 +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:1658745928 +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 +plan9ish.c plan9ish.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:604 epoch:1658434441 +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:1052 language:C typeref:typename:void signature:(void) roles:def end:1067 +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:85 language:C++ scope:struct:lexer typeref:typename:char * access:public roles:def end:85 +promptstr exec.c /^static char *promptstr;$/;" kind:variable line:1008 language:C typeref:typename:char * file: roles:def extras:fileScope end:1008 +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:99 language:C++ scope:struct:lexer typeref:typename:char access:public roles:def end:99 +qstrfmt fmtquote.c /^qstrfmt(char *sin, Quoteinfo *q, Fmt *f)$/;" kind:function line:85 language:C typeref:typename:int file: signature:(char * sin,Quoteinfo * q,Fmt * f) roles:def extras:fileScope end:115 +quoted rc.h /^ char quoted;$/;" kind:member line:49 language:C++ scope:struct:tree typeref:typename:char access:public roles:def end:49 +quotefmtinstall fmtquote.c /^quotefmtinstall(void)$/;" kind:function line:148 language:C typeref:typename:void signature:(void) roles:def end:151 +quotestrfmt fmtquote.c /^quotestrfmt(Fmt *f)$/;" kind:function line:142 language:C typeref:typename:int signature:(Fmt * f) roles:def end:145 +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 haventfork.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 plan9ish.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:168 epoch:1658749802 +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 unixcrap.c /^#include "rc.h"/;" kind:header line:8 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:28 language:C roles:local extras:reference +rcargv haventfork.c /^rcargv(char *s)$/;" kind:function line:10 language:C typeref:typename:char ** file: signature:(char * s) roles:def extras:fileScope end:30 +rchr io.c /^rchr(io *b)$/;" kind:function line:73 language:C typeref:typename:int signature:(io * b) roles:def end:78 +rdfns plan9ish.c /^union code rdfns[4];$/;" kind:variable line:182 language:C typeref:union:code[4] roles:def end:182 +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 +readnb unixcrap.c /^readnb(int fd, char *buf, long cnt)$/;" kind:function line:220 language:C typeref:typename:long signature:(int fd,char * buf,long cnt) roles:def end:242 +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 +rlx unixcrap.c /^static int rlx[] = {$/;" kind:variable line:18 language:C typeref:typename:int[] file: roles:def extras:fileScope end:45 +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:46 language:C++ scope:struct:tree typeref:typename:int access:public roles:def end:46 +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:75 language:C++ scope:union:code typeref:typename:char * access:public roles:def end:75 +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:1109 language:C typeref:typename:void signature:(char * s) roles:def end:1112 +setvar var.c /^setvar(char *name, word *val)$/;" kind:function line:91 language:C typeref:typename:void signature:(char * name,word * val) roles:def end:94 +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:538 epoch:1658749863 +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:1070 language:C typeref:typename:char * signature:(thread * p) roles:def end:1073 +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:51 language:C++ scope:struct:tree typeref:typename:char * access:public roles:def end:51 +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:1658745928 +subwords exec.c /^subwords(word *val, int len, word *sub, word *a)$/;" kind:function line:843 language:C typeref:typename:word * file: signature:(word * val,int len,word * sub,word * a) roles:def extras:fileScope end:872 +syn.y syn.y 1;" kind:file line:1 language:YACC roles:def extras:inputFile end:93 epoch:1658745928 +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/resource.h unixcrap.c /^#include /;" kind:header line:4 language:C roles:system extras:reference +sys/stat.h unixcrap.c /^#include /;" kind:header line:3 language:C roles:system extras:reference +sys/time.h unixcrap.c /^#include /;" kind:header line:2 language:C roles:system extras:reference +sys/wait.h unix.c /^#include /;" kind:header line:19 language:C roles:system extras:reference +syssigname plan9ish.c /^char *syssigname[]={$/;" kind:variable line:16 language:C typeref:typename:char * [] roles:def end:26 +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:1658434441 +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:150 language:C++ signature:(c) roles:def end:150 +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:101 language:C++ scope:struct:lexer typeref:typename:char[] access:public roles:def end:101 +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:1658745928 +tree rc.h /^struct tree{$/;" kind:struct line:44 language:C++ roles:def end:54 +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 x.tab.h /^ struct tree *tree;$/;" kind:member line:29 language:C++ scope:union:__anon8cc35738010a typeref:struct:tree * access:public roles:def end:29 +tree y.tab.c /^ struct tree *tree;$/;" kind:member line:33 language:C scope:union:__anond9bd93f4010a typeref:struct:tree * file: access:public roles:def extras:fileScope end:33 +tree y.tab.h /^ struct tree *tree;$/;" kind:member line:28 language:C++ scope:union:__anond9bd93f9010a typeref:struct:tree * access:public roles:def end:28 +tree.c tree.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:190 epoch:1658745928 +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:52 language:C++ scope:struct:tree typeref:typename:tree * [3] access:public roles:def extras:qualified end:52 +tree::fd0 rc.h /^ int rtype, fd0, fd1; \/* details of REDIR PIPE DUP tokens *\/$/;" kind:member line:46 language:C++ scope:struct:tree typeref:typename:int access:public roles:def extras:qualified end:46 +tree::fd1 rc.h /^ int rtype, fd0, fd1; \/* details of REDIR PIPE DUP tokens *\/$/;" kind:member line:46 language:C++ scope:struct:tree typeref:typename:int access:public roles:def extras:qualified end:46 +tree::glob rc.h /^ char glob; \/* 0=string, 1=glob, 2=pattern see globprop() and noglobs() *\/$/;" kind:member line:48 language:C++ scope:struct:tree typeref:typename:char access:public roles:def extras:qualified end:48 +tree::iskw rc.h /^ char iskw;$/;" kind:member line:50 language:C++ scope:struct:tree typeref:typename:char access:public roles:def extras:qualified end:50 +tree::line rc.h /^ int line;$/;" kind:member line:47 language:C++ scope:struct:tree typeref:typename:int access:public roles:def extras:qualified end:47 +tree::next rc.h /^ tree *next;$/;" kind:member line:53 language:C++ scope:struct:tree typeref:typename:tree * access:public roles:def extras:qualified end:53 +tree::quoted rc.h /^ char quoted;$/;" kind:member line:49 language:C++ scope:struct:tree typeref:typename:char access:public roles:def extras:qualified end:49 +tree::rtype rc.h /^ int rtype, fd0, fd1; \/* details of REDIR PIPE DUP tokens *\/$/;" kind:member line:46 language:C++ scope:struct:tree typeref:typename:int access:public roles:def extras:qualified end:46 +tree::str rc.h /^ char *str;$/;" kind:member line:51 language:C++ scope:struct:tree typeref:typename:char * access:public roles:def extras:qualified end:51 +tree::type rc.h /^ int type;$/;" kind:member line:45 language:C++ scope:struct:tree typeref:typename:int access:public roles:def extras:qualified end:45 +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 +truestatus exec.c /^truestatus(void)$/;" kind:function line:1132 language:C typeref:typename:int signature:(void) roles:def end:1139 +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:149 language:C++ signature:(c) roles:def end:149 +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:45 language:C++ scope:struct:tree typeref:typename:int access:public roles:def end:45 +type var.c /^ int type;$/;" kind:member line:16 language:C scope:struct:kw typeref:typename:int file: access:public roles:def extras:fileScope end:16 +u.h fmtquote.c /^#include /;" kind:header line:14 language:C roles:system extras:reference +u.h rc.h /^#include /;" kind:header line:8 language:C++ roles:system extras:reference +u.h unixcrap.c /^#include /;" kind:header line:1 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:1658749706 +unix.o Makefile /^unix.o: unix.c$/;" kind:target line:45 language:Make roles:def end:47 +unixcrap.c unixcrap.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:242 epoch:1658434441 +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:117 language:C++ scope:struct:var typeref:typename:word * access:public roles:def end:117 +var rc.h /^struct var{$/;" kind:struct line:115 language:C++ roles:def end:123 +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:173 epoch:1658750198 +var::changed rc.h /^ char changed;$/;" kind:member line:121 language:C++ scope:struct:var typeref:typename:char access:public roles:def extras:qualified end:121 +var::fn rc.h /^ code *fn; \/* pointer to function's code vector *\/$/;" kind:member line:118 language:C++ scope:struct:var typeref:typename:code * access:public roles:def extras:qualified end:118 +var::fnchanged rc.h /^ char fnchanged;$/;" kind:member line:120 language:C++ scope:struct:var typeref:typename:char access:public roles:def extras:qualified end:120 +var::name rc.h /^ char name[];$/;" kind:member line:122 language:C++ scope:struct:var typeref:typename:char[] access:public roles:def extras:qualified end:122 +var::next rc.h /^ var *next; \/* next on hash or local list *\/$/;" kind:member line:116 language:C++ scope:struct:var typeref:typename:var * access:public roles:def extras:qualified end:116 +var::pc rc.h /^ int pc; \/* pc of start of function *\/$/;" kind:member line:119 language:C++ scope:struct:var typeref:typename:int access:public roles:def extras:qualified end:119 +var::val rc.h /^ word *val; \/* value *\/$/;" kind:member line:117 language:C++ scope:struct:var typeref:typename:word * access:public roles:def extras:qualified end:117 +vlook var.c /^vlook(char *name)$/;" kind:function line:70 language:C typeref:typename:var * signature:(char * name) roles:def end:77 +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 +waitpids plan9ish.c /^int *waitpids;$/;" kind:variable line:566 language:C typeref:typename:int * roles:def end:566 +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 +x.tab.h x.tab.h 1;" kind:file line:1 language:C++ roles:def extras:inputFile end:31 epoch:1658745895 +xbyte rc.h /^#define xbyte(/;" kind:macro line:152 language:C++ signature:(c) roles:def end:152 +y.debug y.tab.c /^#include "y.debug"/;" kind:header line:198 language:C roles:local extras:reference +y.tab.c y.tab.c 1;" kind:file line:1 language:C roles:def extras:inputFile end:622 epoch:1658749509 +y.tab.h Makefile /^y.tab.h: syn.c$/;" kind:target line:43 language:Make roles:def end:44 +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:30 epoch:1658749509 +yyact y.tab.c /^static const short yyact[] =$/;" kind:variable line:54 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:90 +yychk y.tab.c /^static const short yychk[] =$/;" kind:variable line:134 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:148 +yyclearin y.tab.c /^#define yyclearin /;" kind:macro line:194 language:C file: roles:def extras:fileScope end:194 +yydebug y.tab.c /^#define yydebug /;" kind:macro line:200 language:C file: roles:def extras:fileScope end:200 +yydef y.tab.c /^static const short yydef[] =$/;" kind:variable line:149 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:163 +yyerrflag y.tab.c /^#define yyerrflag /;" kind:macro line:208 language:C file: roles:def extras:fileScope end:208 +yyerrflag y.tab.c /^int yyerrflag = 0; \/* error recovery flag *\/$/;" kind:variable line:213 language:C typeref:typename:int roles:def end:213 +yyerrok y.tab.c /^#define yyerrok /;" kind:macro line:195 language:C file: roles:def extras:fileScope end:195 +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:43 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:50 +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:245 language:C typeref:typename:long file: signature:(struct Yyarg * yyarg) roles:def extras:fileScope end:289 +yylval y.tab.c /^#define yylval /;" kind:macro line:210 language:C file: roles:def extras:fileScope end:210 +yylval y.tab.c /^YYSTYPE yylval;$/;" kind:variable line:39 language:C typeref:typename:YYSTYPE roles:def end:39 +yynerrs y.tab.c /^#define yynerrs /;" kind:macro line:207 language:C file: roles:def extras:fileScope end:207 +yynerrs y.tab.c /^int yynerrs = 0; \/* number of errors *\/$/;" kind:variable line:212 language:C typeref:typename:int roles:def end:212 +yypact y.tab.c /^static const short yypact[] =$/;" kind:variable line:91 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:105 +yyparse y.tab.c /^yyparse(struct Yyarg *yyarg)$/;" kind:function line:293 language:C typeref:typename:int signature:(struct Yyarg * yyarg) roles:def end:622 +yyparse::__anond9bd93f40208::yys y.tab.c /^ int yys;$/;" kind:member line:301 language:C scope:struct:yyparse::__anond9bd93f40208 typeref:typename:int file: access:public roles:def extras:fileScope,qualified end:301 +yyparse::__anond9bd93f40208::yyv y.tab.c /^ YYSTYPE yyv;$/;" kind:member line:300 language:C scope:struct:yyparse::__anond9bd93f40208 typeref:typename:YYSTYPE file: access:public roles:def extras:fileScope,qualified end:300 +yypgo y.tab.c /^static const short yypgo[] =$/;" kind:variable line:106 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:111 +yyr1 y.tab.c /^static const short yyr1[] =$/;" kind:variable line:112 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:122 +yyr2 y.tab.c /^static const short yyr2[] =$/;" kind:variable line:123 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:133 +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:301 language:C scope:struct:yyparse::__anond9bd93f40208 typeref:typename:int file: access:public roles:def extras:fileScope end:301 +yystates y.tab.c /^static const char* yystates[1]; \/* for debugging *\/$/;" kind:variable line:202 language:C typeref:typename:const char * [1] file: roles:def extras:fileScope end:202 +yystatname y.tab.c /^yystatname(int yys)$/;" kind:function line:232 language:C typeref:typename:const char * file: signature:(int yys) roles:def extras:fileScope end:241 +yytok1 y.tab.c /^static const short yytok1[] =$/;" kind:variable line:164 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:179 +yytok2 y.tab.c /^static const short yytok2[] =$/;" kind:variable line:180 language:C typeref:typename:const short[] file: roles:def extras:fileScope end:185 +yytok3 y.tab.c /^static const long yytok3[] =$/;" kind:variable line:186 language:C typeref:typename:const long[] file: roles:def extras:fileScope end:189 +yytokname y.tab.c /^yytokname(int yyc)$/;" kind:function line:220 language:C typeref:typename:const char * file: signature:(int yyc) roles:def extras:fileScope end:229 +yytoknames y.tab.c /^static const char* yytoknames[1]; \/* for debugging *\/$/;" kind:variable line:201 language:C typeref:typename:const char * [1] file: roles:def extras:fileScope end:201 +yyv y.tab.c /^ YYSTYPE yyv;$/;" kind:member line:300 language:C scope:struct:yyparse::__anond9bd93f40208 typeref:typename:YYSTYPE file: access:public roles:def extras:fileScope end:300 +yyval y.tab.c /^#define yyval /;" kind:macro line:209 language:C file: roles:def extras:fileScope end:209 +yyval y.tab.c /^YYSTYPE yyval;$/;" kind:variable line:40 language:C typeref:typename:YYSTYPE roles:def end:40 +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..a5d582ee61 100644 --- a/src/cmd/rc/trap.c +++ b/src/cmd/rc/trap.c @@ -2,36 +2,37 @@ #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]){ - --trap[i]; - --ntrap; - if(getpid()!=mypid) Exit(getstatus()); - trapreq = vlook(Signame[i]); - if(trapreq->fn){ - 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; - } - else if(i==SIGINT || i==SIGQUIT){ - /* - * run the stack down until we uncover the - * command reading loop. Xreturn will exit - * if there is none (i.e. if this is not - * an interactive rc.) - */ - while(!runq->iflag) Xreturn(); - } - else Exit(getstatus()); - } + while(ntrap) + for(i = 0; i < NSIG; i++) + while(trap[i]){ + --trap[i]; + --ntrap; + if(getpid() != mypid) + Exit(); + trapreq = vlook(Signame[i]); + 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 + * command reading loop. Xreturn will exit + * if there is none (i.e. if this is not + * an interactive rc.) + */ + while(!runq->iflag) Xreturn(); + }else + Exit(); + } } diff --git a/src/cmd/rc/tree.c b/src/cmd/rc/tree.c index 2c3ff6bc71..e1374cb715 100644 --- a/src/cmd/rc/tree.c +++ b/src/cmd/rc/tree.c @@ -1,76 +1,101 @@ #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* +tree * newtree(void) { - tree *t = new(tree); - t->iskw = 0; - t->str = 0; + 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->next = treenodes; - treenodes = t; + t->line = lex->line; + t->next = treenodes; + treenodes = t; return t; } 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; } -tree* +tree * tree1(int type, tree *c0) { return tree3(type, c0, (tree *)0, (tree *)0); } -tree* +tree * tree2(int type, tree *c0, tree *c1) { return tree3(type, c0, c1, (tree *)0); } -tree* +tree * tree3(int type, tree *c0, tree *c1, tree *c2) { tree *t; - if(type==';'){ - if(c0==0) + if(type == ';'){ + if(c0 == 0) return c1; - if(c1==0) + if(c1 == 0) return c0; } - t = newtree(); - t->type = type; + t = newtree(); + t->type = type; 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; } -tree* +tree * mung1(tree *t, tree *c0) { t->child[0] = c0; return t; } -tree* +tree * mung2(tree *t, tree *c0, tree *c1) { t->child[0] = c0; @@ -78,7 +103,7 @@ mung2(tree *t, tree *c0, tree *c1) return t; } -tree* +tree * mung3(tree *t, tree *c0, tree *c1, tree *c2) { t->child[0] = c0; @@ -87,60 +112,79 @@ mung3(tree *t, tree *c0, tree *c1, tree *c2) return t; } -tree* +tree * epimung(tree *comp, tree *epi) { tree *p; - if(epi==0) + if(epi == 0) return comp; - for(p = epi;p->child[1];p = p->child[1]); + for(p = epi; p->child[1]; p = p->child[1]) + ; 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* +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); - for(u = t->child[0];u->type==ARGLIST;u = u->child[0]){ - if(u->child[1]->type==DUP - || u->child[1]->type==REDIR){ + + t = tree1(SIMPLE, t); + 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){ u->child[1]->child[1] = t; - t = u->child[1]; - u->child[1] = 0; + t = u->child[1]; + u->child[1] = 0; } } return t; } -tree* -token(char *str, int type) +char * +fnstr(tree *t) { - tree *t = newtree(); - t->type = type; - t->str = strdup(str); + io *f = openiostr(); + pfmt(f, "%t", t); + return closeiostr(f); +} + +tree * +globprop(tree *t) +{ + 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..b2bcfe645b --- /dev/null +++ b/src/cmd/rc/unix.c @@ -0,0 +1,425 @@ +/* + * 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 < NSIG; i++) + if(Signame[i]){ +#ifdef SA_RESTART + struct sigaction a; + + sigaction(i, NULL, &a); + a.sa_flags &= ~SA_RESTART; + a.sa_handler = sighandler; + sigaction(i, &a, NULL); +#else + signal(i, sighandler); +#endif + } +} + +char * +Errstr(void) +{ + return strerror(errno); +} + +int +Waitfor(int pid) +{ + thread *p; + char num[12]; + int wpid, status; + + if(pid >= 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 index 0b91563548..ec754127ab 100644 --- a/src/cmd/rc/unixcrap.c +++ b/src/cmd/rc/unixcrap.c @@ -11,34 +11,30 @@ #include "fns.h" #include "getflags.h" -extern char **mkargv(word*); +extern char **mkargv(word *); extern int mapfd(int); static char *eargs = "cdflmnstuv"; -static int rlx[] = { - RLIMIT_CORE, - RLIMIT_DATA, - RLIMIT_FSIZE, +static int rlx[] = { + RLIMIT_CORE, RLIMIT_DATA, RLIMIT_FSIZE, #ifdef RLIMIT_MEMLOCK - RLIMIT_MEMLOCK, + RLIMIT_MEMLOCK, #else 0, #endif #ifdef RLIMIT_RSS - RLIMIT_RSS, + RLIMIT_RSS, #else 0, #endif - RLIMIT_NOFILE, - RLIMIT_STACK, - RLIMIT_CPU, + RLIMIT_NOFILE, RLIMIT_STACK, RLIMIT_CPU, #ifdef RLIMIT_NPROC - RLIMIT_NPROC, + RLIMIT_NPROC, #else 0, #endif #ifdef RLIMIT_RSS - RLIMIT_RSS, + RLIMIT_RSS, #else 0, #endif @@ -50,10 +46,10 @@ eusage(void) fprint(mapfd(2), "usage: ulimit [-SHa%s [limit]]\n", eargs); } -#define Notset -4 +#define Notset -4 #define Unlimited -3 -#define Hard -2 -#define Soft -1 +#define Hard -2 +#define Soft -1 void execulimit(void) @@ -68,12 +64,13 @@ execulimit(void) argv0 = nil; setstatus(""); oargv = mkargv(runq->argv->words); - argv = oargv+1; - for(argc=0; argv[argc]; argc++) + argv = oargv + 1; + for(argc = 0; argv[argc]; argc++) ; memset(flag, 0, sizeof flag); - ARGBEGIN{ + ARGBEGIN + { default: if(strchr(eargs, ARGC()) == nil){ eusage(); @@ -81,10 +78,9 @@ execulimit(void) } case 'S': case 'H': - case 'a': - flag[ARGC()] = 1; - break; - }ARGEND + case 'a': flag[ARGC()] = 1; break; + } + ARGEND if(argc > 1){ eusage(); @@ -103,7 +99,7 @@ execulimit(void) setsoft = 0; limit = Notset; - if(argc>0){ + if(argc > 0){ if(strcmp(argv[0], "unlimited") == 0) limit = Unlimited; else if(strcmp(argv[0], "hard") == 0) @@ -116,8 +112,8 @@ execulimit(void) } } if(flag['a']){ - for(p=eargs; *p; p++){ - getrlimit(rlx[p-eargs], &rl); + 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); @@ -126,10 +122,10 @@ execulimit(void) } goto out; } - for(p=eargs; *p; p++){ + for(p = eargs; *p; p++){ if(flag[(uchar)*p]){ n = 0; - getrlimit(rlx[p-eargs], &rl); + getrlimit(rlx[p - eargs], &rl); switch(limit){ case Notset: n = flag['H'] ? rl.rlim_max : rl.rlim_cur; @@ -138,15 +134,9 @@ execulimit(void) 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; + 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: @@ -154,7 +144,7 @@ execulimit(void) rl.rlim_cur = n; if(sethard) rl.rlim_max = n; - if(setrlimit(rlx[p-eargs], &rl) < 0) + if(setrlimit(rlx[p - eargs], &rl) < 0) fprint(mapfd(2), "setrlimit: %r\n"); } } @@ -176,16 +166,18 @@ execumask(void) argv0 = nil; setstatus(""); oargv = mkargv(runq->argv->words); - argv = oargv+1; - for(argc=0; argv[argc]; argc++) + argv = oargv + 1; + for(argc = 0; argv[argc]; argc++) ; - ARGBEGIN{ + ARGBEGIN + { default: usage: fprint(mapfd(2), "usage: umask [mode]\n"); goto out; - }ARGEND + } + ARGEND if(argc > 1) goto usage; @@ -226,17 +218,17 @@ readnb(int fd, char *buf, long cnt) 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; + 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; } - goto again; - } return n; } diff --git a/src/cmd/rc/var.c b/src/cmd/rc/var.c index 2564ba2f75..afd9c07f3d 100644 --- a/src/cmd/rc/var.c +++ b/src/cmd/rc/var.c @@ -2,30 +2,32 @@ #include "exec.h" #include "fns.h" +var *gvar[NVAR]; + int hash(char *s, int n) { int h = 0, i = 1; - while(*s) h+=*s++*i++; - h%=n; - return h<0?h+n:h; + while(*s) h += *s++ * i++; + h %= n; + return h < 0 ? h + n : h; } -#define NKW 30 -struct kw{ +#define NKW 30 +struct kw { char *name; int type; struct kw *next; -}*kw[NKW]; +}* kw[NKW]; void kenter(int type, char *name) { - int h = hash(name, NKW); + int h = hash(name, NKW); struct kw *p = new(struct kw); - p->type = type; - p->name = name; - p->next = kw[h]; - kw[h] = p; + p->type = type; + p->name = name; + p->next = kw[h]; + kw[h] = p; } void @@ -43,13 +45,13 @@ kinit(void) kenter(FN, "fn"); } -tree* +tree * klook(char *name) { struct kw *p; tree *t = token(name, WORD); - for(p = kw[hash(name, NKW)];p;p = p->next) - if(strcmp(p->name, name)==0){ + for(p = kw[hash(name, NKW)]; p; p = p->next) + if(strcmp(p->name, name) == 0){ t->type = p->type; t->iskw = 1; break; @@ -57,40 +59,67 @@ klook(char *name) return t; } -var* +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]); + for(v = gvar[h]; v; v = v->next) + if(strcmp(v->name, name) == 0) + return v; + return gvar[h] = newvar(name, gvar[h]); } -var* +var * vlook(char *name) { var *v; if(runq) - for(v = runq->local;v;v = v->next) - if(strcmp(v->name, name)==0) return v; + for(v = runq->local; v; v = v->next) + if(strcmp(v->name, name) == 0) + return v; return gvlook(name); } void -_setvar(char *name, word *val, int callfn) +setvar(char *name, word *val) { - struct var *v = vlook(name); + var *v = vlook(name); freewords(v->val); - v->val=val; - v->changed=1; - if(callfn && v->changefn) - v->changefn(v); + v->val = val; + v->changed = 1; } void -setvar(char *name, word *val) +freevar(var *v) { - _setvar(name, val, 1); + freewords(v->val); + free(v); +} + +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 @@ -117,35 +146,36 @@ bigpath(var *v) if(q) *q = 0; *l = newword(p[0] ? p : ".", nil); - l = &(*l)->next; + l = &(*l)->next; if(q){ *q = ':'; - p = q+1; + p = q + 1; }else p = nil; } _setvar("path", w, 0); } -char* +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++=':'; + 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'; + if(s == value) + *s = '\0'; + else + s[-1] = '\0'; return value; } + void littlepath(var *v) { @@ -153,11 +183,11 @@ littlepath(var *v) char *p; word *w; - p = list2strcolon(v->val); - w = new(word); + p = list2strcolon(v->val); + w = new(word); w->word = p; w->next = nil; - _setvar("PATH", w, 1); /* 1: recompute $path to expose colon problems */ + _setvar("PATH", w, 1); /* 1: recompute $path to expose colon problems */ } void @@ -165,9 +195,9 @@ pathinit(void) { var *v; - v = gvlook("path"); + v = gvlook("path"); v->changefn = littlepath; - v = gvlook("PATH"); + v = gvlook("PATH"); v->changefn = bigpath; bigpath(v); }