Commit | Line | Data |
---|---|---|
f6227721 SL |
1 | #ifndef lint |
2 | static 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 | ||
17 | PROC IOPTR inout(); | |
18 | PROC VOID chkword(); | |
19 | PROC VOID chksym(); | |
20 | PROC TREPTR term(); | |
21 | PROC TREPTR makelist(); | |
22 | PROC TREPTR list(); | |
23 | PROC REGPTR syncase(); | |
24 | PROC TREPTR item(); | |
25 | PROC VOID skipnl(); | |
26 | PROC VOID prsym(); | |
27 | PROC VOID synbad(); | |
28 | ||
29 | ||
30 | /* ======== command line decoding ========*/ | |
31 | ||
32 | ||
33 | ||
34 | ||
35 | TREPTR 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 | ||
46 | LOCAL 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 | ||
69 | TREPTR 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 | ||
120 | LOCAL 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 | ||
138 | LOCAL 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 | ||
154 | LOCAL 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 | ||
193 | LOCAL 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 | ||
312 | LOCAL VOID skipnl() | |
313 | { | |
314 | WHILE (reserv++, word()==NL) DO chkpr(NL) OD | |
315 | return(wdval); | |
316 | } | |
317 | ||
318 | LOCAL 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 | ||
362 | LOCAL VOID chkword() | |
363 | { | |
364 | IF word() | |
365 | THEN synbad(); | |
366 | FI | |
367 | } | |
368 | ||
369 | LOCAL VOID chksym(sym) | |
370 | { | |
371 | REG INT x = sym&wdval; | |
372 | IF ((x&SYMFLG) ? x : sym) != wdval | |
373 | THEN synbad(); | |
374 | FI | |
375 | } | |
376 | ||
377 | LOCAL 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 | ||
395 | LOCAL 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 | } |