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