xref: /NextBSD/release/picobsd/tinyware/msh/sh2.c (revision eb1a5f8de9f7ea602c373a710f531abbf81141c4)
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