From d1a19f0d477a6249d8af9322317b8434b86260ea Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Wed, 13 Oct 2021 08:27:37 -0700 Subject: fix(email): bytes error. updated vendoring --- sys/cmd/rc/code.c | 520 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 337 insertions(+), 183 deletions(-) (limited to 'sys/cmd/rc/code.c') diff --git a/sys/cmd/rc/code.c b/sys/cmd/rc/code.c index edf47cf..fbb5435 100644 --- a/sys/cmd/rc/code.c +++ b/sys/cmd/rc/code.c @@ -1,214 +1,267 @@ #include "rc.h" +#include "io.h" +#include "exec.h" +#include "fns.h" +#include "getflags.h" +#define c0 t->child[0] +#define c1 t->child[1] +#define c2 t->child[2] -#define delcode 100 -#define c0 t->child[0] -#define c1 t->child[1] -#define c2 t->child[2] +int codep, ncode; -#define emitf(x) ((code.ip!=code.end || morecode()), code.ip++->f = (x), code.ip) -#define emiti(x) ((code.ip!=code.end || morecode()), code.ip++->i = (x), code.ip) -#define emits(x) ((code.ip!=code.end || morecode()), code.ip++->s = (x), code.ip) +#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++) -static struct -{ - int cap; - Code *buf, *ip, *end; -} code; +void stuffdot(int); +char *fnstr(tree*); +void outcode(tree*, int); +void codeswitch(tree*, int); +int iscase(tree*); +code *codecopy(code*); +void codefree(code*); -static int morecode(void) { - code.cap += delcode; - code.buf = erealloc(code.buf, code.cap*sizeof(*code.buf)); - code.end = code.ip + delcode; - memset(code.ip, 0, delcode*sizeof(*code.buf)); - - return 0; + 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]); + return 0; } -static void -stuffdot(Code *p) +stuffdot(int a) { - int a; + if(a<0 || codep<=a) + panic("Bad address %d in stuffdot", a); + codebuf[a].i = codep; +} - a = p - code.buf; - if (code.ip <= p || p < code.buf) - panic("bad address %d in stuffdot", a); - code.buf[a].i = code.ip-code.buf; +int +compile(tree *t) +{ + ncode = 100; + codebuf = (code *)emalloc(ncode*sizeof codebuf[0]); + codep = 0; + emiti(0); /* reference count */ + outcode(t, flag['e']?1:0); + if(nerror){ + efree((char *)codebuf); + return 0; + } + readhere(); + emitf(Xreturn); + emitf(0); + return 1; } -static void -rcc(Tree *t, int eflag) +cleanhere(char *f) { - Code *p, *q; - Tree *tt; + emitf(Xdelhere); + emits(strdup(f)); +} - if (!t) - return; +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; +} - switch(t->type) { - default: - pfmt(errio, "bad type %d in rc compiler\n", t->type); +void +outcode(tree *t, int eflag) +{ + int p, q; + tree *tt; + if(t==0) + return; + if(t->type!=NOT && t->type!=';') + runq->iflast = 0; + switch(t->type){ + default: + pfmt(err, "bad type %d in outcode\n", t->type); break; - case Tdol: + case '$': emitf(Xmark); - rcc(c0, eflag); + outcode(c0, eflag); emitf(Xdol); break; - case Tquote: + case '"': emitf(Xmark); - rcc(c0, eflag); - emitf(Xflatten); + outcode(c0, eflag); + emitf(Xqdol); break; - case Tsub: + case SUB: emitf(Xmark); - rcc(c0, eflag); + outcode(c0, eflag); emitf(Xmark); - rcc(c1, eflag); + outcode(c1, eflag); emitf(Xsub); break; - case Tand: + case '&': emitf(Xasync); - p = emiti(0); - rcc(c0, eflag); - emitf(Xexit); - stuffdot(p); + if(havefork){ + p = emiti(0); + outcode(c0, eflag); + emitf(Xexit); + stuffdot(p); + } else + emits(fnstr(c0)); break; - case Tsemi: - rcc(c0, eflag); - rcc(c1, eflag); + case ';': + outcode(c0, eflag); + outcode(c1, eflag); break; - case Tcarot: + case '^': emitf(Xmark); - rcc(c1, eflag); + outcode(c1, eflag); emitf(Xmark); - rcc(c0, eflag); - emitf(Xcat); + outcode(c0, eflag); + emitf(Xconc); break; - case Ttick: - emitf(Xcmdsub); - p = emiti(0); - rcc(c0, 0); - emitf(Xexit); - stuffdot(p); + case '`': + emitf(Xbackq); + if(havefork){ + p = emiti(0); + outcode(c0, 0); + emitf(Xexit); + stuffdot(p); + } else + emits(fnstr(c0)); break; - case Tandand: - rcc(c0, 0); + case ANDAND: + outcode(c0, 0); emitf(Xtrue); p = emiti(0); - rcc(c1, eflag); + outcode(c1, eflag); stuffdot(p); break; - case Targs: - rcc(c1, eflag); - rcc(c0, eflag); + case ARGLIST: + outcode(c1, eflag); + outcode(c0, eflag); break; - case Tbang: - rcc(c0, eflag); - emitf(Xnegate); + case BANG: + outcode(c0, eflag); + emitf(Xbang); break; - case Tparen: - case Tbrace: - rcc(c0, eflag); + case PCMD: + case BRACE: + outcode(c0, eflag); break; - case Tcount: + case COUNT: emitf(Xmark); - rcc(c0, eflag); + outcode(c0, eflag); emitf(Xcount); break; - case Tfunc: + case FN: emitf(Xmark); - rcc(c0, eflag); + outcode(c0, eflag); if(c1){ - emitf(Xfunc); + emitf(Xfn); p = emiti(0); emits(fnstr(c1)); - rcc(c1, eflag); + outcode(c1, eflag); emitf(Xunlocal); /* get rid of $* */ - emitf(Xkill); + emitf(Xreturn); stuffdot(p); - } else - emitf(Xunfunc); + } + else + emitf(Xdelfn); break; - case Tif: - rcc(c0, 0); + case IF: + outcode(c0, 0); emitf(Xif); p = emiti(0); - rcc(c1, eflag); - // emitf(Xwastrue); + outcode(c1, eflag); + emitf(Xwastrue); stuffdot(p); break; - // case Telse: - // if(!runq->iflast) - // rcerror("`else' does not follow `if(...)'"); - // emitf(Xelse); - // p = emiti(0); - // rcc(c0, eflag); - // stuffdot(p); - // break; - case Toror: - rcc(c0, 0); + case NOT: + if(!runq->iflast) + yyerror("`if not' does not follow `if(...)'"); + emitf(Xifnot); + p = emiti(0); + outcode(c0, eflag); + stuffdot(p); + break; + case OROR: + outcode(c0, 0); emitf(Xfalse); p = emiti(0); - rcc(c1, eflag); + outcode(c1, eflag); stuffdot(p); break; - case Tpcmd: - rcc(c0, eflag); + case PAREN: + outcode(c0, eflag); break; - case Tsimple: + case SIMPLE: emitf(Xmark); - rcc(c0, eflag); + outcode(c0, eflag); emitf(Xsimple); if(eflag) emitf(Xeflag); break; - case Tsubshell: + case SUBSHELL: emitf(Xsubshell); - p = emiti(0); - rcc(c0, eflag); - emitf(Xexit); - stuffdot(p); + if(havefork){ + p = emiti(0); + outcode(c0, eflag); + emitf(Xexit); + stuffdot(p); + } else + emits(fnstr(c0)); if(eflag) emitf(Xeflag); break; - case Tswitch: + case SWITCH: codeswitch(t, eflag); break; - case Ttwiddle: + case TWIDDLE: emitf(Xmark); - rcc(c1, eflag); + outcode(c1, eflag); emitf(Xmark); - rcc(c0, eflag); + outcode(c0, eflag); emitf(Xmatch); if(eflag) emitf(Xeflag); break; - case Twhile: - q = code.ip; - rcc(c0, 0); - if(q==code.ip) + case WHILE: + q = codep; + outcode(c0, 0); + if(q==codep) emitf(Xsettrue); /* empty condition == while(true) */ emitf(Xtrue); p = emiti(0); - rcc(c1, eflag); + outcode(c1, eflag); emitf(Xjump); - emiti(q-code.buf); + emiti(q); stuffdot(p); break; - case Twords: - rcc(c1, eflag); - rcc(c0, eflag); + case WORDS: + outcode(c1, eflag); + outcode(c0, eflag); break; - case Tfor: + case FOR: emitf(Xmark); if(c1){ - rcc(c1, eflag); + outcode(c1, eflag); emitf(Xglob); - } else{ + } + else{ emitf(Xmark); emitf(Xword); emits(strdup("*")); @@ -216,120 +269,221 @@ rcc(Tree *t, int eflag) } emitf(Xmark); /* dummy value for Xlocal */ emitf(Xmark); - rcc(c0, eflag); + outcode(c0, eflag); emitf(Xlocal); p = emitf(Xfor); q = emiti(0); - rcc(c2, eflag); + outcode(c2, eflag); emitf(Xjump); - emiti(p-code.buf); + emiti(p); stuffdot(q); emitf(Xunlocal); break; - case Tword: + case WORD: emitf(Xword); emits(strdup(t->str)); break; - case Tdup: - if(t->redir.type == Rdupfd){ + case DUP: + if(t->rtype==DUPFD){ emitf(Xdup); - emiti(t->redir.fd[0]); - emiti(t->redir.fd[1]); - } else{ + emiti(t->fd0); + emiti(t->fd1); + } + else{ emitf(Xclose); - emiti(t->redir.fd[0]); + emiti(t->fd0); } - rcc(c1, eflag); + outcode(c1, eflag); emitf(Xpopredir); break; - case Tpipefd: + case PIPEFD: emitf(Xpipefd); - emiti(t->redir.type); - p = emiti(0); - rcc(c0, eflag); - emitf(Xexit); - stuffdot(p); + emiti(t->rtype); + if(havefork){ + p = emiti(0); + outcode(c0, eflag); + emitf(Xexit); + stuffdot(p); + } else { + emits(fnstr(c0)); + } break; - case Tredir: + case REDIR: emitf(Xmark); - rcc(c0, eflag); + outcode(c0, eflag); emitf(Xglob); - switch(t->redir.type){ - case Rappend: + switch(t->rtype){ + case APPEND: emitf(Xappend); break; - case Rwrite: + case WRITE: emitf(Xwrite); break; - case Rread: - case Rhere: + case READ: + case HERE: emitf(Xread); break; - case Rrdwr: + case RDWR: emitf(Xrdwr); break; } - emiti(t->redir.fd[0]); - rcc(c1, eflag); + emiti(t->fd0); + outcode(c1, eflag); emitf(Xpopredir); break; - case Teq: + case '=': tt = t; - for(;t && t->type==Teq;t = c2); + for(;t && t->type=='=';t = c2); if(t){ - for(t = tt;t->type==Teq;t = c2){ + for(t = tt;t->type=='=';t = c2){ emitf(Xmark); - rcc(c1, eflag); + outcode(c1, eflag); emitf(Xmark); - rcc(c0, eflag); + outcode(c0, eflag); emitf(Xlocal); } - rcc(t, eflag); - for(t = tt; t->type==Teq; t = c2) + outcode(t, eflag); + for(t = tt; t->type=='='; t = c2) emitf(Xunlocal); - } else{ + } + else{ for(t = tt;t;t = c2){ emitf(Xmark); - rcc(c1, eflag); + outcode(c1, eflag); emitf(Xmark); - rcc(c0, eflag); + outcode(c0, eflag); emitf(Xassign); } } t = tt; /* so tests below will work */ break; - case Tpipe: + case PIPE: emitf(Xpipe); - emiti(t->redir.fd[0]); - emiti(t->redir.fd[1]); - p = emiti(0); - q = emiti(0); - rcc(c0, eflag); - emitf(Xexit); - stuffdot(p); - rcc(c1, eflag); - emitf(Xkill); + 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); + } + outcode(c1, eflag); + emitf(Xreturn); stuffdot(q); emitf(Xpipewait); break; } - if(t->type!=Telse && t->type!=Tsemi) - shell->iflast = t->type==Tif; - else if (c0) - shell->iflast = c0->type==Tif; + if(t->type!=NOT && t->type!=';') + runq->iflast = t->type==IF; + else if(c0) runq->iflast = c0->type==IF; +} +/* + * switch code looks like this: + * Xmark + * (get switch value) + * Xjump 1f + * out: Xjump leave + * 1: Xmark + * (get case values) + * Xcase 1f + * (commands) + * Xjump out + * 1: Xmark + * (get case values) + * Xcase 1f + * (commands) + * Xjump out + * 1: + * leave: + * Xpopm + */ + +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 */ + tree *tt; + if(c1->child[0]==nil + || c1->child[0]->type!=';' + || !iscase(c1->child[0]->child[0])){ + yyerror("case missing in switch"); + return; + } + emitf(Xmark); + outcode(c0, eflag); + emitf(Xjump); + nextcase = emiti(0); + out = emitf(Xjump); + leave = emiti(0); + stuffdot(nextcase); + t = c1->child[0]; + while(t->type==';'){ + tt = c1; + emitf(Xmark); + for(t = c0->child[0];t->type==ARGLIST;t = c0) outcode(c1, eflag); + emitf(Xcase); + nextcase = emiti(0); + t = tt; + for(;;){ + if(t->type==';'){ + if(iscase(c0)) break; + outcode(c0, eflag); + t = c1; + } + else{ + if(!iscase(t)) outcode(t, eflag); + break; + } + } + emitf(Xjump); + emiti(out); + stuffdot(nextcase); + } + stuffdot(leave); + emitf(Xpopm); } -Code* -compile(Tree *t) +int +iscase(tree *t) { - code.cap = delcode; - code.buf = code.ip = emalloc(code.cap*sizeof *code.buf); - code.end = code.ip + code.cap; + if(t->type!=SIMPLE) + return 0; + do t = c0; while(t->type==ARGLIST); + return t->type==WORD && !t->quoted && strcmp(t->str, "case")==0; +} - emiti(0); - rcc(t, 0); - emitf(Xkill); - emitf(nil); +code* +codecopy(code *cp) +{ + cp[0].i++; + return cp; +} - return code.buf; +void +codefree(code *cp) +{ + code *p; + 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; + } + } + efree((char *)cp); } -- cgit v1.2.1