Commit | Line | Data |
---|---|---|
862515b8 TL |
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 | ||
13 | PROC IOPTR inout(); | |
14 | PROC VOID chkword(); | |
15 | PROC VOID chksym(); | |
16 | PROC TREPTR term(); | |
17 | PROC TREPTR makelist(); | |
18 | PROC TREPTR list(); | |
19 | PROC REGPTR syncase(); | |
20 | PROC TREPTR item(); | |
21 | PROC VOID skipnl(); | |
22 | PROC VOID prsym(); | |
23 | PROC VOID synbad(); | |
24 | ||
25 | ||
26 | /* ======== command line decoding ========*/ | |
27 | ||
28 | ||
29 | ||
30 | ||
31 | TREPTR 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 | ||
42 | LOCAL 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 | ||
65 | TREPTR 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 | ||
116 | LOCAL 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 | ||
134 | LOCAL 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 | ||
150 | LOCAL 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 | ||
189 | LOCAL 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 | ||
308 | LOCAL VOID skipnl() | |
309 | { | |
310 | WHILE (reserv++, word()==NL) DO chkpr(NL) OD | |
311 | return(wdval); | |
312 | } | |
313 | ||
314 | LOCAL 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 | ||
358 | LOCAL VOID chkword() | |
359 | { | |
360 | IF word() | |
361 | THEN synbad(); | |
362 | FI | |
363 | } | |
364 | ||
365 | LOCAL VOID chksym(sym) | |
366 | { | |
367 | REG INT x = sym&wdval; | |
368 | IF ((x&SYMFLG) ? x : sym) != wdval | |
369 | THEN synbad(); | |
370 | FI | |
371 | } | |
372 | ||
373 | LOCAL 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 | ||
391 | LOCAL 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 | } |