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