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