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