xref: /csrg-svn/old/sh/cmd.c (revision 6685)
1*6685Smckusick /*	cmd.c	4.1	82/05/07	*/
2*6685Smckusick 
3*6685Smckusick #
4*6685Smckusick /*
5*6685Smckusick  * UNIX shell
6*6685Smckusick  *
7*6685Smckusick  * S. R. Bourne
8*6685Smckusick  * Bell Telephone Laboratories
9*6685Smckusick  *
10*6685Smckusick  */
11*6685Smckusick 
12*6685Smckusick #include	"defs.h"
13*6685Smckusick #include	"sym.h"
14*6685Smckusick 
15*6685Smckusick PROC IOPTR	inout();
16*6685Smckusick PROC VOID	chkword();
17*6685Smckusick PROC VOID	chksym();
18*6685Smckusick PROC TREPTR	term();
19*6685Smckusick PROC TREPTR	makelist();
20*6685Smckusick PROC TREPTR	list();
21*6685Smckusick PROC REGPTR	syncase();
22*6685Smckusick PROC TREPTR	item();
23*6685Smckusick PROC VOID	skipnl();
24*6685Smckusick PROC VOID	prsym();
25*6685Smckusick PROC VOID	synbad();
26*6685Smckusick 
27*6685Smckusick 
28*6685Smckusick /* ========	command line decoding	========*/
29*6685Smckusick 
30*6685Smckusick 
31*6685Smckusick 
32*6685Smckusick 
33*6685Smckusick TREPTR	makefork(flgs, i)
34*6685Smckusick 	INT		flgs;
35*6685Smckusick 	TREPTR		i;
36*6685Smckusick {
37*6685Smckusick 	REG TREPTR	t;
38*6685Smckusick 
39*6685Smckusick 	t=getstak(FORKTYPE);
40*6685Smckusick 	t->forktyp=flgs|TFORK; t->forktre=i; t->forkio=0;
41*6685Smckusick 	return(t);
42*6685Smckusick }
43*6685Smckusick 
44*6685Smckusick LOCAL TREPTR	makelist(type,i,r)
45*6685Smckusick 	INT		type;
46*6685Smckusick 	TREPTR		i, r;
47*6685Smckusick {
48*6685Smckusick 	REG TREPTR	t;
49*6685Smckusick 
50*6685Smckusick 	IF i==0 ORF r==0
51*6685Smckusick 	THEN	synbad();
52*6685Smckusick 	ELSE	t = getstak(LSTTYPE);
53*6685Smckusick 		t->lsttyp = type;
54*6685Smckusick 		t->lstlef = i; t->lstrit = r;
55*6685Smckusick 	FI
56*6685Smckusick 	return(t);
57*6685Smckusick }
58*6685Smckusick 
59*6685Smckusick /*
60*6685Smckusick  * cmd
61*6685Smckusick  *	empty
62*6685Smckusick  *	list
63*6685Smckusick  *	list & [ cmd ]
64*6685Smckusick  *	list [ ; cmd ]
65*6685Smckusick  */
66*6685Smckusick 
67*6685Smckusick TREPTR	cmd(sym,flg)
68*6685Smckusick 	REG INT		sym;
69*6685Smckusick 	INT		flg;
70*6685Smckusick {
71*6685Smckusick 	REG TREPTR	i, e;
72*6685Smckusick 
73*6685Smckusick 	i = list(flg);
74*6685Smckusick 
75*6685Smckusick 	IF wdval==NL
76*6685Smckusick 	THEN	IF flg&NLFLG
77*6685Smckusick 		THEN	wdval=';'; chkpr(NL);
78*6685Smckusick 		FI
79*6685Smckusick 	ELIF i==0 ANDF (flg&MTFLG)==0
80*6685Smckusick 	THEN	synbad();
81*6685Smckusick 	FI
82*6685Smckusick 
83*6685Smckusick 	SWITCH wdval IN
84*6685Smckusick 
85*6685Smckusick 	    case '&':
86*6685Smckusick 		IF i
87*6685Smckusick 		THEN	i = makefork(FINT|FPRS|FAMP, i);
88*6685Smckusick 		ELSE	synbad();
89*6685Smckusick 		FI
90*6685Smckusick 
91*6685Smckusick 	    case ';':
92*6685Smckusick 		IF e=cmd(sym,flg|MTFLG)
93*6685Smckusick 		THEN	i=makelist(TLST, i, e);
94*6685Smckusick 		FI
95*6685Smckusick 		break;
96*6685Smckusick 
97*6685Smckusick 	    case EOFSYM:
98*6685Smckusick 		IF sym==NL
99*6685Smckusick 		THEN	break;
100*6685Smckusick 		FI
101*6685Smckusick 
102*6685Smckusick 	    default:
103*6685Smckusick 		IF sym
104*6685Smckusick 		THEN	chksym(sym);
105*6685Smckusick 		FI
106*6685Smckusick 
107*6685Smckusick 	ENDSW
108*6685Smckusick 	return(i);
109*6685Smckusick }
110*6685Smckusick 
111*6685Smckusick /*
112*6685Smckusick  * list
113*6685Smckusick  *	term
114*6685Smckusick  *	list && term
115*6685Smckusick  *	list || term
116*6685Smckusick  */
117*6685Smckusick 
118*6685Smckusick LOCAL TREPTR	list(flg)
119*6685Smckusick {
120*6685Smckusick 	REG TREPTR	r;
121*6685Smckusick 	REG INT		b;
122*6685Smckusick 
123*6685Smckusick 	r = term(flg);
124*6685Smckusick 	WHILE r ANDF ((b=(wdval==ANDFSYM)) ORF wdval==ORFSYM)
125*6685Smckusick 	DO	r = makelist((b ? TAND : TORF), r, term(NLFLG));
126*6685Smckusick 	OD
127*6685Smckusick 	return(r);
128*6685Smckusick }
129*6685Smckusick 
130*6685Smckusick /*
131*6685Smckusick  * term
132*6685Smckusick  *	item
133*6685Smckusick  *	item |^ term
134*6685Smckusick  */
135*6685Smckusick 
136*6685Smckusick LOCAL TREPTR	term(flg)
137*6685Smckusick {
138*6685Smckusick 	REG TREPTR	t;
139*6685Smckusick 
140*6685Smckusick 	reserv++;
141*6685Smckusick 	IF flg&NLFLG
142*6685Smckusick 	THEN	skipnl();
143*6685Smckusick 	ELSE	word();
144*6685Smckusick 	FI
145*6685Smckusick 
146*6685Smckusick 	IF (t=item(TRUE)) ANDF (wdval=='^' ORF wdval=='|')
147*6685Smckusick 	THEN	return(makelist(TFIL, makefork(FPOU,t), makefork(FPIN|FPCL,term(NLFLG))));
148*6685Smckusick 	ELSE	return(t);
149*6685Smckusick 	FI
150*6685Smckusick }
151*6685Smckusick 
152*6685Smckusick LOCAL REGPTR	syncase(esym)
153*6685Smckusick 	REG INT	esym;
154*6685Smckusick {
155*6685Smckusick 	skipnl();
156*6685Smckusick 	IF wdval==esym
157*6685Smckusick 	THEN	return(0);
158*6685Smckusick 	ELSE	REG REGPTR	r=getstak(REGTYPE);
159*6685Smckusick 		r->regptr=0;
160*6685Smckusick 		LOOP wdarg->argnxt=r->regptr;
161*6685Smckusick 		     r->regptr=wdarg;
162*6685Smckusick 		     IF wdval ORF ( word()!=')' ANDF wdval!='|' )
163*6685Smckusick 		     THEN synbad();
164*6685Smckusick 		     FI
165*6685Smckusick 		     IF wdval=='|'
166*6685Smckusick 		     THEN word();
167*6685Smckusick 		     ELSE break;
168*6685Smckusick 		     FI
169*6685Smckusick 		POOL
170*6685Smckusick 		r->regcom=cmd(0,NLFLG|MTFLG);
171*6685Smckusick 		IF wdval==ECSYM
172*6685Smckusick 		THEN	r->regnxt=syncase(esym);
173*6685Smckusick 		ELSE	chksym(esym);
174*6685Smckusick 			r->regnxt=0;
175*6685Smckusick 		FI
176*6685Smckusick 		return(r);
177*6685Smckusick 	FI
178*6685Smckusick }
179*6685Smckusick 
180*6685Smckusick /*
181*6685Smckusick  * item
182*6685Smckusick  *
183*6685Smckusick  *	( cmd ) [ < in  ] [ > out ]
184*6685Smckusick  *	word word* [ < in ] [ > out ]
185*6685Smckusick  *	if ... then ... else ... fi
186*6685Smckusick  *	for ... while ... do ... done
187*6685Smckusick  *	case ... in ... esac
188*6685Smckusick  *	begin ... end
189*6685Smckusick  */
190*6685Smckusick 
191*6685Smckusick LOCAL TREPTR	item(flag)
192*6685Smckusick 	BOOL		flag;
193*6685Smckusick {
194*6685Smckusick 	REG TREPTR	t;
195*6685Smckusick 	REG IOPTR	io;
196*6685Smckusick 
197*6685Smckusick 	IF flag
198*6685Smckusick 	THEN	io=inout((IOPTR)0);
199*6685Smckusick 	ELSE	io=0;
200*6685Smckusick 	FI
201*6685Smckusick 
202*6685Smckusick 	SWITCH wdval IN
203*6685Smckusick 
204*6685Smckusick 	    case CASYM:
205*6685Smckusick 		BEGIN
206*6685Smckusick 		   t=getstak(SWTYPE);
207*6685Smckusick 		   chkword();
208*6685Smckusick 		   t->swarg=wdarg->argval;
209*6685Smckusick 		   skipnl(); chksym(INSYM|BRSYM);
210*6685Smckusick 		   t->swlst=syncase(wdval==INSYM?ESSYM:KTSYM);
211*6685Smckusick 		   t->swtyp=TSW;
212*6685Smckusick 		   break;
213*6685Smckusick 		END
214*6685Smckusick 
215*6685Smckusick 	    case IFSYM:
216*6685Smckusick 		BEGIN
217*6685Smckusick 		   REG INT	w;
218*6685Smckusick 		   t=getstak(IFTYPE);
219*6685Smckusick 		   t->iftyp=TIF;
220*6685Smckusick 		   t->iftre=cmd(THSYM,NLFLG);
221*6685Smckusick 		   t->thtre=cmd(ELSYM|FISYM|EFSYM,NLFLG);
222*6685Smckusick 		   t->eltre=((w=wdval)==ELSYM ? cmd(FISYM,NLFLG) : (w==EFSYM ? (wdval=IFSYM, item(0)) : 0));
223*6685Smckusick 		   IF w==EFSYM THEN return(t) FI
224*6685Smckusick 		   break;
225*6685Smckusick 		END
226*6685Smckusick 
227*6685Smckusick 	    case FORSYM:
228*6685Smckusick 		BEGIN
229*6685Smckusick 		   t=getstak(FORTYPE);
230*6685Smckusick 		   t->fortyp=TFOR;
231*6685Smckusick 		   t->forlst=0;
232*6685Smckusick 		   chkword();
233*6685Smckusick 		   t->fornam=wdarg->argval;
234*6685Smckusick 		   IF skipnl()==INSYM
235*6685Smckusick 		   THEN	chkword();
236*6685Smckusick 			t->forlst=item(0);
237*6685Smckusick 			IF wdval!=NL ANDF wdval!=';'
238*6685Smckusick 			THEN	synbad();
239*6685Smckusick 			FI
240*6685Smckusick 			chkpr(wdval); skipnl();
241*6685Smckusick 		   FI
242*6685Smckusick 		   chksym(DOSYM|BRSYM);
243*6685Smckusick 		   t->fortre=cmd(wdval==DOSYM?ODSYM:KTSYM,NLFLG);
244*6685Smckusick 		   break;
245*6685Smckusick 		END
246*6685Smckusick 
247*6685Smckusick 	    case WHSYM:
248*6685Smckusick 	    case UNSYM:
249*6685Smckusick 		BEGIN
250*6685Smckusick 		   t=getstak(WHTYPE);
251*6685Smckusick 		   t->whtyp=(wdval==WHSYM ? TWH : TUN);
252*6685Smckusick 		   t->whtre = cmd(DOSYM,NLFLG);
253*6685Smckusick 		   t->dotre = cmd(ODSYM,NLFLG);
254*6685Smckusick 		   break;
255*6685Smckusick 		END
256*6685Smckusick 
257*6685Smckusick 	    case BRSYM:
258*6685Smckusick 		t=cmd(KTSYM,NLFLG);
259*6685Smckusick 		break;
260*6685Smckusick 
261*6685Smckusick 	    case '(':
262*6685Smckusick 		BEGIN
263*6685Smckusick 		   REG PARPTR	 p;
264*6685Smckusick 		   p=getstak(PARTYPE);
265*6685Smckusick 		   p->partre=cmd(')',NLFLG);
266*6685Smckusick 		   p->partyp=TPAR;
267*6685Smckusick 		   t=makefork(0,p);
268*6685Smckusick 		   break;
269*6685Smckusick 		END
270*6685Smckusick 
271*6685Smckusick 	    default:
272*6685Smckusick 		IF io==0
273*6685Smckusick 		THEN	return(0);
274*6685Smckusick 		FI
275*6685Smckusick 
276*6685Smckusick 	    case 0:
277*6685Smckusick 		BEGIN
278*6685Smckusick 		   REG ARGPTR	argp;
279*6685Smckusick 		   REG ARGPTR	*argtail;
280*6685Smckusick 		   REG ARGPTR	*argset=0;
281*6685Smckusick 		   INT		keywd=1;
282*6685Smckusick 		   t=getstak(COMTYPE);
283*6685Smckusick 		   t->comio=io; /*initial io chain*/
284*6685Smckusick 		   argtail = &(t->comarg);
285*6685Smckusick 		   WHILE wdval==0
286*6685Smckusick 		   DO	argp = wdarg;
287*6685Smckusick 			IF wdset ANDF keywd
288*6685Smckusick 			THEN	argp->argnxt=argset; argset=argp;
289*6685Smckusick 			ELSE	*argtail=argp; argtail = &(argp->argnxt); keywd=flags&keyflg;
290*6685Smckusick 			FI
291*6685Smckusick 			word();
292*6685Smckusick 			IF flag
293*6685Smckusick 			THEN t->comio=inout(t->comio);
294*6685Smckusick 			FI
295*6685Smckusick 		   OD
296*6685Smckusick 
297*6685Smckusick 		   t->comtyp=TCOM; t->comset=argset; *argtail=0;
298*6685Smckusick 		   return(t);
299*6685Smckusick 		END
300*6685Smckusick 
301*6685Smckusick 	ENDSW
302*6685Smckusick 	reserv++; word();
303*6685Smckusick 	IF io=inout(io)
304*6685Smckusick 	THEN	t=makefork(0,t); t->treio=io;
305*6685Smckusick 	FI
306*6685Smckusick 	return(t);
307*6685Smckusick }
308*6685Smckusick 
309*6685Smckusick 
310*6685Smckusick LOCAL VOID	skipnl()
311*6685Smckusick {
312*6685Smckusick 	WHILE (reserv++, word()==NL) DO chkpr(NL) OD
313*6685Smckusick 	return(wdval);
314*6685Smckusick }
315*6685Smckusick 
316*6685Smckusick LOCAL IOPTR	inout(lastio)
317*6685Smckusick 	IOPTR		lastio;
318*6685Smckusick {
319*6685Smckusick 	REG INT		iof;
320*6685Smckusick 	REG IOPTR	iop;
321*6685Smckusick 	REG CHAR	c;
322*6685Smckusick 
323*6685Smckusick 	iof=wdnum;
324*6685Smckusick 
325*6685Smckusick 	SWITCH wdval IN
326*6685Smckusick 
327*6685Smckusick 	    case DOCSYM:
328*6685Smckusick 		iof |= IODOC; break;
329*6685Smckusick 
330*6685Smckusick 	    case APPSYM:
331*6685Smckusick 	    case '>':
332*6685Smckusick 		IF wdnum==0 THEN iof |= 1 FI
333*6685Smckusick 		iof |= IOPUT;
334*6685Smckusick 		IF wdval==APPSYM
335*6685Smckusick 		THEN	iof |= IOAPP; break;
336*6685Smckusick 		FI
337*6685Smckusick 
338*6685Smckusick 	    case '<':
339*6685Smckusick 		IF (c=nextc(0))=='&'
340*6685Smckusick 		THEN	iof |= IOMOV;
341*6685Smckusick 		ELIF c=='>'
342*6685Smckusick 		THEN	iof |= IORDW;
343*6685Smckusick 		ELSE	peekc=c|MARK;
344*6685Smckusick 		FI
345*6685Smckusick 		break;
346*6685Smckusick 
347*6685Smckusick 	    default:
348*6685Smckusick 		return(lastio);
349*6685Smckusick 	ENDSW
350*6685Smckusick 
351*6685Smckusick 	chkword();
352*6685Smckusick 	iop=getstak(IOTYPE); iop->ioname=wdarg->argval; iop->iofile=iof;
353*6685Smckusick 	IF iof&IODOC
354*6685Smckusick 	THEN iop->iolst=iopend; iopend=iop;
355*6685Smckusick 	FI
356*6685Smckusick 	word(); iop->ionxt=inout(lastio);
357*6685Smckusick 	return(iop);
358*6685Smckusick }
359*6685Smckusick 
360*6685Smckusick LOCAL VOID	chkword()
361*6685Smckusick {
362*6685Smckusick 	IF word()
363*6685Smckusick 	THEN	synbad();
364*6685Smckusick 	FI
365*6685Smckusick }
366*6685Smckusick 
367*6685Smckusick LOCAL VOID	chksym(sym)
368*6685Smckusick {
369*6685Smckusick 	REG INT		x = sym&wdval;
370*6685Smckusick 	IF ((x&SYMFLG) ? x : sym) != wdval
371*6685Smckusick 	THEN	synbad();
372*6685Smckusick 	FI
373*6685Smckusick }
374*6685Smckusick 
375*6685Smckusick LOCAL VOID	prsym(sym)
376*6685Smckusick {
377*6685Smckusick 	IF sym&SYMFLG
378*6685Smckusick 	THEN	REG SYSPTR	sp=reserved;
379*6685Smckusick 		WHILE sp->sysval
380*6685Smckusick 			ANDF sp->sysval!=sym
381*6685Smckusick 		DO sp++ OD
382*6685Smckusick 		prs(sp->sysnam);
383*6685Smckusick 	ELIF sym==EOFSYM
384*6685Smckusick 	THEN	prs(endoffile);
385*6685Smckusick 	ELSE	IF sym&SYMREP THEN prc(sym) FI
386*6685Smckusick 		IF sym==NL
387*6685Smckusick 		THEN	prs("newline");
388*6685Smckusick 		ELSE	prc(sym);
389*6685Smckusick 		FI
390*6685Smckusick 	FI
391*6685Smckusick }
392*6685Smckusick 
393*6685Smckusick LOCAL VOID	synbad()
394*6685Smckusick {
395*6685Smckusick 	prp(); prs(synmsg);
396*6685Smckusick 	IF (flags&ttyflg)==0
397*6685Smckusick 	THEN	prs(atline); prn(standin->flin);
398*6685Smckusick 	FI
399*6685Smckusick 	prs(colon);
400*6685Smckusick 	prc(LQ);
401*6685Smckusick 	IF wdval
402*6685Smckusick 	THEN	prsym(wdval);
403*6685Smckusick 	ELSE	prs(wdarg->argval);
404*6685Smckusick 	FI
405*6685Smckusick 	prc(RQ); prs(unexpected);
406*6685Smckusick 	newline();
407*6685Smckusick 	exitsh(SYNBAD);
408*6685Smckusick }
409