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