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 (at) 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 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 ** 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 * 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 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 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 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 910 nesting_pop(struct nesting_state *saved) 911 { 912 nesting = *saved; 913 } 914 915 static struct op * 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 * 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 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 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 * 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 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 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 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 * 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 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