|
|
1.1 ! root 1: #include "rc.h" ! 2: #include "io.h" ! 3: #include "exec.h" ! 4: #include "fns.h" ! 5: #include "getflags.h" ! 6: #define c0 t->child[0] ! 7: #define c1 t->child[1] ! 8: #define c2 t->child[2] ! 9: int codep, ncode; ! 10: #define emitf(x) ((codep!=ncode || morecode()), codebuf[codep].f=(x), codep++) ! 11: #define emiti(x) ((codep!=ncode || morecode()), codebuf[codep].i=(x), codep++) ! 12: #define emits(x) ((codep!=ncode || morecode()), codebuf[codep].s=(x), codep++) ! 13: void stuffdot(int); ! 14: char *fnstr(tree*); ! 15: void outcode(tree*, int); ! 16: void codeswitch(tree*, int); ! 17: int iscase(tree*); ! 18: code *codecopy(code*); ! 19: void codefree(code*); ! 20: int morecode(void){ ! 21: ncode+=100; ! 22: codebuf=(code *)realloc((char *)codebuf, ncode*sizeof codebuf[0]); ! 23: if(codebuf==0) panic("Can't realloc %d bytes in morecode!", ! 24: ncode*sizeof codebuf[0]); ! 25: } ! 26: void stuffdot(int a){ ! 27: if(a<0 || codep<=a) panic("Bad address %d in stuffdot", a); ! 28: codebuf[a].i=codep; ! 29: } ! 30: int compile(tree *t) ! 31: { ! 32: ncode=100; ! 33: codebuf=(code *)emalloc(ncode*sizeof codebuf[0]); ! 34: codep=0; ! 35: emiti(0); /* reference count */ ! 36: outcode(t, flag['e']?1:0); ! 37: if(nerror){ ! 38: efree((char *)codebuf); ! 39: return 0; ! 40: } ! 41: readhere(); ! 42: emitf(Xreturn); ! 43: emitf(0); ! 44: return 1; ! 45: } ! 46: void cleanhere(char *f) ! 47: { ! 48: emitf(Xdelhere); ! 49: emits(strdup(f)); ! 50: } ! 51: char *fnstr(tree *t) ! 52: { ! 53: io *f=openstr(); ! 54: char *v; ! 55: extern char nl; ! 56: char svnl=nl; ! 57: nl=';'; ! 58: pfmt(f, "%t", t); ! 59: nl=svnl; ! 60: v=f->strp; ! 61: f->strp=0; ! 62: closeio(f); ! 63: return v; ! 64: } ! 65: void outcode(tree *t, int eflag) ! 66: { ! 67: int p, q; ! 68: tree *tt; ! 69: if(t==0) return; ! 70: if(t->type!=NOT && t->type!=';') runq->iflast=0; ! 71: switch(t->type){ ! 72: default: ! 73: pfmt(err, "bad type %d in outcode\n", t->type); ! 74: break; ! 75: case '$': ! 76: emitf(Xmark); ! 77: outcode(c0, eflag); ! 78: emitf(Xdol); ! 79: break; ! 80: case '"': ! 81: emitf(Xmark); ! 82: outcode(c0, eflag); ! 83: emitf(Xqdol); ! 84: break; ! 85: case SUB: ! 86: emitf(Xmark); ! 87: outcode(c0, eflag); ! 88: emitf(Xmark); ! 89: outcode(c1, eflag); ! 90: emitf(Xsub); ! 91: break; ! 92: case '&': ! 93: emitf(Xasync); ! 94: p=emiti(0); ! 95: outcode(c0, eflag); ! 96: emitf(Xexit); ! 97: stuffdot(p); ! 98: break; ! 99: case ';': ! 100: outcode(c0, eflag); ! 101: outcode(c1, eflag); ! 102: break; ! 103: case '^': ! 104: emitf(Xmark); ! 105: outcode(c1, eflag); ! 106: emitf(Xmark); ! 107: outcode(c0, eflag); ! 108: emitf(Xconc); ! 109: break; ! 110: case '`': ! 111: emitf(Xbackq); ! 112: p=emiti(0); ! 113: outcode(c0, 0); ! 114: emitf(Xexit); ! 115: stuffdot(p); ! 116: break; ! 117: case ANDAND: ! 118: outcode(c0, 0); ! 119: emitf(Xtrue); ! 120: p=emiti(0); ! 121: outcode(c1, eflag); ! 122: stuffdot(p); ! 123: break; ! 124: case ARGLIST: ! 125: outcode(c1, eflag); ! 126: outcode(c0, eflag); ! 127: break; ! 128: case BANG: ! 129: outcode(c0, eflag); ! 130: emitf(Xbang); ! 131: break; ! 132: case PCMD: ! 133: case BRACE: ! 134: outcode(c0, eflag); ! 135: break; ! 136: case COUNT: ! 137: emitf(Xmark); ! 138: outcode(c0, eflag); ! 139: emitf(Xcount); ! 140: break; ! 141: case FN: ! 142: emitf(Xmark); ! 143: outcode(c0, eflag); ! 144: if(c1){ ! 145: emitf(Xfn); ! 146: p=emiti(0); ! 147: emits(fnstr(c1)); ! 148: outcode(c1, eflag); ! 149: emitf(Xunlocal); /* get rid of $* */ ! 150: emitf(Xreturn); ! 151: stuffdot(p); ! 152: } ! 153: else ! 154: emitf(Xdelfn); ! 155: break; ! 156: case IF: ! 157: outcode(c0, 0); ! 158: emitf(Xif); ! 159: p=emiti(0); ! 160: outcode(c1, eflag); ! 161: emitf(Xwastrue); ! 162: stuffdot(p); ! 163: break; ! 164: case NOT: ! 165: if(!runq->iflast) yyerror("`if not' does not follow `if(...)'"); ! 166: emitf(Xifnot); ! 167: p=emiti(0); ! 168: outcode(c0, eflag); ! 169: stuffdot(p); ! 170: break; ! 171: case OROR: ! 172: outcode(c0, 0); ! 173: emitf(Xfalse); ! 174: p=emiti(0); ! 175: outcode(c1, eflag); ! 176: stuffdot(p); ! 177: break; ! 178: case PAREN: ! 179: outcode(c0, eflag); ! 180: break; ! 181: case SIMPLE: ! 182: emitf(Xmark); ! 183: outcode(c0, eflag); ! 184: emitf(Xsimple); ! 185: if(eflag) emitf(Xeflag); ! 186: break; ! 187: case SUBSHELL: ! 188: emitf(Xsubshell); ! 189: p=emiti(0); ! 190: outcode(c0, eflag); ! 191: emitf(Xexit); ! 192: stuffdot(p); ! 193: break; ! 194: case SWITCH: ! 195: codeswitch(t, eflag); ! 196: break; ! 197: case TWIDDLE: ! 198: emitf(Xmark); ! 199: outcode(c1, eflag); ! 200: emitf(Xmark); ! 201: outcode(c0, eflag); ! 202: emitf(Xmatch); ! 203: if(eflag) emitf(Xeflag); ! 204: break; ! 205: case WHILE: ! 206: q=codep; ! 207: emitf(Xsettrue); ! 208: outcode(c0, 0); ! 209: emitf(Xtrue); ! 210: p=emiti(0); ! 211: outcode(c1, eflag); ! 212: emitf(Xjump); ! 213: emiti(q); ! 214: stuffdot(p); ! 215: break; ! 216: case WORDS: ! 217: outcode(c1, eflag); ! 218: outcode(c0, eflag); ! 219: break; ! 220: case FOR: ! 221: emitf(Xmark); ! 222: if(c1){ ! 223: outcode(c1, eflag); ! 224: emitf(Xglob); ! 225: } ! 226: else{ ! 227: emitf(Xmark); ! 228: emitf(Xword); ! 229: emits(strdup("*")); ! 230: emitf(Xdol); ! 231: } ! 232: emitf(Xmark); /* dummy value for Xlocal */ ! 233: emitf(Xmark); ! 234: outcode(c0, eflag); ! 235: emitf(Xlocal); ! 236: p=emitf(Xfor); ! 237: q=emiti(0); ! 238: outcode(c2, eflag); ! 239: emitf(Xjump); ! 240: emiti(p); ! 241: stuffdot(q); ! 242: emitf(Xunlocal); ! 243: break; ! 244: case WORD: ! 245: emitf(Xword); ! 246: emits(strdup(t->str)); ! 247: break; ! 248: case DUP: ! 249: if(t->rtype==DUPFD){ ! 250: emitf(Xdup); ! 251: emiti(t->fd0); ! 252: emiti(t->fd1); ! 253: } ! 254: else{ ! 255: emitf(Xclose); ! 256: emiti(t->fd0); ! 257: } ! 258: outcode(c1, eflag); ! 259: emitf(Xpopredir); ! 260: break; ! 261: case PIPEFD: ! 262: emitf(Xpipefd); ! 263: emiti(t->rtype); ! 264: p=emiti(0); ! 265: outcode(c0, eflag); ! 266: emitf(Xexit); ! 267: stuffdot(p); ! 268: break; ! 269: case REDIR: ! 270: emitf(Xmark); ! 271: outcode(c0, eflag); ! 272: emitf(Xglob); ! 273: switch(t->rtype){ ! 274: case APPEND: ! 275: emitf(Xappend); ! 276: break; ! 277: case WRITE: ! 278: emitf(Xwrite); ! 279: break; ! 280: case READ: ! 281: case HERE: ! 282: emitf(Xread); ! 283: break; ! 284: } ! 285: emiti(t->fd0); ! 286: outcode(c1, eflag); ! 287: emitf(Xpopredir); ! 288: break; ! 289: case '=': ! 290: tt=t; ! 291: for(;t && t->type=='=';t=c2); ! 292: if(t){ ! 293: for(t=tt;t->type=='=';t=c2){ ! 294: emitf(Xmark); ! 295: outcode(c1, eflag); ! 296: emitf(Xmark); ! 297: outcode(c0, eflag); ! 298: emitf(Xlocal); ! 299: } ! 300: t=tt; ! 301: outcode(c2, eflag); ! 302: for(;t->type=='=';t=c2) emitf(Xunlocal); ! 303: } ! 304: else{ ! 305: for(t=tt;t;t=c2){ ! 306: emitf(Xmark); ! 307: outcode(c1, eflag); ! 308: emitf(Xmark); ! 309: outcode(c0, eflag); ! 310: emitf(Xassign); ! 311: } ! 312: } ! 313: t=tt; /* so tests below will work */ ! 314: break; ! 315: case PIPE: ! 316: emitf(Xpipe); ! 317: emiti(t->fd0); ! 318: emiti(t->fd1); ! 319: p=emiti(0); ! 320: q=emiti(0); ! 321: outcode(c0, eflag); ! 322: emitf(Xexit); ! 323: stuffdot(p); ! 324: outcode(c1, eflag); ! 325: emitf(Xreturn); ! 326: stuffdot(q); ! 327: emitf(Xpipewait); ! 328: break; ! 329: } ! 330: if(t->type!=NOT && t->type!=';') ! 331: runq->iflast=t->type==IF; ! 332: else if(c0) runq->iflast=c0->type==IF; ! 333: } ! 334: /* ! 335: * switch code looks like this: ! 336: * Xmark ! 337: * (get switch value) ! 338: * Xjump 1f ! 339: * out: Xjump leave ! 340: * 1: Xmark ! 341: * (get case values) ! 342: * Xcase 1f ! 343: * (commands) ! 344: * Xjump out ! 345: * 1: Xmark ! 346: * (get case values) ! 347: * Xcase 1f ! 348: * (commands) ! 349: * Xjump out ! 350: * 1: ! 351: * leave: ! 352: * Xpopm ! 353: */ ! 354: void codeswitch(tree *t, int eflag) ! 355: { ! 356: int leave; /* patch jump address to leave switch */ ! 357: int out; /* jump here to leave switch */ ! 358: int nextcase; /* patch jump address to next case */ ! 359: tree *tt; ! 360: if(c1->child[0]->type!=';' ! 361: || !iscase(c1->child[0]->child[0])){ ! 362: yyerror("case missing in switch"); ! 363: return; ! 364: } ! 365: emitf(Xmark); ! 366: outcode(c0, eflag); ! 367: emitf(Xjump); ! 368: nextcase=emiti(0); ! 369: out=emitf(Xjump); ! 370: leave=emiti(0); ! 371: stuffdot(nextcase); ! 372: t=c1->child[0]; ! 373: while(t->type==';'){ ! 374: tt=c1; ! 375: emitf(Xmark); ! 376: for(t=c0->child[0];t->type==ARGLIST;t=c0) outcode(c1, eflag); ! 377: emitf(Xcase); ! 378: nextcase=emiti(0); ! 379: t=tt; ! 380: for(;;){ ! 381: if(t->type==';'){ ! 382: if(iscase(c0)) break; ! 383: outcode(c0, eflag); ! 384: t=c1; ! 385: } ! 386: else{ ! 387: outcode(t, eflag); ! 388: break; ! 389: } ! 390: } ! 391: emitf(Xjump); ! 392: emiti(out); ! 393: stuffdot(nextcase); ! 394: } ! 395: stuffdot(leave); ! 396: emitf(Xpopm); ! 397: } ! 398: int iscase(tree *t) ! 399: { ! 400: if(t->type!=SIMPLE) return 0; ! 401: do t=c0; while(t->type==ARGLIST); ! 402: return t->type==WORD && !t->quoted && strcmp(t->str, "case")==0; ! 403: } ! 404: code *codecopy(code *cp) ! 405: { ! 406: cp[0].i++; ! 407: return cp; ! 408: } ! 409: void codefree(code *cp) ! 410: { ! 411: code *p; ! 412: if(--cp[0].i!=0) return; ! 413: for(p=cp+1;p->f;p++){ ! 414: if(p->f==Xappend || p->f==Xclose || p->f==Xread || p->f==Xwrite ! 415: || p->f==Xasync || p->f==Xbackq || p->f==Xcase || p->f==Xfalse ! 416: || p->f==Xfor || p->f==Xjump ! 417: || p->f==Xsubshell || p->f==Xtrue) p++; ! 418: else if(p->f==Xdup || p->f==Xpipefd) p+=2; ! 419: else if(p->f==Xpipe) p+=4; ! 420: else if(p->f==Xword || p->f==Xdelhere) efree((++p)->s); ! 421: else if(p->f==Xfn){ ! 422: efree(p[2].s); ! 423: p+=2; ! 424: } ! 425: } ! 426: efree((char *)cp); ! 427: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.