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