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: }
Defined functions
cmd
defined in line
65; used 14 times
item
defined in line
189; used 4 times
list
defined in line
116; used 2 times
term
defined in line
134; used 4 times