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