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