• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*	$OpenBSD: syn.c,v 1.30 2015/09/01 13:12:31 tedu Exp $	*/
2 
3 /*-
4  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009,
5  *		 2011, 2012, 2013, 2014, 2015, 2016, 2017
6  *	mirabilos <m@mirbsd.org>
7  *
8  * Provided that these terms and disclaimer and all copyright notices
9  * are retained or reproduced in an accompanying document, permission
10  * is granted to deal in this work without restriction, including un-
11  * limited rights to use, publicly perform, distribute, sell, modify,
12  * merge, give away, or sublicence.
13  *
14  * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
15  * the utmost extent permitted by applicable law, neither express nor
16  * implied; without malicious intent or gross negligence. In no event
17  * may a licensor, author or contributor be held liable for indirect,
18  * direct, other damage, loss, or other issues arising in any way out
19  * of dealing in the work, even if advised of the possibility of such
20  * damage or existence of a defect, except proven that it results out
21  * of said person's immediate fault when using the work as intended.
22  */
23 
24 #include "sh.h"
25 
26 __RCSID("$MirOS: src/bin/mksh/syn.c,v 1.120 2017/04/06 01:59:57 tg Exp $");
27 
28 struct nesting_state {
29 	int start_token;	/* token than began nesting (eg, FOR) */
30 	int start_line;		/* line nesting began on */
31 };
32 
33 struct yyrecursive_state {
34 	struct ioword *old_heres[HERES];
35 	struct yyrecursive_state *next;
36 	struct ioword **old_herep;
37 	int old_symbol;
38 	int old_nesting_type;
39 	bool old_reject;
40 };
41 
42 static void yyparse(bool);
43 static struct op *pipeline(int, int);
44 static struct op *andor(int);
45 static struct op *c_list(int, bool);
46 static struct ioword *synio(int);
47 static struct op *nested(int, int, int, int);
48 static struct op *get_command(int, int);
49 static struct op *dogroup(int);
50 static struct op *thenpart(int);
51 static struct op *elsepart(int);
52 static struct op *caselist(int);
53 static struct op *casepart(int, int);
54 static struct op *function_body(char *, int, bool);
55 static char **wordlist(int);
56 static struct op *block(int, struct op *, struct op *);
57 static struct op *newtp(int);
58 static void syntaxerr(const char *) MKSH_A_NORETURN;
59 static void nesting_push(struct nesting_state *, int);
60 static void nesting_pop(struct nesting_state *);
61 static int inalias(struct source *) MKSH_A_PURE;
62 static Test_op dbtestp_isa(Test_env *, Test_meta);
63 static const char *dbtestp_getopnd(Test_env *, Test_op, bool);
64 static int dbtestp_eval(Test_env *, Test_op, const char *,
65     const char *, bool);
66 static void dbtestp_error(Test_env *, int, const char *) MKSH_A_NORETURN;
67 
68 static struct op *outtree;		/* yyparse output */
69 static struct nesting_state nesting;	/* \n changed to ; */
70 
71 static bool reject;			/* token(cf) gets symbol again */
72 static int symbol;			/* yylex value */
73 
74 #define REJECT		(reject = true)
75 #define ACCEPT		(reject = false)
76 #define token(cf)	((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf)))
77 #define tpeek(cf)	((reject) ? (symbol) : (REJECT, symbol = yylex(cf)))
78 #define musthave(c,cf)	do { if (token(cf) != (c)) syntaxerr(NULL); } while (/* CONSTCOND */ 0)
79 
80 static const char Tcbrace[] = "}";
81 static const char Tesac[] = "esac";
82 
83 static void
yyparse(bool doalias)84 yyparse(bool doalias)
85 {
86 	int c;
87 
88 	ACCEPT;
89 
90 	outtree = c_list(doalias ? ALIAS : 0, source->type == SSTRING);
91 	c = tpeek(0);
92 	if (c == 0 && !outtree)
93 		outtree = newtp(TEOF);
94 	else if (c != '\n' && c != 0)
95 		syntaxerr(NULL);
96 }
97 
98 static struct op *
pipeline(int cf,int sALIAS)99 pipeline(int cf, int sALIAS)
100 {
101 	struct op *t, *p, *tl = NULL;
102 
103 	t = get_command(cf, sALIAS);
104 	if (t != NULL) {
105 		while (token(0) == '|') {
106 			if ((p = get_command(CONTIN, sALIAS)) == NULL)
107 				syntaxerr(NULL);
108 			if (tl == NULL)
109 				t = tl = block(TPIPE, t, p);
110 			else
111 				tl = tl->right = block(TPIPE, tl->right, p);
112 		}
113 		REJECT;
114 	}
115 	return (t);
116 }
117 
118 static struct op *
andor(int sALIAS)119 andor(int sALIAS)
120 {
121 	struct op *t, *p;
122 	int c;
123 
124 	t = pipeline(0, sALIAS);
125 	if (t != NULL) {
126 		while ((c = token(0)) == LOGAND || c == LOGOR) {
127 			if ((p = pipeline(CONTIN, sALIAS)) == NULL)
128 				syntaxerr(NULL);
129 			t = block(c == LOGAND? TAND: TOR, t, p);
130 		}
131 		REJECT;
132 	}
133 	return (t);
134 }
135 
136 static struct op *
c_list(int sALIAS,bool multi)137 c_list(int sALIAS, bool multi)
138 {
139 	struct op *t = NULL, *p, *tl = NULL;
140 	int c;
141 	bool have_sep;
142 
143 	while (/* CONSTCOND */ 1) {
144 		p = andor(sALIAS);
145 		/*
146 		 * Token has always been read/rejected at this point, so
147 		 * we don't worry about what flags to pass token()
148 		 */
149 		c = token(0);
150 		have_sep = true;
151 		if (c == '\n' && (multi || inalias(source))) {
152 			if (!p)
153 				/* ignore blank lines */
154 				continue;
155 		} else if (!p)
156 			break;
157 		else if (c == '&' || c == COPROC)
158 			p = block(c == '&' ? TASYNC : TCOPROC, p, NULL);
159 		else if (c != ';')
160 			have_sep = false;
161 		if (!t)
162 			t = p;
163 		else if (!tl)
164 			t = tl = block(TLIST, t, p);
165 		else
166 			tl = tl->right = block(TLIST, tl->right, p);
167 		if (!have_sep)
168 			break;
169 	}
170 	REJECT;
171 	return (t);
172 }
173 
174 static const char IONDELIM_delim[] = { CHAR, '<', CHAR, '<', EOS };
175 
176 static struct ioword *
synio(int cf)177 synio(int cf)
178 {
179 	struct ioword *iop;
180 	static struct ioword *nextiop;
181 	bool ishere;
182 
183 	if (nextiop != NULL) {
184 		iop = nextiop;
185 		nextiop = NULL;
186 		return (iop);
187 	}
188 
189 	if (tpeek(cf) != REDIR)
190 		return (NULL);
191 	ACCEPT;
192 	iop = yylval.iop;
193 	ishere = (iop->ioflag & IOTYPE) == IOHERE;
194 	if (iop->ioflag & IOHERESTR) {
195 		musthave(LWORD, 0);
196 	} else if (ishere && tpeek(HEREDELIM) == '\n') {
197 		ACCEPT;
198 		yylval.cp = wdcopy(IONDELIM_delim, ATEMP);
199 		iop->ioflag |= IOEVAL | IONDELIM;
200 	} else
201 		musthave(LWORD, ishere ? HEREDELIM : 0);
202 	if (ishere) {
203 		iop->delim = yylval.cp;
204 		if (*ident != 0 && !(iop->ioflag & IOHERESTR)) {
205 			/* unquoted */
206 			iop->ioflag |= IOEVAL;
207 		}
208 		if (herep > &heres[HERES - 1])
209 			yyerror(Tf_toomany, "<<");
210 		*herep++ = iop;
211 	} else
212 		iop->ioname = yylval.cp;
213 
214 	if (iop->ioflag & IOBASH) {
215 		char *cp;
216 
217 		nextiop = alloc(sizeof(*iop), ATEMP);
218 		nextiop->ioname = cp = alloc(3, ATEMP);
219 		*cp++ = CHAR;
220 		*cp++ = digits_lc[iop->unit % 10];
221 		*cp = EOS;
222 
223 		iop->ioflag &= ~IOBASH;
224 		nextiop->unit = 2;
225 		nextiop->ioflag = IODUP;
226 		nextiop->delim = NULL;
227 		nextiop->heredoc = NULL;
228 	}
229 	return (iop);
230 }
231 
232 static struct op *
nested(int type,int smark,int emark,int sALIAS)233 nested(int type, int smark, int emark, int sALIAS)
234 {
235 	struct op *t;
236 	struct nesting_state old_nesting;
237 
238 	nesting_push(&old_nesting, smark);
239 	t = c_list(sALIAS, true);
240 	musthave(emark, KEYWORD|sALIAS);
241 	nesting_pop(&old_nesting);
242 	return (block(type, t, NULL));
243 }
244 
245 static const char builtin_cmd[] = {
246 	QCHAR, '\\', CHAR, 'b', CHAR, 'u', CHAR, 'i',
247 	CHAR, 'l', CHAR, 't', CHAR, 'i', CHAR, 'n', EOS
248 };
249 static const char let_cmd[] = {
250 	CHAR, 'l', CHAR, 'e', CHAR, 't', EOS
251 };
252 static const char setA_cmd0[] = {
253 	CHAR, 's', CHAR, 'e', CHAR, 't', EOS
254 };
255 static const char setA_cmd1[] = {
256 	CHAR, '-', CHAR, 'A', EOS
257 };
258 static const char setA_cmd2[] = {
259 	CHAR, '-', CHAR, '-', EOS
260 };
261 
262 static struct op *
get_command(int cf,int sALIAS)263 get_command(int cf, int sALIAS)
264 {
265 	struct op *t;
266 	int c, iopn = 0, syniocf, lno;
267 	struct ioword *iop, **iops;
268 	XPtrV args, vars;
269 	struct nesting_state old_nesting;
270 
271 	/* NUFILE is small enough to leave this addition unchecked */
272 	iops = alloc2((NUFILE + 1), sizeof(struct ioword *), ATEMP);
273 	XPinit(args, 16);
274 	XPinit(vars, 16);
275 
276 	syniocf = KEYWORD|sALIAS;
277 	switch (c = token(cf|KEYWORD|sALIAS|CMDASN)) {
278 	default:
279 		REJECT;
280 		afree(iops, ATEMP);
281 		XPfree(args);
282 		XPfree(vars);
283 		/* empty line */
284 		return (NULL);
285 
286 	case LWORD:
287 	case REDIR:
288 		REJECT;
289 		syniocf &= ~(KEYWORD|sALIAS);
290 		t = newtp(TCOM);
291 		t->lineno = source->line;
292 		goto get_command_start;
293 		while (/* CONSTCOND */ 1) {
294 			bool check_decl_utility;
295 
296 			if (XPsize(args) == 0) {
297  get_command_start:
298 				check_decl_utility = true;
299 				cf = sALIAS | CMDASN;
300 			} else if (t->u.evalflags)
301 				cf = CMDWORD | CMDASN;
302 			else
303 				cf = CMDWORD;
304 			switch (tpeek(cf)) {
305 			case REDIR:
306 				while ((iop = synio(cf)) != NULL) {
307 					if (iopn >= NUFILE)
308 						yyerror(Tf_toomany,
309 						    Tredirection);
310 					iops[iopn++] = iop;
311 				}
312 				break;
313 
314 			case LWORD:
315 				ACCEPT;
316 				if (check_decl_utility) {
317 					struct tbl *tt = get_builtin(ident);
318 					uint32_t flag;
319 
320 					flag = tt ? tt->flag : 0;
321 					if (flag & DECL_UTIL)
322 						t->u.evalflags = DOVACHECK;
323 					if (!(flag & DECL_FWDR))
324 						check_decl_utility = false;
325 				}
326 				if ((XPsize(args) == 0 || Flag(FKEYWORD)) &&
327 				    is_wdvarassign(yylval.cp))
328 					XPput(vars, yylval.cp);
329 				else
330 					XPput(args, yylval.cp);
331 				break;
332 
333 			case '(' /*)*/:
334 				if (XPsize(args) == 0 && XPsize(vars) == 1 &&
335 				    is_wdvarassign(yylval.cp)) {
336 					char *tcp;
337 
338 					/* wdarrassign: foo=(bar) */
339 					ACCEPT;
340 
341 					/* manipulate the vars string */
342 					tcp = XPptrv(vars)[(vars.len = 0)];
343 					/* 'varname=' -> 'varname' */
344 					tcp[wdscan(tcp, EOS) - tcp - 3] = EOS;
345 
346 					/* construct new args strings */
347 					XPput(args, wdcopy(builtin_cmd, ATEMP));
348 					XPput(args, wdcopy(setA_cmd0, ATEMP));
349 					XPput(args, wdcopy(setA_cmd1, ATEMP));
350 					XPput(args, tcp);
351 					XPput(args, wdcopy(setA_cmd2, ATEMP));
352 
353 					/* slurp in words till closing paren */
354 					while (token(CONTIN) == LWORD)
355 						XPput(args, yylval.cp);
356 					if (symbol != /*(*/ ')')
357 						syntaxerr(NULL);
358 				} else {
359 					/*
360 					 * Check for "> foo (echo hi)"
361 					 * which AT&T ksh allows (not
362 					 * POSIX, but not disallowed)
363 					 */
364 					afree(t, ATEMP);
365 					if (XPsize(args) == 0 &&
366 					    XPsize(vars) == 0) {
367 						ACCEPT;
368 						goto Subshell;
369 					}
370 
371 					/* must be a function */
372 					if (iopn != 0 || XPsize(args) != 1 ||
373 					    XPsize(vars) != 0)
374 						syntaxerr(NULL);
375 					ACCEPT;
376 					musthave(/*(*/')', 0);
377 					t = function_body(XPptrv(args)[0],
378 					    sALIAS, false);
379 				}
380 				goto Leave;
381 
382 			default:
383 				goto Leave;
384 			}
385 		}
386  Leave:
387 		break;
388 
389 	case '(': /*)*/ {
390 		int subshell_nesting_type_saved;
391  Subshell:
392 		subshell_nesting_type_saved = subshell_nesting_type;
393 		subshell_nesting_type = ')';
394 		t = nested(TPAREN, '(', ')', sALIAS);
395 		subshell_nesting_type = subshell_nesting_type_saved;
396 		break;
397 	    }
398 
399 	case '{': /*}*/
400 		t = nested(TBRACE, '{', '}', sALIAS);
401 		break;
402 
403 	case MDPAREN:
404 		/* leave KEYWORD in syniocf (allow if (( 1 )) then ...) */
405 		lno = source->line;
406 		ACCEPT;
407 		switch (token(LETEXPR)) {
408 		case LWORD:
409 			break;
410 		case '(': /*)*/
411 			c = '(';
412 			goto Subshell;
413 		default:
414 			syntaxerr(NULL);
415 		}
416 		t = newtp(TCOM);
417 		t->lineno = lno;
418 		XPput(args, wdcopy(builtin_cmd, ATEMP));
419 		XPput(args, wdcopy(let_cmd, ATEMP));
420 		XPput(args, yylval.cp);
421 		break;
422 
423 	case DBRACKET: /* [[ .. ]] */
424 		/* leave KEYWORD in syniocf (allow if [[ -n 1 ]] then ...) */
425 		t = newtp(TDBRACKET);
426 		ACCEPT;
427 		{
428 			Test_env te;
429 
430 			te.flags = TEF_DBRACKET;
431 			te.pos.av = &args;
432 			te.isa = dbtestp_isa;
433 			te.getopnd = dbtestp_getopnd;
434 			te.eval = dbtestp_eval;
435 			te.error = dbtestp_error;
436 
437 			test_parse(&te);
438 		}
439 		break;
440 
441 	case FOR:
442 	case SELECT:
443 		t = newtp((c == FOR) ? TFOR : TSELECT);
444 		musthave(LWORD, CMDASN);
445 		if (!is_wdvarname(yylval.cp, true))
446 			yyerror("%s: bad identifier",
447 			    c == FOR ? "for" : Tselect);
448 		strdupx(t->str, ident, ATEMP);
449 		nesting_push(&old_nesting, c);
450 		t->vars = wordlist(sALIAS);
451 		t->left = dogroup(sALIAS);
452 		nesting_pop(&old_nesting);
453 		break;
454 
455 	case WHILE:
456 	case UNTIL:
457 		nesting_push(&old_nesting, c);
458 		t = newtp((c == WHILE) ? TWHILE : TUNTIL);
459 		t->left = c_list(sALIAS, true);
460 		t->right = dogroup(sALIAS);
461 		nesting_pop(&old_nesting);
462 		break;
463 
464 	case CASE:
465 		t = newtp(TCASE);
466 		musthave(LWORD, 0);
467 		t->str = yylval.cp;
468 		nesting_push(&old_nesting, c);
469 		t->left = caselist(sALIAS);
470 		nesting_pop(&old_nesting);
471 		break;
472 
473 	case IF:
474 		nesting_push(&old_nesting, c);
475 		t = newtp(TIF);
476 		t->left = c_list(sALIAS, true);
477 		t->right = thenpart(sALIAS);
478 		musthave(FI, KEYWORD|sALIAS);
479 		nesting_pop(&old_nesting);
480 		break;
481 
482 	case BANG:
483 		syniocf &= ~(KEYWORD|sALIAS);
484 		t = pipeline(0, sALIAS);
485 		if (t == NULL)
486 			syntaxerr(NULL);
487 		t = block(TBANG, NULL, t);
488 		break;
489 
490 	case TIME:
491 		syniocf &= ~(KEYWORD|sALIAS);
492 		t = pipeline(0, sALIAS);
493 		if (t && t->type == TCOM) {
494 			t->str = alloc(2, ATEMP);
495 			/* TF_* flags */
496 			t->str[0] = '\0';
497 			t->str[1] = '\0';
498 		}
499 		t = block(TTIME, t, NULL);
500 		break;
501 
502 	case FUNCTION:
503 		musthave(LWORD, 0);
504 		t = function_body(yylval.cp, sALIAS, true);
505 		break;
506 	}
507 
508 	while ((iop = synio(syniocf)) != NULL) {
509 		if (iopn >= NUFILE)
510 			yyerror(Tf_toomany, Tredirection);
511 		iops[iopn++] = iop;
512 	}
513 
514 	if (iopn == 0) {
515 		afree(iops, ATEMP);
516 		t->ioact = NULL;
517 	} else {
518 		iops[iopn++] = NULL;
519 		iops = aresize2(iops, iopn, sizeof(struct ioword *), ATEMP);
520 		t->ioact = iops;
521 	}
522 
523 	if (t->type == TCOM || t->type == TDBRACKET) {
524 		XPput(args, NULL);
525 		t->args = (const char **)XPclose(args);
526 		XPput(vars, NULL);
527 		t->vars = (char **)XPclose(vars);
528 	} else {
529 		XPfree(args);
530 		XPfree(vars);
531 	}
532 
533 	if (c == MDPAREN) {
534 		t = block(TBRACE, t, NULL);
535 		t->ioact = t->left->ioact;
536 		t->left->ioact = NULL;
537 	}
538 
539 	return (t);
540 }
541 
542 static struct op *
dogroup(int sALIAS)543 dogroup(int sALIAS)
544 {
545 	int c;
546 	struct op *list;
547 
548 	c = token(CONTIN|KEYWORD|sALIAS);
549 	/*
550 	 * A {...} can be used instead of do...done for for/select loops
551 	 * but not for while/until loops - we don't need to check if it
552 	 * is a while loop because it would have been parsed as part of
553 	 * the conditional command list...
554 	 */
555 	if (c == DO)
556 		c = DONE;
557 	else if (c == '{')
558 		c = '}';
559 	else
560 		syntaxerr(NULL);
561 	list = c_list(sALIAS, true);
562 	musthave(c, KEYWORD|sALIAS);
563 	return (list);
564 }
565 
566 static struct op *
thenpart(int sALIAS)567 thenpart(int sALIAS)
568 {
569 	struct op *t;
570 
571 	musthave(THEN, KEYWORD|sALIAS);
572 	t = newtp(0);
573 	t->left = c_list(sALIAS, true);
574 	if (t->left == NULL)
575 		syntaxerr(NULL);
576 	t->right = elsepart(sALIAS);
577 	return (t);
578 }
579 
580 static struct op *
elsepart(int sALIAS)581 elsepart(int sALIAS)
582 {
583 	struct op *t;
584 
585 	switch (token(KEYWORD|sALIAS|CMDASN)) {
586 	case ELSE:
587 		if ((t = c_list(sALIAS, true)) == NULL)
588 			syntaxerr(NULL);
589 		return (t);
590 
591 	case ELIF:
592 		t = newtp(TELIF);
593 		t->left = c_list(sALIAS, true);
594 		t->right = thenpart(sALIAS);
595 		return (t);
596 
597 	default:
598 		REJECT;
599 	}
600 	return (NULL);
601 }
602 
603 static struct op *
caselist(int sALIAS)604 caselist(int sALIAS)
605 {
606 	struct op *t, *tl;
607 	int c;
608 
609 	c = token(CONTIN|KEYWORD|sALIAS);
610 	/* A {...} can be used instead of in...esac for case statements */
611 	if (c == IN)
612 		c = ESAC;
613 	else if (c == '{')
614 		c = '}';
615 	else
616 		syntaxerr(NULL);
617 	t = tl = NULL;
618 	/* no ALIAS here */
619 	while ((tpeek(CONTIN|KEYWORD|ESACONLY)) != c) {
620 		struct op *tc = casepart(c, sALIAS);
621 		if (tl == NULL)
622 			t = tl = tc, tl->right = NULL;
623 		else
624 			tl->right = tc, tl = tc;
625 	}
626 	musthave(c, KEYWORD|sALIAS);
627 	return (t);
628 }
629 
630 static struct op *
casepart(int endtok,int sALIAS)631 casepart(int endtok, int sALIAS)
632 {
633 	struct op *t;
634 	XPtrV ptns;
635 
636 	XPinit(ptns, 16);
637 	t = newtp(TPAT);
638 	/* no ALIAS here */
639 	if (token(CONTIN | KEYWORD) != '(')
640 		REJECT;
641 	do {
642 		switch (token(0)) {
643 		case LWORD:
644 			break;
645 		case '}':
646 		case ESAC:
647 			if (symbol != endtok) {
648 				strdupx(yylval.cp,
649 				    symbol == '}' ? Tcbrace : Tesac, ATEMP);
650 				break;
651 			}
652 			/* FALLTHROUGH */
653 		default:
654 			syntaxerr(NULL);
655 		}
656 		XPput(ptns, yylval.cp);
657 	} while (token(0) == '|');
658 	REJECT;
659 	XPput(ptns, NULL);
660 	t->vars = (char **)XPclose(ptns);
661 	musthave(')', 0);
662 
663 	t->left = c_list(sALIAS, true);
664 
665 	/* initialise to default for ;; or omitted */
666 	t->u.charflag = ';';
667 	/* SUSv4 requires the ;; except in the last casepart */
668 	if ((tpeek(CONTIN|KEYWORD|sALIAS)) != endtok)
669 		switch (symbol) {
670 		default:
671 			syntaxerr(NULL);
672 		case BRKEV:
673 			t->u.charflag = '|';
674 			if (0)
675 				/* FALLTHROUGH */
676 		case BRKFT:
677 			t->u.charflag = '&';
678 			/* FALLTHROUGH */
679 		case BREAK:
680 			/* initialised above, but we need to eat the token */
681 			ACCEPT;
682 		}
683 	return (t);
684 }
685 
686 static struct op *
function_body(char * name,int sALIAS,bool ksh_func)687 function_body(char *name, int sALIAS,
688     /* function foo { ... } vs foo() { .. } */
689     bool ksh_func)
690 {
691 	char *sname, *p;
692 	struct op *t;
693 
694 	sname = wdstrip(name, 0);
695 	/*-
696 	 * Check for valid characters in name. POSIX and AT&T ksh93 say
697 	 * only allow [a-zA-Z_0-9] but this allows more as old pdkshs
698 	 * have allowed more; the following were never allowed:
699 	 *	NUL TAB NL SP " $ & ' ( ) ; < = > \ ` |
700 	 * C_QUOTE covers all but adds # * ? [ ]
701 	 */
702 	for (p = sname; *p; p++)
703 		if (ctype(*p, C_QUOTE))
704 			yyerror(Tinvname, sname, Tfunction);
705 
706 	/*
707 	 * Note that POSIX allows only compound statements after foo(),
708 	 * sh and AT&T ksh allow any command, go with the later since it
709 	 * shouldn't break anything. However, for function foo, AT&T ksh
710 	 * only accepts an open-brace.
711 	 */
712 	if (ksh_func) {
713 		if (tpeek(CONTIN|KEYWORD|sALIAS) == '(' /*)*/) {
714 			/* function foo () { //}*/
715 			ACCEPT;
716 			musthave(')', 0);
717 			/* degrade to POSIX function */
718 			ksh_func = false;
719 		}
720 		musthave('{' /*}*/, CONTIN|KEYWORD|sALIAS);
721 		REJECT;
722 	}
723 
724 	t = newtp(TFUNCT);
725 	t->str = sname;
726 	t->u.ksh_func = tobool(ksh_func);
727 	t->lineno = source->line;
728 
729 	if ((t->left = get_command(CONTIN, sALIAS)) == NULL) {
730 		char *tv;
731 		/*
732 		 * Probably something like foo() followed by EOF or ';'.
733 		 * This is accepted by sh and ksh88.
734 		 * To make "typeset -f foo" work reliably (so its output can
735 		 * be used as input), we pretend there is a colon here.
736 		 */
737 		t->left = newtp(TCOM);
738 		/* (2 * sizeof(char *)) is small enough */
739 		t->left->args = alloc(2 * sizeof(char *), ATEMP);
740 		t->left->args[0] = tv = alloc(3, ATEMP);
741 		tv[0] = QCHAR;
742 		tv[1] = ':';
743 		tv[2] = EOS;
744 		t->left->args[1] = NULL;
745 		t->left->vars = alloc(sizeof(char *), ATEMP);
746 		t->left->vars[0] = NULL;
747 		t->left->lineno = 1;
748 	}
749 
750 	return (t);
751 }
752 
753 static char **
wordlist(int sALIAS)754 wordlist(int sALIAS)
755 {
756 	int c;
757 	XPtrV args;
758 
759 	XPinit(args, 16);
760 	/* POSIX does not do alias expansion here... */
761 	if ((c = token(CONTIN|KEYWORD|sALIAS)) != IN) {
762 		if (c != ';')
763 			/* non-POSIX, but AT&T ksh accepts a ; here */
764 			REJECT;
765 		return (NULL);
766 	}
767 	while ((c = token(0)) == LWORD)
768 		XPput(args, yylval.cp);
769 	if (c != '\n' && c != ';')
770 		syntaxerr(NULL);
771 	XPput(args, NULL);
772 	return ((char **)XPclose(args));
773 }
774 
775 /*
776  * supporting functions
777  */
778 
779 static struct op *
block(int type,struct op * t1,struct op * t2)780 block(int type, struct op *t1, struct op *t2)
781 {
782 	struct op *t;
783 
784 	t = newtp(type);
785 	t->left = t1;
786 	t->right = t2;
787 	return (t);
788 }
789 
790 static const struct tokeninfo {
791 	const char *name;
792 	short val;
793 	short reserved;
794 } tokentab[] = {
795 	/* Reserved words */
796 	{ "if",		IF,	true },
797 	{ "then",	THEN,	true },
798 	{ "else",	ELSE,	true },
799 	{ "elif",	ELIF,	true },
800 	{ "fi",		FI,	true },
801 	{ "case",	CASE,	true },
802 	{ Tesac,	ESAC,	true },
803 	{ "for",	FOR,	true },
804 	{ Tselect,	SELECT,	true },
805 	{ "while",	WHILE,	true },
806 	{ "until",	UNTIL,	true },
807 	{ "do",		DO,	true },
808 	{ "done",	DONE,	true },
809 	{ "in",		IN,	true },
810 	{ Tfunction,	FUNCTION, true },
811 	{ Ttime,	TIME,	true },
812 	{ "{",		'{',	true },
813 	{ Tcbrace,	'}',	true },
814 	{ "!",		BANG,	true },
815 	{ "[[",		DBRACKET, true },
816 	/* Lexical tokens (0[EOF], LWORD and REDIR handled specially) */
817 	{ "&&",		LOGAND,	false },
818 	{ "||",		LOGOR,	false },
819 	{ ";;",		BREAK,	false },
820 	{ ";|",		BRKEV,	false },
821 	{ ";&",		BRKFT,	false },
822 	{ "((",		MDPAREN, false },
823 	{ "|&",		COPROC,	false },
824 	/* and some special cases... */
825 	{ "newline",	'\n',	false },
826 	{ NULL,		0,	false }
827 };
828 
829 void
initkeywords(void)830 initkeywords(void)
831 {
832 	struct tokeninfo const *tt;
833 	struct tbl *p;
834 
835 	ktinit(APERM, &keywords,
836 	    /* currently 28 keywords: 75% of 64 = 2^6 */
837 	    6);
838 	for (tt = tokentab; tt->name; tt++) {
839 		if (tt->reserved) {
840 			p = ktenter(&keywords, tt->name, hash(tt->name));
841 			p->flag |= DEFINED|ISSET;
842 			p->type = CKEYWD;
843 			p->val.i = tt->val;
844 		}
845 	}
846 }
847 
848 static void
syntaxerr(const char * what)849 syntaxerr(const char *what)
850 {
851 	/* 23<<- is the longest redirection, I think */
852 	char redir[8];
853 	const char *s;
854 	struct tokeninfo const *tt;
855 	int c;
856 
857 	if (!what)
858 		what = Tunexpected;
859 	REJECT;
860 	c = token(0);
861  Again:
862 	switch (c) {
863 	case 0:
864 		if (nesting.start_token) {
865 			c = nesting.start_token;
866 			source->errline = nesting.start_line;
867 			what = "unmatched";
868 			goto Again;
869 		}
870 		/* don't quote the EOF */
871 		yyerror("%s: unexpected EOF", Tsynerr);
872 		/* NOTREACHED */
873 
874 	case LWORD:
875 		s = snptreef(NULL, 32, Tf_S, yylval.cp);
876 		break;
877 
878 	case REDIR:
879 		s = snptreef(redir, sizeof(redir), Tft_R, yylval.iop);
880 		break;
881 
882 	default:
883 		for (tt = tokentab; tt->name; tt++)
884 			if (tt->val == c)
885 			    break;
886 		if (tt->name)
887 			s = tt->name;
888 		else {
889 			if (c > 0 && c < 256) {
890 				redir[0] = c;
891 				redir[1] = '\0';
892 			} else
893 				shf_snprintf(redir, sizeof(redir),
894 					"?%d", c);
895 			s = redir;
896 		}
897 	}
898 	yyerror(Tf_sD_s_qs, Tsynerr, what, s);
899 }
900 
901 static void
nesting_push(struct nesting_state * save,int tok)902 nesting_push(struct nesting_state *save, int tok)
903 {
904 	*save = nesting;
905 	nesting.start_token = tok;
906 	nesting.start_line = source->line;
907 }
908 
909 static void
nesting_pop(struct nesting_state * saved)910 nesting_pop(struct nesting_state *saved)
911 {
912 	nesting = *saved;
913 }
914 
915 static struct op *
newtp(int type)916 newtp(int type)
917 {
918 	struct op *t;
919 
920 	t = alloc(sizeof(struct op), ATEMP);
921 	t->type = type;
922 	t->u.evalflags = 0;
923 	t->args = NULL;
924 	t->vars = NULL;
925 	t->ioact = NULL;
926 	t->left = t->right = NULL;
927 	t->str = NULL;
928 	return (t);
929 }
930 
931 struct op *
compile(Source * s,bool skiputf8bom,bool doalias)932 compile(Source *s, bool skiputf8bom, bool doalias)
933 {
934 	nesting.start_token = 0;
935 	nesting.start_line = 0;
936 	herep = heres;
937 	source = s;
938 	if (skiputf8bom)
939 		yyskiputf8bom();
940 	yyparse(doalias);
941 	return (outtree);
942 }
943 
944 /* Check if we are in the middle of reading an alias */
945 static int
inalias(struct source * s)946 inalias(struct source *s)
947 {
948 	while (s && s->type == SALIAS) {
949 		if (!(s->flags & SF_ALIASEND))
950 			return (1);
951 		s = s->next;
952 	}
953 	return (0);
954 }
955 
956 
957 /*
958  * Order important - indexed by Test_meta values
959  * Note that ||, &&, ( and ) can't appear in as unquoted strings
960  * in normal shell input, so these can be interpreted unambiguously
961  * in the evaluation pass.
962  */
963 static const char dbtest_or[] = { CHAR, '|', CHAR, '|', EOS };
964 static const char dbtest_and[] = { CHAR, '&', CHAR, '&', EOS };
965 static const char dbtest_not[] = { CHAR, '!', EOS };
966 static const char dbtest_oparen[] = { CHAR, '(', EOS };
967 static const char dbtest_cparen[] = { CHAR, ')', EOS };
968 const char * const dbtest_tokens[] = {
969 	dbtest_or, dbtest_and, dbtest_not,
970 	dbtest_oparen, dbtest_cparen
971 };
972 static const char db_close[] = { CHAR, ']', CHAR, ']', EOS };
973 static const char db_lthan[] = { CHAR, '<', EOS };
974 static const char db_gthan[] = { CHAR, '>', EOS };
975 
976 /*
977  * Test if the current token is a whatever. Accepts the current token if
978  * it is. Returns 0 if it is not, non-zero if it is (in the case of
979  * TM_UNOP and TM_BINOP, the returned value is a Test_op).
980  */
981 static Test_op
dbtestp_isa(Test_env * te,Test_meta meta)982 dbtestp_isa(Test_env *te, Test_meta meta)
983 {
984 	int c = tpeek(CMDASN | (meta == TM_BINOP ? 0 : CONTIN));
985 	bool uqword;
986 	char *save = NULL;
987 	Test_op ret = TO_NONOP;
988 
989 	/* unquoted word? */
990 	uqword = c == LWORD && *ident;
991 
992 	if (meta == TM_OR)
993 		ret = c == LOGOR ? TO_NONNULL : TO_NONOP;
994 	else if (meta == TM_AND)
995 		ret = c == LOGAND ? TO_NONNULL : TO_NONOP;
996 	else if (meta == TM_NOT)
997 		ret = (uqword && !strcmp(yylval.cp,
998 		    dbtest_tokens[(int)TM_NOT])) ? TO_NONNULL : TO_NONOP;
999 	else if (meta == TM_OPAREN)
1000 		ret = c == '(' /*)*/ ? TO_NONNULL : TO_NONOP;
1001 	else if (meta == TM_CPAREN)
1002 		ret = c == /*(*/ ')' ? TO_NONNULL : TO_NONOP;
1003 	else if (meta == TM_UNOP || meta == TM_BINOP) {
1004 		if (meta == TM_BINOP && c == REDIR &&
1005 		    (yylval.iop->ioflag == IOREAD ||
1006 		    yylval.iop->ioflag == IOWRITE)) {
1007 			ret = TO_NONNULL;
1008 			save = wdcopy(yylval.iop->ioflag == IOREAD ?
1009 			    db_lthan : db_gthan, ATEMP);
1010 		} else if (uqword && (ret = test_isop(meta, ident)))
1011 			save = yylval.cp;
1012 	} else
1013 		/* meta == TM_END */
1014 		ret = (uqword && !strcmp(yylval.cp,
1015 		    db_close)) ? TO_NONNULL : TO_NONOP;
1016 	if (ret != TO_NONOP) {
1017 		ACCEPT;
1018 		if ((unsigned int)meta < NELEM(dbtest_tokens))
1019 			save = wdcopy(dbtest_tokens[(int)meta], ATEMP);
1020 		if (save)
1021 			XPput(*te->pos.av, save);
1022 	}
1023 	return (ret);
1024 }
1025 
1026 static const char *
dbtestp_getopnd(Test_env * te,Test_op op MKSH_A_UNUSED,bool do_eval MKSH_A_UNUSED)1027 dbtestp_getopnd(Test_env *te, Test_op op MKSH_A_UNUSED,
1028     bool do_eval MKSH_A_UNUSED)
1029 {
1030 	int c = tpeek(CMDASN);
1031 
1032 	if (c != LWORD)
1033 		return (NULL);
1034 
1035 	ACCEPT;
1036 	XPput(*te->pos.av, yylval.cp);
1037 
1038 	return (null);
1039 }
1040 
1041 static int
dbtestp_eval(Test_env * te MKSH_A_UNUSED,Test_op op MKSH_A_UNUSED,const char * opnd1 MKSH_A_UNUSED,const char * opnd2 MKSH_A_UNUSED,bool do_eval MKSH_A_UNUSED)1042 dbtestp_eval(Test_env *te MKSH_A_UNUSED, Test_op op MKSH_A_UNUSED,
1043     const char *opnd1 MKSH_A_UNUSED, const char *opnd2 MKSH_A_UNUSED,
1044     bool do_eval MKSH_A_UNUSED)
1045 {
1046 	return (1);
1047 }
1048 
1049 static void
dbtestp_error(Test_env * te,int offset,const char * msg)1050 dbtestp_error(Test_env *te, int offset, const char *msg)
1051 {
1052 	te->flags |= TEF_ERROR;
1053 
1054 	if (offset < 0) {
1055 		REJECT;
1056 		/* Kludgy to say the least... */
1057 		symbol = LWORD;
1058 		yylval.cp = *(XPptrv(*te->pos.av) + XPsize(*te->pos.av) +
1059 		    offset);
1060 	}
1061 	syntaxerr(msg);
1062 }
1063 
1064 #if HAVE_SELECT
1065 
1066 #ifndef EOVERFLOW
1067 #ifdef ERANGE
1068 #define EOVERFLOW	ERANGE
1069 #else
1070 #define EOVERFLOW	EINVAL
1071 #endif
1072 #endif
1073 
1074 bool
parse_usec(const char * s,struct timeval * tv)1075 parse_usec(const char *s, struct timeval *tv)
1076 {
1077 	struct timeval tt;
1078 	int i;
1079 
1080 	tv->tv_sec = 0;
1081 	/* parse integral part */
1082 	while (ksh_isdigit(*s)) {
1083 		tt.tv_sec = tv->tv_sec * 10 + ksh_numdig(*s++);
1084 		/*XXX this overflow check maybe UB */
1085 		if (tt.tv_sec / 10 != tv->tv_sec) {
1086 			errno = EOVERFLOW;
1087 			return (true);
1088 		}
1089 		tv->tv_sec = tt.tv_sec;
1090 	}
1091 
1092 	tv->tv_usec = 0;
1093 	if (!*s)
1094 		/* no decimal fraction */
1095 		return (false);
1096 	else if (*s++ != '.') {
1097 		/* junk after integral part */
1098 		errno = EINVAL;
1099 		return (true);
1100 	}
1101 
1102 	/* parse decimal fraction */
1103 	i = 100000;
1104 	while (ksh_isdigit(*s)) {
1105 		tv->tv_usec += i * ksh_numdig(*s++);
1106 		if (i == 1)
1107 			break;
1108 		i /= 10;
1109 	}
1110 	/* check for junk after fractional part */
1111 	while (ksh_isdigit(*s))
1112 		++s;
1113 	if (*s) {
1114 		errno = EINVAL;
1115 		return (true);
1116 	}
1117 
1118 	/* end of input string reached, no errors */
1119 	return (false);
1120 }
1121 #endif
1122 
1123 /*
1124  * Helper function called from within lex.c:yylex() to parse
1125  * a COMSUB recursively using the main shell parser and lexer
1126  */
1127 char *
yyrecursive(int subtype)1128 yyrecursive(int subtype)
1129 {
1130 	struct op *t;
1131 	char *cp;
1132 	struct yyrecursive_state *ys;
1133 	int stok, etok;
1134 
1135 	if (subtype != COMSUB) {
1136 		stok = '{';
1137 		etok = '}';
1138 	} else {
1139 		stok = '(';
1140 		etok = ')';
1141 	}
1142 
1143 	ys = alloc(sizeof(struct yyrecursive_state), ATEMP);
1144 
1145 	/* tell the lexer to accept a closing parenthesis as EOD */
1146 	ys->old_nesting_type = subshell_nesting_type;
1147 	subshell_nesting_type = etok;
1148 
1149 	/* push reject state, parse recursively, pop reject state */
1150 	ys->old_reject = reject;
1151 	ys->old_symbol = symbol;
1152 	ACCEPT;
1153 	memcpy(ys->old_heres, heres, sizeof(heres));
1154 	ys->old_herep = herep;
1155 	herep = heres;
1156 	ys->next = e->yyrecursive_statep;
1157 	e->yyrecursive_statep = ys;
1158 	/* we use TPAREN as a helper container here */
1159 	t = nested(TPAREN, stok, etok, ALIAS);
1160 	yyrecursive_pop(false);
1161 
1162 	/* t->left because nested(TPAREN, ...) hides our goodies there */
1163 	cp = snptreef(NULL, 0, Tf_T, t->left);
1164 	tfree(t, ATEMP);
1165 
1166 	return (cp);
1167 }
1168 
1169 void
yyrecursive_pop(bool popall)1170 yyrecursive_pop(bool popall)
1171 {
1172 	struct yyrecursive_state *ys;
1173 
1174  popnext:
1175 	if (!(ys = e->yyrecursive_statep))
1176 		return;
1177 	e->yyrecursive_statep = ys->next;
1178 
1179 	memcpy(heres, ys->old_heres, sizeof(heres));
1180 	herep = ys->old_herep;
1181 	reject = ys->old_reject;
1182 	symbol = ys->old_symbol;
1183 
1184 	subshell_nesting_type = ys->old_nesting_type;
1185 
1186 	afree(ys, ATEMP);
1187 	if (popall)
1188 		goto popnext;
1189 }
1190