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