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