|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley Software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char *sccsid = "@(#)sh.parse.c 5.3 (Berkeley) 5/13/86";
9: #endif
10:
11: #include "sh.h"
12:
13: /*
14: * C shell
15: */
16:
17: /*
18: * Perform aliasing on the word list lex
19: * Do a (very rudimentary) parse to separate into commands.
20: * If word 0 of a command has an alias, do it.
21: * Repeat a maximum of 20 times.
22: */
23: alias(lex)
24: register struct wordent *lex;
25: {
26: int aleft = 21;
27: jmp_buf osetexit;
28:
29: getexit(osetexit);
30: setexit();
31: if (haderr) {
32: resexit(osetexit);
33: reset();
34: }
35: if (--aleft == 0)
36: error("Alias loop");
37: asyntax(lex->next, lex);
38: resexit(osetexit);
39: }
40:
41: asyntax(p1, p2)
42: register struct wordent *p1, *p2;
43: {
44:
45: while (p1 != p2)
46: if (any(p1->word[0], ";&\n"))
47: p1 = p1->next;
48: else {
49: asyn0(p1, p2);
50: return;
51: }
52: }
53:
54: asyn0(p1, p2)
55: struct wordent *p1;
56: register struct wordent *p2;
57: {
58: register struct wordent *p;
59: register int l = 0;
60:
61: for (p = p1; p != p2; p = p->next)
62: switch (p->word[0]) {
63:
64: case '(':
65: l++;
66: continue;
67:
68: case ')':
69: l--;
70: if (l < 0)
71: error("Too many )'s");
72: continue;
73:
74: case '>':
75: if (p->next != p2 && eq(p->next->word, "&"))
76: p = p->next;
77: continue;
78:
79: case '&':
80: case '|':
81: case ';':
82: case '\n':
83: if (l != 0)
84: continue;
85: asyn3(p1, p);
86: asyntax(p->next, p2);
87: return;
88: }
89: if (l == 0)
90: asyn3(p1, p2);
91: }
92:
93: asyn3(p1, p2)
94: struct wordent *p1;
95: register struct wordent *p2;
96: {
97: register struct varent *ap;
98: struct wordent alout;
99: register bool redid;
100:
101: if (p1 == p2)
102: return;
103: if (p1->word[0] == '(') {
104: for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
105: if (p2 == p1)
106: return;
107: if (p2 == p1->next)
108: return;
109: asyn0(p1->next, p2);
110: return;
111: }
112: ap = adrof1(p1->word, &aliases);
113: if (ap == 0)
114: return;
115: alhistp = p1->prev;
116: alhistt = p2;
117: alvec = ap->vec;
118: redid = lex(&alout);
119: alhistp = alhistt = 0;
120: alvec = 0;
121: if (err) {
122: freelex(&alout);
123: error(err);
124: }
125: if (p1->word[0] && eq(p1->word, alout.next->word)) {
126: char *cp = alout.next->word;
127:
128: alout.next->word = strspl("\200", cp);
129: XFREE(cp)
130: }
131: p1 = freenod(p1, redid ? p2 : p1->next);
132: if (alout.next != &alout) {
133: p1->next->prev = alout.prev->prev;
134: alout.prev->prev->next = p1->next;
135: alout.next->prev = p1;
136: p1->next = alout.next;
137: XFREE(alout.prev->word)
138: XFREE((char *)alout.prev)
139: }
140: reset(); /* throw! */
141: }
142:
143: struct wordent *
144: freenod(p1, p2)
145: register struct wordent *p1, *p2;
146: {
147: register struct wordent *retp = p1->prev;
148:
149: while (p1 != p2) {
150: XFREE(p1->word)
151: p1 = p1->next;
152: XFREE((char *)p1->prev)
153: }
154: retp->next = p2;
155: p2->prev = retp;
156: return (retp);
157: }
158:
159: #define PHERE 1
160: #define PIN 2
161: #define POUT 4
162: #define PDIAG 8
163:
164: /*
165: * syntax
166: * empty
167: * syn0
168: */
169: struct command *
170: syntax(p1, p2, flags)
171: register struct wordent *p1, *p2;
172: int flags;
173: {
174:
175: while (p1 != p2)
176: if (any(p1->word[0], ";&\n"))
177: p1 = p1->next;
178: else
179: return (syn0(p1, p2, flags));
180: return (0);
181: }
182:
183: /*
184: * syn0
185: * syn1
186: * syn1 & syntax
187: */
188: struct command *
189: syn0(p1, p2, flags)
190: struct wordent *p1, *p2;
191: int flags;
192: {
193: register struct wordent *p;
194: register struct command *t, *t1;
195: int l;
196:
197: l = 0;
198: for (p = p1; p != p2; p = p->next)
199: switch (p->word[0]) {
200:
201: case '(':
202: l++;
203: continue;
204:
205: case ')':
206: l--;
207: if (l < 0)
208: seterr("Too many )'s");
209: continue;
210:
211: case '|':
212: if (p->word[1] == '|')
213: continue;
214: /* fall into ... */
215:
216: case '>':
217: if (p->next != p2 && eq(p->next->word, "&"))
218: p = p->next;
219: continue;
220:
221: case '&':
222: if (l != 0)
223: break;
224: if (p->word[1] == '&')
225: continue;
226: t1 = syn1(p1, p, flags);
227: if (t1->t_dtyp == TLST ||
228: t1->t_dtyp == TAND ||
229: t1->t_dtyp == TOR) {
230: t = (struct command *) calloc(1, sizeof (*t));
231: t->t_dtyp = TPAR;
232: t->t_dflg = FAND|FINT;
233: t->t_dspr = t1;
234: t1 = t;
235: } else
236: t1->t_dflg |= FAND|FINT;
237: t = (struct command *) calloc(1, sizeof (*t));
238: t->t_dtyp = TLST;
239: t->t_dflg = 0;
240: t->t_dcar = t1;
241: t->t_dcdr = syntax(p, p2, flags);
242: return(t);
243: }
244: if (l == 0)
245: return (syn1(p1, p2, flags));
246: seterr("Too many ('s");
247: return (0);
248: }
249:
250: /*
251: * syn1
252: * syn1a
253: * syn1a ; syntax
254: */
255: struct command *
256: syn1(p1, p2, flags)
257: struct wordent *p1, *p2;
258: int flags;
259: {
260: register struct wordent *p;
261: register struct command *t;
262: int l;
263:
264: l = 0;
265: for (p = p1; p != p2; p = p->next)
266: switch (p->word[0]) {
267:
268: case '(':
269: l++;
270: continue;
271:
272: case ')':
273: l--;
274: continue;
275:
276: case ';':
277: case '\n':
278: if (l != 0)
279: break;
280: t = (struct command *) calloc(1, sizeof (*t));
281: t->t_dtyp = TLST;
282: t->t_dcar = syn1a(p1, p, flags);
283: t->t_dcdr = syntax(p->next, p2, flags);
284: if (t->t_dcdr == 0)
285: t->t_dcdr = t->t_dcar, t->t_dcar = 0;
286: return (t);
287: }
288: return (syn1a(p1, p2, flags));
289: }
290:
291: /*
292: * syn1a
293: * syn1b
294: * syn1b || syn1a
295: */
296: struct command *
297: syn1a(p1, p2, flags)
298: struct wordent *p1, *p2;
299: int flags;
300: {
301: register struct wordent *p;
302: register struct command *t;
303: register int l = 0;
304:
305: for (p = p1; p != p2; p = p->next)
306: switch (p->word[0]) {
307:
308: case '(':
309: l++;
310: continue;
311:
312: case ')':
313: l--;
314: continue;
315:
316: case '|':
317: if (p->word[1] != '|')
318: continue;
319: if (l == 0) {
320: t = (struct command *) calloc(1, sizeof (*t));
321: t->t_dtyp = TOR;
322: t->t_dcar = syn1b(p1, p, flags);
323: t->t_dcdr = syn1a(p->next, p2, flags);
324: t->t_dflg = 0;
325: return (t);
326: }
327: continue;
328: }
329: return (syn1b(p1, p2, flags));
330: }
331:
332: /*
333: * syn1b
334: * syn2
335: * syn2 && syn1b
336: */
337: struct command *
338: syn1b(p1, p2, flags)
339: struct wordent *p1, *p2;
340: int flags;
341: {
342: register struct wordent *p;
343: register struct command *t;
344: register int l = 0;
345:
346: l = 0;
347: for (p = p1; p != p2; p = p->next)
348: switch (p->word[0]) {
349:
350: case '(':
351: l++;
352: continue;
353:
354: case ')':
355: l--;
356: continue;
357:
358: case '&':
359: if (p->word[1] == '&' && l == 0) {
360: t = (struct command *) calloc(1, sizeof (*t));
361: t->t_dtyp = TAND;
362: t->t_dcar = syn2(p1, p, flags);
363: t->t_dcdr = syn1b(p->next, p2, flags);
364: t->t_dflg = 0;
365: return (t);
366: }
367: continue;
368: }
369: return (syn2(p1, p2, flags));
370: }
371:
372: /*
373: * syn2
374: * syn3
375: * syn3 | syn2
376: * syn3 |& syn2
377: */
378: struct command *
379: syn2(p1, p2, flags)
380: struct wordent *p1, *p2;
381: int flags;
382: {
383: register struct wordent *p, *pn;
384: register struct command *t;
385: register int l = 0;
386: int f;
387:
388: for (p = p1; p != p2; p = p->next)
389: switch (p->word[0]) {
390:
391: case '(':
392: l++;
393: continue;
394:
395: case ')':
396: l--;
397: continue;
398:
399: case '|':
400: if (l != 0)
401: continue;
402: t = (struct command *) calloc(1, sizeof (*t));
403: f = flags | POUT;
404: pn = p->next;
405: if (pn != p2 && pn->word[0] == '&') {
406: f |= PDIAG;
407: t->t_dflg |= FDIAG;
408: }
409: t->t_dtyp = TFIL;
410: t->t_dcar = syn3(p1, p, f);
411: if (pn != p2 && pn->word[0] == '&')
412: p = pn;
413: t->t_dcdr = syn2(p->next, p2, flags | PIN);
414: return (t);
415: }
416: return (syn3(p1, p2, flags));
417: }
418:
419: char *RELPAR = "<>()";
420:
421: /*
422: * syn3
423: * ( syn0 ) [ < in ] [ > out ]
424: * word word* [ < in ] [ > out ]
425: * KEYWORD ( word* ) word* [ < in ] [ > out ]
426: *
427: * KEYWORD = (@ exit foreach if set switch test while)
428: */
429: struct command *
430: syn3(p1, p2, flags)
431: struct wordent *p1, *p2;
432: int flags;
433: {
434: register struct wordent *p;
435: struct wordent *lp, *rp;
436: register struct command *t;
437: register int l;
438: char **av;
439: int n, c;
440: bool specp = 0;
441:
442: if (p1 != p2) {
443: p = p1;
444: again:
445: switch (srchx(p->word)) {
446:
447: case ZELSE:
448: p = p->next;
449: if (p != p2)
450: goto again;
451: break;
452:
453: case ZEXIT:
454: case ZFOREACH:
455: case ZIF:
456: case ZLET:
457: case ZSET:
458: case ZSWITCH:
459: case ZWHILE:
460: specp = 1;
461: break;
462: }
463: }
464: n = 0;
465: l = 0;
466: for (p = p1; p != p2; p = p->next)
467: switch (p->word[0]) {
468:
469: case '(':
470: if (specp)
471: n++;
472: l++;
473: continue;
474:
475: case ')':
476: if (specp)
477: n++;
478: l--;
479: continue;
480:
481: case '>':
482: case '<':
483: if (l != 0) {
484: if (specp)
485: n++;
486: continue;
487: }
488: if (p->next == p2)
489: continue;
490: if (any(p->next->word[0], RELPAR))
491: continue;
492: n--;
493: continue;
494:
495: default:
496: if (!specp && l != 0)
497: continue;
498: n++;
499: continue;
500: }
501: if (n < 0)
502: n = 0;
503: t = (struct command *) calloc(1, sizeof (*t));
504: av = (char **) calloc((unsigned) (n + 1), sizeof (char **));
505: t->t_dcom = av;
506: n = 0;
507: if (p2->word[0] == ')')
508: t->t_dflg = FPAR;
509: lp = 0;
510: rp = 0;
511: l = 0;
512: for (p = p1; p != p2; p = p->next) {
513: c = p->word[0];
514: switch (c) {
515:
516: case '(':
517: if (l == 0) {
518: if (lp != 0 && !specp)
519: seterr("Badly placed (");
520: lp = p->next;
521: }
522: l++;
523: goto savep;
524:
525: case ')':
526: l--;
527: if (l == 0)
528: rp = p;
529: goto savep;
530:
531: case '>':
532: if (l != 0)
533: goto savep;
534: if (p->word[1] == '>')
535: t->t_dflg |= FCAT;
536: if (p->next != p2 && eq(p->next->word, "&")) {
537: t->t_dflg |= FDIAG, p = p->next;
538: if (flags & (POUT|PDIAG))
539: goto badout;
540: }
541: if (p->next != p2 && eq(p->next->word, "!"))
542: t->t_dflg |= FANY, p = p->next;
543: if (p->next == p2) {
544: missfile:
545: seterr("Missing name for redirect");
546: continue;
547: }
548: p = p->next;
549: if (any(p->word[0], RELPAR))
550: goto missfile;
551: if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit)
552: badout:
553: seterr("Ambiguous output redirect");
554: else
555: t->t_drit = savestr(p->word);
556: continue;
557:
558: case '<':
559: if (l != 0)
560: goto savep;
561: if (p->word[1] == '<')
562: t->t_dflg |= FHERE;
563: if (p->next == p2)
564: goto missfile;
565: p = p->next;
566: if (any(p->word[0], RELPAR))
567: goto missfile;
568: if ((flags & PHERE) && (t->t_dflg & FHERE))
569: seterr("Can't << within ()'s");
570: else if ((flags & PIN) || t->t_dlef)
571: seterr("Ambiguous input redirect");
572: else
573: t->t_dlef = savestr(p->word);
574: continue;
575:
576: savep:
577: if (!specp)
578: continue;
579: default:
580: if (l != 0 && !specp)
581: continue;
582: if (err == 0)
583: av[n] = savestr(p->word);
584: n++;
585: continue;
586: }
587: }
588: if (lp != 0 && !specp) {
589: if (n != 0)
590: seterr("Badly placed ()'s");
591: t->t_dtyp = TPAR;
592: t->t_dspr = syn0(lp, rp, PHERE);
593: } else {
594: if (n == 0)
595: seterr("Invalid null command");
596: t->t_dtyp = TCOM;
597: }
598: return (t);
599: }
600:
601: freesyn(t)
602: register struct command *t;
603: {
604: register char **v;
605:
606: if (t == 0)
607: return;
608: switch (t->t_dtyp) {
609:
610: case TCOM:
611: for (v = t->t_dcom; *v; v++)
612: XFREE(*v)
613: XFREE((char *)t->t_dcom)
614: goto lr;
615:
616: case TPAR:
617: freesyn(t->t_dspr);
618: /* fall into ... */
619:
620: lr:
621: XFREE(t->t_dlef)
622: XFREE(t->t_drit)
623: break;
624:
625: case TAND:
626: case TOR:
627: case TFIL:
628: case TLST:
629: freesyn(t->t_dcar), freesyn(t->t_dcdr);
630: break;
631: }
632: XFREE((char *)t)
633: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.