1 #define Extern extern
2 #include <sys/types.h>
3 #include <signal.h>
4 #define _NSIG NSIG
5 #include <errno.h>
6 #include <setjmp.h>
7 #include "sh.h"
8
9 /* -------- csyn.c -------- */
10 /*
11 * shell: syntax (C version)
12 */
13
14 typedef union {
15 char *cp;
16 char **wp;
17 int i;
18 struct op *o;
19 } YYSTYPE;
20 #define WORD 256
21 #define LOGAND 257
22 #define LOGOR 258
23 #define BREAK 259
24 #define IF 260
25 #define THEN 261
26 #define ELSE 262
27 #define ELIF 263
28 #define FI 264
29 #define CASE 265
30 #define ESAC 266
31 #define FOR 267
32 #define WHILE 268
33 #define UNTIL 269
34 #define DO 270
35 #define DONE 271
36 #define IN 272
37 #define YYERRCODE 300
38
39 /* flags to yylex */
40 #define CONTIN 01 /* skip new lines to complete command */
41
42 /* #include "sh.h" */
43 #define SYNTAXERR zzerr()
44 static int startl;
45 static int peeksym;
46 static int nlseen;
47 static int iounit = IODEFAULT;
48
49 static YYSTYPE yylval;
50
51 _PROTOTYPE(static struct op *pipeline, (int cf ));
52 _PROTOTYPE(static struct op *andor, (void));
53 _PROTOTYPE(static struct op *c_list, (void));
54 _PROTOTYPE(static int synio, (int cf ));
55 _PROTOTYPE(static void musthave, (int c, int cf ));
56 _PROTOTYPE(static struct op *simple, (void));
57 _PROTOTYPE(static struct op *nested, (int type, int mark ));
58 _PROTOTYPE(static struct op *command, (int cf ));
59 _PROTOTYPE(static struct op *dogroup, (int onlydone ));
60 _PROTOTYPE(static struct op *thenpart, (void));
61 _PROTOTYPE(static struct op *elsepart, (void));
62 _PROTOTYPE(static struct op *caselist, (void));
63 _PROTOTYPE(static struct op *casepart, (void));
64 _PROTOTYPE(static char **pattern, (void));
65 _PROTOTYPE(static char **wordlist, (void));
66 _PROTOTYPE(static struct op *list, (struct op *t1, struct op *t2 ));
67 _PROTOTYPE(static struct op *block, (int type, struct op *t1, struct op *t2, char **wp ));
68 _PROTOTYPE(static struct op *newtp, (void));
69 _PROTOTYPE(static struct op *namelist, (struct op *t ));
70 _PROTOTYPE(static char **copyw, (void));
71 _PROTOTYPE(static void word, (char *cp ));
72 _PROTOTYPE(static struct ioword **copyio, (void));
73 _PROTOTYPE(static struct ioword *io, (int u, int f, char *cp ));
74 _PROTOTYPE(static void zzerr, (void));
75 _PROTOTYPE(void yyerror, (char *s ));
76 _PROTOTYPE(static int yylex, (int cf ));
77 _PROTOTYPE(int collect, (int c, int c1 ));
78 _PROTOTYPE(int dual, (int c ));
79 _PROTOTYPE(static void diag, (int ec ));
80 _PROTOTYPE(static char *tree, (unsigned size ));
81 _PROTOTYPE(void printf, (char *s ));
82
83 int
yyparse()84 yyparse()
85 {
86 startl = 1;
87 peeksym = 0;
88 yynerrs = 0;
89 outtree = c_list();
90 musthave('\n', 0);
91 return(yynerrs!=0);
92 }
93
94 static struct op *
pipeline(cf)95 pipeline(cf)
96 int cf;
97 {
98 register struct op *t, *p;
99 register int c;
100
101 t = command(cf);
102 if (t != NULL) {
103 while ((c = yylex(0)) == '|') {
104 if ((p = command(CONTIN)) == NULL)
105 SYNTAXERR;
106 if (t->type != TPAREN && t->type != TCOM) {
107 /* shell statement */
108 t = block(TPAREN, t, NOBLOCK, NOWORDS);
109 }
110 t = block(TPIPE, t, p, NOWORDS);
111 }
112 peeksym = c;
113 }
114 return(t);
115 }
116
117 static struct op *
andor()118 andor()
119 {
120 register struct op *t, *p;
121 register int c;
122
123 t = pipeline(0);
124 if (t != NULL) {
125 while ((c = yylex(0)) == LOGAND || c == LOGOR) {
126 if ((p = pipeline(CONTIN)) == NULL)
127 SYNTAXERR;
128 t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS);
129 }
130 peeksym = c;
131 }
132 return(t);
133 }
134
135 static struct op *
c_list()136 c_list()
137 {
138 register struct op *t, *p;
139 register int c;
140
141 t = andor();
142 if (t != NULL) {
143 if((peeksym = yylex(0)) == '&')
144 t = block(TASYNC, t, NOBLOCK, NOWORDS);
145 while ((c = yylex(0)) == ';' || c == '&' || (multiline && c == '\n')) {
146 if ((p = andor()) == NULL)
147 return(t);
148 if((peeksym = yylex(0)) == '&')
149 p = block(TASYNC, p, NOBLOCK, NOWORDS);
150 t = list(t, p);
151 }
152 peeksym = c;
153 }
154 return(t);
155 }
156
157
158 static int
synio(cf)159 synio(cf)
160 int cf;
161 {
162 register struct ioword *iop;
163 register int i;
164 register int c;
165
166 if ((c = yylex(cf)) != '<' && c != '>') {
167 peeksym = c;
168 return(0);
169 }
170 i = yylval.i;
171 musthave(WORD, 0);
172 iop = io(iounit, i, yylval.cp);
173 iounit = IODEFAULT;
174 if (i & IOHERE)
175 markhere(yylval.cp, iop);
176 return(1);
177 }
178
179 static void
musthave(c,cf)180 musthave(c, cf)
181 int c, cf;
182 {
183 if ((peeksym = yylex(cf)) != c)
184 SYNTAXERR;
185 peeksym = 0;
186 }
187
188 static struct op *
simple()189 simple()
190 {
191 register struct op *t;
192
193 t = NULL;
194 for (;;) {
195 switch (peeksym = yylex(0)) {
196 case '<':
197 case '>':
198 (void) synio(0);
199 break;
200
201 case WORD:
202 if (t == NULL) {
203 t = newtp();
204 t->type = TCOM;
205 }
206 peeksym = 0;
207 word(yylval.cp);
208 break;
209
210 default:
211 return(t);
212 }
213 }
214 }
215
216 static struct op *
nested(type,mark)217 nested(type, mark)
218 int type, mark;
219 {
220 register struct op *t;
221
222 multiline++;
223 t = c_list();
224 musthave(mark, 0);
225 multiline--;
226 return(block(type, t, NOBLOCK, NOWORDS));
227 }
228
229 static struct op *
command(cf)230 command(cf)
231 int cf;
232 {
233 register struct op *t;
234 struct wdblock *iosave;
235 register int c;
236
237 iosave = iolist;
238 iolist = NULL;
239 if (multiline)
240 cf |= CONTIN;
241 while (synio(cf))
242 cf = 0;
243 switch (c = yylex(cf)) {
244 default:
245 peeksym = c;
246 if ((t = simple()) == NULL) {
247 if (iolist == NULL)
248 return((struct op *)NULL);
249 t = newtp();
250 t->type = TCOM;
251 }
252 break;
253
254 case '(':
255 t = nested(TPAREN, ')');
256 break;
257
258 case '{':
259 t = nested(TBRACE, '}');
260 break;
261
262 case FOR:
263 t = newtp();
264 t->type = TFOR;
265 musthave(WORD, 0);
266 startl = 1;
267 t->str = yylval.cp;
268 multiline++;
269 t->words = wordlist();
270 if ((c = yylex(0)) != '\n' && c != ';')
271 peeksym = c;
272 t->left = dogroup(0);
273 multiline--;
274 break;
275
276 case WHILE:
277 case UNTIL:
278 multiline++;
279 t = newtp();
280 t->type = c == WHILE? TWHILE: TUNTIL;
281 t->left = c_list();
282 t->right = dogroup(1);
283 t->words = NULL;
284 multiline--;
285 break;
286
287 case CASE:
288 t = newtp();
289 t->type = TCASE;
290 musthave(WORD, 0);
291 t->str = yylval.cp;
292 startl++;
293 multiline++;
294 musthave(IN, CONTIN);
295 startl++;
296 t->left = caselist();
297 musthave(ESAC, 0);
298 multiline--;
299 break;
300
301 case IF:
302 multiline++;
303 t = newtp();
304 t->type = TIF;
305 t->left = c_list();
306 t->right = thenpart();
307 musthave(FI, 0);
308 multiline--;
309 break;
310 }
311 while (synio(0))
312 ;
313 t = namelist(t);
314 iolist = iosave;
315 return(t);
316 }
317
318 static struct op *
dogroup(onlydone)319 dogroup(onlydone)
320 int onlydone;
321 {
322 register int c;
323 register struct op *list;
324
325 c = yylex(CONTIN);
326 if (c == DONE && onlydone)
327 return((struct op *)NULL);
328 if (c != DO)
329 SYNTAXERR;
330 list = c_list();
331 musthave(DONE, 0);
332 return(list);
333 }
334
335 static struct op *
thenpart()336 thenpart()
337 {
338 register int c;
339 register struct op *t;
340
341 if ((c = yylex(0)) != THEN) {
342 peeksym = c;
343 return((struct op *)NULL);
344 }
345 t = newtp();
346 t->type = 0;
347 t->left = c_list();
348 if (t->left == NULL)
349 SYNTAXERR;
350 t->right = elsepart();
351 return(t);
352 }
353
354 static struct op *
elsepart()355 elsepart()
356 {
357 register int c;
358 register struct op *t;
359
360 switch (c = yylex(0)) {
361 case ELSE:
362 if ((t = c_list()) == NULL)
363 SYNTAXERR;
364 return(t);
365
366 case ELIF:
367 t = newtp();
368 t->type = TELIF;
369 t->left = c_list();
370 t->right = thenpart();
371 return(t);
372
373 default:
374 peeksym = c;
375 return((struct op *)NULL);
376 }
377 }
378
379 static struct op *
caselist()380 caselist()
381 {
382 register struct op *t;
383
384 t = NULL;
385 while ((peeksym = yylex(CONTIN)) != ESAC)
386 t = list(t, casepart());
387 return(t);
388 }
389
390 static struct op *
casepart()391 casepart()
392 {
393 register struct op *t;
394
395 t = newtp();
396 t->type = TPAT;
397 t->words = pattern();
398 musthave(')', 0);
399 t->left = c_list();
400 if ((peeksym = yylex(CONTIN)) != ESAC)
401 musthave(BREAK, CONTIN);
402 return(t);
403 }
404
405 static char **
pattern()406 pattern()
407 {
408 register int c, cf;
409
410 cf = CONTIN;
411 do {
412 musthave(WORD, cf);
413 word(yylval.cp);
414 cf = 0;
415 } while ((c = yylex(0)) == '|');
416 peeksym = c;
417 word(NOWORD);
418 return(copyw());
419 }
420
421 static char **
wordlist()422 wordlist()
423 {
424 register int c;
425
426 if ((c = yylex(0)) != IN) {
427 peeksym = c;
428 return((char **)NULL);
429 }
430 startl = 0;
431 while ((c = yylex(0)) == WORD)
432 word(yylval.cp);
433 word(NOWORD);
434 peeksym = c;
435 return(copyw());
436 }
437
438 /*
439 * supporting functions
440 */
441 static struct op *
list(t1,t2)442 list(t1, t2)
443 register struct op *t1, *t2;
444 {
445 if (t1 == NULL)
446 return(t2);
447 if (t2 == NULL)
448 return(t1);
449 return(block(TLIST, t1, t2, NOWORDS));
450 }
451
452 static struct op *
block(type,t1,t2,wp)453 block(type, t1, t2, wp)
454 int type;
455 struct op *t1, *t2;
456 char **wp;
457 {
458 register struct op *t;
459
460 t = newtp();
461 t->type = type;
462 t->left = t1;
463 t->right = t2;
464 t->words = wp;
465 return(t);
466 }
467
468 struct res {
469 char *r_name;
470 int r_val;
471 } restab[] = {
472 "for", FOR,
473 "case", CASE,
474 "esac", ESAC,
475 "while", WHILE,
476 "do", DO,
477 "done", DONE,
478 "if", IF,
479 "in", IN,
480 "then", THEN,
481 "else", ELSE,
482 "elif", ELIF,
483 "until", UNTIL,
484 "fi", FI,
485
486 ";;", BREAK,
487 "||", LOGOR,
488 "&&", LOGAND,
489 "{", '{',
490 "}", '}',
491
492 0,
493 };
494
495 int
rlookup(n)496 rlookup(n)
497 register char *n;
498 {
499 register struct res *rp;
500
501 for (rp = restab; rp->r_name; rp++)
502 if (strcmp(rp->r_name, n) == 0)
503 return(rp->r_val);
504 return(0);
505 }
506
507 static struct op *
newtp()508 newtp()
509 {
510 register struct op *t;
511
512 t = (struct op *)tree(sizeof(*t));
513 t->type = 0;
514 t->words = NULL;
515 t->ioact = NULL;
516 t->left = NULL;
517 t->right = NULL;
518 t->str = NULL;
519 return(t);
520 }
521
522 static struct op *
namelist(t)523 namelist(t)
524 register struct op *t;
525 {
526 if (iolist) {
527 iolist = addword((char *)NULL, iolist);
528 t->ioact = copyio();
529 } else
530 t->ioact = NULL;
531 if (t->type != TCOM) {
532 if (t->type != TPAREN && t->ioact != NULL) {
533 t = block(TPAREN, t, NOBLOCK, NOWORDS);
534 t->ioact = t->left->ioact;
535 t->left->ioact = NULL;
536 }
537 return(t);
538 }
539 word(NOWORD);
540 t->words = copyw();
541 return(t);
542 }
543
544 static char **
copyw()545 copyw()
546 {
547 register char **wd;
548
549 wd = getwords(wdlist);
550 wdlist = 0;
551 return(wd);
552 }
553
554 static void
word(cp)555 word(cp)
556 char *cp;
557 {
558 wdlist = addword(cp, wdlist);
559 }
560
561 static struct ioword **
copyio()562 copyio()
563 {
564 register struct ioword **iop;
565
566 iop = (struct ioword **) getwords(iolist);
567 iolist = 0;
568 return(iop);
569 }
570
571 static struct ioword *
io(u,f,cp)572 io(u, f, cp)
573 int u;
574 int f;
575 char *cp;
576 {
577 register struct ioword *iop;
578
579 iop = (struct ioword *) tree(sizeof(*iop));
580 iop->io_unit = u;
581 iop->io_flag = f;
582 iop->io_name = cp;
583 iolist = addword((char *)iop, iolist);
584 return(iop);
585 }
586
587 static void
zzerr()588 zzerr()
589 {
590 yyerror("syntax error");
591 }
592
593 void
yyerror(s)594 yyerror(s)
595 char *s;
596 {
597 yynerrs++;
598 if (talking && e.iop <= iostack) {
599 multiline = 0;
600 while (eofc() == 0 && yylex(0) != '\n')
601 ;
602 }
603 err(s);
604 fail();
605 }
606
607 static int
yylex(cf)608 yylex(cf)
609 int cf;
610 {
611 register int c, c1;
612 int atstart;
613
614 if ((c = peeksym) > 0) {
615 peeksym = 0;
616 if (c == '\n')
617 startl = 1;
618 return(c);
619 }
620 nlseen = 0;
621 e.linep = line;
622 atstart = startl;
623 startl = 0;
624 yylval.i = 0;
625
626 loop:
627 while ((c = getc(0)) == ' ' || c == '\t')
628 ;
629 switch (c) {
630 default:
631 if (any(c, "0123456789")) {
632 unget(c1 = getc(0));
633 if (c1 == '<' || c1 == '>') {
634 iounit = c - '0';
635 goto loop;
636 }
637 *e.linep++ = c;
638 c = c1;
639 }
640 break;
641
642 case '#':
643 while ((c = getc(0)) != 0 && c != '\n')
644 ;
645 unget(c);
646 goto loop;
647
648 case 0:
649 return(c);
650
651 case '$':
652 *e.linep++ = c;
653 if ((c = getc(0)) == '{') {
654 if ((c = collect(c, '}')) != '\0')
655 return(c);
656 goto pack;
657 }
658 break;
659
660 case '`':
661 case '\'':
662 case '"':
663 if ((c = collect(c, c)) != '\0')
664 return(c);
665 goto pack;
666
667 case '|':
668 case '&':
669 case ';':
670 if ((c1 = dual(c)) != '\0') {
671 startl = 1;
672 return(c1);
673 }
674 startl = 1;
675 return(c);
676 case '^':
677 startl = 1;
678 return('|');
679 case '>':
680 case '<':
681 diag(c);
682 return(c);
683
684 case '\n':
685 nlseen++;
686 gethere();
687 startl = 1;
688 if (multiline || cf & CONTIN) {
689 if (talking && e.iop <= iostack)
690 prs(cprompt->value);
691 if (cf & CONTIN)
692 goto loop;
693 }
694 return(c);
695
696 case '(':
697 case ')':
698 startl = 1;
699 return(c);
700 }
701
702 unget(c);
703
704 pack:
705 while ((c = getc(0)) != 0 && !any(c, "`$ '\"\t;&<>()|^\n"))
706 if (e.linep >= elinep)
707 err("word too long");
708 else
709 *e.linep++ = c;
710 unget(c);
711 if(any(c, "\"'`$"))
712 goto loop;
713 *e.linep++ = '\0';
714 if (atstart && (c = rlookup(line))!=0) {
715 startl = 1;
716 return(c);
717 }
718 yylval.cp = strsave(line, areanum);
719 return(WORD);
720 }
721
722 int
collect(c,c1)723 collect(c, c1)
724 register c, c1;
725 {
726 char s[2];
727
728 *e.linep++ = c;
729 while ((c = getc(c1)) != c1) {
730 if (c == 0) {
731 unget(c);
732 s[0] = c1;
733 s[1] = 0;
734 prs("no closing "); yyerror(s);
735 return(YYERRCODE);
736 }
737 if (talking && c == '\n' && e.iop <= iostack)
738 prs(cprompt->value);
739 *e.linep++ = c;
740 }
741 *e.linep++ = c;
742 return(0);
743 }
744
745 int
dual(c)746 dual(c)
747 register c;
748 {
749 char s[3];
750 register char *cp = s;
751
752 *cp++ = c;
753 *cp++ = getc(0);
754 *cp = 0;
755 if ((c = rlookup(s)) == 0)
756 unget(*--cp);
757 return(c);
758 }
759
760 static void
diag(ec)761 diag(ec)
762 register int ec;
763 {
764 register int c;
765
766 c = getc(0);
767 if (c == '>' || c == '<') {
768 if (c != ec)
769 zzerr();
770 yylval.i = ec == '>'? IOWRITE|IOCAT: IOHERE;
771 c = getc(0);
772 } else
773 yylval.i = ec == '>'? IOWRITE: IOREAD;
774 if (c != '&' || yylval.i == IOHERE)
775 unget(c);
776 else
777 yylval.i |= IODUP;
778 }
779
780 static char *
tree(size)781 tree(size)
782 unsigned size;
783 {
784 register char *t;
785
786 if ((t = getcell(size)) == NULL) {
787 prs("command line too complicated\n");
788 fail();
789 /* NOTREACHED */
790 }
791 return(t);
792 }
793
794 /* VARARGS1 */
795 /* ARGSUSED */
796 void
printf(s)797 printf(s) /* yyparse calls it */
798 char *s;
799 {
800 }
801
802