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 case RDWR: 323 emitf(Xrdwr); 324 break; 325 } 326 emiti(t->fd0); 327 outcode(c1, eflag); 328 emitf(Xpopredir); 329 break; 330 case '=': 331 tt = t; 332 for(;t && t->type=='=';t = c2); 333 if(t){ 334 for(t = tt;t->type=='=';t = c2){ 335 emitf(Xmark); 336 outcode(c1, eflag); 337 emitf(Xmark); 338 outcode(c0, eflag); 339 emitf(Xlocal); 340 } 341 t = tt; 342 outcode(c2, eflag); 343 for(;t->type=='=';t = c2) emitf(Xunlocal); 344 } 345 else{ 346 for(t = tt;t;t = c2){ 347 emitf(Xmark); 348 outcode(c1, eflag); 349 emitf(Xmark); 350 outcode(c0, eflag); 351 emitf(Xassign); 352 } 353 } 354 t = tt; /* so tests below will work */ 355 break; 356 case PIPE: 357 emitf(Xpipe); 358 emiti(t->fd0); 359 emiti(t->fd1); 360 if(havefork){ 361 p = emiti(0); 362 q = emiti(0); 363 outcode(c0, eflag); 364 emitf(Xexit); 365 stuffdot(p); 366 } else { 367 emits(fnstr(c0)); 368 q = emiti(0); 369 } 370 outcode(c1, eflag); 371 emitf(Xreturn); 372 stuffdot(q); 373 emitf(Xpipewait); 374 break; 375 } 376 if(t->type!=NOT && t->type!=';') 377 runq->iflast = t->type==IF; 378 else if(c0) runq->iflast = c0->type==IF; 379 } 380 /* 381 * switch code looks like this: 382 * Xmark 383 * (get switch value) 384 * Xjump 1f 385 * out: Xjump leave 386 * 1: Xmark 387 * (get case values) 388 * Xcase 1f 389 * (commands) 390 * Xjump out 391 * 1: Xmark 392 * (get case values) 393 * Xcase 1f 394 * (commands) 395 * Xjump out 396 * 1: 397 * leave: 398 * Xpopm 399 */ 400 401 void 402 codeswitch(tree *t, int eflag) 403 { 404 int leave; /* patch jump address to leave switch */ 405 int out; /* jump here to leave switch */ 406 int nextcase; /* patch jump address to next case */ 407 tree *tt; 408 if(c1->child[0]==nil 409 || c1->child[0]->type!=';' 410 || !iscase(c1->child[0]->child[0])){ 411 yyerror("case missing in switch"); 412 return; 413 } 414 emitf(Xmark); 415 outcode(c0, eflag); 416 emitf(Xjump); 417 nextcase = emiti(0); 418 out = emitf(Xjump); 419 leave = emiti(0); 420 stuffdot(nextcase); 421 t = c1->child[0]; 422 while(t->type==';'){ 423 tt = c1; 424 emitf(Xmark); 425 for(t = c0->child[0];t->type==ARGLIST;t = c0) outcode(c1, eflag); 426 emitf(Xcase); 427 nextcase = emiti(0); 428 t = tt; 429 for(;;){ 430 if(t->type==';'){ 431 if(iscase(c0)) break; 432 outcode(c0, eflag); 433 t = c1; 434 } 435 else{ 436 if(!iscase(t)) outcode(t, eflag); 437 break; 438 } 439 } 440 emitf(Xjump); 441 emiti(out); 442 stuffdot(nextcase); 443 } 444 stuffdot(leave); 445 emitf(Xpopm); 446 } 447 448 int 449 iscase(tree *t) 450 { 451 if(t->type!=SIMPLE) 452 return 0; 453 do t = c0; while(t->type==ARGLIST); 454 return t->type==WORD && !t->quoted && strcmp(t->str, "case")==0; 455 } 456 457 code* 458 codecopy(code *cp) 459 { 460 cp[0].i++; 461 return cp; 462 } 463 464 void 465 codefree(code *cp) 466 { 467 code *p; 468 if(--cp[0].i!=0) 469 return; 470 for(p = cp+1;p->f;p++){ 471 if(p->f==Xappend || p->f==Xclose || p->f==Xread || p->f==Xwrite 472 || p->f==Xrdwr 473 || p->f==Xasync || p->f==Xbackq || p->f==Xcase || p->f==Xfalse 474 || p->f==Xfor || p->f==Xjump 475 || p->f==Xsubshell || p->f==Xtrue) p++; 476 else if(p->f==Xdup || p->f==Xpipefd) p+=2; 477 else if(p->f==Xpipe) p+=4; 478 else if(p->f==Xword || p->f==Xdelhere) efree((++p)->s); 479 else if(p->f==Xfn){ 480 efree(p[2].s); 481 p+=2; 482 } 483 } 484 efree((char *)cp); 485 } 486