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