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
morecode(void)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
stuffdot(int a)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
compile(Tree * t)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
cleanhere(char * f)59 cleanhere(char *f)
60 {
61 emitf(Xdelhere);
62 emits(strdup(f));
63 }
64
65 char *
fnstr(Tree * t)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
outcode(Tree * t,int eflag)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
codeswitch(Tree * t,int eflag)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
iscase(Tree * t)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 *
codecopy(Code * cp)450 codecopy(Code *cp)
451 {
452 cp[0].i++;
453 return cp;
454 }
455
456 void
codefree(Code * cp)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