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