13e12c5d1SDavid du Colombier #include "rc.h" 23e12c5d1SDavid du Colombier #include "io.h" 33e12c5d1SDavid du Colombier #include "exec.h" 43e12c5d1SDavid du Colombier #include "fns.h" 5219b2ee8SDavid du Colombier #include "getflags.h" 63e12c5d1SDavid du Colombier #define c0 t->child[0] 73e12c5d1SDavid du Colombier #define c1 t->child[1] 83e12c5d1SDavid du Colombier #define c2 t->child[2] 93e12c5d1SDavid du Colombier int codep, ncode; 103e12c5d1SDavid du Colombier #define emitf(x) ((codep!=ncode || morecode()), codebuf[codep].f = (x), codep++) 113e12c5d1SDavid du Colombier #define emiti(x) ((codep!=ncode || morecode()), codebuf[codep].i = (x), codep++) 123e12c5d1SDavid du Colombier #define emits(x) ((codep!=ncode || morecode()), codebuf[codep].s = (x), codep++) 133e12c5d1SDavid du Colombier void stuffdot(int); 143e12c5d1SDavid du Colombier char *fnstr(tree*); 15219b2ee8SDavid du Colombier void outcode(tree*, int); 16219b2ee8SDavid du Colombier void codeswitch(tree*, int); 173e12c5d1SDavid du Colombier int iscase(tree*); 183e12c5d1SDavid du Colombier code *codecopy(code*); 193e12c5d1SDavid du Colombier void codefree(code*); 20*dc5a79c1SDavid du Colombier 21*dc5a79c1SDavid du Colombier int 22*dc5a79c1SDavid du Colombier morecode(void) 23*dc5a79c1SDavid du Colombier { 243e12c5d1SDavid du Colombier ncode+=100; 253e12c5d1SDavid du Colombier codebuf = (code *)realloc((char *)codebuf, ncode*sizeof codebuf[0]); 26*dc5a79c1SDavid du Colombier if(codebuf==0) 27*dc5a79c1SDavid du Colombier panic("Can't realloc %d bytes in morecode!", 283e12c5d1SDavid du Colombier ncode*sizeof codebuf[0]); 297dd7cddfSDavid du Colombier return 0; 303e12c5d1SDavid du Colombier } 31*dc5a79c1SDavid du Colombier 32*dc5a79c1SDavid du Colombier void 33*dc5a79c1SDavid du Colombier stuffdot(int a) 34*dc5a79c1SDavid du Colombier { 35*dc5a79c1SDavid du Colombier if(a<0 || codep<=a) 36*dc5a79c1SDavid du Colombier panic("Bad address %d in stuffdot", a); 373e12c5d1SDavid du Colombier codebuf[a].i = codep; 383e12c5d1SDavid du Colombier } 39*dc5a79c1SDavid du Colombier 40*dc5a79c1SDavid du Colombier int 41*dc5a79c1SDavid du Colombier compile(tree *t) 423e12c5d1SDavid du Colombier { 433e12c5d1SDavid du Colombier ncode = 100; 443e12c5d1SDavid du Colombier codebuf = (code *)emalloc(ncode*sizeof codebuf[0]); 453e12c5d1SDavid du Colombier codep = 0; 463e12c5d1SDavid du Colombier emiti(0); /* reference count */ 47219b2ee8SDavid du Colombier outcode(t, flag['e']?1:0); 483e12c5d1SDavid du Colombier if(nerror){ 493e12c5d1SDavid du Colombier efree((char *)codebuf); 503e12c5d1SDavid du Colombier return 0; 513e12c5d1SDavid du Colombier } 523e12c5d1SDavid du Colombier readhere(); 533e12c5d1SDavid du Colombier emitf(Xreturn); 543e12c5d1SDavid du Colombier emitf(0); 553e12c5d1SDavid du Colombier return 1; 563e12c5d1SDavid du Colombier } 57*dc5a79c1SDavid du Colombier 58*dc5a79c1SDavid du Colombier void 59*dc5a79c1SDavid du Colombier cleanhere(char *f) 603e12c5d1SDavid du Colombier { 613e12c5d1SDavid du Colombier emitf(Xdelhere); 623e12c5d1SDavid du Colombier emits(strdup(f)); 633e12c5d1SDavid du Colombier } 64*dc5a79c1SDavid du Colombier 65*dc5a79c1SDavid du Colombier char* 66*dc5a79c1SDavid du Colombier fnstr(tree *t) 673e12c5d1SDavid du Colombier { 683e12c5d1SDavid du Colombier io *f = openstr(); 693e12c5d1SDavid du Colombier char *v; 703e12c5d1SDavid du Colombier extern char nl; 713e12c5d1SDavid du Colombier char svnl = nl; 723e12c5d1SDavid du Colombier nl=';'; 733e12c5d1SDavid du Colombier pfmt(f, "%t", t); 743e12c5d1SDavid du Colombier nl = svnl; 753e12c5d1SDavid du Colombier v = f->strp; 763e12c5d1SDavid du Colombier f->strp = 0; 773e12c5d1SDavid du Colombier closeio(f); 783e12c5d1SDavid du Colombier return v; 793e12c5d1SDavid du Colombier } 80*dc5a79c1SDavid du Colombier 81*dc5a79c1SDavid du Colombier void 82*dc5a79c1SDavid du Colombier outcode(tree *t, int eflag) 833e12c5d1SDavid du Colombier { 843e12c5d1SDavid du Colombier int p, q; 853e12c5d1SDavid du Colombier tree *tt; 86*dc5a79c1SDavid du Colombier if(t==0) 87*dc5a79c1SDavid du Colombier return; 88*dc5a79c1SDavid du Colombier if(t->type!=NOT && t->type!=';') 89*dc5a79c1SDavid du Colombier runq->iflast = 0; 903e12c5d1SDavid du Colombier switch(t->type){ 913e12c5d1SDavid du Colombier default: 923e12c5d1SDavid du Colombier pfmt(err, "bad type %d in outcode\n", t->type); 933e12c5d1SDavid du Colombier break; 943e12c5d1SDavid du Colombier case '$': 953e12c5d1SDavid du Colombier emitf(Xmark); 96219b2ee8SDavid du Colombier outcode(c0, eflag); 973e12c5d1SDavid du Colombier emitf(Xdol); 983e12c5d1SDavid du Colombier break; 993e12c5d1SDavid du Colombier case '"': 1003e12c5d1SDavid du Colombier emitf(Xmark); 101219b2ee8SDavid du Colombier outcode(c0, eflag); 1023e12c5d1SDavid du Colombier emitf(Xqdol); 1033e12c5d1SDavid du Colombier break; 1043e12c5d1SDavid du Colombier case SUB: 1053e12c5d1SDavid du Colombier emitf(Xmark); 106219b2ee8SDavid du Colombier outcode(c0, eflag); 1073e12c5d1SDavid du Colombier emitf(Xmark); 108219b2ee8SDavid du Colombier outcode(c1, eflag); 1093e12c5d1SDavid du Colombier emitf(Xsub); 1103e12c5d1SDavid du Colombier break; 1113e12c5d1SDavid du Colombier case '&': 1123e12c5d1SDavid du Colombier emitf(Xasync); 113*dc5a79c1SDavid du Colombier if(havefork){ 1143e12c5d1SDavid du Colombier p = emiti(0); 115219b2ee8SDavid du Colombier outcode(c0, eflag); 1163e12c5d1SDavid du Colombier emitf(Xexit); 1173e12c5d1SDavid du Colombier stuffdot(p); 118*dc5a79c1SDavid du Colombier } else 119*dc5a79c1SDavid du Colombier emits(fnstr(c0)); 1203e12c5d1SDavid du Colombier break; 1213e12c5d1SDavid du Colombier case ';': 122219b2ee8SDavid du Colombier outcode(c0, eflag); 123219b2ee8SDavid du Colombier outcode(c1, eflag); 1243e12c5d1SDavid du Colombier break; 1253e12c5d1SDavid du Colombier case '^': 1263e12c5d1SDavid du Colombier emitf(Xmark); 127219b2ee8SDavid du Colombier outcode(c1, eflag); 1283e12c5d1SDavid du Colombier emitf(Xmark); 129219b2ee8SDavid du Colombier outcode(c0, eflag); 1303e12c5d1SDavid du Colombier emitf(Xconc); 1313e12c5d1SDavid du Colombier break; 1323e12c5d1SDavid du Colombier case '`': 1333e12c5d1SDavid du Colombier emitf(Xbackq); 134*dc5a79c1SDavid du Colombier if(havefork){ 1353e12c5d1SDavid du Colombier p = emiti(0); 136219b2ee8SDavid du Colombier outcode(c0, 0); 1373e12c5d1SDavid du Colombier emitf(Xexit); 1383e12c5d1SDavid du Colombier stuffdot(p); 139*dc5a79c1SDavid du Colombier } else 140*dc5a79c1SDavid du Colombier emits(fnstr(c0)); 1413e12c5d1SDavid du Colombier break; 1423e12c5d1SDavid du Colombier case ANDAND: 143219b2ee8SDavid du Colombier outcode(c0, 0); 1443e12c5d1SDavid du Colombier emitf(Xtrue); 1453e12c5d1SDavid du Colombier p = emiti(0); 146219b2ee8SDavid du Colombier outcode(c1, eflag); 1473e12c5d1SDavid du Colombier stuffdot(p); 1483e12c5d1SDavid du Colombier break; 1493e12c5d1SDavid du Colombier case ARGLIST: 150219b2ee8SDavid du Colombier outcode(c1, eflag); 151219b2ee8SDavid du Colombier outcode(c0, eflag); 1523e12c5d1SDavid du Colombier break; 1533e12c5d1SDavid du Colombier case BANG: 154219b2ee8SDavid du Colombier outcode(c0, eflag); 1553e12c5d1SDavid du Colombier emitf(Xbang); 1563e12c5d1SDavid du Colombier break; 1573e12c5d1SDavid du Colombier case PCMD: 1583e12c5d1SDavid du Colombier case BRACE: 159219b2ee8SDavid du Colombier outcode(c0, eflag); 1603e12c5d1SDavid du Colombier break; 1613e12c5d1SDavid du Colombier case COUNT: 1623e12c5d1SDavid du Colombier emitf(Xmark); 163219b2ee8SDavid du Colombier outcode(c0, eflag); 1643e12c5d1SDavid du Colombier emitf(Xcount); 1653e12c5d1SDavid du Colombier break; 1663e12c5d1SDavid du Colombier case FN: 1673e12c5d1SDavid du Colombier emitf(Xmark); 168219b2ee8SDavid du Colombier outcode(c0, eflag); 1693e12c5d1SDavid du Colombier if(c1){ 1703e12c5d1SDavid du Colombier emitf(Xfn); 1713e12c5d1SDavid du Colombier p = emiti(0); 1723e12c5d1SDavid du Colombier emits(fnstr(c1)); 173219b2ee8SDavid du Colombier outcode(c1, eflag); 1743e12c5d1SDavid du Colombier emitf(Xunlocal); /* get rid of $* */ 1753e12c5d1SDavid du Colombier emitf(Xreturn); 1763e12c5d1SDavid du Colombier stuffdot(p); 1773e12c5d1SDavid du Colombier } 1783e12c5d1SDavid du Colombier else 1793e12c5d1SDavid du Colombier emitf(Xdelfn); 1803e12c5d1SDavid du Colombier break; 1813e12c5d1SDavid du Colombier case IF: 182219b2ee8SDavid du Colombier outcode(c0, 0); 1833e12c5d1SDavid du Colombier emitf(Xif); 1843e12c5d1SDavid du Colombier p = emiti(0); 185219b2ee8SDavid du Colombier outcode(c1, eflag); 1863e12c5d1SDavid du Colombier emitf(Xwastrue); 1873e12c5d1SDavid du Colombier stuffdot(p); 1883e12c5d1SDavid du Colombier break; 1893e12c5d1SDavid du Colombier case NOT: 190*dc5a79c1SDavid du Colombier if(!runq->iflast) 191*dc5a79c1SDavid du Colombier yyerror("`if not' does not follow `if(...)'"); 1923e12c5d1SDavid du Colombier emitf(Xifnot); 1933e12c5d1SDavid du Colombier p = emiti(0); 194219b2ee8SDavid du Colombier outcode(c0, eflag); 1953e12c5d1SDavid du Colombier stuffdot(p); 1963e12c5d1SDavid du Colombier break; 1973e12c5d1SDavid du Colombier case OROR: 198219b2ee8SDavid du Colombier outcode(c0, 0); 1993e12c5d1SDavid du Colombier emitf(Xfalse); 2003e12c5d1SDavid du Colombier p = emiti(0); 201219b2ee8SDavid du Colombier outcode(c1, eflag); 2023e12c5d1SDavid du Colombier stuffdot(p); 2033e12c5d1SDavid du Colombier break; 2043e12c5d1SDavid du Colombier case PAREN: 205219b2ee8SDavid du Colombier outcode(c0, eflag); 2063e12c5d1SDavid du Colombier break; 2073e12c5d1SDavid du Colombier case SIMPLE: 2083e12c5d1SDavid du Colombier emitf(Xmark); 209219b2ee8SDavid du Colombier outcode(c0, eflag); 2103e12c5d1SDavid du Colombier emitf(Xsimple); 211*dc5a79c1SDavid du Colombier if(eflag) 212*dc5a79c1SDavid du Colombier emitf(Xeflag); 2133e12c5d1SDavid du Colombier break; 2143e12c5d1SDavid du Colombier case SUBSHELL: 2153e12c5d1SDavid du Colombier emitf(Xsubshell); 216*dc5a79c1SDavid du Colombier if(havefork){ 2173e12c5d1SDavid du Colombier p = emiti(0); 218219b2ee8SDavid du Colombier outcode(c0, eflag); 2193e12c5d1SDavid du Colombier emitf(Xexit); 2203e12c5d1SDavid du Colombier stuffdot(p); 221*dc5a79c1SDavid du Colombier } else 222*dc5a79c1SDavid du Colombier emits(fnstr(c0)); 223*dc5a79c1SDavid du Colombier if(eflag) 224*dc5a79c1SDavid du Colombier emitf(Xeflag); 2253e12c5d1SDavid du Colombier break; 2263e12c5d1SDavid du Colombier case SWITCH: 227219b2ee8SDavid du Colombier codeswitch(t, eflag); 2283e12c5d1SDavid du Colombier break; 2293e12c5d1SDavid du Colombier case TWIDDLE: 2303e12c5d1SDavid du Colombier emitf(Xmark); 231219b2ee8SDavid du Colombier outcode(c1, eflag); 2323e12c5d1SDavid du Colombier emitf(Xmark); 233219b2ee8SDavid du Colombier outcode(c0, eflag); 2343e12c5d1SDavid du Colombier emitf(Xmatch); 235*dc5a79c1SDavid du Colombier if(eflag) 236*dc5a79c1SDavid du Colombier emitf(Xeflag); 2373e12c5d1SDavid du Colombier break; 2383e12c5d1SDavid du Colombier case WHILE: 2393e12c5d1SDavid du Colombier q = codep; 240219b2ee8SDavid du Colombier outcode(c0, 0); 241*dc5a79c1SDavid du Colombier if(q==codep) 242*dc5a79c1SDavid du Colombier emitf(Xsettrue); /* empty condition == while(true) */ 2433e12c5d1SDavid du Colombier emitf(Xtrue); 2443e12c5d1SDavid du Colombier p = emiti(0); 245219b2ee8SDavid du Colombier outcode(c1, eflag); 2463e12c5d1SDavid du Colombier emitf(Xjump); 2473e12c5d1SDavid du Colombier emiti(q); 2483e12c5d1SDavid du Colombier stuffdot(p); 2493e12c5d1SDavid du Colombier break; 2503e12c5d1SDavid du Colombier case WORDS: 251219b2ee8SDavid du Colombier outcode(c1, eflag); 252219b2ee8SDavid du Colombier outcode(c0, eflag); 2533e12c5d1SDavid du Colombier break; 2543e12c5d1SDavid du Colombier case FOR: 2553e12c5d1SDavid du Colombier emitf(Xmark); 2563e12c5d1SDavid du Colombier if(c1){ 257219b2ee8SDavid du Colombier outcode(c1, eflag); 2583e12c5d1SDavid du Colombier emitf(Xglob); 2593e12c5d1SDavid du Colombier } 2603e12c5d1SDavid du Colombier else{ 2613e12c5d1SDavid du Colombier emitf(Xmark); 2623e12c5d1SDavid du Colombier emitf(Xword); 2633e12c5d1SDavid du Colombier emits(strdup("*")); 2643e12c5d1SDavid du Colombier emitf(Xdol); 2653e12c5d1SDavid du Colombier } 2663e12c5d1SDavid du Colombier emitf(Xmark); /* dummy value for Xlocal */ 2673e12c5d1SDavid du Colombier emitf(Xmark); 268219b2ee8SDavid du Colombier outcode(c0, eflag); 2693e12c5d1SDavid du Colombier emitf(Xlocal); 2703e12c5d1SDavid du Colombier p = emitf(Xfor); 2713e12c5d1SDavid du Colombier q = emiti(0); 272219b2ee8SDavid du Colombier outcode(c2, eflag); 2733e12c5d1SDavid du Colombier emitf(Xjump); 2743e12c5d1SDavid du Colombier emiti(p); 2753e12c5d1SDavid du Colombier stuffdot(q); 2763e12c5d1SDavid du Colombier emitf(Xunlocal); 2773e12c5d1SDavid du Colombier break; 2783e12c5d1SDavid du Colombier case WORD: 2793e12c5d1SDavid du Colombier emitf(Xword); 2803e12c5d1SDavid du Colombier emits(strdup(t->str)); 2813e12c5d1SDavid du Colombier break; 2823e12c5d1SDavid du Colombier case DUP: 2833e12c5d1SDavid du Colombier if(t->rtype==DUPFD){ 2843e12c5d1SDavid du Colombier emitf(Xdup); 2853e12c5d1SDavid du Colombier emiti(t->fd0); 2863e12c5d1SDavid du Colombier emiti(t->fd1); 2873e12c5d1SDavid du Colombier } 2883e12c5d1SDavid du Colombier else{ 2893e12c5d1SDavid du Colombier emitf(Xclose); 2903e12c5d1SDavid du Colombier emiti(t->fd0); 2913e12c5d1SDavid du Colombier } 292219b2ee8SDavid du Colombier outcode(c1, eflag); 2933e12c5d1SDavid du Colombier emitf(Xpopredir); 2943e12c5d1SDavid du Colombier break; 2953e12c5d1SDavid du Colombier case PIPEFD: 2963e12c5d1SDavid du Colombier emitf(Xpipefd); 2973e12c5d1SDavid du Colombier emiti(t->rtype); 298*dc5a79c1SDavid du Colombier if(havefork){ 2993e12c5d1SDavid du Colombier p = emiti(0); 300219b2ee8SDavid du Colombier outcode(c0, eflag); 3013e12c5d1SDavid du Colombier emitf(Xexit); 3023e12c5d1SDavid du Colombier stuffdot(p); 303*dc5a79c1SDavid du Colombier } else { 304*dc5a79c1SDavid du Colombier emits(fnstr(c0)); 305*dc5a79c1SDavid du Colombier } 3063e12c5d1SDavid du Colombier break; 3073e12c5d1SDavid du Colombier case REDIR: 3083e12c5d1SDavid du Colombier emitf(Xmark); 309219b2ee8SDavid du Colombier outcode(c0, eflag); 310219b2ee8SDavid du Colombier emitf(Xglob); 3113e12c5d1SDavid du Colombier switch(t->rtype){ 3123e12c5d1SDavid du Colombier case APPEND: 3133e12c5d1SDavid du Colombier emitf(Xappend); 3143e12c5d1SDavid du Colombier break; 3153e12c5d1SDavid du Colombier case WRITE: 3163e12c5d1SDavid du Colombier emitf(Xwrite); 3173e12c5d1SDavid du Colombier break; 3183e12c5d1SDavid du Colombier case READ: 3193e12c5d1SDavid du Colombier case HERE: 3203e12c5d1SDavid du Colombier emitf(Xread); 3213e12c5d1SDavid du Colombier break; 3223e12c5d1SDavid du Colombier } 3233e12c5d1SDavid du Colombier emiti(t->fd0); 324219b2ee8SDavid du Colombier outcode(c1, eflag); 3253e12c5d1SDavid du Colombier emitf(Xpopredir); 3263e12c5d1SDavid du Colombier break; 3273e12c5d1SDavid du Colombier case '=': 3283e12c5d1SDavid du Colombier tt = t; 3293e12c5d1SDavid du Colombier for(;t && t->type=='=';t = c2); 3303e12c5d1SDavid du Colombier if(t){ 3313e12c5d1SDavid du Colombier for(t = tt;t->type=='=';t = c2){ 3323e12c5d1SDavid du Colombier emitf(Xmark); 333219b2ee8SDavid du Colombier outcode(c1, eflag); 3343e12c5d1SDavid du Colombier emitf(Xmark); 335219b2ee8SDavid du Colombier outcode(c0, eflag); 3363e12c5d1SDavid du Colombier emitf(Xlocal); 3373e12c5d1SDavid du Colombier } 3383e12c5d1SDavid du Colombier t = tt; 339219b2ee8SDavid du Colombier outcode(c2, eflag); 3403e12c5d1SDavid du Colombier for(;t->type=='=';t = c2) emitf(Xunlocal); 3413e12c5d1SDavid du Colombier } 3423e12c5d1SDavid du Colombier else{ 3433e12c5d1SDavid du Colombier for(t = tt;t;t = c2){ 3443e12c5d1SDavid du Colombier emitf(Xmark); 345219b2ee8SDavid du Colombier outcode(c1, eflag); 3463e12c5d1SDavid du Colombier emitf(Xmark); 347219b2ee8SDavid du Colombier outcode(c0, eflag); 3483e12c5d1SDavid du Colombier emitf(Xassign); 3493e12c5d1SDavid du Colombier } 3503e12c5d1SDavid du Colombier } 3513e12c5d1SDavid du Colombier t = tt; /* so tests below will work */ 3523e12c5d1SDavid du Colombier break; 3533e12c5d1SDavid du Colombier case PIPE: 3543e12c5d1SDavid du Colombier emitf(Xpipe); 3553e12c5d1SDavid du Colombier emiti(t->fd0); 3563e12c5d1SDavid du Colombier emiti(t->fd1); 357*dc5a79c1SDavid du Colombier if(havefork){ 3583e12c5d1SDavid du Colombier p = emiti(0); 3593e12c5d1SDavid du Colombier q = emiti(0); 360219b2ee8SDavid du Colombier outcode(c0, eflag); 3613e12c5d1SDavid du Colombier emitf(Xexit); 3623e12c5d1SDavid du Colombier stuffdot(p); 363*dc5a79c1SDavid du Colombier } else { 364*dc5a79c1SDavid du Colombier emits(fnstr(c0)); 365*dc5a79c1SDavid du Colombier q = emiti(0); 366*dc5a79c1SDavid du Colombier } 367219b2ee8SDavid du Colombier outcode(c1, eflag); 3683e12c5d1SDavid du Colombier emitf(Xreturn); 3693e12c5d1SDavid du Colombier stuffdot(q); 3703e12c5d1SDavid du Colombier emitf(Xpipewait); 3713e12c5d1SDavid du Colombier break; 3723e12c5d1SDavid du Colombier } 3733e12c5d1SDavid du Colombier if(t->type!=NOT && t->type!=';') 3743e12c5d1SDavid du Colombier runq->iflast = t->type==IF; 3753e12c5d1SDavid du Colombier else if(c0) runq->iflast = c0->type==IF; 3763e12c5d1SDavid du Colombier } 3773e12c5d1SDavid du Colombier /* 3783e12c5d1SDavid du Colombier * switch code looks like this: 3793e12c5d1SDavid du Colombier * Xmark 3803e12c5d1SDavid du Colombier * (get switch value) 3813e12c5d1SDavid du Colombier * Xjump 1f 3823e12c5d1SDavid du Colombier * out: Xjump leave 3833e12c5d1SDavid du Colombier * 1: Xmark 3843e12c5d1SDavid du Colombier * (get case values) 3853e12c5d1SDavid du Colombier * Xcase 1f 3863e12c5d1SDavid du Colombier * (commands) 3873e12c5d1SDavid du Colombier * Xjump out 3883e12c5d1SDavid du Colombier * 1: Xmark 3893e12c5d1SDavid du Colombier * (get case values) 3903e12c5d1SDavid du Colombier * Xcase 1f 3913e12c5d1SDavid du Colombier * (commands) 3923e12c5d1SDavid du Colombier * Xjump out 3933e12c5d1SDavid du Colombier * 1: 3943e12c5d1SDavid du Colombier * leave: 3953e12c5d1SDavid du Colombier * Xpopm 3963e12c5d1SDavid du Colombier */ 397*dc5a79c1SDavid du Colombier 398*dc5a79c1SDavid du Colombier void 399*dc5a79c1SDavid du Colombier codeswitch(tree *t, int eflag) 4003e12c5d1SDavid du Colombier { 4013e12c5d1SDavid du Colombier int leave; /* patch jump address to leave switch */ 4023e12c5d1SDavid du Colombier int out; /* jump here to leave switch */ 4033e12c5d1SDavid du Colombier int nextcase; /* patch jump address to next case */ 4043e12c5d1SDavid du Colombier tree *tt; 4057dd7cddfSDavid du Colombier if(c1->child[0]==nil 4067dd7cddfSDavid du Colombier || c1->child[0]->type!=';' 4073e12c5d1SDavid du Colombier || !iscase(c1->child[0]->child[0])){ 4083e12c5d1SDavid du Colombier yyerror("case missing in switch"); 4093e12c5d1SDavid du Colombier return; 4103e12c5d1SDavid du Colombier } 4113e12c5d1SDavid du Colombier emitf(Xmark); 412219b2ee8SDavid du Colombier outcode(c0, eflag); 4133e12c5d1SDavid du Colombier emitf(Xjump); 4143e12c5d1SDavid du Colombier nextcase = emiti(0); 4153e12c5d1SDavid du Colombier out = emitf(Xjump); 4163e12c5d1SDavid du Colombier leave = emiti(0); 4173e12c5d1SDavid du Colombier stuffdot(nextcase); 4183e12c5d1SDavid du Colombier t = c1->child[0]; 4193e12c5d1SDavid du Colombier while(t->type==';'){ 4203e12c5d1SDavid du Colombier tt = c1; 4213e12c5d1SDavid du Colombier emitf(Xmark); 422219b2ee8SDavid du Colombier for(t = c0->child[0];t->type==ARGLIST;t = c0) outcode(c1, eflag); 4233e12c5d1SDavid du Colombier emitf(Xcase); 4243e12c5d1SDavid du Colombier nextcase = emiti(0); 4253e12c5d1SDavid du Colombier t = tt; 4263e12c5d1SDavid du Colombier for(;;){ 4273e12c5d1SDavid du Colombier if(t->type==';'){ 4283e12c5d1SDavid du Colombier if(iscase(c0)) break; 429219b2ee8SDavid du Colombier outcode(c0, eflag); 4303e12c5d1SDavid du Colombier t = c1; 4313e12c5d1SDavid du Colombier } 4323e12c5d1SDavid du Colombier else{ 4337dd7cddfSDavid du Colombier if(!iscase(t)) outcode(t, eflag); 4343e12c5d1SDavid du Colombier break; 4353e12c5d1SDavid du Colombier } 4363e12c5d1SDavid du Colombier } 4373e12c5d1SDavid du Colombier emitf(Xjump); 4383e12c5d1SDavid du Colombier emiti(out); 4393e12c5d1SDavid du Colombier stuffdot(nextcase); 4403e12c5d1SDavid du Colombier } 4413e12c5d1SDavid du Colombier stuffdot(leave); 4423e12c5d1SDavid du Colombier emitf(Xpopm); 4433e12c5d1SDavid du Colombier } 444*dc5a79c1SDavid du Colombier 445*dc5a79c1SDavid du Colombier int 446*dc5a79c1SDavid du Colombier iscase(tree *t) 4473e12c5d1SDavid du Colombier { 448*dc5a79c1SDavid du Colombier if(t->type!=SIMPLE) 449*dc5a79c1SDavid du Colombier return 0; 4503e12c5d1SDavid du Colombier do t = c0; while(t->type==ARGLIST); 4513e12c5d1SDavid du Colombier return t->type==WORD && !t->quoted && strcmp(t->str, "case")==0; 4523e12c5d1SDavid du Colombier } 453*dc5a79c1SDavid du Colombier 454*dc5a79c1SDavid du Colombier code* 455*dc5a79c1SDavid du Colombier codecopy(code *cp) 4563e12c5d1SDavid du Colombier { 4573e12c5d1SDavid du Colombier cp[0].i++; 4583e12c5d1SDavid du Colombier return cp; 4593e12c5d1SDavid du Colombier } 460*dc5a79c1SDavid du Colombier 461*dc5a79c1SDavid du Colombier void 462*dc5a79c1SDavid du Colombier codefree(code *cp) 4633e12c5d1SDavid du Colombier { 4643e12c5d1SDavid du Colombier code *p; 465*dc5a79c1SDavid du Colombier if(--cp[0].i!=0) 466*dc5a79c1SDavid du Colombier return; 4673e12c5d1SDavid du Colombier for(p = cp+1;p->f;p++){ 4683e12c5d1SDavid du Colombier if(p->f==Xappend || p->f==Xclose || p->f==Xread || p->f==Xwrite 4693e12c5d1SDavid du Colombier || p->f==Xasync || p->f==Xbackq || p->f==Xcase || p->f==Xfalse 4703e12c5d1SDavid du Colombier || p->f==Xfor || p->f==Xjump 4713e12c5d1SDavid du Colombier || p->f==Xsubshell || p->f==Xtrue) p++; 4723e12c5d1SDavid du Colombier else if(p->f==Xdup || p->f==Xpipefd) p+=2; 4733e12c5d1SDavid du Colombier else if(p->f==Xpipe) p+=4; 4743e12c5d1SDavid du Colombier else if(p->f==Xword || p->f==Xdelhere) efree((++p)->s); 4753e12c5d1SDavid du Colombier else if(p->f==Xfn){ 4763e12c5d1SDavid du Colombier efree(p[2].s); 4773e12c5d1SDavid du Colombier p+=2; 4783e12c5d1SDavid du Colombier } 4793e12c5d1SDavid du Colombier } 4803e12c5d1SDavid du Colombier efree((char *)cp); 4813e12c5d1SDavid du Colombier } 482