|
|
1.1 root 1: /*
2: * shell parser (C version)
3: */
4:
5: static char *RCSid = "$Header: syn.c,v 3.1 88/11/03 09:17:23 egisin Exp $";
6:
7: #include <stddef.h>
8: #include <stdlib.h>
9: #include <stdio.h>
10: #include <string.h>
11: #include <errno.h>
12: #include <setjmp.h>
13: #include "sh.h"
14: #include "lex.h"
15: #include "tree.h"
16: #include "table.h"
17: #include "expand.h"
18:
19: static void zzerr();
20: static struct op *block(), *newtp();
21: static struct op *pipeline(), *andor(), *command();
22: static struct op *nested(), *c_list();
23: static struct op *dogroup(), *thenpart(), *casepart(), *caselist();
24: static struct op *elsepart();
25: static char **wordlist();
26: static void musthave();
27: static struct ioword *synio(), *io();
28:
29: static struct op *outtree; /* yyparse output */
30:
31: static int reject; /* token(cf) gets symbol again */
32: static int symbol; /* yylex value */
33:
34: #define REJECT (reject = 1)
35: #define ACCEPT (reject = 0)
36: #define token(cf) \
37: ((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf)))
38: #define tpeek(cf) \
39: ((reject) ? (symbol) : (REJECT, symbol = yylex(cf)))
40:
41: int
42: yyparse()
43: {
44: ACCEPT;
45: yynerrs = 0;
46: if ((tpeek(KEYWORD|ALIAS)) == 0) { /* EOF */
47: outtree = newtp(TEOF);
48: return 0;
49: }
50: outtree = c_list();
51: musthave('\n', 0);
52: return (yynerrs != 0);
53: }
54:
55: static struct op *
56: pipeline(cf)
57: int cf;
58: {
59: register struct op *t, *p, *tl = NULL;
60: register int c;
61:
62: t = command(cf);
63: if (t != NULL) {
64: while ((c = token(0)) == '|') {
65: if ((p = command(CONTIN)) == NULL)
66: SYNTAXERR;
67: if (tl == NULL)
68: t = tl = block(TPIPE, t, p, NOWORDS);
69: else
70: tl = tl->right = block(TPIPE, tl->right, p, NOWORDS);
71: /*t = block(TPIPE, t, p, NOWORDS);*/
72: }
73: REJECT;
74: }
75: return (t);
76: }
77:
78: static struct op *
79: andor()
80: {
81: register struct op *t, *p;
82: register int c;
83:
84: t = pipeline(0);
85: if (t != NULL) {
86: while ((c = token(0)) == LOGAND || c == LOGOR) {
87: if ((p = pipeline(CONTIN)) == NULL)
88: SYNTAXERR;
89: t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS);
90: }
91: REJECT;
92: }
93: return (t);
94: }
95:
96: static struct op *
97: c_list()
98: {
99: register struct op *t, *p, *tl = NULL;
100: register int c;
101:
102: t = andor();
103: if (t != NULL) {
104: while ((c = token(0)) == ';' || c == '&' ||
105: multiline && c == '\n') {
106: if (c == '&')
107: t = block(TASYNC, t, NOBLOCK, NOWORDS);
108: if ((p = andor()) == NULL)
109: return (t);
110: if (tl == NULL)
111: t = tl = block(TLIST, t, p, NOWORDS);
112: else
113: tl = tl->right = block(TLIST, tl->right, p, NOWORDS);
114: }
115: REJECT;
116: }
117: return (t);
118: }
119:
120: static struct ioword *
121: synio(cf)
122: int cf;
123: {
124: register struct ioword *iop;
125: register int i;
126:
127: if (tpeek(cf) != REDIR)
128: return NULL;
129: ACCEPT;
130: i = yylval.i; /* IO* flags */
131: musthave(LWORD, 0);
132: iop = io(iounit, i, yylval.cp);
133: if (i&IOHERE) {
134: if (*ident != 0) /* unquoted */
135: iop->flag |= IOXHERE;
136: if (herep >= &heres[HERES])
137: errorf("too many <<'s\n");
138: *herep++ = iop;
139: }
140: return iop;
141: }
142:
143: static void
144: musthave(c, cf)
145: int c, cf;
146: {
147: if ((token(cf)) != c)
148: SYNTAXERR;
149: }
150:
151: static struct op *
152: nested(type, mark)
153: int type, mark;
154: {
155: register struct op *t;
156:
157: multiline++;
158: t = c_list();
159: musthave(mark, KEYWORD);
160: multiline--;
161: return (block(type, t, NOBLOCK, NOWORDS));
162: }
163:
164: static struct op *
165: command(cf)
166: int cf;
167: {
168: register struct op *t;
169: register int c, iopn = 0;
170: struct ioword *iop, **iops;
171: XPtrV args, vars;
172:
173: iops = (struct ioword **) alloc(sizeofN(struct ioword *, NUFILE+1), ATEMP);
174: XPinit(args, 16);
175: XPinit(vars, 16);
176:
177: if (multiline)
178: cf = CONTIN;
179: cf |= KEYWORD|ALIAS;
180:
181: while ((iop = synio(cf)) != NULL) {
182: if (iopn >= NUFILE)
183: yyerror("too many redirections");
184: iops[iopn++] = iop;
185: cf &=~ CONTIN;
186: }
187:
188: switch (c = token(cf)) {
189: case 0:
190: yyerror("unexpected EOF");
191: return NULL;
192:
193: default:
194: REJECT;
195: if (iopn == 0)
196: return NULL; /* empty line */
197: t = newtp(TCOM);
198: break;
199:
200: case LWORD:
201: REJECT;
202: t = newtp(TCOM);
203: while (1)
204: switch (tpeek(0)) {
205: case REDIR:
206: if (iopn >= NUFILE)
207: yyerror("too many redirections");
208: iops[iopn++] = synio(0);
209: break;
210:
211: case LWORD:
212: ACCEPT;
213: if ((XPsize(args) == 0 || flag[FKEYWORD])
214: && strchr(ident+1, '='))
215: {XPput(vars, yylval.cp);}
216: else
217: {XPput(args, yylval.cp);}
218: break;
219:
220: case MPAREN:
221: ACCEPT;
222: if (XPsize(args) != 1)
223: SYNTAXERR;
224: if (*ident == 0)
225: yyerror("invalid function name\n");
226: t = newtp(TFUNCT);
227: t->str = strsave(ident, ATEMP);
228: musthave('{', CONTIN|KEYWORD);
229: t->left = nested(TBRACE, '}');
230: return t;
231:
232: default:
233: goto Leave;
234: }
235: Leave:
236: break;
237:
238: case '(':
239: t = nested(TPAREN, ')');
240: break;
241:
242: case '{':
243: t = nested(TBRACE, '}');
244: break;
245:
246: case FOR:
247: t = newtp(TFOR);
248: musthave(LWORD, 0);
249: t->str = strsave(ident, ATEMP);
250: multiline++;
251: t->vars = wordlist();
252: t->left = dogroup(0);
253: multiline--;
254: break;
255:
256: case WHILE:
257: case UNTIL:
258: multiline++;
259: t = newtp((c == WHILE) ? TWHILE: TUNTIL);
260: t->left = c_list();
261: t->right = dogroup(1);
262: multiline--;
263: break;
264:
265: case CASE:
266: t = newtp(TCASE);
267: musthave(LWORD, 0);
268: t->str = yylval.cp;
269: multiline++;
270: musthave(IN, KEYWORD|CONTIN);
271: t->left = caselist();
272: musthave(ESAC, KEYWORD);
273: multiline--;
274: break;
275:
276: case IF:
277: multiline++;
278: t = newtp(TIF);
279: t->left = c_list();
280: t->right = thenpart();
281: musthave(FI, KEYWORD);
282: multiline--;
283: break;
284:
285: case TIME:
286: t = pipeline(CONTIN);
287: t = block(TTIME, t, NOBLOCK, NOWORDS);
288: break;
289:
290: case FUNCTION:
291: t = newtp(TFUNCT);
292: musthave(LWORD, 0);
293: t->str = strsave(ident, ATEMP);
294: musthave('{', CONTIN|KEYWORD);
295: t->left = nested(TBRACE, '}');
296: break;
297: }
298:
299: while ((iop = synio(0)) != NULL) {
300: if (iopn >= NUFILE)
301: yyerror("too many redirections");
302: iops[iopn++] = iop;
303: }
304:
305: if (iopn == 0) {
306: afree((Void*) iops, ATEMP);
307: t->ioact = NULL;
308: } else {
309: iops[iopn++] = NULL;
310: aresize((Void*) iops, sizeofN(struct ioword *, iopn), ATEMP);
311: t->ioact = iops;
312: }
313:
314: if (t->type == TCOM) {
315: XPput(args, NULL);
316: t->args = (char **) XPclose(args);
317: XPput(vars, NULL);
318: t->vars = (char **) XPclose(vars);
319: } else {
320: XPfree(args);
321: XPfree(vars);
322: }
323:
324: return t;
325: }
326:
327: static struct op *
328: dogroup(onlydone)
329: int onlydone;
330: {
331: register int c;
332: register struct op *list;
333:
334: c = token(CONTIN|KEYWORD);
335: if (c == DONE && onlydone)
336: return NULL;
337: if (c != DO)
338: SYNTAXERR;
339: list = c_list();
340: musthave(DONE, KEYWORD);
341: return list;
342: }
343:
344: static struct op *
345: thenpart()
346: {
347: register int c;
348: register struct op *t;
349:
350: if ((c = token(0)) != THEN) {
351: REJECT;
352: return NULL;
353: }
354: t = newtp(0);
355: t->left = c_list();
356: if (t->left == NULL)
357: SYNTAXERR;
358: t->right = elsepart();
359: return (t);
360: }
361:
362: static struct op *
363: elsepart()
364: {
365: register int c;
366: register struct op *t;
367:
368: switch (c = token(0)) {
369: case ELSE:
370: if ((t = c_list()) == NULL)
371: SYNTAXERR;
372: return (t);
373:
374: case ELIF:
375: t = newtp(TELIF);
376: t->left = c_list();
377: t->right = thenpart();
378: return (t);
379:
380: default:
381: REJECT;
382: return NULL;
383: }
384: }
385:
386: static struct op *
387: caselist()
388: {
389: register struct op *t, *tl;
390:
391: t = tl = NULL;
392: while ((tpeek(CONTIN|KEYWORD)) != ESAC) {
393: struct op *tc = casepart();
394: if (tl == NULL)
395: t = tl = tc, tl->right = NULL;
396: else
397: tl->right = tc, tl = tc;
398: }
399: return (t);
400: }
401:
402: static struct op *
403: casepart()
404: {
405: register struct op *t;
406: register int c, cf;
407: XPtrV ptns;
408:
409: XPinit(ptns, 16);
410: t = newtp(TPAT);
411: cf = CONTIN|KEYWORD;
412: c = token(cf);
413: if (c != '(')
414: REJECT;
415: else
416: cf = 0;
417: do {
418: musthave(LWORD, cf);
419: XPput(ptns, yylval.cp);
420: cf = 0;
421: } while ((c = token(0)) == '|');
422: REJECT;
423: XPput(ptns, NULL);
424: t->vars = (char **) XPclose(ptns);
425: musthave(')', 0);
426:
427: t->left = c_list();
428: if ((tpeek(CONTIN|KEYWORD)) != ESAC)
429: musthave(BREAK, CONTIN|KEYWORD);
430: return (t);
431: }
432:
433: static char **
434: wordlist()
435: {
436: register int c;
437: XPtrV args;
438:
439: XPinit(args, 16);
440: if ((c = token(CONTIN|KEYWORD)) != IN) {
441: REJECT;
442: return NULL;
443: }
444: while ((c = token(0)) == LWORD)
445: XPput(args, yylval.cp);
446: if (c != '\n' && c != ';')
447: SYNTAXERR;
448: if (XPsize(args) == 0) {
449: XPfree(args);
450: return NULL;
451: } else {
452: XPput(args, NULL);
453: return (char **) XPclose(args);
454: }
455: }
456:
457: /*
458: * supporting functions
459: */
460:
461: static struct op *
462: block(type, t1, t2, wp)
463: struct op *t1, *t2;
464: char **wp;
465: {
466: register struct op *t;
467:
468: t = newtp(type);
469: t->left = t1;
470: t->right = t2;
471: t->vars = wp;
472: return (t);
473: }
474:
475: Const struct res {
476: char *name;
477: int val;
478: } restab[] = {
479: "for", FOR,
480: "case", CASE,
481: "esac", ESAC,
482: "while", WHILE,
483: "do", DO,
484: "done", DONE,
485: "if", IF,
486: "in", IN,
487: "then", THEN,
488: "else", ELSE,
489: "elif", ELIF,
490: "until", UNTIL,
491: "fi", FI,
492: "function", FUNCTION,
493: "time", TIME,
494: "{", '{',
495: "}", '}',
496: 0
497: };
498:
499: keywords()
500: {
501: register struct res Const *rp;
502: register struct tbl *p;
503:
504: for (rp = restab; rp->name; rp++) {
505: p = tenter(&lexicals, rp->name, hash(rp->name));
506: p->flag |= DEFINED|ISSET;
507: p->type = CKEYWD;
508: p->val.i = rp->val;
509: }
510: }
511:
512: static struct op *
513: newtp(type)
514: int type;
515: {
516: register struct op *t;
517:
518: t = (struct op *) alloc(sizeof(*t), ATEMP);
519: t->type = type;
520: t->args = t->vars = NULL;
521: t->ioact = NULL;
522: t->left = t->right = NULL;
523: t->str = NULL;
524: return (t);
525: }
526:
527: static struct ioword *
528: io(u, f, cp)
529: int u, f; /* unit, flags */
530: char *cp;
531: {
532: register struct ioword *iop;
533:
534: iop = (struct ioword *) alloc(sizeof(*iop), ATEMP);
535: iop->unit = !(u < 0) ? u : (f&(IOREAD|IOHERE)) ? 0 : 1;
536: iop->flag = f;
537: iop->name = cp;
538: return iop;
539: }
540:
541: static void
542: zzerr()
543: {
544: yyerror("syntax error");
545: }
546:
547: struct op *
548: compile(s)
549: Source *s;
550: {
551: yynerrs = 0;
552: multiline = 0;
553: herep = heres;
554: source = s;
555: if (yyparse())
556: unwind();
557: if (s->type == STTY || s->type == SFILE)
558: s->str = null; /* line is not preserved */
559: return outtree;
560: }
561:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.