parser.c revision 222134
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 222134 2011-05-20 16:03:36Z 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 == '\0' || *p == '\n') && *q == '\0') { 1517 c = PEOF; 1518 if (*p == '\n') { 1519 plinno++; 1520 needprompt = doprompt; 1521 } 1522 } else { 1523 pushstring(line, strlen(line), NULL); 1524 } 1525 } 1526 } 1527 } 1528 goto checkend_return; 1529} 1530 1531 1532/* 1533 * Parse a redirection operator. The variable "out" points to a string 1534 * specifying the fd to be redirected. The variable "c" contains the 1535 * first character of the redirection operator. 1536 */ 1537 1538parseredir: { 1539 char fd = *out; 1540 union node *np; 1541 1542 np = (union node *)stalloc(sizeof (struct nfile)); 1543 if (c == '>') { 1544 np->nfile.fd = 1; 1545 c = pgetc(); 1546 if (c == '>') 1547 np->type = NAPPEND; 1548 else if (c == '&') 1549 np->type = NTOFD; 1550 else if (c == '|') 1551 np->type = NCLOBBER; 1552 else { 1553 np->type = NTO; 1554 pungetc(); 1555 } 1556 } else { /* c == '<' */ 1557 np->nfile.fd = 0; 1558 c = pgetc(); 1559 if (c == '<') { 1560 if (sizeof (struct nfile) != sizeof (struct nhere)) { 1561 np = (union node *)stalloc(sizeof (struct nhere)); 1562 np->nfile.fd = 0; 1563 } 1564 np->type = NHERE; 1565 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc)); 1566 heredoc->here = np; 1567 if ((c = pgetc()) == '-') { 1568 heredoc->striptabs = 1; 1569 } else { 1570 heredoc->striptabs = 0; 1571 pungetc(); 1572 } 1573 } else if (c == '&') 1574 np->type = NFROMFD; 1575 else if (c == '>') 1576 np->type = NFROMTO; 1577 else { 1578 np->type = NFROM; 1579 pungetc(); 1580 } 1581 } 1582 if (fd != '\0') 1583 np->nfile.fd = digit_val(fd); 1584 redirnode = np; 1585 goto parseredir_return; 1586} 1587 1588 1589/* 1590 * Parse a substitution. At this point, we have read the dollar sign 1591 * and nothing else. 1592 */ 1593 1594parsesub: { 1595 char buf[10]; 1596 int subtype; 1597 int typeloc; 1598 int flags; 1599 char *p; 1600 static const char types[] = "}-+?="; 1601 int bracketed_name = 0; /* used to handle ${[0-9]*} variables */ 1602 int linno; 1603 int length; 1604 int c1; 1605 1606 c = pgetc(); 1607 if (c == '(') { /* $(command) or $((arith)) */ 1608 if (pgetc() == '(') { 1609 PARSEARITH(); 1610 } else { 1611 pungetc(); 1612 out = parsebackq(out, &bqlist, 0, 1613 state[level].syntax == DQSYNTAX && 1614 (eofmark == NULL || newvarnest > 0), 1615 state[level].syntax == DQSYNTAX || 1616 state[level].syntax == ARISYNTAX); 1617 } 1618 } else if (c == '{' || is_name(c) || is_special(c)) { 1619 USTPUTC(CTLVAR, out); 1620 typeloc = out - stackblock(); 1621 USTPUTC(VSNORMAL, out); 1622 subtype = VSNORMAL; 1623 flags = 0; 1624 if (c == '{') { 1625 bracketed_name = 1; 1626 c = pgetc(); 1627 subtype = 0; 1628 } 1629varname: 1630 if (!is_eof(c) && is_name(c)) { 1631 length = 0; 1632 do { 1633 STPUTC(c, out); 1634 c = pgetc(); 1635 length++; 1636 } while (!is_eof(c) && is_in_name(c)); 1637 if (length == 6 && 1638 strncmp(out - length, "LINENO", length) == 0) { 1639 /* Replace the variable name with the 1640 * current line number. */ 1641 linno = plinno; 1642 if (funclinno != 0) 1643 linno -= funclinno - 1; 1644 snprintf(buf, sizeof(buf), "%d", linno); 1645 STADJUST(-6, out); 1646 STPUTS(buf, out); 1647 flags |= VSLINENO; 1648 } 1649 } else if (is_digit(c)) { 1650 if (bracketed_name) { 1651 do { 1652 STPUTC(c, out); 1653 c = pgetc(); 1654 } while (is_digit(c)); 1655 } else { 1656 STPUTC(c, out); 1657 c = pgetc(); 1658 } 1659 } else if (is_special(c)) { 1660 c1 = c; 1661 c = pgetc(); 1662 if (subtype == 0 && c1 == '#') { 1663 subtype = VSLENGTH; 1664 if (strchr(types, c) == NULL && c != ':' && 1665 c != '#' && c != '%') 1666 goto varname; 1667 c1 = c; 1668 c = pgetc(); 1669 if (c1 != '}' && c == '}') { 1670 pungetc(); 1671 c = c1; 1672 goto varname; 1673 } 1674 pungetc(); 1675 c = c1; 1676 c1 = '#'; 1677 subtype = 0; 1678 } 1679 USTPUTC(c1, out); 1680 } else { 1681 subtype = VSERROR; 1682 if (c == '}') 1683 pungetc(); 1684 else if (c == '\n' || c == PEOF) 1685 synerror("Unexpected end of line in substitution"); 1686 else 1687 USTPUTC(c, out); 1688 } 1689 if (subtype == 0) { 1690 switch (c) { 1691 case ':': 1692 flags |= VSNUL; 1693 c = pgetc(); 1694 /*FALLTHROUGH*/ 1695 default: 1696 p = strchr(types, c); 1697 if (p == NULL) { 1698 if (c == '\n' || c == PEOF) 1699 synerror("Unexpected end of line in substitution"); 1700 if (flags == VSNUL) 1701 STPUTC(':', out); 1702 STPUTC(c, out); 1703 subtype = VSERROR; 1704 } else 1705 subtype = p - types + VSNORMAL; 1706 break; 1707 case '%': 1708 case '#': 1709 { 1710 int cc = c; 1711 subtype = c == '#' ? VSTRIMLEFT : 1712 VSTRIMRIGHT; 1713 c = pgetc(); 1714 if (c == cc) 1715 subtype++; 1716 else 1717 pungetc(); 1718 break; 1719 } 1720 } 1721 } else if (subtype != VSERROR) { 1722 if (subtype == VSLENGTH && c != '}') 1723 subtype = VSERROR; 1724 pungetc(); 1725 } 1726 STPUTC('=', out); 1727 if (state[level].syntax == DQSYNTAX || 1728 state[level].syntax == ARISYNTAX) 1729 flags |= VSQUOTE; 1730 *(stackblock() + typeloc) = subtype | flags; 1731 if (subtype != VSNORMAL) { 1732 if (level + 1 >= maxnest) { 1733 maxnest *= 2; 1734 if (state == state_static) { 1735 state = parser_temp_alloc( 1736 maxnest * sizeof(*state)); 1737 memcpy(state, state_static, 1738 MAXNEST_static * sizeof(*state)); 1739 } else 1740 state = parser_temp_realloc(state, 1741 maxnest * sizeof(*state)); 1742 } 1743 level++; 1744 state[level].parenlevel = 0; 1745 if (subtype == VSMINUS || subtype == VSPLUS || 1746 subtype == VSQUESTION || subtype == VSASSIGN) { 1747 /* 1748 * For operators that were in the Bourne shell, 1749 * inherit the double-quote state. 1750 */ 1751 state[level].syntax = state[level - 1].syntax; 1752 state[level].category = TSTATE_VAR_OLD; 1753 } else { 1754 /* 1755 * The other operators take a pattern, 1756 * so go to BASESYNTAX. 1757 * Also, ' and " are now special, even 1758 * in here documents. 1759 */ 1760 state[level].syntax = BASESYNTAX; 1761 state[level].category = TSTATE_VAR_NEW; 1762 newvarnest++; 1763 } 1764 } 1765 } else if (c == '\'' && state[level].syntax == BASESYNTAX) { 1766 /* $'cstylequotes' */ 1767 USTPUTC(CTLQUOTEMARK, out); 1768 state[level].syntax = SQSYNTAX; 1769 sqiscstyle = 1; 1770 } else { 1771 USTPUTC('$', out); 1772 pungetc(); 1773 } 1774 goto parsesub_return; 1775} 1776 1777 1778/* 1779 * Parse an arithmetic expansion (indicate start of one and set state) 1780 */ 1781parsearith: { 1782 1783 if (level + 1 >= maxnest) { 1784 maxnest *= 2; 1785 if (state == state_static) { 1786 state = parser_temp_alloc( 1787 maxnest * sizeof(*state)); 1788 memcpy(state, state_static, 1789 MAXNEST_static * sizeof(*state)); 1790 } else 1791 state = parser_temp_realloc(state, 1792 maxnest * sizeof(*state)); 1793 } 1794 level++; 1795 state[level].syntax = ARISYNTAX; 1796 state[level].parenlevel = 0; 1797 state[level].category = TSTATE_ARITH; 1798 USTPUTC(CTLARI, out); 1799 if (state[level - 1].syntax == DQSYNTAX) 1800 USTPUTC('"',out); 1801 else 1802 USTPUTC(' ',out); 1803 goto parsearith_return; 1804} 1805 1806} /* end of readtoken */ 1807 1808 1809 1810#ifdef mkinit 1811RESET { 1812 tokpushback = 0; 1813 checkkwd = 0; 1814} 1815#endif 1816 1817/* 1818 * Returns true if the text contains nothing to expand (no dollar signs 1819 * or backquotes). 1820 */ 1821 1822static int 1823noexpand(char *text) 1824{ 1825 char *p; 1826 char c; 1827 1828 p = text; 1829 while ((c = *p++) != '\0') { 1830 if ( c == CTLQUOTEMARK) 1831 continue; 1832 if (c == CTLESC) 1833 p++; 1834 else if (BASESYNTAX[(int)c] == CCTL) 1835 return 0; 1836 } 1837 return 1; 1838} 1839 1840 1841/* 1842 * Return true if the argument is a legal variable name (a letter or 1843 * underscore followed by zero or more letters, underscores, and digits). 1844 */ 1845 1846int 1847goodname(const char *name) 1848{ 1849 const char *p; 1850 1851 p = name; 1852 if (! is_name(*p)) 1853 return 0; 1854 while (*++p) { 1855 if (! is_in_name(*p)) 1856 return 0; 1857 } 1858 return 1; 1859} 1860 1861 1862/* 1863 * Called when an unexpected token is read during the parse. The argument 1864 * is the token that is expected, or -1 if more than one type of token can 1865 * occur at this point. 1866 */ 1867 1868static void 1869synexpect(int token) 1870{ 1871 char msg[64]; 1872 1873 if (token >= 0) { 1874 fmtstr(msg, 64, "%s unexpected (expecting %s)", 1875 tokname[lasttoken], tokname[token]); 1876 } else { 1877 fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]); 1878 } 1879 synerror(msg); 1880} 1881 1882 1883static void 1884synerror(const char *msg) 1885{ 1886 if (commandname) 1887 outfmt(out2, "%s: %d: ", commandname, startlinno); 1888 outfmt(out2, "Syntax error: %s\n", msg); 1889 error((char *)NULL); 1890} 1891 1892static void 1893setprompt(int which) 1894{ 1895 whichprompt = which; 1896 1897#ifndef NO_HISTORY 1898 if (!el) 1899#endif 1900 { 1901 out2str(getprompt(NULL)); 1902 flushout(out2); 1903 } 1904} 1905 1906/* 1907 * called by editline -- any expansions to the prompt 1908 * should be added here. 1909 */ 1910char * 1911getprompt(void *unused __unused) 1912{ 1913 static char ps[PROMPTLEN]; 1914 char *fmt; 1915 const char *pwd; 1916 int i, trim; 1917 static char internal_error[] = "??"; 1918 1919 /* 1920 * Select prompt format. 1921 */ 1922 switch (whichprompt) { 1923 case 0: 1924 fmt = nullstr; 1925 break; 1926 case 1: 1927 fmt = ps1val(); 1928 break; 1929 case 2: 1930 fmt = ps2val(); 1931 break; 1932 default: 1933 return internal_error; 1934 } 1935 1936 /* 1937 * Format prompt string. 1938 */ 1939 for (i = 0; (i < 127) && (*fmt != '\0'); i++, fmt++) 1940 if (*fmt == '\\') 1941 switch (*++fmt) { 1942 1943 /* 1944 * Hostname. 1945 * 1946 * \h specifies just the local hostname, 1947 * \H specifies fully-qualified hostname. 1948 */ 1949 case 'h': 1950 case 'H': 1951 ps[i] = '\0'; 1952 gethostname(&ps[i], PROMPTLEN - i); 1953 /* Skip to end of hostname. */ 1954 trim = (*fmt == 'h') ? '.' : '\0'; 1955 while ((ps[i+1] != '\0') && (ps[i+1] != trim)) 1956 i++; 1957 break; 1958 1959 /* 1960 * Working directory. 1961 * 1962 * \W specifies just the final component, 1963 * \w specifies the entire path. 1964 */ 1965 case 'W': 1966 case 'w': 1967 pwd = lookupvar("PWD"); 1968 if (pwd == NULL) 1969 pwd = "?"; 1970 if (*fmt == 'W' && 1971 *pwd == '/' && pwd[1] != '\0') 1972 strlcpy(&ps[i], strrchr(pwd, '/') + 1, 1973 PROMPTLEN - i); 1974 else 1975 strlcpy(&ps[i], pwd, PROMPTLEN - i); 1976 /* Skip to end of path. */ 1977 while (ps[i + 1] != '\0') 1978 i++; 1979 break; 1980 1981 /* 1982 * Superuser status. 1983 * 1984 * '$' for normal users, '#' for root. 1985 */ 1986 case '$': 1987 ps[i] = (geteuid() != 0) ? '$' : '#'; 1988 break; 1989 1990 /* 1991 * A literal \. 1992 */ 1993 case '\\': 1994 ps[i] = '\\'; 1995 break; 1996 1997 /* 1998 * Emit unrecognized formats verbatim. 1999 */ 2000 default: 2001 ps[i++] = '\\'; 2002 ps[i] = *fmt; 2003 break; 2004 } 2005 else 2006 ps[i] = *fmt; 2007 ps[i] = '\0'; 2008 return (ps); 2009} 2010