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