parser.c revision 221669
1/*- 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Kenneth Almquist. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 4. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33#ifndef lint 34#if 0 35static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; 36#endif 37#endif /* not lint */ 38#include <sys/cdefs.h> 39__FBSDID("$FreeBSD: head/bin/sh/parser.c 221669 2011-05-08 17:40:10Z jilles $"); 40 41#include <stdlib.h> 42#include <unistd.h> 43#include <stdio.h> 44 45#include "shell.h" 46#include "parser.h" 47#include "nodes.h" 48#include "expand.h" /* defines rmescapes() */ 49#include "syntax.h" 50#include "options.h" 51#include "input.h" 52#include "output.h" 53#include "var.h" 54#include "error.h" 55#include "memalloc.h" 56#include "mystring.h" 57#include "alias.h" 58#include "show.h" 59#include "eval.h" 60#include "exec.h" /* to check for special builtins */ 61#ifndef NO_HISTORY 62#include "myhistedit.h" 63#endif 64 65/* 66 * Shell command parser. 67 */ 68 69#define EOFMARKLEN 79 70#define PROMPTLEN 128 71 72/* values of checkkwd variable */ 73#define CHKALIAS 0x1 74#define CHKKWD 0x2 75#define CHKNL 0x4 76 77/* values returned by readtoken */ 78#include "token.h" 79 80 81 82struct heredoc { 83 struct heredoc *next; /* next here document in list */ 84 union node *here; /* redirection node */ 85 char *eofmark; /* string indicating end of input */ 86 int striptabs; /* if set, strip leading tabs */ 87}; 88 89struct parser_temp { 90 struct parser_temp *next; 91 void *data; 92}; 93 94 95static struct heredoc *heredoclist; /* list of here documents to read */ 96static int doprompt; /* if set, prompt the user */ 97static int needprompt; /* true if interactive and at start of line */ 98static int lasttoken; /* last token read */ 99MKINIT int tokpushback; /* last token pushed back */ 100static char *wordtext; /* text of last word returned by readtoken */ 101MKINIT int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */ 102static struct nodelist *backquotelist; 103static union node *redirnode; 104static struct heredoc *heredoc; 105static int quoteflag; /* set if (part of) last token was quoted */ 106static int startlinno; /* line # where last token started */ 107static int funclinno; /* line # where the current function started */ 108static struct parser_temp *parser_temp; 109 110 111static union node *list(int, int); 112static union node *andor(void); 113static union node *pipeline(void); 114static union node *command(void); 115static union node *simplecmd(union node **, union node *); 116static union node *makename(void); 117static void parsefname(void); 118static void parseheredoc(void); 119static int peektoken(void); 120static int readtoken(void); 121static int xxreadtoken(void); 122static int readtoken1(int, char const *, char *, int); 123static int noexpand(char *); 124static void synexpect(int) __dead2; 125static void synerror(const char *) __dead2; 126static void setprompt(int); 127 128 129static void * 130parser_temp_alloc(size_t len) 131{ 132 struct parser_temp *t; 133 134 INTOFF; 135 t = ckmalloc(sizeof(*t)); 136 t->data = NULL; 137 t->next = parser_temp; 138 parser_temp = t; 139 t->data = ckmalloc(len); 140 INTON; 141 return t->data; 142} 143 144 145static void * 146parser_temp_realloc(void *ptr, size_t len) 147{ 148 struct parser_temp *t; 149 150 INTOFF; 151 t = parser_temp; 152 if (ptr != t->data) 153 error("bug: parser_temp_realloc misused"); 154 t->data = ckrealloc(t->data, len); 155 INTON; 156 return t->data; 157} 158 159 160static void 161parser_temp_free_upto(void *ptr) 162{ 163 struct parser_temp *t; 164 int done = 0; 165 166 INTOFF; 167 while (parser_temp != NULL && !done) { 168 t = parser_temp; 169 parser_temp = t->next; 170 done = t->data == ptr; 171 ckfree(t->data); 172 ckfree(t); 173 } 174 INTON; 175 if (!done) 176 error("bug: parser_temp_free_upto misused"); 177} 178 179 180static void 181parser_temp_free_all(void) 182{ 183 struct parser_temp *t; 184 185 INTOFF; 186 while (parser_temp != NULL) { 187 t = parser_temp; 188 parser_temp = t->next; 189 ckfree(t->data); 190 ckfree(t); 191 } 192 INTON; 193} 194 195 196/* 197 * Read and parse a command. Returns NEOF on end of file. (NULL is a 198 * valid parse tree indicating a blank line.) 199 */ 200 201union node * 202parsecmd(int interact) 203{ 204 int t; 205 206 /* This assumes the parser is not re-entered, 207 * which could happen if we add command substitution on PS1/PS2. 208 */ 209 parser_temp_free_all(); 210 heredoclist = NULL; 211 212 tokpushback = 0; 213 doprompt = interact; 214 if (doprompt) 215 setprompt(1); 216 else 217 setprompt(0); 218 needprompt = 0; 219 t = readtoken(); 220 if (t == TEOF) 221 return NEOF; 222 if (t == TNL) 223 return NULL; 224 tokpushback++; 225 return list(1, 1); 226} 227 228 229static union node * 230list(int nlflag, int erflag) 231{ 232 union node *ntop, *n1, *n2, *n3; 233 int tok; 234 235 checkkwd = CHKNL | CHKKWD | CHKALIAS; 236 if (!nlflag && !erflag && tokendlist[peektoken()]) 237 return NULL; 238 ntop = n1 = NULL; 239 for (;;) { 240 n2 = andor(); 241 tok = readtoken(); 242 if (tok == TBACKGND) { 243 if (n2->type == NCMD || n2->type == NPIPE) { 244 n2->ncmd.backgnd = 1; 245 } else if (n2->type == NREDIR) { 246 n2->type = NBACKGND; 247 } else { 248 n3 = (union node *)stalloc(sizeof (struct nredir)); 249 n3->type = NBACKGND; 250 n3->nredir.n = n2; 251 n3->nredir.redirect = NULL; 252 n2 = n3; 253 } 254 } 255 if (ntop == NULL) 256 ntop = n2; 257 else if (n1 == NULL) { 258 n1 = (union node *)stalloc(sizeof (struct nbinary)); 259 n1->type = NSEMI; 260 n1->nbinary.ch1 = ntop; 261 n1->nbinary.ch2 = n2; 262 ntop = n1; 263 } 264 else { 265 n3 = (union node *)stalloc(sizeof (struct nbinary)); 266 n3->type = NSEMI; 267 n3->nbinary.ch1 = n1->nbinary.ch2; 268 n3->nbinary.ch2 = n2; 269 n1->nbinary.ch2 = n3; 270 n1 = n3; 271 } 272 switch (tok) { 273 case TBACKGND: 274 case TSEMI: 275 tok = readtoken(); 276 /* FALLTHROUGH */ 277 case TNL: 278 if (tok == TNL) { 279 parseheredoc(); 280 if (nlflag) 281 return ntop; 282 } else if (tok == TEOF && nlflag) { 283 parseheredoc(); 284 return ntop; 285 } else { 286 tokpushback++; 287 } 288 checkkwd = CHKNL | CHKKWD | CHKALIAS; 289 if (!nlflag && !erflag && tokendlist[peektoken()]) 290 return ntop; 291 break; 292 case TEOF: 293 if (heredoclist) 294 parseheredoc(); 295 else 296 pungetc(); /* push back EOF on input */ 297 return ntop; 298 default: 299 if (nlflag || erflag) 300 synexpect(-1); 301 tokpushback++; 302 return ntop; 303 } 304 } 305} 306 307 308 309static union node * 310andor(void) 311{ 312 union node *n1, *n2, *n3; 313 int t; 314 315 n1 = pipeline(); 316 for (;;) { 317 if ((t = readtoken()) == TAND) { 318 t = NAND; 319 } else if (t == TOR) { 320 t = NOR; 321 } else { 322 tokpushback++; 323 return n1; 324 } 325 n2 = pipeline(); 326 n3 = (union node *)stalloc(sizeof (struct nbinary)); 327 n3->type = t; 328 n3->nbinary.ch1 = n1; 329 n3->nbinary.ch2 = n2; 330 n1 = n3; 331 } 332} 333 334 335 336static union node * 337pipeline(void) 338{ 339 union node *n1, *n2, *pipenode; 340 struct nodelist *lp, *prev; 341 int negate, t; 342 343 negate = 0; 344 checkkwd = CHKNL | CHKKWD | CHKALIAS; 345 TRACE(("pipeline: entered\n")); 346 while (readtoken() == TNOT) 347 negate = !negate; 348 tokpushback++; 349 n1 = command(); 350 if (readtoken() == TPIPE) { 351 pipenode = (union node *)stalloc(sizeof (struct npipe)); 352 pipenode->type = NPIPE; 353 pipenode->npipe.backgnd = 0; 354 lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); 355 pipenode->npipe.cmdlist = lp; 356 lp->n = n1; 357 do { 358 prev = lp; 359 lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); 360 checkkwd = CHKNL | CHKKWD | CHKALIAS; 361 t = readtoken(); 362 tokpushback++; 363 if (t == TNOT) 364 lp->n = pipeline(); 365 else 366 lp->n = command(); 367 prev->next = lp; 368 } while (readtoken() == TPIPE); 369 lp->next = NULL; 370 n1 = pipenode; 371 } 372 tokpushback++; 373 if (negate) { 374 n2 = (union node *)stalloc(sizeof (struct nnot)); 375 n2->type = NNOT; 376 n2->nnot.com = n1; 377 return n2; 378 } else 379 return n1; 380} 381 382 383 384static union node * 385command(void) 386{ 387 union node *n1, *n2; 388 union node *ap, **app; 389 union node *cp, **cpp; 390 union node *redir, **rpp; 391 int t; 392 int is_subshell; 393 394 checkkwd = CHKNL | CHKKWD | CHKALIAS; 395 is_subshell = 0; 396 redir = NULL; 397 n1 = NULL; 398 rpp = &redir; 399 400 /* Check for redirection which may precede command */ 401 while (readtoken() == TREDIR) { 402 *rpp = n2 = redirnode; 403 rpp = &n2->nfile.next; 404 parsefname(); 405 } 406 tokpushback++; 407 408 switch (readtoken()) { 409 case TIF: 410 n1 = (union node *)stalloc(sizeof (struct nif)); 411 n1->type = NIF; 412 if ((n1->nif.test = list(0, 0)) == NULL) 413 synexpect(-1); 414 if (readtoken() != TTHEN) 415 synexpect(TTHEN); 416 n1->nif.ifpart = list(0, 0); 417 n2 = n1; 418 while (readtoken() == TELIF) { 419 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif)); 420 n2 = n2->nif.elsepart; 421 n2->type = NIF; 422 if ((n2->nif.test = list(0, 0)) == NULL) 423 synexpect(-1); 424 if (readtoken() != TTHEN) 425 synexpect(TTHEN); 426 n2->nif.ifpart = list(0, 0); 427 } 428 if (lasttoken == TELSE) 429 n2->nif.elsepart = list(0, 0); 430 else { 431 n2->nif.elsepart = NULL; 432 tokpushback++; 433 } 434 if (readtoken() != TFI) 435 synexpect(TFI); 436 checkkwd = CHKKWD | CHKALIAS; 437 break; 438 case TWHILE: 439 case TUNTIL: { 440 int got; 441 n1 = (union node *)stalloc(sizeof (struct nbinary)); 442 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL; 443 if ((n1->nbinary.ch1 = list(0, 0)) == NULL) 444 synexpect(-1); 445 if ((got=readtoken()) != TDO) { 446TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); 447 synexpect(TDO); 448 } 449 n1->nbinary.ch2 = list(0, 0); 450 if (readtoken() != TDONE) 451 synexpect(TDONE); 452 checkkwd = CHKKWD | CHKALIAS; 453 break; 454 } 455 case TFOR: 456 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext)) 457 synerror("Bad for loop variable"); 458 n1 = (union node *)stalloc(sizeof (struct nfor)); 459 n1->type = NFOR; 460 n1->nfor.var = wordtext; 461 while (readtoken() == TNL) 462 ; 463 if (lasttoken == TWORD && ! quoteflag && equal(wordtext, "in")) { 464 app = ≈ 465 while (readtoken() == TWORD) { 466 n2 = (union node *)stalloc(sizeof (struct narg)); 467 n2->type = NARG; 468 n2->narg.text = wordtext; 469 n2->narg.backquote = backquotelist; 470 *app = n2; 471 app = &n2->narg.next; 472 } 473 *app = NULL; 474 n1->nfor.args = ap; 475 if (lasttoken != TNL && lasttoken != TSEMI) 476 synexpect(-1); 477 } else { 478 static char argvars[5] = { 479 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' 480 }; 481 n2 = (union node *)stalloc(sizeof (struct narg)); 482 n2->type = NARG; 483 n2->narg.text = argvars; 484 n2->narg.backquote = NULL; 485 n2->narg.next = NULL; 486 n1->nfor.args = n2; 487 /* 488 * Newline or semicolon here is optional (but note 489 * that the original Bourne shell only allowed NL). 490 */ 491 if (lasttoken != TNL && lasttoken != TSEMI) 492 tokpushback++; 493 } 494 checkkwd = CHKNL | CHKKWD | CHKALIAS; 495 if ((t = readtoken()) == TDO) 496 t = TDONE; 497 else if (t == TBEGIN) 498 t = TEND; 499 else 500 synexpect(-1); 501 n1->nfor.body = list(0, 0); 502 if (readtoken() != t) 503 synexpect(t); 504 checkkwd = CHKKWD | CHKALIAS; 505 break; 506 case TCASE: 507 n1 = (union node *)stalloc(sizeof (struct ncase)); 508 n1->type = NCASE; 509 if (readtoken() != TWORD) 510 synexpect(TWORD); 511 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg)); 512 n2->type = NARG; 513 n2->narg.text = wordtext; 514 n2->narg.backquote = backquotelist; 515 n2->narg.next = NULL; 516 while (readtoken() == TNL); 517 if (lasttoken != TWORD || ! equal(wordtext, "in")) 518 synerror("expecting \"in\""); 519 cpp = &n1->ncase.cases; 520 checkkwd = CHKNL | CHKKWD, readtoken(); 521 while (lasttoken != TESAC) { 522 *cpp = cp = (union node *)stalloc(sizeof (struct nclist)); 523 cp->type = NCLIST; 524 app = &cp->nclist.pattern; 525 if (lasttoken == TLP) 526 readtoken(); 527 for (;;) { 528 *app = ap = (union node *)stalloc(sizeof (struct narg)); 529 ap->type = NARG; 530 ap->narg.text = wordtext; 531 ap->narg.backquote = backquotelist; 532 checkkwd = CHKNL | CHKKWD; 533 if (readtoken() != TPIPE) 534 break; 535 app = &ap->narg.next; 536 readtoken(); 537 } 538 ap->narg.next = NULL; 539 if (lasttoken != TRP) 540 synexpect(TRP); 541 cp->nclist.body = list(0, 0); 542 543 checkkwd = CHKNL | CHKKWD | CHKALIAS; 544 if ((t = readtoken()) != TESAC) { 545 if (t != TENDCASE) 546 synexpect(TENDCASE); 547 else 548 checkkwd = CHKNL | CHKKWD, readtoken(); 549 } 550 cpp = &cp->nclist.next; 551 } 552 *cpp = NULL; 553 checkkwd = CHKKWD | CHKALIAS; 554 break; 555 case TLP: 556 n1 = (union node *)stalloc(sizeof (struct nredir)); 557 n1->type = NSUBSHELL; 558 n1->nredir.n = list(0, 0); 559 n1->nredir.redirect = NULL; 560 if (readtoken() != TRP) 561 synexpect(TRP); 562 checkkwd = CHKKWD | CHKALIAS; 563 is_subshell = 1; 564 break; 565 case TBEGIN: 566 n1 = list(0, 0); 567 if (readtoken() != TEND) 568 synexpect(TEND); 569 checkkwd = CHKKWD | CHKALIAS; 570 break; 571 /* Handle an empty command like other simple commands. */ 572 case TBACKGND: 573 case TSEMI: 574 case TAND: 575 case TOR: 576 /* 577 * An empty command before a ; doesn't make much sense, and 578 * should certainly be disallowed in the case of `if ;'. 579 */ 580 if (!redir) 581 synexpect(-1); 582 case TNL: 583 case TEOF: 584 case TWORD: 585 case TRP: 586 tokpushback++; 587 n1 = simplecmd(rpp, redir); 588 return n1; 589 default: 590 synexpect(-1); 591 } 592 593 /* Now check for redirection which may follow command */ 594 while (readtoken() == TREDIR) { 595 *rpp = n2 = redirnode; 596 rpp = &n2->nfile.next; 597 parsefname(); 598 } 599 tokpushback++; 600 *rpp = NULL; 601 if (redir) { 602 if (!is_subshell) { 603 n2 = (union node *)stalloc(sizeof (struct nredir)); 604 n2->type = NREDIR; 605 n2->nredir.n = n1; 606 n1 = n2; 607 } 608 n1->nredir.redirect = redir; 609 } 610 611 return n1; 612} 613 614 615static union node * 616simplecmd(union node **rpp, union node *redir) 617{ 618 union node *args, **app; 619 union node **orig_rpp = rpp; 620 union node *n = NULL; 621 int special; 622 623 /* If we don't have any redirections already, then we must reset */ 624 /* rpp to be the address of the local redir variable. */ 625 if (redir == 0) 626 rpp = &redir; 627 628 args = NULL; 629 app = &args; 630 /* 631 * We save the incoming value, because we need this for shell 632 * functions. There can not be a redirect or an argument between 633 * the function name and the open parenthesis. 634 */ 635 orig_rpp = rpp; 636 637 for (;;) { 638 if (readtoken() == TWORD) { 639 n = (union node *)stalloc(sizeof (struct narg)); 640 n->type = NARG; 641 n->narg.text = wordtext; 642 n->narg.backquote = backquotelist; 643 *app = n; 644 app = &n->narg.next; 645 } else if (lasttoken == TREDIR) { 646 *rpp = n = redirnode; 647 rpp = &n->nfile.next; 648 parsefname(); /* read name of redirection file */ 649 } else if (lasttoken == TLP && app == &args->narg.next 650 && rpp == orig_rpp) { 651 /* We have a function */ 652 if (readtoken() != TRP) 653 synexpect(TRP); 654 funclinno = plinno; 655 /* 656 * - Require plain text. 657 * - Functions with '/' cannot be called. 658 * - Reject name=(). 659 * - Reject ksh extended glob patterns. 660 */ 661 if (!noexpand(n->narg.text) || quoteflag || 662 strchr(n->narg.text, '/') || 663 strchr("!%*+-=?@}~", 664 n->narg.text[strlen(n->narg.text) - 1])) 665 synerror("Bad function name"); 666 rmescapes(n->narg.text); 667 if (find_builtin(n->narg.text, &special) >= 0 && 668 special) 669 synerror("Cannot override a special builtin with a function"); 670 n->type = NDEFUN; 671 n->narg.next = command(); 672 funclinno = 0; 673 return n; 674 } else { 675 tokpushback++; 676 break; 677 } 678 } 679 *app = NULL; 680 *rpp = NULL; 681 n = (union node *)stalloc(sizeof (struct ncmd)); 682 n->type = NCMD; 683 n->ncmd.backgnd = 0; 684 n->ncmd.args = args; 685 n->ncmd.redirect = redir; 686 return n; 687} 688 689static union node * 690makename(void) 691{ 692 union node *n; 693 694 n = (union node *)stalloc(sizeof (struct narg)); 695 n->type = NARG; 696 n->narg.next = NULL; 697 n->narg.text = wordtext; 698 n->narg.backquote = backquotelist; 699 return n; 700} 701 702void 703fixredir(union node *n, const char *text, int err) 704{ 705 TRACE(("Fix redir %s %d\n", text, err)); 706 if (!err) 707 n->ndup.vname = NULL; 708 709 if (is_digit(text[0]) && text[1] == '\0') 710 n->ndup.dupfd = digit_val(text[0]); 711 else if (text[0] == '-' && text[1] == '\0') 712 n->ndup.dupfd = -1; 713 else { 714 715 if (err) 716 synerror("Bad fd number"); 717 else 718 n->ndup.vname = makename(); 719 } 720} 721 722 723static void 724parsefname(void) 725{ 726 union node *n = redirnode; 727 728 if (readtoken() != TWORD) 729 synexpect(-1); 730 if (n->type == NHERE) { 731 struct heredoc *here = heredoc; 732 struct heredoc *p; 733 int i; 734 735 if (quoteflag == 0) 736 n->type = NXHERE; 737 TRACE(("Here document %d\n", n->type)); 738 if (here->striptabs) { 739 while (*wordtext == '\t') 740 wordtext++; 741 } 742 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN) 743 synerror("Illegal eof marker for << redirection"); 744 rmescapes(wordtext); 745 here->eofmark = wordtext; 746 here->next = NULL; 747 if (heredoclist == NULL) 748 heredoclist = here; 749 else { 750 for (p = heredoclist ; p->next ; p = p->next); 751 p->next = here; 752 } 753 } else if (n->type == NTOFD || n->type == NFROMFD) { 754 fixredir(n, wordtext, 0); 755 } else { 756 n->nfile.fname = makename(); 757 } 758} 759 760 761/* 762 * Input any here documents. 763 */ 764 765static void 766parseheredoc(void) 767{ 768 struct heredoc *here; 769 union node *n; 770 771 while (heredoclist) { 772 here = heredoclist; 773 heredoclist = here->next; 774 if (needprompt) { 775 setprompt(2); 776 needprompt = 0; 777 } 778 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX, 779 here->eofmark, here->striptabs); 780 n = (union node *)stalloc(sizeof (struct narg)); 781 n->narg.type = NARG; 782 n->narg.next = NULL; 783 n->narg.text = wordtext; 784 n->narg.backquote = backquotelist; 785 here->here->nhere.doc = n; 786 } 787} 788 789static int 790peektoken(void) 791{ 792 int t; 793 794 t = readtoken(); 795 tokpushback++; 796 return (t); 797} 798 799static int 800readtoken(void) 801{ 802 int t; 803 struct alias *ap; 804#ifdef DEBUG 805 int alreadyseen = tokpushback; 806#endif 807 808 top: 809 t = xxreadtoken(); 810 811 /* 812 * eat newlines 813 */ 814 if (checkkwd & CHKNL) { 815 while (t == TNL) { 816 parseheredoc(); 817 t = xxreadtoken(); 818 } 819 } 820 821 /* 822 * check for keywords and aliases 823 */ 824 if (t == TWORD && !quoteflag) 825 { 826 const char * const *pp; 827 828 if (checkkwd & CHKKWD) 829 for (pp = parsekwd; *pp; pp++) { 830 if (**pp == *wordtext && equal(*pp, wordtext)) 831 { 832 lasttoken = t = pp - parsekwd + KWDOFFSET; 833 TRACE(("keyword %s recognized\n", tokname[t])); 834 goto out; 835 } 836 } 837 if (checkkwd & CHKALIAS && 838 (ap = lookupalias(wordtext, 1)) != NULL) { 839 pushstring(ap->val, strlen(ap->val), ap); 840 goto top; 841 } 842 } 843out: 844 if (t != TNOT) 845 checkkwd = 0; 846 847#ifdef DEBUG 848 if (!alreadyseen) 849 TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : "")); 850 else 851 TRACE(("reread token %s %s\n", tokname[t], t == TWORD ? wordtext : "")); 852#endif 853 return (t); 854} 855 856 857/* 858 * Read the next input token. 859 * If the token is a word, we set backquotelist to the list of cmds in 860 * backquotes. We set quoteflag to true if any part of the word was 861 * quoted. 862 * If the token is TREDIR, then we set redirnode to a structure containing 863 * the redirection. 864 * In all cases, the variable startlinno is set to the number of the line 865 * on which the token starts. 866 * 867 * [Change comment: here documents and internal procedures] 868 * [Readtoken shouldn't have any arguments. Perhaps we should make the 869 * word parsing code into a separate routine. In this case, readtoken 870 * doesn't need to have any internal procedures, but parseword does. 871 * We could also make parseoperator in essence the main routine, and 872 * have parseword (readtoken1?) handle both words and redirection.] 873 */ 874 875#define RETURN(token) return lasttoken = token 876 877static int 878xxreadtoken(void) 879{ 880 int c; 881 882 if (tokpushback) { 883 tokpushback = 0; 884 return lasttoken; 885 } 886 if (needprompt) { 887 setprompt(2); 888 needprompt = 0; 889 } 890 startlinno = plinno; 891 for (;;) { /* until token or start of word found */ 892 c = pgetc_macro(); 893 switch (c) { 894 case ' ': case '\t': 895 continue; 896 case '#': 897 while ((c = pgetc()) != '\n' && c != PEOF); 898 pungetc(); 899 continue; 900 case '\\': 901 if (pgetc() == '\n') { 902 startlinno = ++plinno; 903 if (doprompt) 904 setprompt(2); 905 else 906 setprompt(0); 907 continue; 908 } 909 pungetc(); 910 goto breakloop; 911 case '\n': 912 plinno++; 913 needprompt = doprompt; 914 RETURN(TNL); 915 case PEOF: 916 RETURN(TEOF); 917 case '&': 918 if (pgetc() == '&') 919 RETURN(TAND); 920 pungetc(); 921 RETURN(TBACKGND); 922 case '|': 923 if (pgetc() == '|') 924 RETURN(TOR); 925 pungetc(); 926 RETURN(TPIPE); 927 case ';': 928 if (pgetc() == ';') 929 RETURN(TENDCASE); 930 pungetc(); 931 RETURN(TSEMI); 932 case '(': 933 RETURN(TLP); 934 case ')': 935 RETURN(TRP); 936 default: 937 goto breakloop; 938 } 939 } 940breakloop: 941 return readtoken1(c, BASESYNTAX, (char *)NULL, 0); 942#undef RETURN 943} 944 945 946#define MAXNEST_static 8 947struct tokenstate 948{ 949 const char *syntax; /* *SYNTAX */ 950 int parenlevel; /* levels of parentheses in arithmetic */ 951 enum tokenstate_category 952 { 953 TSTATE_TOP, 954 TSTATE_VAR_OLD, /* ${var+-=?}, inherits dquotes */ 955 TSTATE_VAR_NEW, /* other ${var...}, own dquote state */ 956 TSTATE_ARITH 957 } category; 958}; 959 960 961/* 962 * Called to parse command substitutions. 963 */ 964 965static char * 966parsebackq(char *out, struct nodelist **pbqlist, 967 int oldstyle, int dblquote, int quoted) 968{ 969 struct nodelist **nlpp; 970 union node *n; 971 char *volatile str; 972 struct jmploc jmploc; 973 struct jmploc *const savehandler = handler; 974 int savelen; 975 int saveprompt; 976 const int bq_startlinno = plinno; 977 char *volatile ostr = NULL; 978 struct parsefile *const savetopfile = getcurrentfile(); 979 struct heredoc *const saveheredoclist = heredoclist; 980 struct heredoc *here; 981 982 str = NULL; 983 if (setjmp(jmploc.loc)) { 984 popfilesupto(savetopfile); 985 if (str) 986 ckfree(str); 987 if (ostr) 988 ckfree(ostr); 989 heredoclist = saveheredoclist; 990 handler = savehandler; 991 if (exception == EXERROR) { 992 startlinno = bq_startlinno; 993 synerror("Error in command substitution"); 994 } 995 longjmp(handler->loc, 1); 996 } 997 INTOFF; 998 savelen = out - stackblock(); 999 if (savelen > 0) { 1000 str = ckmalloc(savelen); 1001 memcpy(str, stackblock(), savelen); 1002 } 1003 handler = &jmploc; 1004 heredoclist = NULL; 1005 INTON; 1006 if (oldstyle) { 1007 /* We must read until the closing backquote, giving special 1008 treatment to some slashes, and then push the string and 1009 reread it as input, interpreting it normally. */ 1010 char *oout; 1011 int c; 1012 int olen; 1013 1014 1015 STARTSTACKSTR(oout); 1016 for (;;) { 1017 if (needprompt) { 1018 setprompt(2); 1019 needprompt = 0; 1020 } 1021 CHECKSTRSPACE(2, oout); 1022 switch (c = pgetc()) { 1023 case '`': 1024 goto done; 1025 1026 case '\\': 1027 if ((c = pgetc()) == '\n') { 1028 plinno++; 1029 if (doprompt) 1030 setprompt(2); 1031 else 1032 setprompt(0); 1033 /* 1034 * If eating a newline, avoid putting 1035 * the newline into the new character 1036 * stream (via the USTPUTC after the 1037 * switch). 1038 */ 1039 continue; 1040 } 1041 if (c != '\\' && c != '`' && c != '$' 1042 && (!dblquote || c != '"')) 1043 USTPUTC('\\', oout); 1044 break; 1045 1046 case '\n': 1047 plinno++; 1048 needprompt = doprompt; 1049 break; 1050 1051 case PEOF: 1052 startlinno = plinno; 1053 synerror("EOF in backquote substitution"); 1054 break; 1055 1056 default: 1057 break; 1058 } 1059 USTPUTC(c, oout); 1060 } 1061done: 1062 USTPUTC('\0', oout); 1063 olen = oout - stackblock(); 1064 INTOFF; 1065 ostr = ckmalloc(olen); 1066 memcpy(ostr, stackblock(), olen); 1067 setinputstring(ostr, 1); 1068 INTON; 1069 } 1070 nlpp = pbqlist; 1071 while (*nlpp) 1072 nlpp = &(*nlpp)->next; 1073 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist)); 1074 (*nlpp)->next = NULL; 1075 1076 if (oldstyle) { 1077 saveprompt = doprompt; 1078 doprompt = 0; 1079 } 1080 1081 n = list(0, oldstyle); 1082 1083 if (oldstyle) 1084 doprompt = saveprompt; 1085 else { 1086 if (readtoken() != TRP) 1087 synexpect(TRP); 1088 } 1089 1090 (*nlpp)->n = n; 1091 if (oldstyle) { 1092 /* 1093 * Start reading from old file again, ignoring any pushed back 1094 * tokens left from the backquote parsing 1095 */ 1096 popfile(); 1097 tokpushback = 0; 1098 } 1099 STARTSTACKSTR(out); 1100 CHECKSTRSPACE(savelen + 1, out); 1101 INTOFF; 1102 if (str) { 1103 memcpy(out, str, savelen); 1104 STADJUST(savelen, out); 1105 ckfree(str); 1106 str = NULL; 1107 } 1108 if (ostr) { 1109 ckfree(ostr); 1110 ostr = NULL; 1111 } 1112 here = saveheredoclist; 1113 if (here != NULL) { 1114 while (here->next != NULL) 1115 here = here->next; 1116 here->next = heredoclist; 1117 heredoclist = saveheredoclist; 1118 } 1119 handler = savehandler; 1120 INTON; 1121 if (quoted) 1122 USTPUTC(CTLBACKQ | CTLQUOTE, out); 1123 else 1124 USTPUTC(CTLBACKQ, out); 1125 return out; 1126} 1127 1128 1129/* 1130 * Called to parse a backslash escape sequence inside $'...'. 1131 * The backslash has already been read. 1132 */ 1133static char * 1134readcstyleesc(char *out) 1135{ 1136 int c, v, i, n; 1137 1138 c = pgetc(); 1139 switch (c) { 1140 case '\0': 1141 synerror("Unterminated quoted string"); 1142 case '\n': 1143 plinno++; 1144 if (doprompt) 1145 setprompt(2); 1146 else 1147 setprompt(0); 1148 return out; 1149 case '\\': 1150 case '\'': 1151 case '"': 1152 v = c; 1153 break; 1154 case 'a': v = '\a'; break; 1155 case 'b': v = '\b'; break; 1156 case 'e': v = '\033'; break; 1157 case 'f': v = '\f'; break; 1158 case 'n': v = '\n'; break; 1159 case 'r': v = '\r'; break; 1160 case 't': v = '\t'; break; 1161 case 'v': v = '\v'; break; 1162 case 'x': 1163 v = 0; 1164 for (;;) { 1165 c = pgetc(); 1166 if (c >= '0' && c <= '9') 1167 v = (v << 4) + c - '0'; 1168 else if (c >= 'A' && c <= 'F') 1169 v = (v << 4) + c - 'A' + 10; 1170 else if (c >= 'a' && c <= 'f') 1171 v = (v << 4) + c - 'a' + 10; 1172 else 1173 break; 1174 } 1175 pungetc(); 1176 break; 1177 case '0': case '1': case '2': case '3': 1178 case '4': case '5': case '6': case '7': 1179 v = c - '0'; 1180 c = pgetc(); 1181 if (c >= '0' && c <= '7') { 1182 v <<= 3; 1183 v += c - '0'; 1184 c = pgetc(); 1185 if (c >= '0' && c <= '7') { 1186 v <<= 3; 1187 v += c - '0'; 1188 } else 1189 pungetc(); 1190 } else 1191 pungetc(); 1192 break; 1193 case 'c': 1194 c = pgetc(); 1195 if (c < 0x3f || c > 0x7a || c == 0x60) 1196 synerror("Bad escape sequence"); 1197 if (c == '\\' && pgetc() != '\\') 1198 synerror("Bad escape sequence"); 1199 if (c == '?') 1200 v = 127; 1201 else 1202 v = c & 0x1f; 1203 break; 1204 case 'u': 1205 case 'U': 1206 n = c == 'U' ? 8 : 4; 1207 v = 0; 1208 for (i = 0; i < n; i++) { 1209 c = pgetc(); 1210 if (c >= '0' && c <= '9') 1211 v = (v << 4) + c - '0'; 1212 else if (c >= 'A' && c <= 'F') 1213 v = (v << 4) + c - 'A' + 10; 1214 else if (c >= 'a' && c <= 'f') 1215 v = (v << 4) + c - 'a' + 10; 1216 else 1217 synerror("Bad escape sequence"); 1218 } 1219 if (v == 0 || (v >= 0xd800 && v <= 0xdfff)) 1220 synerror("Bad escape sequence"); 1221 /* We really need iconv here. */ 1222 if (initial_localeisutf8 && v > 127) { 1223 CHECKSTRSPACE(4, out); 1224 /* 1225 * We cannot use wctomb() as the locale may have 1226 * changed. 1227 */ 1228 if (v <= 0x7ff) { 1229 USTPUTC(0xc0 | v >> 6, out); 1230 USTPUTC(0x80 | (v & 0x3f), out); 1231 return out; 1232 } else if (v <= 0xffff) { 1233 USTPUTC(0xe0 | v >> 12, out); 1234 USTPUTC(0x80 | ((v >> 6) & 0x3f), out); 1235 USTPUTC(0x80 | (v & 0x3f), out); 1236 return out; 1237 } else if (v <= 0x10ffff) { 1238 USTPUTC(0xf0 | v >> 18, out); 1239 USTPUTC(0x80 | ((v >> 12) & 0x3f), out); 1240 USTPUTC(0x80 | ((v >> 6) & 0x3f), out); 1241 USTPUTC(0x80 | (v & 0x3f), out); 1242 return out; 1243 } 1244 } 1245 if (v > 127) 1246 v = '?'; 1247 break; 1248 default: 1249 synerror("Bad escape sequence"); 1250 } 1251 v = (char)v; 1252 /* 1253 * We can't handle NUL bytes. 1254 * POSIX says we should skip till the closing quote. 1255 */ 1256 if (v == '\0') { 1257 while ((c = pgetc()) != '\'') { 1258 if (c == '\\') 1259 c = pgetc(); 1260 if (c == PEOF) 1261 synerror("Unterminated quoted string"); 1262 } 1263 pungetc(); 1264 return out; 1265 } 1266 if (SQSYNTAX[v] == CCTL) 1267 USTPUTC(CTLESC, out); 1268 USTPUTC(v, out); 1269 return out; 1270} 1271 1272 1273/* 1274 * If eofmark is NULL, read a word or a redirection symbol. If eofmark 1275 * is not NULL, read a here document. In the latter case, eofmark is the 1276 * word which marks the end of the document and striptabs is true if 1277 * leading tabs should be stripped from the document. The argument firstc 1278 * is the first character of the input token or document. 1279 * 1280 * Because C does not have internal subroutines, I have simulated them 1281 * using goto's to implement the subroutine linkage. The following macros 1282 * will run code that appears at the end of readtoken1. 1283 */ 1284 1285#define CHECKEND() {goto checkend; checkend_return:;} 1286#define PARSEREDIR() {goto parseredir; parseredir_return:;} 1287#define PARSESUB() {goto parsesub; parsesub_return:;} 1288#define PARSEARITH() {goto parsearith; parsearith_return:;} 1289 1290static int 1291readtoken1(int firstc, char const *initialsyntax, char *eofmark, int striptabs) 1292{ 1293 int c = firstc; 1294 char *out; 1295 int len; 1296 char line[EOFMARKLEN + 1]; 1297 struct nodelist *bqlist; 1298 int quotef; 1299 int newvarnest; 1300 int level; 1301 int synentry; 1302 struct tokenstate state_static[MAXNEST_static]; 1303 int maxnest = MAXNEST_static; 1304 struct tokenstate *state = state_static; 1305 int sqiscstyle = 0; 1306 1307 startlinno = plinno; 1308 quotef = 0; 1309 bqlist = NULL; 1310 newvarnest = 0; 1311 level = 0; 1312 state[level].syntax = initialsyntax; 1313 state[level].parenlevel = 0; 1314 state[level].category = TSTATE_TOP; 1315 1316 STARTSTACKSTR(out); 1317 loop: { /* for each line, until end of word */ 1318 CHECKEND(); /* set c to PEOF if at end of here document */ 1319 for (;;) { /* until end of line or end of word */ 1320 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */ 1321 1322 synentry = state[level].syntax[c]; 1323 1324 switch(synentry) { 1325 case CNL: /* '\n' */ 1326 if (state[level].syntax == BASESYNTAX) 1327 goto endword; /* exit outer loop */ 1328 USTPUTC(c, out); 1329 plinno++; 1330 if (doprompt) 1331 setprompt(2); 1332 else 1333 setprompt(0); 1334 c = pgetc(); 1335 goto loop; /* continue outer loop */ 1336 case CSBACK: 1337 if (sqiscstyle) { 1338 out = readcstyleesc(out); 1339 break; 1340 } 1341 /* FALLTHROUGH */ 1342 case CWORD: 1343 USTPUTC(c, out); 1344 break; 1345 case CCTL: 1346 if (eofmark == NULL || initialsyntax != SQSYNTAX) 1347 USTPUTC(CTLESC, out); 1348 USTPUTC(c, out); 1349 break; 1350 case CBACK: /* backslash */ 1351 c = pgetc(); 1352 if (c == PEOF) { 1353 USTPUTC('\\', out); 1354 pungetc(); 1355 } else if (c == '\n') { 1356 plinno++; 1357 if (doprompt) 1358 setprompt(2); 1359 else 1360 setprompt(0); 1361 } else { 1362 if (state[level].syntax == DQSYNTAX && 1363 c != '\\' && c != '`' && c != '$' && 1364 (c != '"' || (eofmark != NULL && 1365 newvarnest == 0)) && 1366 (c != '}' || state[level].category != TSTATE_VAR_OLD)) 1367 USTPUTC('\\', out); 1368 if ((eofmark == NULL || 1369 newvarnest > 0) && 1370 state[level].syntax == BASESYNTAX) 1371 USTPUTC(CTLQUOTEMARK, out); 1372 if (SQSYNTAX[c] == CCTL) 1373 USTPUTC(CTLESC, out); 1374 USTPUTC(c, out); 1375 if ((eofmark == NULL || 1376 newvarnest > 0) && 1377 state[level].syntax == BASESYNTAX && 1378 state[level].category == TSTATE_VAR_OLD) 1379 USTPUTC(CTLQUOTEEND, out); 1380 quotef++; 1381 } 1382 break; 1383 case CSQUOTE: 1384 USTPUTC(CTLQUOTEMARK, out); 1385 state[level].syntax = SQSYNTAX; 1386 sqiscstyle = 0; 1387 break; 1388 case CDQUOTE: 1389 USTPUTC(CTLQUOTEMARK, out); 1390 state[level].syntax = DQSYNTAX; 1391 break; 1392 case CENDQUOTE: 1393 if (eofmark != NULL && newvarnest == 0) 1394 USTPUTC(c, out); 1395 else { 1396 if (state[level].category == TSTATE_VAR_OLD) 1397 USTPUTC(CTLQUOTEEND, out); 1398 state[level].syntax = BASESYNTAX; 1399 quotef++; 1400 } 1401 break; 1402 case CVAR: /* '$' */ 1403 PARSESUB(); /* parse substitution */ 1404 break; 1405 case CENDVAR: /* '}' */ 1406 if (level > 0 && 1407 ((state[level].category == TSTATE_VAR_OLD && 1408 state[level].syntax == 1409 state[level - 1].syntax) || 1410 (state[level].category == TSTATE_VAR_NEW && 1411 state[level].syntax == BASESYNTAX))) { 1412 if (state[level].category == TSTATE_VAR_NEW) 1413 newvarnest--; 1414 level--; 1415 USTPUTC(CTLENDVAR, out); 1416 } else { 1417 USTPUTC(c, out); 1418 } 1419 break; 1420 case CLP: /* '(' in arithmetic */ 1421 state[level].parenlevel++; 1422 USTPUTC(c, out); 1423 break; 1424 case CRP: /* ')' in arithmetic */ 1425 if (state[level].parenlevel > 0) { 1426 USTPUTC(c, out); 1427 --state[level].parenlevel; 1428 } else { 1429 if (pgetc() == ')') { 1430 if (level > 0 && 1431 state[level].category == TSTATE_ARITH) { 1432 level--; 1433 USTPUTC(CTLENDARI, out); 1434 } else 1435 USTPUTC(')', out); 1436 } else { 1437 /* 1438 * unbalanced parens 1439 * (don't 2nd guess - no error) 1440 */ 1441 pungetc(); 1442 USTPUTC(')', out); 1443 } 1444 } 1445 break; 1446 case CBQUOTE: /* '`' */ 1447 out = parsebackq(out, &bqlist, 1, 1448 state[level].syntax == DQSYNTAX && 1449 (eofmark == NULL || newvarnest > 0), 1450 state[level].syntax == DQSYNTAX || state[level].syntax == ARISYNTAX); 1451 break; 1452 case CEOF: 1453 goto endword; /* exit outer loop */ 1454 case CIGN: 1455 break; 1456 default: 1457 if (level == 0) 1458 goto endword; /* exit outer loop */ 1459 USTPUTC(c, out); 1460 } 1461 c = pgetc_macro(); 1462 } 1463 } 1464endword: 1465 if (state[level].syntax == ARISYNTAX) 1466 synerror("Missing '))'"); 1467 if (state[level].syntax != BASESYNTAX && eofmark == NULL) 1468 synerror("Unterminated quoted string"); 1469 if (state[level].category == TSTATE_VAR_OLD || 1470 state[level].category == TSTATE_VAR_NEW) { 1471 startlinno = plinno; 1472 synerror("Missing '}'"); 1473 } 1474 if (state != state_static) 1475 parser_temp_free_upto(state); 1476 USTPUTC('\0', out); 1477 len = out - stackblock(); 1478 out = stackblock(); 1479 if (eofmark == NULL) { 1480 if ((c == '>' || c == '<') 1481 && quotef == 0 1482 && len <= 2 1483 && (*out == '\0' || is_digit(*out))) { 1484 PARSEREDIR(); 1485 return lasttoken = TREDIR; 1486 } else { 1487 pungetc(); 1488 } 1489 } 1490 quoteflag = quotef; 1491 backquotelist = bqlist; 1492 grabstackblock(len); 1493 wordtext = out; 1494 return lasttoken = TWORD; 1495/* end of readtoken routine */ 1496 1497 1498/* 1499 * Check to see whether we are at the end of the here document. When this 1500 * is called, c is set to the first character of the next input line. If 1501 * we are at the end of the here document, this routine sets the c to PEOF. 1502 */ 1503 1504checkend: { 1505 if (eofmark) { 1506 if (striptabs) { 1507 while (c == '\t') 1508 c = pgetc(); 1509 } 1510 if (c == *eofmark) { 1511 if (pfgets(line, sizeof line) != NULL) { 1512 char *p, *q; 1513 1514 p = line; 1515 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++); 1516 if (*p == '\n' && *q == '\0') { 1517 c = PEOF; 1518 plinno++; 1519 needprompt = doprompt; 1520 } else { 1521 pushstring(line, strlen(line), NULL); 1522 } 1523 } 1524 } 1525 } 1526 goto checkend_return; 1527} 1528 1529 1530/* 1531 * Parse a redirection operator. The variable "out" points to a string 1532 * specifying the fd to be redirected. The variable "c" contains the 1533 * first character of the redirection operator. 1534 */ 1535 1536parseredir: { 1537 char fd = *out; 1538 union node *np; 1539 1540 np = (union node *)stalloc(sizeof (struct nfile)); 1541 if (c == '>') { 1542 np->nfile.fd = 1; 1543 c = pgetc(); 1544 if (c == '>') 1545 np->type = NAPPEND; 1546 else if (c == '&') 1547 np->type = NTOFD; 1548 else if (c == '|') 1549 np->type = NCLOBBER; 1550 else { 1551 np->type = NTO; 1552 pungetc(); 1553 } 1554 } else { /* c == '<' */ 1555 np->nfile.fd = 0; 1556 c = pgetc(); 1557 if (c == '<') { 1558 if (sizeof (struct nfile) != sizeof (struct nhere)) { 1559 np = (union node *)stalloc(sizeof (struct nhere)); 1560 np->nfile.fd = 0; 1561 } 1562 np->type = NHERE; 1563 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc)); 1564 heredoc->here = np; 1565 if ((c = pgetc()) == '-') { 1566 heredoc->striptabs = 1; 1567 } else { 1568 heredoc->striptabs = 0; 1569 pungetc(); 1570 } 1571 } else if (c == '&') 1572 np->type = NFROMFD; 1573 else if (c == '>') 1574 np->type = NFROMTO; 1575 else { 1576 np->type = NFROM; 1577 pungetc(); 1578 } 1579 } 1580 if (fd != '\0') 1581 np->nfile.fd = digit_val(fd); 1582 redirnode = np; 1583 goto parseredir_return; 1584} 1585 1586 1587/* 1588 * Parse a substitution. At this point, we have read the dollar sign 1589 * and nothing else. 1590 */ 1591 1592parsesub: { 1593 char buf[10]; 1594 int subtype; 1595 int typeloc; 1596 int flags; 1597 char *p; 1598 static const char types[] = "}-+?="; 1599 int bracketed_name = 0; /* used to handle ${[0-9]*} variables */ 1600 int linno; 1601 int length; 1602 int c1; 1603 1604 c = pgetc(); 1605 if (c == '(') { /* $(command) or $((arith)) */ 1606 if (pgetc() == '(') { 1607 PARSEARITH(); 1608 } else { 1609 pungetc(); 1610 out = parsebackq(out, &bqlist, 0, 1611 state[level].syntax == DQSYNTAX && 1612 (eofmark == NULL || newvarnest > 0), 1613 state[level].syntax == DQSYNTAX || 1614 state[level].syntax == ARISYNTAX); 1615 } 1616 } else if (c == '{' || is_name(c) || is_special(c)) { 1617 USTPUTC(CTLVAR, out); 1618 typeloc = out - stackblock(); 1619 USTPUTC(VSNORMAL, out); 1620 subtype = VSNORMAL; 1621 flags = 0; 1622 if (c == '{') { 1623 bracketed_name = 1; 1624 c = pgetc(); 1625 subtype = 0; 1626 } 1627varname: 1628 if (!is_eof(c) && is_name(c)) { 1629 length = 0; 1630 do { 1631 STPUTC(c, out); 1632 c = pgetc(); 1633 length++; 1634 } while (!is_eof(c) && is_in_name(c)); 1635 if (length == 6 && 1636 strncmp(out - length, "LINENO", length) == 0) { 1637 /* Replace the variable name with the 1638 * current line number. */ 1639 linno = plinno; 1640 if (funclinno != 0) 1641 linno -= funclinno - 1; 1642 snprintf(buf, sizeof(buf), "%d", linno); 1643 STADJUST(-6, out); 1644 STPUTS(buf, out); 1645 flags |= VSLINENO; 1646 } 1647 } else if (is_digit(c)) { 1648 if (bracketed_name) { 1649 do { 1650 STPUTC(c, out); 1651 c = pgetc(); 1652 } while (is_digit(c)); 1653 } else { 1654 STPUTC(c, out); 1655 c = pgetc(); 1656 } 1657 } else if (is_special(c)) { 1658 c1 = c; 1659 c = pgetc(); 1660 if (subtype == 0 && c1 == '#') { 1661 subtype = VSLENGTH; 1662 if (strchr(types, c) == NULL && c != ':' && 1663 c != '#' && c != '%') 1664 goto varname; 1665 c1 = c; 1666 c = pgetc(); 1667 if (c1 != '}' && c == '}') { 1668 pungetc(); 1669 c = c1; 1670 goto varname; 1671 } 1672 pungetc(); 1673 c = c1; 1674 c1 = '#'; 1675 subtype = 0; 1676 } 1677 USTPUTC(c1, out); 1678 } else { 1679 subtype = VSERROR; 1680 if (c == '}') 1681 pungetc(); 1682 else if (c == '\n' || c == PEOF) 1683 synerror("Unexpected end of line in substitution"); 1684 else 1685 USTPUTC(c, out); 1686 } 1687 if (subtype == 0) { 1688 switch (c) { 1689 case ':': 1690 flags |= VSNUL; 1691 c = pgetc(); 1692 /*FALLTHROUGH*/ 1693 default: 1694 p = strchr(types, c); 1695 if (p == NULL) { 1696 if (c == '\n' || c == PEOF) 1697 synerror("Unexpected end of line in substitution"); 1698 if (flags == VSNUL) 1699 STPUTC(':', out); 1700 STPUTC(c, out); 1701 subtype = VSERROR; 1702 } else 1703 subtype = p - types + VSNORMAL; 1704 break; 1705 case '%': 1706 case '#': 1707 { 1708 int cc = c; 1709 subtype = c == '#' ? VSTRIMLEFT : 1710 VSTRIMRIGHT; 1711 c = pgetc(); 1712 if (c == cc) 1713 subtype++; 1714 else 1715 pungetc(); 1716 break; 1717 } 1718 } 1719 } else if (subtype != VSERROR) { 1720 if (subtype == VSLENGTH && c != '}') 1721 subtype = VSERROR; 1722 pungetc(); 1723 } 1724 STPUTC('=', out); 1725 if (state[level].syntax == DQSYNTAX || 1726 state[level].syntax == ARISYNTAX) 1727 flags |= VSQUOTE; 1728 *(stackblock() + typeloc) = subtype | flags; 1729 if (subtype != VSNORMAL) { 1730 if (level + 1 >= maxnest) { 1731 maxnest *= 2; 1732 if (state == state_static) { 1733 state = parser_temp_alloc( 1734 maxnest * sizeof(*state)); 1735 memcpy(state, state_static, 1736 MAXNEST_static * sizeof(*state)); 1737 } else 1738 state = parser_temp_realloc(state, 1739 maxnest * sizeof(*state)); 1740 } 1741 level++; 1742 state[level].parenlevel = 0; 1743 if (subtype == VSMINUS || subtype == VSPLUS || 1744 subtype == VSQUESTION || subtype == VSASSIGN) { 1745 /* 1746 * For operators that were in the Bourne shell, 1747 * inherit the double-quote state. 1748 */ 1749 state[level].syntax = state[level - 1].syntax; 1750 state[level].category = TSTATE_VAR_OLD; 1751 } else { 1752 /* 1753 * The other operators take a pattern, 1754 * so go to BASESYNTAX. 1755 * Also, ' and " are now special, even 1756 * in here documents. 1757 */ 1758 state[level].syntax = BASESYNTAX; 1759 state[level].category = TSTATE_VAR_NEW; 1760 newvarnest++; 1761 } 1762 } 1763 } else if (c == '\'' && state[level].syntax == BASESYNTAX) { 1764 /* $'cstylequotes' */ 1765 USTPUTC(CTLQUOTEMARK, out); 1766 state[level].syntax = SQSYNTAX; 1767 sqiscstyle = 1; 1768 } else { 1769 USTPUTC('$', out); 1770 pungetc(); 1771 } 1772 goto parsesub_return; 1773} 1774 1775 1776/* 1777 * Parse an arithmetic expansion (indicate start of one and set state) 1778 */ 1779parsearith: { 1780 1781 if (level + 1 >= maxnest) { 1782 maxnest *= 2; 1783 if (state == state_static) { 1784 state = parser_temp_alloc( 1785 maxnest * sizeof(*state)); 1786 memcpy(state, state_static, 1787 MAXNEST_static * sizeof(*state)); 1788 } else 1789 state = parser_temp_realloc(state, 1790 maxnest * sizeof(*state)); 1791 } 1792 level++; 1793 state[level].syntax = ARISYNTAX; 1794 state[level].parenlevel = 0; 1795 state[level].category = TSTATE_ARITH; 1796 USTPUTC(CTLARI, out); 1797 if (state[level - 1].syntax == DQSYNTAX) 1798 USTPUTC('"',out); 1799 else 1800 USTPUTC(' ',out); 1801 goto parsearith_return; 1802} 1803 1804} /* end of readtoken */ 1805 1806 1807 1808#ifdef mkinit 1809RESET { 1810 tokpushback = 0; 1811 checkkwd = 0; 1812} 1813#endif 1814 1815/* 1816 * Returns true if the text contains nothing to expand (no dollar signs 1817 * or backquotes). 1818 */ 1819 1820static int 1821noexpand(char *text) 1822{ 1823 char *p; 1824 char c; 1825 1826 p = text; 1827 while ((c = *p++) != '\0') { 1828 if ( c == CTLQUOTEMARK) 1829 continue; 1830 if (c == CTLESC) 1831 p++; 1832 else if (BASESYNTAX[(int)c] == CCTL) 1833 return 0; 1834 } 1835 return 1; 1836} 1837 1838 1839/* 1840 * Return true if the argument is a legal variable name (a letter or 1841 * underscore followed by zero or more letters, underscores, and digits). 1842 */ 1843 1844int 1845goodname(const char *name) 1846{ 1847 const char *p; 1848 1849 p = name; 1850 if (! is_name(*p)) 1851 return 0; 1852 while (*++p) { 1853 if (! is_in_name(*p)) 1854 return 0; 1855 } 1856 return 1; 1857} 1858 1859 1860/* 1861 * Called when an unexpected token is read during the parse. The argument 1862 * is the token that is expected, or -1 if more than one type of token can 1863 * occur at this point. 1864 */ 1865 1866static void 1867synexpect(int token) 1868{ 1869 char msg[64]; 1870 1871 if (token >= 0) { 1872 fmtstr(msg, 64, "%s unexpected (expecting %s)", 1873 tokname[lasttoken], tokname[token]); 1874 } else { 1875 fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]); 1876 } 1877 synerror(msg); 1878} 1879 1880 1881static void 1882synerror(const char *msg) 1883{ 1884 if (commandname) 1885 outfmt(out2, "%s: %d: ", commandname, startlinno); 1886 outfmt(out2, "Syntax error: %s\n", msg); 1887 error((char *)NULL); 1888} 1889 1890static void 1891setprompt(int which) 1892{ 1893 whichprompt = which; 1894 1895#ifndef NO_HISTORY 1896 if (!el) 1897#endif 1898 { 1899 out2str(getprompt(NULL)); 1900 flushout(out2); 1901 } 1902} 1903 1904/* 1905 * called by editline -- any expansions to the prompt 1906 * should be added here. 1907 */ 1908char * 1909getprompt(void *unused __unused) 1910{ 1911 static char ps[PROMPTLEN]; 1912 char *fmt; 1913 const char *pwd; 1914 int i, trim; 1915 static char internal_error[] = "??"; 1916 1917 /* 1918 * Select prompt format. 1919 */ 1920 switch (whichprompt) { 1921 case 0: 1922 fmt = nullstr; 1923 break; 1924 case 1: 1925 fmt = ps1val(); 1926 break; 1927 case 2: 1928 fmt = ps2val(); 1929 break; 1930 default: 1931 return internal_error; 1932 } 1933 1934 /* 1935 * Format prompt string. 1936 */ 1937 for (i = 0; (i < 127) && (*fmt != '\0'); i++, fmt++) 1938 if (*fmt == '\\') 1939 switch (*++fmt) { 1940 1941 /* 1942 * Hostname. 1943 * 1944 * \h specifies just the local hostname, 1945 * \H specifies fully-qualified hostname. 1946 */ 1947 case 'h': 1948 case 'H': 1949 ps[i] = '\0'; 1950 gethostname(&ps[i], PROMPTLEN - i); 1951 /* Skip to end of hostname. */ 1952 trim = (*fmt == 'h') ? '.' : '\0'; 1953 while ((ps[i+1] != '\0') && (ps[i+1] != trim)) 1954 i++; 1955 break; 1956 1957 /* 1958 * Working directory. 1959 * 1960 * \W specifies just the final component, 1961 * \w specifies the entire path. 1962 */ 1963 case 'W': 1964 case 'w': 1965 pwd = lookupvar("PWD"); 1966 if (pwd == NULL) 1967 pwd = "?"; 1968 if (*fmt == 'W' && 1969 *pwd == '/' && pwd[1] != '\0') 1970 strlcpy(&ps[i], strrchr(pwd, '/') + 1, 1971 PROMPTLEN - i); 1972 else 1973 strlcpy(&ps[i], pwd, PROMPTLEN - i); 1974 /* Skip to end of path. */ 1975 while (ps[i + 1] != '\0') 1976 i++; 1977 break; 1978 1979 /* 1980 * Superuser status. 1981 * 1982 * '$' for normal users, '#' for root. 1983 */ 1984 case '$': 1985 ps[i] = (geteuid() != 0) ? '$' : '#'; 1986 break; 1987 1988 /* 1989 * A literal \. 1990 */ 1991 case '\\': 1992 ps[i] = '\\'; 1993 break; 1994 1995 /* 1996 * Emit unrecognized formats verbatim. 1997 */ 1998 default: 1999 ps[i++] = '\\'; 2000 ps[i] = *fmt; 2001 break; 2002 } 2003 else 2004 ps[i] = *fmt; 2005 ps[i] = '\0'; 2006 return (ps); 2007} 2008