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