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
14typedef 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()
44static	int	startl;
45static	int	peeksym;
46static	int	nlseen;
47static	int	iounit = IODEFAULT;
48
49static	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
83int
84yyparse()
85{
86	startl  = 1;
87	peeksym = 0;
88	yynerrs = 0;
89	outtree = c_list();
90	musthave('\n', 0);
91	return(yynerrs!=0);
92}
93
94static struct op *
95pipeline(cf)
96int 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
117static struct op *
118andor()
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
135static struct op *
136c_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
158static int
159synio(cf)
160int 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
179static void
180musthave(c, cf)
181int c, cf;
182{
183	if ((peeksym = yylex(cf)) != c)
184		SYNTAXERR;
185	peeksym = 0;
186}
187
188static struct op *
189simple()
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
216static struct op *
217nested(type, mark)
218int 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
229static struct op *
230command(cf)
231int 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
318static struct op *
319dogroup(onlydone)
320int 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
335static struct op *
336thenpart()
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
354static struct op *
355elsepart()
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
379static struct op *
380caselist()
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
390static struct op *
391casepart()
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
405static char **
406pattern()
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
421static char **
422wordlist()
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 */
441static struct op *
442list(t1, t2)
443register 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
452static struct op *
453block(type, t1, t2, wp)
454int type;
455struct op *t1, *t2;
456char **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
468struct 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
495int
496rlookup(n)
497register 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
507static struct op *
508newtp()
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
522static struct op *
523namelist(t)
524register 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
544static char **
545copyw()
546{
547	register char **wd;
548
549	wd = getwords(wdlist);
550	wdlist = 0;
551	return(wd);
552}
553
554static void
555word(cp)
556char *cp;
557{
558	wdlist = addword(cp, wdlist);
559}
560
561static struct ioword **
562copyio()
563{
564	register struct ioword **iop;
565
566	iop = (struct ioword **) getwords(iolist);
567	iolist = 0;
568	return(iop);
569}
570
571static struct ioword *
572io(u, f, cp)
573int u;
574int f;
575char *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
587static void
588zzerr()
589{
590	yyerror("syntax error");
591}
592
593void
594yyerror(s)
595char *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
607static int
608yylex(cf)
609int 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
626loop:
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
704pack:
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
722int
723collect(c, c1)
724register 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
745int
746dual(c)
747register 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
760static void
761diag(ec)
762register 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
780static char *
781tree(size)
782unsigned 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 */
796void
797printf(s)	/* yyparse calls it */
798char *s;
799{
800}
801
802