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