1*47139Sbostic /*- 2*47139Sbostic * Copyright (c) 1991 The Regents of the University of California. 3*47139Sbostic * All rights reserved. 4*47139Sbostic * 5*47139Sbostic * This code is derived from software contributed to Berkeley by 6*47139Sbostic * Kenneth Almquist. 7*47139Sbostic * 8*47139Sbostic * %sccs.include.redist.c% 9*47139Sbostic */ 10*47139Sbostic 11*47139Sbostic #ifndef lint 12*47139Sbostic static char sccsid[] = "@(#)parser.c 5.1 (Berkeley) 03/07/91"; 13*47139Sbostic #endif /* not lint */ 14*47139Sbostic 15*47139Sbostic #include "shell.h" 16*47139Sbostic #include "parser.h" 17*47139Sbostic #include "nodes.h" 18*47139Sbostic #include "expand.h" /* defines rmescapes() */ 19*47139Sbostic #include "redir.h" /* defines copyfd() */ 20*47139Sbostic #include "syntax.h" 21*47139Sbostic #include "options.h" 22*47139Sbostic #include "input.h" 23*47139Sbostic #include "output.h" 24*47139Sbostic #include "var.h" 25*47139Sbostic #include "error.h" 26*47139Sbostic #include "memalloc.h" 27*47139Sbostic #include "mystring.h" 28*47139Sbostic 29*47139Sbostic 30*47139Sbostic /* 31*47139Sbostic * Shell command parser. 32*47139Sbostic */ 33*47139Sbostic 34*47139Sbostic #define EOFMARKLEN 79 35*47139Sbostic 36*47139Sbostic /* values returned by readtoken */ 37*47139Sbostic #include "token.def" 38*47139Sbostic 39*47139Sbostic 40*47139Sbostic 41*47139Sbostic struct heredoc { 42*47139Sbostic struct heredoc *next; /* next here document in list */ 43*47139Sbostic union node *here; /* redirection node */ 44*47139Sbostic char *eofmark; /* string indicating end of input */ 45*47139Sbostic int striptabs; /* if set, strip leading tabs */ 46*47139Sbostic }; 47*47139Sbostic 48*47139Sbostic 49*47139Sbostic 50*47139Sbostic struct heredoc *heredoclist; /* list of here documents to read */ 51*47139Sbostic int parsebackquote; /* nonzero if we are inside backquotes */ 52*47139Sbostic int doprompt; /* if set, prompt the user */ 53*47139Sbostic int needprompt; /* true if interactive and at start of line */ 54*47139Sbostic int lasttoken; /* last token read */ 55*47139Sbostic MKINIT int tokpushback; /* last token pushed back */ 56*47139Sbostic char *wordtext; /* text of last word returned by readtoken */ 57*47139Sbostic struct nodelist *backquotelist; 58*47139Sbostic union node *redirnode; 59*47139Sbostic struct heredoc *heredoc; 60*47139Sbostic int quoteflag; /* set if (part of) last token was quoted */ 61*47139Sbostic int startlinno; /* line # where last token started */ 62*47139Sbostic 63*47139Sbostic 64*47139Sbostic #define GDB_HACK 1 /* avoid local declarations which gdb can't handle */ 65*47139Sbostic #ifdef GDB_HACK 66*47139Sbostic static const char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'}; 67*47139Sbostic static const char types[] = "}-+?="; 68*47139Sbostic #endif 69*47139Sbostic 70*47139Sbostic 71*47139Sbostic #ifdef __STDC__ 72*47139Sbostic STATIC union node *list(int); 73*47139Sbostic STATIC union node *andor(void); 74*47139Sbostic STATIC union node *pipeline(void); 75*47139Sbostic STATIC union node *command(void); 76*47139Sbostic STATIC union node *simplecmd(void); 77*47139Sbostic STATIC void parsefname(void); 78*47139Sbostic STATIC void parseheredoc(void); 79*47139Sbostic STATIC void checkkwd(void); 80*47139Sbostic STATIC int readtoken(void); 81*47139Sbostic STATIC int readtoken1(int, char const *, char *, int); 82*47139Sbostic STATIC void attyline(void); 83*47139Sbostic STATIC int noexpand(char *); 84*47139Sbostic STATIC void synexpect(int); 85*47139Sbostic STATIC void synerror(char *); 86*47139Sbostic #else 87*47139Sbostic STATIC union node *list(); 88*47139Sbostic STATIC union node *andor(); 89*47139Sbostic STATIC union node *pipeline(); 90*47139Sbostic STATIC union node *command(); 91*47139Sbostic STATIC union node *simplecmd(); 92*47139Sbostic STATIC void parsefname(); 93*47139Sbostic STATIC void parseheredoc(); 94*47139Sbostic STATIC void checkkwd(); 95*47139Sbostic STATIC int readtoken(); 96*47139Sbostic STATIC int readtoken1(); 97*47139Sbostic STATIC void attyline(); 98*47139Sbostic STATIC int noexpand(); 99*47139Sbostic STATIC void synexpect(); 100*47139Sbostic STATIC void synerror(); 101*47139Sbostic #endif 102*47139Sbostic 103*47139Sbostic #if ATTY 104*47139Sbostic #ifdef __STDC__ 105*47139Sbostic STATIC void putprompt(char *); 106*47139Sbostic #else 107*47139Sbostic STATIC void putprompt(); 108*47139Sbostic #endif 109*47139Sbostic #else /* not ATTY */ 110*47139Sbostic #define putprompt(s) out2str(s) 111*47139Sbostic #endif 112*47139Sbostic 113*47139Sbostic 114*47139Sbostic 115*47139Sbostic 116*47139Sbostic /* 117*47139Sbostic * Read and parse a command. Returns NEOF on end of file. (NULL is a 118*47139Sbostic * valid parse tree indicating a blank line.) 119*47139Sbostic */ 120*47139Sbostic 121*47139Sbostic union node * 122*47139Sbostic parsecmd(interact) { 123*47139Sbostic int t; 124*47139Sbostic 125*47139Sbostic doprompt = interact; 126*47139Sbostic if (doprompt) 127*47139Sbostic putprompt(ps1val()); 128*47139Sbostic needprompt = 0; 129*47139Sbostic if ((t = readtoken()) == TEOF) 130*47139Sbostic return NEOF; 131*47139Sbostic if (t == TNL) 132*47139Sbostic return NULL; 133*47139Sbostic tokpushback++; 134*47139Sbostic return list(1); 135*47139Sbostic } 136*47139Sbostic 137*47139Sbostic 138*47139Sbostic STATIC union node * 139*47139Sbostic list(nlflag) { 140*47139Sbostic union node *n1, *n2, *n3; 141*47139Sbostic 142*47139Sbostic checkkwd(); 143*47139Sbostic if (nlflag == 0 && tokendlist[lasttoken]) 144*47139Sbostic return NULL; 145*47139Sbostic n1 = andor(); 146*47139Sbostic for (;;) { 147*47139Sbostic switch (readtoken()) { 148*47139Sbostic case TBACKGND: 149*47139Sbostic if (n1->type == NCMD || n1->type == NPIPE) { 150*47139Sbostic n1->ncmd.backgnd = 1; 151*47139Sbostic } else if (n1->type == NREDIR) { 152*47139Sbostic n1->type = NBACKGND; 153*47139Sbostic } else { 154*47139Sbostic n3 = (union node *)stalloc(sizeof (struct nredir)); 155*47139Sbostic n3->type = NBACKGND; 156*47139Sbostic n3->nredir.n = n1; 157*47139Sbostic n3->nredir.redirect = NULL; 158*47139Sbostic n1 = n3; 159*47139Sbostic } 160*47139Sbostic goto tsemi; 161*47139Sbostic case TNL: 162*47139Sbostic tokpushback++; 163*47139Sbostic /* fall through */ 164*47139Sbostic tsemi: case TSEMI: 165*47139Sbostic if (readtoken() == TNL) { 166*47139Sbostic parseheredoc(); 167*47139Sbostic if (nlflag) 168*47139Sbostic return n1; 169*47139Sbostic } else { 170*47139Sbostic tokpushback++; 171*47139Sbostic } 172*47139Sbostic checkkwd(); 173*47139Sbostic if (tokendlist[lasttoken]) 174*47139Sbostic return n1; 175*47139Sbostic n2 = andor(); 176*47139Sbostic n3 = (union node *)stalloc(sizeof (struct nbinary)); 177*47139Sbostic n3->type = NSEMI; 178*47139Sbostic n3->nbinary.ch1 = n1; 179*47139Sbostic n3->nbinary.ch2 = n2; 180*47139Sbostic n1 = n3; 181*47139Sbostic break; 182*47139Sbostic case TEOF: 183*47139Sbostic if (heredoclist) 184*47139Sbostic parseheredoc(); 185*47139Sbostic else 186*47139Sbostic pungetc(); /* push back EOF on input */ 187*47139Sbostic return n1; 188*47139Sbostic default: 189*47139Sbostic if (nlflag) 190*47139Sbostic synexpect(-1); 191*47139Sbostic tokpushback++; 192*47139Sbostic return n1; 193*47139Sbostic } 194*47139Sbostic } 195*47139Sbostic } 196*47139Sbostic 197*47139Sbostic 198*47139Sbostic 199*47139Sbostic STATIC union node * 200*47139Sbostic andor() { 201*47139Sbostic union node *n1, *n2, *n3; 202*47139Sbostic int t; 203*47139Sbostic 204*47139Sbostic n1 = pipeline(); 205*47139Sbostic for (;;) { 206*47139Sbostic if ((t = readtoken()) == TAND) { 207*47139Sbostic t = NAND; 208*47139Sbostic } else if (t == TOR) { 209*47139Sbostic t = NOR; 210*47139Sbostic } else { 211*47139Sbostic tokpushback++; 212*47139Sbostic return n1; 213*47139Sbostic } 214*47139Sbostic n2 = pipeline(); 215*47139Sbostic n3 = (union node *)stalloc(sizeof (struct nbinary)); 216*47139Sbostic n3->type = t; 217*47139Sbostic n3->nbinary.ch1 = n1; 218*47139Sbostic n3->nbinary.ch2 = n2; 219*47139Sbostic n1 = n3; 220*47139Sbostic } 221*47139Sbostic } 222*47139Sbostic 223*47139Sbostic 224*47139Sbostic 225*47139Sbostic STATIC union node * 226*47139Sbostic pipeline() { 227*47139Sbostic union node *n1, *pipenode; 228*47139Sbostic struct nodelist *lp, *prev; 229*47139Sbostic 230*47139Sbostic n1 = command(); 231*47139Sbostic if (readtoken() == TPIPE) { 232*47139Sbostic pipenode = (union node *)stalloc(sizeof (struct npipe)); 233*47139Sbostic pipenode->type = NPIPE; 234*47139Sbostic pipenode->npipe.backgnd = 0; 235*47139Sbostic lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); 236*47139Sbostic pipenode->npipe.cmdlist = lp; 237*47139Sbostic lp->n = n1; 238*47139Sbostic do { 239*47139Sbostic prev = lp; 240*47139Sbostic lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); 241*47139Sbostic lp->n = command(); 242*47139Sbostic prev->next = lp; 243*47139Sbostic } while (readtoken() == TPIPE); 244*47139Sbostic lp->next = NULL; 245*47139Sbostic n1 = pipenode; 246*47139Sbostic } 247*47139Sbostic tokpushback++; 248*47139Sbostic return n1; 249*47139Sbostic } 250*47139Sbostic 251*47139Sbostic 252*47139Sbostic 253*47139Sbostic STATIC union node * 254*47139Sbostic command() { 255*47139Sbostic union node *n1, *n2; 256*47139Sbostic union node *ap, **app; 257*47139Sbostic union node *cp, **cpp; 258*47139Sbostic union node *redir, **rpp; 259*47139Sbostic int t; 260*47139Sbostic 261*47139Sbostic checkkwd(); 262*47139Sbostic switch (readtoken()) { 263*47139Sbostic case TIF: 264*47139Sbostic n1 = (union node *)stalloc(sizeof (struct nif)); 265*47139Sbostic n1->type = NIF; 266*47139Sbostic n1->nif.test = list(0); 267*47139Sbostic if (readtoken() != TTHEN) 268*47139Sbostic synexpect(TTHEN); 269*47139Sbostic n1->nif.ifpart = list(0); 270*47139Sbostic n2 = n1; 271*47139Sbostic while (readtoken() == TELIF) { 272*47139Sbostic n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif)); 273*47139Sbostic n2 = n2->nif.elsepart; 274*47139Sbostic n2->type = NIF; 275*47139Sbostic n2->nif.test = list(0); 276*47139Sbostic if (readtoken() != TTHEN) 277*47139Sbostic synexpect(TTHEN); 278*47139Sbostic n2->nif.ifpart = list(0); 279*47139Sbostic } 280*47139Sbostic if (lasttoken == TELSE) 281*47139Sbostic n2->nif.elsepart = list(0); 282*47139Sbostic else { 283*47139Sbostic n2->nif.elsepart = NULL; 284*47139Sbostic tokpushback++; 285*47139Sbostic } 286*47139Sbostic if (readtoken() != TFI) 287*47139Sbostic synexpect(TFI); 288*47139Sbostic break; 289*47139Sbostic case TWHILE: 290*47139Sbostic case TUNTIL: 291*47139Sbostic n1 = (union node *)stalloc(sizeof (struct nbinary)); 292*47139Sbostic n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL; 293*47139Sbostic n1->nbinary.ch1 = list(0); 294*47139Sbostic if (readtoken() != TDO) 295*47139Sbostic synexpect(TDO); 296*47139Sbostic n1->nbinary.ch2 = list(0); 297*47139Sbostic if (readtoken() != TDONE) 298*47139Sbostic synexpect(TDONE); 299*47139Sbostic break; 300*47139Sbostic case TFOR: 301*47139Sbostic if (readtoken() != TWORD || quoteflag || ! goodname(wordtext)) 302*47139Sbostic synerror("Bad for loop variable"); 303*47139Sbostic n1 = (union node *)stalloc(sizeof (struct nfor)); 304*47139Sbostic n1->type = NFOR; 305*47139Sbostic n1->nfor.var = wordtext; 306*47139Sbostic if (readtoken() == TWORD && ! quoteflag && equal(wordtext, "in")) { 307*47139Sbostic app = ≈ 308*47139Sbostic while (readtoken() == TWORD) { 309*47139Sbostic n2 = (union node *)stalloc(sizeof (struct narg)); 310*47139Sbostic n2->type = NARG; 311*47139Sbostic n2->narg.text = wordtext; 312*47139Sbostic n2->narg.backquote = backquotelist; 313*47139Sbostic *app = n2; 314*47139Sbostic app = &n2->narg.next; 315*47139Sbostic } 316*47139Sbostic *app = NULL; 317*47139Sbostic n1->nfor.args = ap; 318*47139Sbostic } else { 319*47139Sbostic #ifndef GDB_HACK 320*47139Sbostic static const char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE, 321*47139Sbostic '@', '=', '\0'}; 322*47139Sbostic #endif 323*47139Sbostic n2 = (union node *)stalloc(sizeof (struct narg)); 324*47139Sbostic n2->type = NARG; 325*47139Sbostic n2->narg.text = (char *)argvars; 326*47139Sbostic n2->narg.backquote = NULL; 327*47139Sbostic n2->narg.next = NULL; 328*47139Sbostic n1->nfor.args = n2; 329*47139Sbostic } 330*47139Sbostic if (lasttoken != TNL && lasttoken != TSEMI) 331*47139Sbostic synexpect(-1); 332*47139Sbostic checkkwd(); 333*47139Sbostic if ((t = readtoken()) == TDO) 334*47139Sbostic t = TDONE; 335*47139Sbostic else if (t == TBEGIN) 336*47139Sbostic t = TEND; 337*47139Sbostic else 338*47139Sbostic synexpect(-1); 339*47139Sbostic n1->nfor.body = list(0); 340*47139Sbostic if (readtoken() != t) 341*47139Sbostic synexpect(t); 342*47139Sbostic break; 343*47139Sbostic case TCASE: 344*47139Sbostic n1 = (union node *)stalloc(sizeof (struct ncase)); 345*47139Sbostic n1->type = NCASE; 346*47139Sbostic if (readtoken() != TWORD) 347*47139Sbostic synexpect(TWORD); 348*47139Sbostic n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg)); 349*47139Sbostic n2->type = NARG; 350*47139Sbostic n2->narg.text = wordtext; 351*47139Sbostic n2->narg.backquote = backquotelist; 352*47139Sbostic n2->narg.next = NULL; 353*47139Sbostic while (readtoken() == TNL); 354*47139Sbostic if (lasttoken != TWORD || ! equal(wordtext, "in")) 355*47139Sbostic synerror("expecting \"in\""); 356*47139Sbostic cpp = &n1->ncase.cases; 357*47139Sbostic while (checkkwd(), readtoken() == TWORD) { 358*47139Sbostic *cpp = cp = (union node *)stalloc(sizeof (struct nclist)); 359*47139Sbostic cp->type = NCLIST; 360*47139Sbostic app = &cp->nclist.pattern; 361*47139Sbostic for (;;) { 362*47139Sbostic *app = ap = (union node *)stalloc(sizeof (struct narg)); 363*47139Sbostic ap->type = NARG; 364*47139Sbostic ap->narg.text = wordtext; 365*47139Sbostic ap->narg.backquote = backquotelist; 366*47139Sbostic if (readtoken() != TPIPE) 367*47139Sbostic break; 368*47139Sbostic app = &ap->narg.next; 369*47139Sbostic if (readtoken() != TWORD) 370*47139Sbostic synexpect(TWORD); 371*47139Sbostic } 372*47139Sbostic ap->narg.next = NULL; 373*47139Sbostic if (lasttoken != TRP) 374*47139Sbostic synexpect(TRP); 375*47139Sbostic cp->nclist.body = list(0); 376*47139Sbostic if ((t = readtoken()) == TESAC) 377*47139Sbostic tokpushback++; 378*47139Sbostic else if (t != TENDCASE) 379*47139Sbostic synexpect(TENDCASE); 380*47139Sbostic cpp = &cp->nclist.next; 381*47139Sbostic } 382*47139Sbostic *cpp = NULL; 383*47139Sbostic if (lasttoken != TESAC) 384*47139Sbostic synexpect(TESAC); 385*47139Sbostic break; 386*47139Sbostic case TLP: 387*47139Sbostic n1 = (union node *)stalloc(sizeof (struct nredir)); 388*47139Sbostic n1->type = NSUBSHELL; 389*47139Sbostic n1->nredir.n = list(0); 390*47139Sbostic n1->nredir.redirect = NULL; 391*47139Sbostic if (readtoken() != TRP) 392*47139Sbostic synexpect(TRP); 393*47139Sbostic break; 394*47139Sbostic case TBEGIN: 395*47139Sbostic n1 = list(0); 396*47139Sbostic if (readtoken() != TEND) 397*47139Sbostic synexpect(TEND); 398*47139Sbostic break; 399*47139Sbostic case TWORD: 400*47139Sbostic case TREDIR: 401*47139Sbostic tokpushback++; 402*47139Sbostic return simplecmd(); 403*47139Sbostic default: 404*47139Sbostic synexpect(-1); 405*47139Sbostic } 406*47139Sbostic 407*47139Sbostic /* Now check for redirection which may follow command */ 408*47139Sbostic rpp = &redir; 409*47139Sbostic while (readtoken() == TREDIR) { 410*47139Sbostic *rpp = n2 = redirnode; 411*47139Sbostic rpp = &n2->nfile.next; 412*47139Sbostic parsefname(); 413*47139Sbostic } 414*47139Sbostic tokpushback++; 415*47139Sbostic *rpp = NULL; 416*47139Sbostic if (redir) { 417*47139Sbostic if (n1->type != NSUBSHELL) { 418*47139Sbostic n2 = (union node *)stalloc(sizeof (struct nredir)); 419*47139Sbostic n2->type = NREDIR; 420*47139Sbostic n2->nredir.n = n1; 421*47139Sbostic n1 = n2; 422*47139Sbostic } 423*47139Sbostic n1->nredir.redirect = redir; 424*47139Sbostic } 425*47139Sbostic return n1; 426*47139Sbostic } 427*47139Sbostic 428*47139Sbostic 429*47139Sbostic STATIC union node * 430*47139Sbostic simplecmd() { 431*47139Sbostic union node *args, **app; 432*47139Sbostic union node *redir, **rpp; 433*47139Sbostic union node *n; 434*47139Sbostic 435*47139Sbostic args = NULL; 436*47139Sbostic app = &args; 437*47139Sbostic rpp = &redir; 438*47139Sbostic for (;;) { 439*47139Sbostic if (readtoken() == TWORD) { 440*47139Sbostic n = (union node *)stalloc(sizeof (struct narg)); 441*47139Sbostic n->type = NARG; 442*47139Sbostic n->narg.text = wordtext; 443*47139Sbostic n->narg.backquote = backquotelist; 444*47139Sbostic *app = n; 445*47139Sbostic app = &n->narg.next; 446*47139Sbostic } else if (lasttoken == TREDIR) { 447*47139Sbostic *rpp = n = redirnode; 448*47139Sbostic rpp = &n->nfile.next; 449*47139Sbostic parsefname(); /* read name of redirection file */ 450*47139Sbostic } else if (lasttoken == TLP && app == &args->narg.next 451*47139Sbostic && rpp == &redir) { 452*47139Sbostic /* We have a function */ 453*47139Sbostic if (readtoken() != TRP) 454*47139Sbostic synexpect(TRP); 455*47139Sbostic if (! goodname(n->narg.text)) 456*47139Sbostic synerror("Bad function name"); 457*47139Sbostic n->type = NDEFUN; 458*47139Sbostic n->narg.next = command(); 459*47139Sbostic return n; 460*47139Sbostic } else { 461*47139Sbostic tokpushback++; 462*47139Sbostic break; 463*47139Sbostic } 464*47139Sbostic } 465*47139Sbostic *app = NULL; 466*47139Sbostic *rpp = NULL; 467*47139Sbostic n = (union node *)stalloc(sizeof (struct ncmd)); 468*47139Sbostic n->type = NCMD; 469*47139Sbostic n->ncmd.backgnd = 0; 470*47139Sbostic n->ncmd.args = args; 471*47139Sbostic n->ncmd.redirect = redir; 472*47139Sbostic return n; 473*47139Sbostic } 474*47139Sbostic 475*47139Sbostic 476*47139Sbostic STATIC void 477*47139Sbostic parsefname() { 478*47139Sbostic union node *n = redirnode; 479*47139Sbostic 480*47139Sbostic if (readtoken() != TWORD) 481*47139Sbostic synexpect(-1); 482*47139Sbostic if (n->type == NHERE) { 483*47139Sbostic struct heredoc *here = heredoc; 484*47139Sbostic struct heredoc *p; 485*47139Sbostic int i; 486*47139Sbostic 487*47139Sbostic if (quoteflag == 0) 488*47139Sbostic n->type = NXHERE; 489*47139Sbostic TRACE(("Here document %d\n", n->type)); 490*47139Sbostic if (here->striptabs) { 491*47139Sbostic while (*wordtext == '\t') 492*47139Sbostic wordtext++; 493*47139Sbostic } 494*47139Sbostic if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN) 495*47139Sbostic synerror("Illegal eof marker for << redirection"); 496*47139Sbostic rmescapes(wordtext); 497*47139Sbostic here->eofmark = wordtext; 498*47139Sbostic here->next = NULL; 499*47139Sbostic if (heredoclist == NULL) 500*47139Sbostic heredoclist = here; 501*47139Sbostic else { 502*47139Sbostic for (p = heredoclist ; p->next ; p = p->next); 503*47139Sbostic p->next = here; 504*47139Sbostic } 505*47139Sbostic } else if (n->type == NTOFD || n->type == NFROMFD) { 506*47139Sbostic if (is_digit(wordtext[0])) 507*47139Sbostic n->ndup.dupfd = digit_val(wordtext[0]); 508*47139Sbostic else if (wordtext[0] == '-') 509*47139Sbostic n->ndup.dupfd = -1; 510*47139Sbostic else 511*47139Sbostic goto bad; 512*47139Sbostic if (wordtext[1] != '\0') { 513*47139Sbostic bad: 514*47139Sbostic synerror("Bad fd number"); 515*47139Sbostic } 516*47139Sbostic } else { 517*47139Sbostic n->nfile.fname = (union node *)stalloc(sizeof (struct narg)); 518*47139Sbostic n = n->nfile.fname; 519*47139Sbostic n->type = NARG; 520*47139Sbostic n->narg.next = NULL; 521*47139Sbostic n->narg.text = wordtext; 522*47139Sbostic n->narg.backquote = backquotelist; 523*47139Sbostic } 524*47139Sbostic } 525*47139Sbostic 526*47139Sbostic 527*47139Sbostic /* 528*47139Sbostic * Input any here documents. 529*47139Sbostic */ 530*47139Sbostic 531*47139Sbostic STATIC void 532*47139Sbostic parseheredoc() { 533*47139Sbostic struct heredoc *here; 534*47139Sbostic union node *n; 535*47139Sbostic 536*47139Sbostic while (heredoclist) { 537*47139Sbostic here = heredoclist; 538*47139Sbostic heredoclist = here->next; 539*47139Sbostic if (needprompt) { 540*47139Sbostic putprompt(ps2val()); 541*47139Sbostic needprompt = 0; 542*47139Sbostic } 543*47139Sbostic readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX, 544*47139Sbostic here->eofmark, here->striptabs); 545*47139Sbostic n = (union node *)stalloc(sizeof (struct narg)); 546*47139Sbostic n->narg.type = NARG; 547*47139Sbostic n->narg.next = NULL; 548*47139Sbostic n->narg.text = wordtext; 549*47139Sbostic n->narg.backquote = backquotelist; 550*47139Sbostic here->here->nhere.doc = n; 551*47139Sbostic } 552*47139Sbostic } 553*47139Sbostic 554*47139Sbostic 555*47139Sbostic 556*47139Sbostic /* 557*47139Sbostic * This routine is called to tell readtoken that we are at the beginning 558*47139Sbostic * of a command, so newlines should be ignored and keywords should be 559*47139Sbostic * checked for. We munge things here rather than setting a flag for 560*47139Sbostic * readtoken. 561*47139Sbostic */ 562*47139Sbostic 563*47139Sbostic STATIC void 564*47139Sbostic checkkwd() { 565*47139Sbostic register char *const *pp; 566*47139Sbostic int t; 567*47139Sbostic 568*47139Sbostic while ((t = readtoken()) == TNL); 569*47139Sbostic if (t == TWORD && quoteflag == 0) { 570*47139Sbostic for (pp = parsekwd ; *pp ; pp++) { 571*47139Sbostic if (**pp == *wordtext && equal(*pp, wordtext)) { 572*47139Sbostic lasttoken = pp - parsekwd + KWDOFFSET; 573*47139Sbostic break; 574*47139Sbostic } 575*47139Sbostic } 576*47139Sbostic } 577*47139Sbostic tokpushback++; 578*47139Sbostic } 579*47139Sbostic 580*47139Sbostic 581*47139Sbostic 582*47139Sbostic STATIC int xxreadtoken(); 583*47139Sbostic 584*47139Sbostic STATIC int 585*47139Sbostic readtoken() { 586*47139Sbostic int t; 587*47139Sbostic 588*47139Sbostic if (tokpushback) { 589*47139Sbostic return xxreadtoken(); 590*47139Sbostic } else { 591*47139Sbostic t = xxreadtoken(); 592*47139Sbostic TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : "")); 593*47139Sbostic if (vflag) 594*47139Sbostic outfmt(out2, "%s %s\n", tokname[t], 595*47139Sbostic t == TWORD ? wordtext : ""); 596*47139Sbostic return t; 597*47139Sbostic } 598*47139Sbostic } 599*47139Sbostic 600*47139Sbostic 601*47139Sbostic /* 602*47139Sbostic * Read the next input token. 603*47139Sbostic * If the token is a word, we set backquotelist to the list of cmds in 604*47139Sbostic * backquotes. We set quoteflag to true if any part of the word was 605*47139Sbostic * quoted. 606*47139Sbostic * If the token is TREDIR, then we set redirnode to a structure containing 607*47139Sbostic * the redirection. 608*47139Sbostic * In all cases, the variable startlinno is set to the number of the line 609*47139Sbostic * on which the token starts. 610*47139Sbostic * 611*47139Sbostic * [Change comment: here documents and internal procedures] 612*47139Sbostic * [Readtoken shouldn't have any arguments. Perhaps we should make the 613*47139Sbostic * word parsing code into a separate routine. In this case, readtoken 614*47139Sbostic * doesn't need to have any internal procedures, but parseword does. 615*47139Sbostic * We could also make parseoperator in essence the main routine, and 616*47139Sbostic * have parseword (readtoken1?) handle both words and redirection.] 617*47139Sbostic */ 618*47139Sbostic 619*47139Sbostic #define RETURN(token) return lasttoken = token 620*47139Sbostic 621*47139Sbostic STATIC int 622*47139Sbostic xxreadtoken() { 623*47139Sbostic register c; 624*47139Sbostic 625*47139Sbostic if (tokpushback) { 626*47139Sbostic tokpushback = 0; 627*47139Sbostic return lasttoken; 628*47139Sbostic } 629*47139Sbostic if (needprompt) { 630*47139Sbostic putprompt(ps2val()); 631*47139Sbostic needprompt = 0; 632*47139Sbostic } 633*47139Sbostic startlinno = plinno; 634*47139Sbostic for (;;) { /* until token or start of word found */ 635*47139Sbostic c = pgetc_macro(); 636*47139Sbostic if (c == ' ' || c == '\t') 637*47139Sbostic continue; /* quick check for white space first */ 638*47139Sbostic switch (c) { 639*47139Sbostic case ' ': case '\t': 640*47139Sbostic continue; 641*47139Sbostic case '#': 642*47139Sbostic while ((c = pgetc()) != '\n' && c != PEOF); 643*47139Sbostic pungetc(); 644*47139Sbostic continue; 645*47139Sbostic case '\\': 646*47139Sbostic if (pgetc() == '\n') { 647*47139Sbostic startlinno = ++plinno; 648*47139Sbostic if (doprompt) 649*47139Sbostic putprompt(ps2val()); 650*47139Sbostic continue; 651*47139Sbostic } 652*47139Sbostic pungetc(); 653*47139Sbostic goto breakloop; 654*47139Sbostic case '\n': 655*47139Sbostic plinno++; 656*47139Sbostic needprompt = doprompt; 657*47139Sbostic RETURN(TNL); 658*47139Sbostic case PEOF: 659*47139Sbostic RETURN(TEOF); 660*47139Sbostic case '&': 661*47139Sbostic if (pgetc() == '&') 662*47139Sbostic RETURN(TAND); 663*47139Sbostic pungetc(); 664*47139Sbostic RETURN(TBACKGND); 665*47139Sbostic case '|': 666*47139Sbostic if (pgetc() == '|') 667*47139Sbostic RETURN(TOR); 668*47139Sbostic pungetc(); 669*47139Sbostic RETURN(TPIPE); 670*47139Sbostic case ';': 671*47139Sbostic if (pgetc() == ';') 672*47139Sbostic RETURN(TENDCASE); 673*47139Sbostic pungetc(); 674*47139Sbostic RETURN(TSEMI); 675*47139Sbostic case '(': 676*47139Sbostic RETURN(TLP); 677*47139Sbostic case ')': 678*47139Sbostic RETURN(TRP); 679*47139Sbostic default: 680*47139Sbostic goto breakloop; 681*47139Sbostic } 682*47139Sbostic } 683*47139Sbostic breakloop: 684*47139Sbostic return readtoken1(c, BASESYNTAX, (char *)NULL, 0); 685*47139Sbostic #undef RETURN 686*47139Sbostic } 687*47139Sbostic 688*47139Sbostic 689*47139Sbostic 690*47139Sbostic /* 691*47139Sbostic * If eofmark is NULL, read a word or a redirection symbol. If eofmark 692*47139Sbostic * is not NULL, read a here document. In the latter case, eofmark is the 693*47139Sbostic * word which marks the end of the document and striptabs is true if 694*47139Sbostic * leading tabs should be stripped from the document. The argument firstc 695*47139Sbostic * is the first character of the input token or document. 696*47139Sbostic * 697*47139Sbostic * Because C does not have internal subroutines, I have simulated them 698*47139Sbostic * using goto's to implement the subroutine linkage. The following macros 699*47139Sbostic * will run code that appears at the end of readtoken1. 700*47139Sbostic */ 701*47139Sbostic 702*47139Sbostic #define CHECKEND() {goto checkend; checkend_return:;} 703*47139Sbostic #define PARSEREDIR() {goto parseredir; parseredir_return:;} 704*47139Sbostic #define PARSESUB() {goto parsesub; parsesub_return:;} 705*47139Sbostic #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;} 706*47139Sbostic #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;} 707*47139Sbostic 708*47139Sbostic STATIC int 709*47139Sbostic readtoken1(firstc, syntax, eofmark, striptabs) 710*47139Sbostic int firstc; 711*47139Sbostic char const *syntax; 712*47139Sbostic char *eofmark; 713*47139Sbostic int striptabs; 714*47139Sbostic { 715*47139Sbostic register c = firstc; 716*47139Sbostic register char *out; 717*47139Sbostic int len; 718*47139Sbostic char line[EOFMARKLEN + 1]; 719*47139Sbostic struct nodelist *bqlist; 720*47139Sbostic int quotef; 721*47139Sbostic int dblquote; 722*47139Sbostic int varnest; 723*47139Sbostic int oldstyle; 724*47139Sbostic 725*47139Sbostic startlinno = plinno; 726*47139Sbostic dblquote = 0; 727*47139Sbostic if (syntax == DQSYNTAX) 728*47139Sbostic dblquote = 1; 729*47139Sbostic quotef = 0; 730*47139Sbostic bqlist = NULL; 731*47139Sbostic varnest = 0; 732*47139Sbostic STARTSTACKSTR(out); 733*47139Sbostic loop: { /* for each line, until end of word */ 734*47139Sbostic #if ATTY 735*47139Sbostic if (c == '\034' && doprompt 736*47139Sbostic && attyset() && ! equal(termval(), "emacs")) { 737*47139Sbostic attyline(); 738*47139Sbostic if (syntax == BASESYNTAX) 739*47139Sbostic return readtoken(); 740*47139Sbostic c = pgetc(); 741*47139Sbostic goto loop; 742*47139Sbostic } 743*47139Sbostic #endif 744*47139Sbostic CHECKEND(); /* set c to PEOF if at end of here document */ 745*47139Sbostic for (;;) { /* until end of line or end of word */ 746*47139Sbostic CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */ 747*47139Sbostic switch(syntax[c]) { 748*47139Sbostic case CNL: /* '\n' */ 749*47139Sbostic if (syntax == BASESYNTAX) 750*47139Sbostic goto endword; /* exit outer loop */ 751*47139Sbostic USTPUTC(c, out); 752*47139Sbostic plinno++; 753*47139Sbostic if (doprompt) { 754*47139Sbostic putprompt(ps2val()); 755*47139Sbostic } 756*47139Sbostic c = pgetc(); 757*47139Sbostic goto loop; /* continue outer loop */ 758*47139Sbostic case CWORD: 759*47139Sbostic USTPUTC(c, out); 760*47139Sbostic break; 761*47139Sbostic case CCTL: 762*47139Sbostic if (eofmark == NULL || dblquote) 763*47139Sbostic USTPUTC(CTLESC, out); 764*47139Sbostic USTPUTC(c, out); 765*47139Sbostic break; 766*47139Sbostic case CBACK: /* backslash */ 767*47139Sbostic c = pgetc(); 768*47139Sbostic if (c == PEOF) { 769*47139Sbostic USTPUTC('\\', out); 770*47139Sbostic pungetc(); 771*47139Sbostic } else if (c == '\n') { 772*47139Sbostic if (doprompt) 773*47139Sbostic putprompt(ps2val()); 774*47139Sbostic } else { 775*47139Sbostic if (dblquote && c != '\\' && c != '`' && c != '$' 776*47139Sbostic && (c != '"' || eofmark != NULL)) 777*47139Sbostic USTPUTC('\\', out); 778*47139Sbostic if (SQSYNTAX[c] == CCTL) 779*47139Sbostic USTPUTC(CTLESC, out); 780*47139Sbostic USTPUTC(c, out); 781*47139Sbostic quotef++; 782*47139Sbostic } 783*47139Sbostic break; 784*47139Sbostic case CSQUOTE: 785*47139Sbostic syntax = SQSYNTAX; 786*47139Sbostic break; 787*47139Sbostic case CDQUOTE: 788*47139Sbostic syntax = DQSYNTAX; 789*47139Sbostic dblquote = 1; 790*47139Sbostic break; 791*47139Sbostic case CENDQUOTE: 792*47139Sbostic if (eofmark) { 793*47139Sbostic USTPUTC(c, out); 794*47139Sbostic } else { 795*47139Sbostic syntax = BASESYNTAX; 796*47139Sbostic quotef++; 797*47139Sbostic dblquote = 0; 798*47139Sbostic } 799*47139Sbostic break; 800*47139Sbostic case CVAR: /* '$' */ 801*47139Sbostic PARSESUB(); /* parse substitution */ 802*47139Sbostic break; 803*47139Sbostic case CENDVAR: /* '}' */ 804*47139Sbostic if (varnest > 0) { 805*47139Sbostic varnest--; 806*47139Sbostic USTPUTC(CTLENDVAR, out); 807*47139Sbostic } else { 808*47139Sbostic USTPUTC(c, out); 809*47139Sbostic } 810*47139Sbostic break; 811*47139Sbostic case CBQUOTE: /* '`' */ 812*47139Sbostic if (parsebackquote && syntax == BASESYNTAX) { 813*47139Sbostic if (out == stackblock()) 814*47139Sbostic return lasttoken = TENDBQUOTE; 815*47139Sbostic else 816*47139Sbostic goto endword; /* exit outer loop */ 817*47139Sbostic } 818*47139Sbostic PARSEBACKQOLD(); 819*47139Sbostic break; 820*47139Sbostic case CEOF: 821*47139Sbostic goto endword; /* exit outer loop */ 822*47139Sbostic default: 823*47139Sbostic if (varnest == 0) 824*47139Sbostic goto endword; /* exit outer loop */ 825*47139Sbostic USTPUTC(c, out); 826*47139Sbostic } 827*47139Sbostic c = pgetc_macro(); 828*47139Sbostic } 829*47139Sbostic } 830*47139Sbostic endword: 831*47139Sbostic if (syntax != BASESYNTAX && eofmark == NULL) 832*47139Sbostic synerror("Unterminated quoted string"); 833*47139Sbostic if (varnest != 0) { 834*47139Sbostic startlinno = plinno; 835*47139Sbostic synerror("Missing '}'"); 836*47139Sbostic } 837*47139Sbostic USTPUTC('\0', out); 838*47139Sbostic len = out - stackblock(); 839*47139Sbostic out = stackblock(); 840*47139Sbostic if (eofmark == NULL) { 841*47139Sbostic if ((c == '>' || c == '<') 842*47139Sbostic && quotef == 0 843*47139Sbostic && len <= 2 844*47139Sbostic && (*out == '\0' || is_digit(*out))) { 845*47139Sbostic PARSEREDIR(); 846*47139Sbostic return lasttoken = TREDIR; 847*47139Sbostic } else { 848*47139Sbostic pungetc(); 849*47139Sbostic } 850*47139Sbostic } 851*47139Sbostic quoteflag = quotef; 852*47139Sbostic backquotelist = bqlist; 853*47139Sbostic grabstackblock(len); 854*47139Sbostic wordtext = out; 855*47139Sbostic return lasttoken = TWORD; 856*47139Sbostic /* end of readtoken routine */ 857*47139Sbostic 858*47139Sbostic 859*47139Sbostic 860*47139Sbostic /* 861*47139Sbostic * Check to see whether we are at the end of the here document. When this 862*47139Sbostic * is called, c is set to the first character of the next input line. If 863*47139Sbostic * we are at the end of the here document, this routine sets the c to PEOF. 864*47139Sbostic */ 865*47139Sbostic 866*47139Sbostic checkend: { 867*47139Sbostic if (eofmark) { 868*47139Sbostic if (striptabs) { 869*47139Sbostic while (c == '\t') 870*47139Sbostic c = pgetc(); 871*47139Sbostic } 872*47139Sbostic if (c == *eofmark) { 873*47139Sbostic if (pfgets(line, sizeof line) != NULL) { 874*47139Sbostic register char *p, *q; 875*47139Sbostic 876*47139Sbostic p = line; 877*47139Sbostic for (q = eofmark + 1 ; *q && *p == *q ; p++, q++); 878*47139Sbostic if (*p == '\n' && *q == '\0') { 879*47139Sbostic c = PEOF; 880*47139Sbostic plinno++; 881*47139Sbostic needprompt = doprompt; 882*47139Sbostic } else { 883*47139Sbostic ppushback(line, strlen(line)); 884*47139Sbostic } 885*47139Sbostic } 886*47139Sbostic } 887*47139Sbostic } 888*47139Sbostic goto checkend_return; 889*47139Sbostic } 890*47139Sbostic 891*47139Sbostic 892*47139Sbostic /* 893*47139Sbostic * Parse a redirection operator. The variable "out" points to a string 894*47139Sbostic * specifying the fd to be redirected. The variable "c" contains the 895*47139Sbostic * first character of the redirection operator. 896*47139Sbostic */ 897*47139Sbostic 898*47139Sbostic parseredir: { 899*47139Sbostic char fd = *out; 900*47139Sbostic union node *np; 901*47139Sbostic 902*47139Sbostic np = (union node *)stalloc(sizeof (struct nfile)); 903*47139Sbostic if (c == '>') { 904*47139Sbostic np->nfile.fd = 1; 905*47139Sbostic c = pgetc(); 906*47139Sbostic if (c == '>') 907*47139Sbostic np->type = NAPPEND; 908*47139Sbostic else if (c == '&') 909*47139Sbostic np->type = NTOFD; 910*47139Sbostic else { 911*47139Sbostic np->type = NTO; 912*47139Sbostic pungetc(); 913*47139Sbostic } 914*47139Sbostic } else { /* c == '<' */ 915*47139Sbostic np->nfile.fd = 0; 916*47139Sbostic c = pgetc(); 917*47139Sbostic if (c == '<') { 918*47139Sbostic if (sizeof (struct nfile) != sizeof (struct nhere)) { 919*47139Sbostic np = (union node *)stalloc(sizeof (struct nhere)); 920*47139Sbostic np->nfile.fd = 0; 921*47139Sbostic } 922*47139Sbostic np->type = NHERE; 923*47139Sbostic heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc)); 924*47139Sbostic heredoc->here = np; 925*47139Sbostic if ((c = pgetc()) == '-') { 926*47139Sbostic heredoc->striptabs = 1; 927*47139Sbostic } else { 928*47139Sbostic heredoc->striptabs = 0; 929*47139Sbostic pungetc(); 930*47139Sbostic } 931*47139Sbostic } else if (c == '&') 932*47139Sbostic np->type = NFROMFD; 933*47139Sbostic else { 934*47139Sbostic np->type = NFROM; 935*47139Sbostic pungetc(); 936*47139Sbostic } 937*47139Sbostic } 938*47139Sbostic if (fd != '\0') 939*47139Sbostic np->nfile.fd = digit_val(fd); 940*47139Sbostic redirnode = np; 941*47139Sbostic goto parseredir_return; 942*47139Sbostic } 943*47139Sbostic 944*47139Sbostic 945*47139Sbostic /* 946*47139Sbostic * Parse a substitution. At this point, we have read the dollar sign 947*47139Sbostic * and nothing else. 948*47139Sbostic */ 949*47139Sbostic 950*47139Sbostic parsesub: { 951*47139Sbostic int subtype; 952*47139Sbostic int typeloc; 953*47139Sbostic int flags; 954*47139Sbostic char *p; 955*47139Sbostic #ifndef GDB_HACK 956*47139Sbostic static const char types[] = "}-+?="; 957*47139Sbostic #endif 958*47139Sbostic 959*47139Sbostic c = pgetc(); 960*47139Sbostic if (c == ' ' || c == '\t' || c == '\n' || c == PEOF 961*47139Sbostic #ifndef STRICT_VARCHECKING /* make this an option? */ 962*47139Sbostic || (c != '(' && c != '{' && !is_name(c) && !is_special(c)) 963*47139Sbostic #endif 964*47139Sbostic ) { 965*47139Sbostic USTPUTC('$', out); 966*47139Sbostic pungetc(); 967*47139Sbostic } else if (c == '(') { /* $(command) */ 968*47139Sbostic PARSEBACKQNEW(); 969*47139Sbostic } else { 970*47139Sbostic USTPUTC(CTLVAR, out); 971*47139Sbostic typeloc = out - stackblock(); 972*47139Sbostic USTPUTC(VSNORMAL, out); 973*47139Sbostic subtype = VSNORMAL; 974*47139Sbostic if (c == '{') { 975*47139Sbostic c = pgetc(); 976*47139Sbostic subtype = 0; 977*47139Sbostic } 978*47139Sbostic if (is_name(c)) { 979*47139Sbostic do { 980*47139Sbostic STPUTC(c, out); 981*47139Sbostic c = pgetc(); 982*47139Sbostic } while (is_in_name(c)); 983*47139Sbostic } else { 984*47139Sbostic if (! is_special(c)) 985*47139Sbostic badsub: synerror("Bad substitution"); 986*47139Sbostic USTPUTC(c, out); 987*47139Sbostic c = pgetc(); 988*47139Sbostic } 989*47139Sbostic STPUTC('=', out); 990*47139Sbostic flags = 0; 991*47139Sbostic if (subtype == 0) { 992*47139Sbostic if (c == ':') { 993*47139Sbostic flags = VSNUL; 994*47139Sbostic c = pgetc(); 995*47139Sbostic } 996*47139Sbostic p = strchr(types, c); 997*47139Sbostic if (p == NULL) 998*47139Sbostic goto badsub; 999*47139Sbostic subtype = p - types + VSNORMAL; 1000*47139Sbostic } else { 1001*47139Sbostic pungetc(); 1002*47139Sbostic } 1003*47139Sbostic if (dblquote) 1004*47139Sbostic flags |= VSQUOTE; 1005*47139Sbostic *(stackblock() + typeloc) = subtype | flags; 1006*47139Sbostic if (subtype != VSNORMAL) 1007*47139Sbostic varnest++; 1008*47139Sbostic } 1009*47139Sbostic goto parsesub_return; 1010*47139Sbostic } 1011*47139Sbostic 1012*47139Sbostic 1013*47139Sbostic /* 1014*47139Sbostic * Called to parse command substitutions. Newstyle is set if the command 1015*47139Sbostic * is enclosed inside $(...); nlpp is a pointer to the head of the linked 1016*47139Sbostic * list of commands (passed by reference), and savelen is the number of 1017*47139Sbostic * characters on the top of the stack which must be preserved. 1018*47139Sbostic */ 1019*47139Sbostic 1020*47139Sbostic parsebackq: { 1021*47139Sbostic struct nodelist **nlpp; 1022*47139Sbostic int savepbq; 1023*47139Sbostic union node *n; 1024*47139Sbostic char *volatile str; 1025*47139Sbostic struct jmploc jmploc; 1026*47139Sbostic struct jmploc *volatile savehandler; 1027*47139Sbostic int savelen; 1028*47139Sbostic int t; 1029*47139Sbostic 1030*47139Sbostic savepbq = parsebackquote; 1031*47139Sbostic if (setjmp(jmploc.loc)) { 1032*47139Sbostic if (str) 1033*47139Sbostic ckfree(str); 1034*47139Sbostic parsebackquote = 0; 1035*47139Sbostic handler = savehandler; 1036*47139Sbostic longjmp(handler, 1); 1037*47139Sbostic } 1038*47139Sbostic INTOFF; 1039*47139Sbostic str = NULL; 1040*47139Sbostic savelen = out - stackblock(); 1041*47139Sbostic if (savelen > 0) { 1042*47139Sbostic str = ckmalloc(savelen); 1043*47139Sbostic bcopy(stackblock(), str, savelen); 1044*47139Sbostic } 1045*47139Sbostic savehandler = handler; 1046*47139Sbostic handler = &jmploc; 1047*47139Sbostic INTON; 1048*47139Sbostic nlpp = &bqlist; 1049*47139Sbostic while (*nlpp) 1050*47139Sbostic nlpp = &(*nlpp)->next; 1051*47139Sbostic *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist)); 1052*47139Sbostic (*nlpp)->next = NULL; 1053*47139Sbostic parsebackquote = oldstyle; 1054*47139Sbostic n = list(0); 1055*47139Sbostic t = oldstyle? TENDBQUOTE : TRP; 1056*47139Sbostic if (readtoken() != t) 1057*47139Sbostic synexpect(t); 1058*47139Sbostic (*nlpp)->n = n; 1059*47139Sbostic while (stackblocksize() <= savelen) 1060*47139Sbostic growstackblock(); 1061*47139Sbostic STARTSTACKSTR(out); 1062*47139Sbostic if (str) { 1063*47139Sbostic bcopy(str, out, savelen); 1064*47139Sbostic STADJUST(savelen, out); 1065*47139Sbostic INTOFF; 1066*47139Sbostic ckfree(str); 1067*47139Sbostic str = NULL; 1068*47139Sbostic INTON; 1069*47139Sbostic } 1070*47139Sbostic parsebackquote = savepbq; 1071*47139Sbostic handler = savehandler; 1072*47139Sbostic USTPUTC(CTLBACKQ + dblquote, out); 1073*47139Sbostic if (oldstyle) 1074*47139Sbostic goto parsebackq_oldreturn; 1075*47139Sbostic else 1076*47139Sbostic goto parsebackq_newreturn; 1077*47139Sbostic } 1078*47139Sbostic 1079*47139Sbostic } /* end of readtoken */ 1080*47139Sbostic 1081*47139Sbostic 1082*47139Sbostic 1083*47139Sbostic #ifdef mkinit 1084*47139Sbostic RESET { 1085*47139Sbostic tokpushback = 0; 1086*47139Sbostic } 1087*47139Sbostic #endif 1088*47139Sbostic 1089*47139Sbostic 1090*47139Sbostic #if ATTY 1091*47139Sbostic /* 1092*47139Sbostic * Called to process a command generated by atty. We execute the line, 1093*47139Sbostic * and catch any errors that occur so they don't propagate outside of 1094*47139Sbostic * this routine. 1095*47139Sbostic */ 1096*47139Sbostic 1097*47139Sbostic STATIC void 1098*47139Sbostic attyline() { 1099*47139Sbostic char line[256]; 1100*47139Sbostic struct stackmark smark; 1101*47139Sbostic struct jmploc jmploc; 1102*47139Sbostic struct jmploc *volatile savehandler; 1103*47139Sbostic 1104*47139Sbostic if (pfgets(line, sizeof line) == NULL) 1105*47139Sbostic return; /* "can't happen" */ 1106*47139Sbostic if (setjmp(jmploc.loc)) { 1107*47139Sbostic if (exception == EXERROR) 1108*47139Sbostic out2str("\033]D\n"); 1109*47139Sbostic handler = savehandler; 1110*47139Sbostic longjmp(handler, 1); 1111*47139Sbostic } 1112*47139Sbostic savehandler = handler; 1113*47139Sbostic handler = &jmploc; 1114*47139Sbostic setstackmark(&smark); 1115*47139Sbostic evalstring(line); 1116*47139Sbostic popstackmark(&smark); 1117*47139Sbostic handler = savehandler; 1118*47139Sbostic doprompt = 1; 1119*47139Sbostic } 1120*47139Sbostic 1121*47139Sbostic 1122*47139Sbostic /* 1123*47139Sbostic * Output a prompt for atty. We output the prompt as part of the 1124*47139Sbostic * appropriate escape sequence. 1125*47139Sbostic */ 1126*47139Sbostic 1127*47139Sbostic STATIC void 1128*47139Sbostic putprompt(s) 1129*47139Sbostic char *s; 1130*47139Sbostic { 1131*47139Sbostic register char *p; 1132*47139Sbostic 1133*47139Sbostic if (attyset() && ! equal(termval(), "emacs")) { 1134*47139Sbostic if (strchr(s, '\7')) 1135*47139Sbostic out2c('\7'); 1136*47139Sbostic out2str("\033]P1;"); 1137*47139Sbostic for (p = s ; *p ; p++) { 1138*47139Sbostic if ((unsigned)(*p - ' ') <= '~' - ' ') 1139*47139Sbostic out2c(*p); 1140*47139Sbostic } 1141*47139Sbostic out2c('\n'); 1142*47139Sbostic } else { 1143*47139Sbostic out2str(s); 1144*47139Sbostic } 1145*47139Sbostic } 1146*47139Sbostic #endif 1147*47139Sbostic 1148*47139Sbostic 1149*47139Sbostic 1150*47139Sbostic /* 1151*47139Sbostic * Returns true if the text contains nothing to expand (no dollar signs 1152*47139Sbostic * or backquotes). 1153*47139Sbostic */ 1154*47139Sbostic 1155*47139Sbostic STATIC int 1156*47139Sbostic noexpand(text) 1157*47139Sbostic char *text; 1158*47139Sbostic { 1159*47139Sbostic register char *p; 1160*47139Sbostic register char c; 1161*47139Sbostic 1162*47139Sbostic p = text; 1163*47139Sbostic while ((c = *p++) != '\0') { 1164*47139Sbostic if (c == CTLESC) 1165*47139Sbostic p++; 1166*47139Sbostic else if (BASESYNTAX[c] == CCTL) 1167*47139Sbostic return 0; 1168*47139Sbostic } 1169*47139Sbostic return 1; 1170*47139Sbostic } 1171*47139Sbostic 1172*47139Sbostic 1173*47139Sbostic /* 1174*47139Sbostic * Return true if the argument is a legal variable name (a letter or 1175*47139Sbostic * underscore followed by zero or more letters, underscores, and digits). 1176*47139Sbostic */ 1177*47139Sbostic 1178*47139Sbostic int 1179*47139Sbostic goodname(name) 1180*47139Sbostic char *name; 1181*47139Sbostic { 1182*47139Sbostic register char *p; 1183*47139Sbostic 1184*47139Sbostic p = name; 1185*47139Sbostic if (! is_name(*p)) 1186*47139Sbostic return 0; 1187*47139Sbostic while (*++p) { 1188*47139Sbostic if (! is_in_name(*p)) 1189*47139Sbostic return 0; 1190*47139Sbostic } 1191*47139Sbostic return 1; 1192*47139Sbostic } 1193*47139Sbostic 1194*47139Sbostic 1195*47139Sbostic /* 1196*47139Sbostic * Called when an unexpected token is read during the parse. The argument 1197*47139Sbostic * is the token that is expected, or -1 if more than one type of token can 1198*47139Sbostic * occur at this point. 1199*47139Sbostic */ 1200*47139Sbostic 1201*47139Sbostic STATIC void 1202*47139Sbostic synexpect(token) { 1203*47139Sbostic char msg[64]; 1204*47139Sbostic 1205*47139Sbostic if (token >= 0) { 1206*47139Sbostic fmtstr(msg, 64, "%s unexpected (expecting %s)", 1207*47139Sbostic tokname[lasttoken], tokname[token]); 1208*47139Sbostic } else { 1209*47139Sbostic fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]); 1210*47139Sbostic } 1211*47139Sbostic synerror(msg); 1212*47139Sbostic } 1213*47139Sbostic 1214*47139Sbostic 1215*47139Sbostic STATIC void 1216*47139Sbostic synerror(msg) 1217*47139Sbostic char *msg; 1218*47139Sbostic { 1219*47139Sbostic if (commandname) 1220*47139Sbostic outfmt(&errout, "%s: %d: ", commandname, startlinno); 1221*47139Sbostic outfmt(&errout, "Syntax error: %s\n", msg); 1222*47139Sbostic error((char *)NULL); 1223*47139Sbostic } 1224