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