|
|
1.1 root 1: /* @(#)cmd.c 1.5 */
2: /*
3: * UNIX shell
4: *
5: * Bell Telephone Laboratories
6: *
7: */
8:
9: #include "defs.h"
10: #include "sym.h"
11:
12: static struct ionod * inout();
13: static int chkword();
14: static int chksym();
15: static struct trenod * term();
16: static struct trenod * makelist();
17: static struct trenod * list();
18: static struct regnod * syncase();
19: static struct trenod * item();
20: static int skipnl();
21: static int prsym();
22: static int synbad();
23:
24:
25: /* ======== storage allocation for functions ======== */
26:
27: char *
28: getstor(asize)
29: int asize;
30: {
31: if (fndef)
32: return(shalloc(asize));
33: else
34: return(getstak(asize));
35: }
36:
37:
38: /* ======== command line decoding ========*/
39:
40:
41:
42:
43: struct trenod *
44: makefork(flgs, i)
45: int flgs;
46: struct trenod *i;
47: {
48: register struct forknod *t;
49:
50: t = (struct forknod *)getstor(sizeof(struct forknod));
51: t->forktyp = flgs|TFORK;
52: t->forktre = i;
53: t->forkio = 0;
54: return((struct trenod *)t);
55: }
56:
57: static struct trenod *
58: makelist(type, i, r)
59: int type;
60: struct trenod *i, *r;
61: {
62: register struct lstnod *t;
63:
64: if (i == 0 || r == 0)
65: synbad();
66: else
67: {
68: t = (struct lstnod *)getstor(sizeof(struct lstnod));
69: t->lsttyp = type;
70: t->lstlef = i;
71: t->lstrit = r;
72: }
73: return((struct trenod *)t);
74: }
75:
76: /*
77: * cmd
78: * empty
79: * list
80: * list & [ cmd ]
81: * list [ ; cmd ]
82: */
83: struct trenod *
84: cmd(sym, flg)
85: register int sym;
86: int flg;
87: {
88: register struct trenod *i, *e;
89:
90: i = list(flg);
91: if (wdval == NL)
92: {
93: if (flg & NLFLG)
94: {
95: wdval = ';';
96: chkpr();
97: }
98: }
99: else if (i == 0 && (flg & MTFLG) == 0)
100: synbad();
101:
102: switch (wdval)
103: {
104: case '&':
105: if (i)
106: i = makefork(FINT | FPRS | FAMP, i);
107: else
108: synbad();
109:
110: case ';':
111: if (e = cmd(sym, flg | MTFLG))
112: i = makelist(TLST, i, e);
113: else if (i==0 && (flg & MTFLG) == 0)
114: synbad();
115: break;
116:
117: case EOFSYM:
118: if (sym == NL)
119: break;
120:
121: default:
122: if (sym)
123: chksym(sym);
124: }
125: return(i);
126: }
127:
128: /*
129: * list
130: * term
131: * list && term
132: * list || term
133: */
134: static struct trenod *
135: list(flg)
136: {
137: register struct trenod *r;
138: register int b;
139:
140: r = term(flg);
141: while (r && ((b = (wdval == ANDFSYM)) || wdval == ORFSYM))
142: r = makelist((b ? TAND : TORF), r, term(NLFLG));
143: return(r);
144: }
145:
146: /*
147: * term
148: * item
149: * item | term
150: */
151: static struct trenod *
152: term(flg)
153: {
154: register struct trenod *t;
155:
156: reserv++;
157: if (flg & NLFLG)
158: skipnl();
159: else
160: word();
161: if ((t = item(TRUE)) && wdval == '|')
162: {
163: struct trenod *left;
164: struct trenod *right;
165:
166: left = makefork(FPOU, t);
167: right = makefork(FPIN | FPCL, term(NLFLG));
168: return(makefork(0, makelist(TFIL, left, right)));
169: }
170: else
171: return(t);
172: }
173:
174: static struct regnod *
175: syncase(esym)
176: register int esym;
177: {
178: skipnl();
179: if (wdval == esym)
180: return(0);
181: else
182: {
183: register struct regnod *r = (struct regnod *)getstor(sizeof(struct regnod));
184: register struct argnod *argp;
185:
186: r->regptr = 0;
187: for (;;)
188: {
189: if (fndef)
190: {
191: argp= wdarg;
192: wdarg = (struct argnod *)shalloc(length(argp->argval) + BYTESPERWORD);
193: movstr(argp->argval, wdarg->argval);
194: }
195:
196: wdarg->argnxt = r->regptr;
197: r->regptr = wdarg;
198: if (wdval || (word() != ')' && wdval != '|'))
199: synbad();
200: if (wdval == '|')
201: word();
202: else
203: break;
204: }
205: r->regcom = cmd(0, NLFLG | MTFLG);
206: if (wdval == ECSYM)
207: r->regnxt = syncase(esym);
208: else
209: {
210: chksym(esym);
211: r->regnxt = 0;
212: }
213: return(r);
214: }
215: }
216:
217: /*
218: * item
219: *
220: * ( cmd ) [ < in ] [ > out ]
221: * word word* [ < in ] [ > out ]
222: * if ... then ... else ... fi
223: * for ... while ... do ... done
224: * case ... in ... esac
225: * begin ... end
226: */
227: static struct trenod *
228: item(flag)
229: BOOL flag;
230: {
231: register struct trenod *r;
232: register struct ionod *io;
233:
234: if (flag)
235: io = inout((struct ionod *)0);
236: else
237: io = 0;
238: switch (wdval)
239: {
240: case CASYM:
241: {
242: register struct swnod *t;
243:
244: t = (struct swnod *)getstor(sizeof(struct swnod));
245: r = (struct trenod *)t;
246:
247: chkword();
248: if (fndef)
249: t->swarg = make(wdarg->argval);
250: else
251: t->swarg = wdarg->argval;
252: skipnl();
253: chksym(INSYM);
254: t->swlst = syncase(ESSYM);
255: t->swtyp = TSW;
256: break;
257: }
258:
259: case IFSYM:
260: {
261: register int w;
262: register struct ifnod *t;
263:
264: t = (struct ifnod *)getstor(sizeof(struct ifnod));
265: r = (struct trenod *)t;
266:
267: t->iftyp = TIF;
268: t->iftre = cmd(THSYM, NLFLG);
269: t->thtre = cmd(ELSYM | FISYM | EFSYM, NLFLG);
270: t->eltre = ((w = wdval) == ELSYM ? cmd(FISYM, NLFLG) : (w == EFSYM ? (wdval = IFSYM, item(0)) : 0));
271: if (w == EFSYM)
272: return(r);
273: break;
274: }
275:
276: case FORSYM:
277: {
278: register struct fornod *t;
279:
280: t = (struct fornod *)getstor(sizeof(struct fornod));
281: r = (struct trenod *)t;
282:
283: t->fortyp = TFOR;
284: t->forlst = 0;
285: chkword();
286: if (fndef)
287: t->fornam = make(wdarg->argval);
288: else
289: t->fornam = wdarg->argval;
290: if (skipnl() == INSYM)
291: {
292: chkword();
293:
294: t->forlst = (struct comnod *)item(0);
295:
296: if (wdval != NL && wdval != ';')
297: synbad();
298: if (wdval == NL)
299: chkpr();
300: skipnl();
301: }
302: else if (wdval == ';')
303: reserv++, word(); /* eat the ';' */
304: chksym(DOSYM);
305: t->fortre = cmd(ODSYM, NLFLG);
306: break;
307: }
308:
309: case WHSYM:
310: case UNSYM:
311: {
312: register struct whnod *t;
313:
314: t = (struct whnod *)getstor(sizeof(struct whnod));
315: r = (struct trenod *)t;
316:
317: t->whtyp = (wdval == WHSYM ? TWH : TUN);
318: t->whtre = cmd(DOSYM, NLFLG);
319: t->dotre = cmd(ODSYM, NLFLG);
320: break;
321: }
322:
323: case '{':
324: r = cmd('}', NLFLG);
325: break;
326:
327: case '(':
328: {
329: register struct parnod *p;
330:
331: p = (struct parnod *)getstor(sizeof(struct parnod));
332: p->partre = cmd(')', NLFLG);
333: p->partyp = TPAR;
334: r = makefork(0, p);
335: break;
336: }
337:
338: default:
339: if (io == 0)
340: return(0);
341:
342: case 0:
343: {
344: register struct comnod *t;
345: register struct argnod *argp;
346: register struct argnod **argtail;
347: register struct argnod **argset = 0;
348: int keywd = 1;
349: char *com;
350:
351: if ((wdval != NL) && ((peekn = skipc()) == '('))
352: {
353: struct fndnod *f;
354: struct ionod *saveio;
355:
356: saveio = iotemp;
357: peekn = 0;
358: if (skipc() != ')')
359: synbad();
360:
361: f = (struct fndnod *)getstor(sizeof(struct fndnod));
362: r = (struct trenod *)f;
363:
364: f->fndtyp = TFND;
365: if (fndef)
366: f->fndnam = make(wdarg->argval);
367: else
368: f->fndnam = wdarg->argval;
369: reserv++;
370: fndef++;
371: skipnl();
372: f->fndval = (struct trenod *)item(TRUE);
373: fndef--;
374:
375: if (iotemp != saveio)
376: {
377: struct ionod *ioptr = iotemp;
378:
379: while (ioptr->iolst != saveio)
380: ioptr = ioptr->iolst;
381:
382: ioptr->iolst = fiotemp;
383: fiotemp = iotemp;
384: iotemp = saveio;
385: }
386: return(r);
387: }
388: else
389: {
390: t = (struct comnod *)getstor(sizeof(struct comnod));
391: r = (struct trenod *)t;
392:
393: t->comio = io; /*initial io chain*/
394: argtail = &(t->comarg);
395:
396: while (wdval == 0)
397: {
398: if (fndef)
399: {
400: argp = wdarg;
401: wdarg = (struct argnod *)shalloc(length(argp->argval) + BYTESPERWORD);
402: movstr(argp->argval, wdarg->argval);
403: }
404:
405: argp = wdarg;
406: if (wdset && keywd)
407: {
408: argp->argnxt = (struct argnod *)argset;
409: argset = (struct argnod **)argp;
410: }
411: else
412: {
413: *argtail = argp;
414: argtail = &(argp->argnxt);
415: keywd = flags & keyflg;
416: }
417: word();
418: if (flag)
419: t->comio = inout(t->comio);
420: }
421:
422: t->comtyp = TCOM;
423: t->comset = (struct argnod *)argset;
424: *argtail = 0;
425:
426: return(r);
427: }
428: }
429:
430: }
431: reserv++;
432: word();
433: if (io = inout(io))
434: {
435: r = makefork(0,r);
436: r->treio = io;
437: }
438: return(r);
439: }
440:
441:
442: static int
443: skipnl()
444: {
445: while ((reserv++, word() == NL))
446: chkpr();
447: return(wdval);
448: }
449:
450: static struct ionod *
451: inout(lastio)
452: struct ionod *lastio;
453: {
454: register int iof;
455: register struct ionod *iop;
456: register char c;
457:
458: iof = wdnum;
459: switch (wdval)
460: {
461: case DOCSYM: /* << */
462: iof |= IODOC;
463: break;
464:
465: case APPSYM: /* >> */
466: case '>':
467: if (wdnum == 0)
468: iof |= 1;
469: iof |= IOPUT;
470: if (wdval == APPSYM)
471: {
472: iof |= IOAPP;
473: break;
474: }
475:
476: case '<':
477: if ((c = nextc(0)) == '&')
478: iof |= IOMOV;
479: else if (c == '>')
480: iof |= IORDW;
481: else
482: peekc = c | MARK;
483: break;
484:
485: default:
486: return(lastio);
487: }
488:
489: chkword();
490: iop = (struct ionod *)getstor(sizeof(struct ionod));
491:
492: if (fndef)
493: iop->ioname = make(wdarg->argval);
494: else
495: iop->ioname = wdarg->argval;
496:
497: iop->iolink = 0;
498: iop->iofile = iof;
499: if (iof & IODOC)
500: {
501: iop->iolst = iopend;
502: iopend = iop;
503: }
504: word();
505: iop->ionxt = inout(lastio);
506: return(iop);
507: }
508:
509: static int
510: chkword()
511: {
512: if (word())
513: synbad();
514: }
515:
516: static int
517: chksym(sym)
518: {
519: register int x = sym & wdval;
520:
521: if (((x & SYMFLG) ? x : sym) != wdval)
522: synbad();
523: }
524:
525: static int
526: prsym(sym)
527: {
528: if (sym & SYMFLG)
529: {
530: register struct sysnod *sp = reserved;
531:
532: while (sp->sysval && sp->sysval != sym)
533: sp++;
534: prs(sp->sysnam);
535: }
536: else if (sym == EOFSYM)
537: prs(endoffile);
538: else
539: {
540: if (sym & SYMREP)
541: prc(sym);
542: if (sym == NL)
543: prs("newline or ;");
544: else
545: prc(sym);
546: }
547: }
548:
549: static int
550: synbad()
551: {
552: prp();
553: prs(synmsg);
554: if ((flags & ttyflg) == 0)
555: {
556: prs(atline);
557: prn(standin->flin);
558: }
559: prs(colon);
560: prc(LQ);
561: if (wdval)
562: prsym(wdval);
563: else
564: prs_cntl(wdarg->argval);
565: prc(RQ);
566: prs(unexpected);
567: newline();
568: exitsh(SYNBAD);
569: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.