1 1.184 kre /* $NetBSD: parser.c,v 1.184 2024/10/21 15:57:45 kre Exp $ */ 2 1.24 cgd 3 1.1 cgd /*- 4 1.11 jtc * Copyright (c) 1991, 1993 5 1.11 jtc * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * This code is derived from software contributed to Berkeley by 8 1.1 cgd * Kenneth Almquist. 9 1.1 cgd * 10 1.1 cgd * Redistribution and use in source and binary forms, with or without 11 1.1 cgd * modification, are permitted provided that the following conditions 12 1.1 cgd * are met: 13 1.1 cgd * 1. Redistributions of source code must retain the above copyright 14 1.1 cgd * notice, this list of conditions and the following disclaimer. 15 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 cgd * notice, this list of conditions and the following disclaimer in the 17 1.1 cgd * documentation and/or other materials provided with the distribution. 18 1.55 agc * 3. Neither the name of the University nor the names of its contributors 19 1.1 cgd * may be used to endorse or promote products derived from this software 20 1.1 cgd * without specific prior written permission. 21 1.1 cgd * 22 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.1 cgd * SUCH DAMAGE. 33 1.1 cgd */ 34 1.1 cgd 35 1.36 christos #include <sys/cdefs.h> 36 1.1 cgd #ifndef lint 37 1.24 cgd #if 0 38 1.26 christos static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; 39 1.24 cgd #else 40 1.184 kre __RCSID("$NetBSD: parser.c,v 1.184 2024/10/21 15:57:45 kre Exp $"); 41 1.24 cgd #endif 42 1.1 cgd #endif /* not lint */ 43 1.1 cgd 44 1.166 kre #include <limits.h> 45 1.166 kre #include <signal.h> 46 1.85 christos #include <stdio.h> 47 1.25 christos #include <stdlib.h> 48 1.25 christos 49 1.1 cgd #include "shell.h" 50 1.1 cgd #include "parser.h" 51 1.1 cgd #include "nodes.h" 52 1.1 cgd #include "expand.h" /* defines rmescapes() */ 53 1.46 christos #include "eval.h" /* defines commandname */ 54 1.1 cgd #include "syntax.h" 55 1.1 cgd #include "options.h" 56 1.1 cgd #include "input.h" 57 1.1 cgd #include "output.h" 58 1.173 kre #include "redir.h" /* defines max_user_fd */ 59 1.1 cgd #include "var.h" 60 1.1 cgd #include "error.h" 61 1.1 cgd #include "memalloc.h" 62 1.1 cgd #include "mystring.h" 63 1.11 jtc #include "alias.h" 64 1.25 christos #include "show.h" 65 1.35 christos #ifndef SMALL 66 1.11 jtc #include "myhistedit.h" 67 1.14 cgd #endif 68 1.163 kre #ifdef DEBUG 69 1.163 kre #include "nodenames.h" 70 1.163 kre #endif 71 1.1 cgd 72 1.1 cgd /* 73 1.1 cgd * Shell command parser. 74 1.1 cgd */ 75 1.1 cgd 76 1.1 cgd /* values returned by readtoken */ 77 1.30 christos #include "token.h" 78 1.1 cgd 79 1.51 christos #define OPENBRACE '{' 80 1.51 christos #define CLOSEBRACE '}' 81 1.1 cgd 82 1.140 kre struct HereDoc { 83 1.140 kre struct HereDoc *next; /* next here document in list */ 84 1.1 cgd union node *here; /* redirection node */ 85 1.1 cgd char *eofmark; /* string indicating end of input */ 86 1.1 cgd int striptabs; /* if set, strip leading tabs */ 87 1.116 christos int startline; /* line number where << seen */ 88 1.1 cgd }; 89 1.1 cgd 90 1.140 kre MKINIT struct parse_state parse_state; 91 1.140 kre union parse_state_p psp = { .c_current_parser = &parse_state }; 92 1.1 cgd 93 1.140 kre static const struct parse_state init_parse_state = { /* all 0's ... */ 94 1.140 kre .ps_heredoclist = NULL, 95 1.140 kre .ps_parsebackquote = 0, 96 1.140 kre .ps_doprompt = 0, 97 1.140 kre .ps_needprompt = 0, 98 1.140 kre .ps_lasttoken = 0, 99 1.140 kre .ps_tokpushback = 0, 100 1.140 kre .ps_wordtext = NULL, 101 1.140 kre .ps_checkkwd = 0, 102 1.140 kre .ps_redirnode = NULL, 103 1.140 kre .ps_heredoc = NULL, 104 1.140 kre .ps_quoteflag = 0, 105 1.140 kre .ps_startlinno = 0, 106 1.140 kre .ps_funclinno = 0, 107 1.140 kre .ps_elided_nl = 0, 108 1.140 kre }; 109 1.1 cgd 110 1.142 kre STATIC union node *list(int); 111 1.54 christos STATIC union node *andor(void); 112 1.54 christos STATIC union node *pipeline(void); 113 1.54 christos STATIC union node *command(void); 114 1.54 christos STATIC union node *simplecmd(union node **, union node *); 115 1.155 kre STATIC union node *makeword(int); 116 1.54 christos STATIC void parsefname(void); 117 1.134 kre STATIC int slurp_heredoc(char *const, const int, const int); 118 1.111 christos STATIC void readheredocs(void); 119 1.54 christos STATIC int peektoken(void); 120 1.54 christos STATIC int readtoken(void); 121 1.54 christos STATIC int xxreadtoken(void); 122 1.111 christos STATIC int readtoken1(int, char const *, int); 123 1.54 christos STATIC int noexpand(char *); 124 1.142 kre STATIC void linebreak(void); 125 1.142 kre STATIC void consumetoken(int); 126 1.108 christos STATIC void synexpect(int, const char *) __dead; 127 1.66 perry STATIC void synerror(const char *) __dead; 128 1.54 christos STATIC void setprompt(int); 129 1.121 kre STATIC int pgetc_linecont(void); 130 1.1 cgd 131 1.102 christos static const char EOFhere[] = "EOF reading here (<<) document"; 132 1.102 christos 133 1.134 kre #ifdef DEBUG 134 1.134 kre int parsing = 0; 135 1.134 kre #endif 136 1.108 christos 137 1.1 cgd /* 138 1.1 cgd * Read and parse a command. Returns NEOF on end of file. (NULL is a 139 1.1 cgd * valid parse tree indicating a blank line.) 140 1.1 cgd */ 141 1.1 cgd 142 1.1 cgd union node * 143 1.45 cgd parsecmd(int interact) 144 1.22 cgd { 145 1.1 cgd int t; 146 1.116 christos union node *n; 147 1.1 cgd 148 1.134 kre #ifdef DEBUG 149 1.134 kre parsing++; 150 1.134 kre #endif 151 1.47 christos tokpushback = 0; 152 1.142 kre checkkwd = 0; 153 1.1 cgd doprompt = interact; 154 1.1 cgd if (doprompt) 155 1.11 jtc setprompt(1); 156 1.11 jtc else 157 1.11 jtc setprompt(0); 158 1.1 cgd needprompt = 0; 159 1.11 jtc t = readtoken(); 160 1.134 kre #ifdef DEBUG 161 1.134 kre parsing--; 162 1.134 kre #endif 163 1.11 jtc if (t == TEOF) 164 1.1 cgd return NEOF; 165 1.1 cgd if (t == TNL) 166 1.1 cgd return NULL; 167 1.134 kre 168 1.134 kre #ifdef DEBUG 169 1.134 kre parsing++; 170 1.134 kre #endif 171 1.1 cgd tokpushback++; 172 1.142 kre n = list(1); 173 1.134 kre #ifdef DEBUG 174 1.134 kre parsing--; 175 1.134 kre #endif 176 1.116 christos if (heredoclist) 177 1.116 christos error("%d: Here document (<<%s) expected but not present", 178 1.116 christos heredoclist->startline, heredoclist->eofmark); 179 1.116 christos return n; 180 1.1 cgd } 181 1.1 cgd 182 1.1 cgd 183 1.1 cgd STATIC union node * 184 1.142 kre list(int nlflag) 185 1.22 cgd { 186 1.150 kre union node *ntop, *n1, *n2, *n3; 187 1.12 jtc int tok; 188 1.126 kre 189 1.142 kre CTRACE(DBG_PARSE, ("list(%d): entered @%d\n",nlflag,plinno)); 190 1.1 cgd 191 1.156 kre checkkwd = CHKNL | CHKKWD | CHKALIAS; 192 1.1 cgd if (nlflag == 0 && tokendlist[peektoken()]) 193 1.1 cgd return NULL; 194 1.150 kre ntop = n1 = NULL; 195 1.1 cgd for (;;) { 196 1.12 jtc n2 = andor(); 197 1.12 jtc tok = readtoken(); 198 1.12 jtc if (tok == TBACKGND) { 199 1.142 kre if (n2->type == NCMD || n2->type == NPIPE) 200 1.12 jtc n2->ncmd.backgnd = 1; 201 1.142 kre else if (n2->type == NREDIR) 202 1.12 jtc n2->type = NBACKGND; 203 1.142 kre else { 204 1.101 christos n3 = stalloc(sizeof(struct nredir)); 205 1.1 cgd n3->type = NBACKGND; 206 1.12 jtc n3->nredir.n = n2; 207 1.1 cgd n3->nredir.redirect = NULL; 208 1.12 jtc n2 = n3; 209 1.1 cgd } 210 1.12 jtc } 211 1.142 kre 212 1.150 kre if (ntop == NULL) 213 1.150 kre ntop = n2; 214 1.150 kre else if (n1 == NULL) { 215 1.150 kre n1 = stalloc(sizeof(struct nbinary)); 216 1.150 kre n1->type = NSEMI; 217 1.150 kre n1->nbinary.ch1 = ntop; 218 1.150 kre n1->nbinary.ch2 = n2; 219 1.150 kre ntop = n1; 220 1.150 kre } else { 221 1.101 christos n3 = stalloc(sizeof(struct nbinary)); 222 1.12 jtc n3->type = NSEMI; 223 1.150 kre n3->nbinary.ch1 = n1->nbinary.ch2; 224 1.12 jtc n3->nbinary.ch2 = n2; 225 1.150 kre n1->nbinary.ch2 = n3; 226 1.12 jtc n1 = n3; 227 1.150 kre } 228 1.142 kre 229 1.12 jtc switch (tok) { 230 1.12 jtc case TBACKGND: 231 1.12 jtc case TSEMI: 232 1.12 jtc tok = readtoken(); 233 1.108 christos /* FALLTHROUGH */ 234 1.1 cgd case TNL: 235 1.12 jtc if (tok == TNL) { 236 1.111 christos readheredocs(); 237 1.1 cgd if (nlflag) 238 1.150 kre return ntop; 239 1.142 kre } else if (tok == TEOF && nlflag) 240 1.150 kre return ntop; 241 1.142 kre else 242 1.1 cgd tokpushback++; 243 1.142 kre 244 1.156 kre checkkwd = CHKNL | CHKKWD | CHKALIAS; 245 1.142 kre if (!nlflag && tokendlist[peektoken()]) 246 1.150 kre return ntop; 247 1.1 cgd break; 248 1.1 cgd case TEOF: 249 1.116 christos pungetc(); /* push back EOF on input */ 250 1.150 kre return ntop; 251 1.1 cgd default: 252 1.142 kre if (nlflag) 253 1.108 christos synexpect(-1, 0); 254 1.1 cgd tokpushback++; 255 1.150 kre return ntop; 256 1.1 cgd } 257 1.1 cgd } 258 1.1 cgd } 259 1.1 cgd 260 1.1 cgd STATIC union node * 261 1.54 christos andor(void) 262 1.54 christos { 263 1.1 cgd union node *n1, *n2, *n3; 264 1.1 cgd int t; 265 1.1 cgd 266 1.130 kre CTRACE(DBG_PARSE, ("andor: entered @%d\n", plinno)); 267 1.126 kre 268 1.1 cgd n1 = pipeline(); 269 1.1 cgd for (;;) { 270 1.1 cgd if ((t = readtoken()) == TAND) { 271 1.1 cgd t = NAND; 272 1.1 cgd } else if (t == TOR) { 273 1.1 cgd t = NOR; 274 1.1 cgd } else { 275 1.1 cgd tokpushback++; 276 1.1 cgd return n1; 277 1.1 cgd } 278 1.1 cgd n2 = pipeline(); 279 1.101 christos n3 = stalloc(sizeof(struct nbinary)); 280 1.1 cgd n3->type = t; 281 1.1 cgd n3->nbinary.ch1 = n1; 282 1.1 cgd n3->nbinary.ch2 = n2; 283 1.1 cgd n1 = n3; 284 1.1 cgd } 285 1.1 cgd } 286 1.1 cgd 287 1.1 cgd STATIC union node * 288 1.54 christos pipeline(void) 289 1.54 christos { 290 1.44 christos union node *n1, *n2, *pipenode; 291 1.1 cgd struct nodelist *lp, *prev; 292 1.44 christos int negate; 293 1.1 cgd 294 1.130 kre CTRACE(DBG_PARSE, ("pipeline: entered @%d\n", plinno)); 295 1.65 dsl 296 1.44 christos negate = 0; 297 1.156 kre checkkwd = CHKNL | CHKKWD | CHKALIAS; 298 1.65 dsl while (readtoken() == TNOT) { 299 1.130 kre CTRACE(DBG_PARSE, ("pipeline: TNOT recognized\n")); 300 1.129 kre #ifndef BOGUS_NOT_COMMAND 301 1.129 kre if (posix && negate) 302 1.129 kre synerror("2nd \"!\" unexpected"); 303 1.129 kre #endif 304 1.125 kre negate++; 305 1.65 dsl } 306 1.44 christos tokpushback++; 307 1.1 cgd n1 = command(); 308 1.1 cgd if (readtoken() == TPIPE) { 309 1.101 christos pipenode = stalloc(sizeof(struct npipe)); 310 1.1 cgd pipenode->type = NPIPE; 311 1.1 cgd pipenode->npipe.backgnd = 0; 312 1.101 christos lp = stalloc(sizeof(struct nodelist)); 313 1.1 cgd pipenode->npipe.cmdlist = lp; 314 1.1 cgd lp->n = n1; 315 1.1 cgd do { 316 1.1 cgd prev = lp; 317 1.101 christos lp = stalloc(sizeof(struct nodelist)); 318 1.1 cgd lp->n = command(); 319 1.1 cgd prev->next = lp; 320 1.1 cgd } while (readtoken() == TPIPE); 321 1.1 cgd lp->next = NULL; 322 1.1 cgd n1 = pipenode; 323 1.1 cgd } 324 1.1 cgd tokpushback++; 325 1.44 christos if (negate) { 326 1.130 kre CTRACE(DBG_PARSE, ("%snegate pipeline\n", 327 1.130 kre (negate&1) ? "" : "double ")); 328 1.101 christos n2 = stalloc(sizeof(struct nnot)); 329 1.125 kre n2->type = (negate & 1) ? NNOT : NDNOT; 330 1.44 christos n2->nnot.com = n1; 331 1.44 christos return n2; 332 1.44 christos } else 333 1.44 christos return n1; 334 1.1 cgd } 335 1.1 cgd 336 1.1 cgd 337 1.1 cgd 338 1.1 cgd STATIC union node * 339 1.54 christos command(void) 340 1.54 christos { 341 1.1 cgd union node *n1, *n2; 342 1.1 cgd union node *ap, **app; 343 1.1 cgd union node *cp, **cpp; 344 1.1 cgd union node *redir, **rpp; 345 1.129 kre int t; 346 1.129 kre #ifdef BOGUS_NOT_COMMAND 347 1.129 kre int negate = 0; 348 1.129 kre #endif 349 1.1 cgd 350 1.130 kre CTRACE(DBG_PARSE, ("command: entered @%d\n", plinno)); 351 1.65 dsl 352 1.156 kre checkkwd = CHKNL | CHKKWD | CHKALIAS; 353 1.25 christos redir = NULL; 354 1.25 christos n1 = NULL; 355 1.5 sef rpp = &redir; 356 1.31 christos 357 1.5 sef /* Check for redirection which may precede command */ 358 1.5 sef while (readtoken() == TREDIR) { 359 1.5 sef *rpp = n2 = redirnode; 360 1.5 sef rpp = &n2->nfile.next; 361 1.5 sef parsefname(); 362 1.5 sef } 363 1.5 sef tokpushback++; 364 1.5 sef 365 1.179 andvar #ifdef BOGUS_NOT_COMMAND /* only in pipeline() */ 366 1.31 christos while (readtoken() == TNOT) { 367 1.130 kre CTRACE(DBG_PARSE, ("command: TNOT (bogus) recognized\n")); 368 1.125 kre negate++; 369 1.31 christos } 370 1.31 christos tokpushback++; 371 1.129 kre #endif 372 1.31 christos 373 1.1 cgd switch (readtoken()) { 374 1.1 cgd case TIF: 375 1.101 christos n1 = stalloc(sizeof(struct nif)); 376 1.1 cgd n1->type = NIF; 377 1.142 kre n1->nif.test = list(0); 378 1.142 kre consumetoken(TTHEN); 379 1.142 kre n1->nif.ifpart = list(0); 380 1.1 cgd n2 = n1; 381 1.1 cgd while (readtoken() == TELIF) { 382 1.101 christos n2->nif.elsepart = stalloc(sizeof(struct nif)); 383 1.1 cgd n2 = n2->nif.elsepart; 384 1.1 cgd n2->type = NIF; 385 1.142 kre n2->nif.test = list(0); 386 1.142 kre consumetoken(TTHEN); 387 1.142 kre n2->nif.ifpart = list(0); 388 1.1 cgd } 389 1.1 cgd if (lasttoken == TELSE) 390 1.142 kre n2->nif.elsepart = list(0); 391 1.1 cgd else { 392 1.1 cgd n2->nif.elsepart = NULL; 393 1.1 cgd tokpushback++; 394 1.1 cgd } 395 1.142 kre consumetoken(TFI); 396 1.156 kre checkkwd = CHKKWD | CHKALIAS; 397 1.1 cgd break; 398 1.1 cgd case TWHILE: 399 1.142 kre case TUNTIL: 400 1.101 christos n1 = stalloc(sizeof(struct nbinary)); 401 1.1 cgd n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL; 402 1.142 kre n1->nbinary.ch1 = list(0); 403 1.142 kre consumetoken(TDO); 404 1.142 kre n1->nbinary.ch2 = list(0); 405 1.142 kre consumetoken(TDONE); 406 1.156 kre checkkwd = CHKKWD | CHKALIAS; 407 1.1 cgd break; 408 1.1 cgd case TFOR: 409 1.1 cgd if (readtoken() != TWORD || quoteflag || ! goodname(wordtext)) 410 1.1 cgd synerror("Bad for loop variable"); 411 1.101 christos n1 = stalloc(sizeof(struct nfor)); 412 1.1 cgd n1->type = NFOR; 413 1.1 cgd n1->nfor.var = wordtext; 414 1.175 kre n1->nfor.lineno = startlinno; 415 1.142 kre linebreak(); 416 1.142 kre if (lasttoken==TWORD && !quoteflag && equal(wordtext,"in")) { 417 1.1 cgd app = ≈ 418 1.1 cgd while (readtoken() == TWORD) { 419 1.155 kre n2 = makeword(startlinno); 420 1.1 cgd *app = n2; 421 1.1 cgd app = &n2->narg.next; 422 1.1 cgd } 423 1.1 cgd *app = NULL; 424 1.1 cgd n1->nfor.args = ap; 425 1.5 sef if (lasttoken != TNL && lasttoken != TSEMI) 426 1.142 kre synexpect(TSEMI, 0); 427 1.172 kre if (lasttoken == TNL) 428 1.172 kre readheredocs(); 429 1.1 cgd } else { 430 1.95 christos static char argvars[5] = { 431 1.95 christos CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' 432 1.95 christos }; 433 1.126 kre 434 1.101 christos n2 = stalloc(sizeof(struct narg)); 435 1.1 cgd n2->type = NARG; 436 1.43 christos n2->narg.text = argvars; 437 1.1 cgd n2->narg.backquote = NULL; 438 1.1 cgd n2->narg.next = NULL; 439 1.135 kre n2->narg.lineno = startlinno; 440 1.1 cgd n1->nfor.args = n2; 441 1.11 jtc /* 442 1.11 jtc * Newline or semicolon here is optional (but note 443 1.11 jtc * that the original Bourne shell only allowed NL). 444 1.11 jtc */ 445 1.11 jtc if (lasttoken != TNL && lasttoken != TSEMI) 446 1.11 jtc tokpushback++; 447 1.1 cgd } 448 1.156 kre checkkwd = CHKNL | CHKKWD | CHKALIAS; 449 1.1 cgd if ((t = readtoken()) == TDO) 450 1.1 cgd t = TDONE; 451 1.1 cgd else if (t == TBEGIN) 452 1.1 cgd t = TEND; 453 1.1 cgd else 454 1.142 kre synexpect(TDO, 0); 455 1.142 kre n1->nfor.body = list(0); 456 1.142 kre consumetoken(t); 457 1.156 kre checkkwd = CHKKWD | CHKALIAS; 458 1.1 cgd break; 459 1.1 cgd case TCASE: 460 1.101 christos n1 = stalloc(sizeof(struct ncase)); 461 1.1 cgd n1->type = NCASE; 462 1.134 kre n1->ncase.lineno = startlinno - elided_nl; 463 1.142 kre consumetoken(TWORD); 464 1.155 kre n1->ncase.expr = makeword(startlinno); 465 1.142 kre linebreak(); 466 1.142 kre if (lasttoken != TWORD || !equal(wordtext, "in")) 467 1.108 christos synexpect(-1, "in"); 468 1.1 cgd cpp = &n1->ncase.cases; 469 1.156 kre checkkwd = CHKNL | CHKKWD; 470 1.142 kre readtoken(); 471 1.87 christos /* 472 1.88 christos * Both ksh and bash accept 'case x in esac' 473 1.87 christos * so configure scripts started taking advantage of this. 474 1.88 christos * The page: http://pubs.opengroup.org/onlinepubs/\ 475 1.88 christos * 009695399/utilities/xcu_chap02.html contradicts itself, 476 1.88 christos * as to if this is legal; the "Case Conditional Format" 477 1.88 christos * paragraph shows one case is required, but the "Grammar" 478 1.88 christos * section shows a grammar that explicitly allows the no 479 1.88 christos * case option. 480 1.141 kre * 481 1.141 kre * The standard also says (section 2.10): 482 1.141 kre * This formal syntax shall take precedence over the 483 1.141 kre * preceding text syntax description. 484 1.141 kre * ie: the "Grammar" section wins. The text is just 485 1.141 kre * a rough guide (introduction to the common case.) 486 1.87 christos */ 487 1.87 christos while (lasttoken != TESAC) { 488 1.101 christos *cpp = cp = stalloc(sizeof(struct nclist)); 489 1.142 kre cp->type = NCLIST; 490 1.142 kre app = &cp->nclist.pattern; 491 1.61 christos if (lasttoken == TLP) 492 1.61 christos readtoken(); 493 1.1 cgd for (;;) { 494 1.142 kre if (lasttoken < TWORD) 495 1.142 kre synexpect(TWORD, 0); 496 1.155 kre *app = ap = makeword(startlinno); 497 1.156 kre checkkwd = CHKNL | CHKKWD; 498 1.142 kre if (readtoken() != TPIPE) 499 1.1 cgd break; 500 1.1 cgd app = &ap->narg.next; 501 1.16 jtc readtoken(); 502 1.1 cgd } 503 1.142 kre if (lasttoken != TRP) 504 1.108 christos synexpect(TRP, 0); 505 1.135 kre cp->nclist.lineno = startlinno; 506 1.142 kre cp->nclist.body = list(0); 507 1.15 jtc 508 1.156 kre checkkwd = CHKNL | CHKKWD | CHKALIAS; 509 1.15 jtc if ((t = readtoken()) != TESAC) { 510 1.123 kre if (t != TENDCASE && t != TCASEFALL) { 511 1.108 christos synexpect(TENDCASE, 0); 512 1.48 christos } else { 513 1.123 kre if (t == TCASEFALL) 514 1.123 kre cp->type = NCLISTCONT; 515 1.156 kre checkkwd = CHKNL | CHKKWD; 516 1.48 christos readtoken(); 517 1.48 christos } 518 1.15 jtc } 519 1.1 cgd cpp = &cp->nclist.next; 520 1.86 christos } 521 1.1 cgd *cpp = NULL; 522 1.156 kre checkkwd = CHKKWD | CHKALIAS; 523 1.1 cgd break; 524 1.1 cgd case TLP: 525 1.101 christos n1 = stalloc(sizeof(struct nredir)); 526 1.1 cgd n1->type = NSUBSHELL; 527 1.142 kre n1->nredir.n = list(0); 528 1.1 cgd n1->nredir.redirect = NULL; 529 1.120 kre if (n1->nredir.n == NULL) 530 1.120 kre synexpect(-1, 0); 531 1.142 kre consumetoken(TRP); 532 1.156 kre checkkwd = CHKKWD | CHKALIAS; 533 1.1 cgd break; 534 1.1 cgd case TBEGIN: 535 1.142 kre n1 = list(0); 536 1.120 kre if (posix && n1 == NULL) 537 1.120 kre synexpect(-1, 0); 538 1.142 kre consumetoken(TEND); 539 1.156 kre checkkwd = CHKKWD | CHKALIAS; 540 1.1 cgd break; 541 1.119 kre 542 1.142 kre case TBACKGND: 543 1.19 mycroft case TSEMI: 544 1.119 kre case TAND: 545 1.119 kre case TOR: 546 1.119 kre case TPIPE: 547 1.119 kre case TNL: 548 1.119 kre case TEOF: 549 1.119 kre case TRP: 550 1.142 kre case TENDCASE: 551 1.142 kre case TCASEFALL: 552 1.19 mycroft /* 553 1.119 kre * simple commands must have something in them, 554 1.119 kre * either a word (which at this point includes a=b) 555 1.119 kre * or a redirection. If we reached the end of the 556 1.119 kre * command (which one of these tokens indicates) 557 1.119 kre * when we are just starting, and have not had a 558 1.119 kre * redirect, then ... 559 1.119 kre * 560 1.119 kre * nb: it is still possible to end up with empty 561 1.119 kre * simple commands, if the "command" is a var 562 1.142 kre * expansion that produces nothing: 563 1.119 kre * X= ; $X && $X 564 1.119 kre * --> && 565 1.142 kre * That is OK and is handled after word expansions. 566 1.19 mycroft */ 567 1.19 mycroft if (!redir) 568 1.108 christos synexpect(-1, 0); 569 1.142 kre /* 570 1.142 kre * continue to build a node containing the redirect. 571 1.142 kre * the tokpushback means that our ending token will be 572 1.142 kre * read again in simplecmd, causing it to terminate, 573 1.142 kre * so only the redirect(s) will be contained in the 574 1.142 kre * returned n1 575 1.142 kre */ 576 1.142 kre /* FALLTHROUGH */ 577 1.1 cgd case TWORD: 578 1.1 cgd tokpushback++; 579 1.31 christos n1 = simplecmd(rpp, redir); 580 1.31 christos goto checkneg; 581 1.1 cgd default: 582 1.108 christos synexpect(-1, 0); 583 1.39 mycroft /* NOTREACHED */ 584 1.1 cgd } 585 1.1 cgd 586 1.1 cgd /* Now check for redirection which may follow command */ 587 1.1 cgd while (readtoken() == TREDIR) { 588 1.1 cgd *rpp = n2 = redirnode; 589 1.1 cgd rpp = &n2->nfile.next; 590 1.1 cgd parsefname(); 591 1.1 cgd } 592 1.1 cgd tokpushback++; 593 1.1 cgd *rpp = NULL; 594 1.1 cgd if (redir) { 595 1.152 kre if (n1 == NULL || n1->type != NSUBSHELL) { 596 1.101 christos n2 = stalloc(sizeof(struct nredir)); 597 1.1 cgd n2->type = NREDIR; 598 1.1 cgd n2->nredir.n = n1; 599 1.1 cgd n1 = n2; 600 1.1 cgd } 601 1.1 cgd n1->nredir.redirect = redir; 602 1.1 cgd } 603 1.31 christos 604 1.182 kre checkneg:; 605 1.129 kre #ifdef BOGUS_NOT_COMMAND 606 1.31 christos if (negate) { 607 1.130 kre VTRACE(DBG_PARSE, ("bogus %snegate command\n", 608 1.130 kre (negate&1) ? "" : "double ")); 609 1.101 christos n2 = stalloc(sizeof(struct nnot)); 610 1.125 kre n2->type = (negate & 1) ? NNOT : NDNOT; 611 1.31 christos n2->nnot.com = n1; 612 1.31 christos return n2; 613 1.31 christos } 614 1.31 christos else 615 1.129 kre #endif 616 1.31 christos return n1; 617 1.1 cgd } 618 1.1 cgd 619 1.1 cgd 620 1.1 cgd STATIC union node * 621 1.54 christos simplecmd(union node **rpp, union node *redir) 622 1.54 christos { 623 1.1 cgd union node *args, **app; 624 1.129 kre union node *n = NULL; 625 1.134 kre int line = 0; 626 1.156 kre int savecheckkwd; 627 1.129 kre #ifdef BOGUS_NOT_COMMAND 628 1.129 kre union node *n2; 629 1.31 christos int negate = 0; 630 1.129 kre #endif 631 1.1 cgd 632 1.130 kre CTRACE(DBG_PARSE, ("simple command with%s redir already @%d\n", 633 1.130 kre redir ? "" : "out", plinno)); 634 1.130 kre 635 1.11 jtc /* If we don't have any redirections already, then we must reset */ 636 1.11 jtc /* rpp to be the address of the local redir variable. */ 637 1.5 sef if (redir == 0) 638 1.5 sef rpp = &redir; 639 1.5 sef 640 1.1 cgd args = NULL; 641 1.1 cgd app = &args; 642 1.11 jtc 643 1.129 kre #ifdef BOGUS_NOT_COMMAND /* pipelines get negated, commands do not */ 644 1.31 christos while (readtoken() == TNOT) { 645 1.130 kre VTRACE(DBG_PARSE, ("simplcmd: bogus TNOT recognized\n")); 646 1.125 kre negate++; 647 1.31 christos } 648 1.31 christos tokpushback++; 649 1.129 kre #endif 650 1.31 christos 651 1.156 kre savecheckkwd = CHKALIAS; 652 1.1 cgd for (;;) { 653 1.156 kre checkkwd = savecheckkwd; 654 1.1 cgd if (readtoken() == TWORD) { 655 1.134 kre if (line == 0) 656 1.134 kre line = startlinno; 657 1.155 kre n = makeword(startlinno); 658 1.1 cgd *app = n; 659 1.1 cgd app = &n->narg.next; 660 1.156 kre if (savecheckkwd != 0 && !isassignment(wordtext)) 661 1.156 kre savecheckkwd = 0; 662 1.1 cgd } else if (lasttoken == TREDIR) { 663 1.134 kre if (line == 0) 664 1.134 kre line = startlinno; 665 1.1 cgd *rpp = n = redirnode; 666 1.1 cgd rpp = &n->nfile.next; 667 1.1 cgd parsefname(); /* read name of redirection file */ 668 1.1 cgd } else if (lasttoken == TLP && app == &args->narg.next 669 1.110 christos && redir == 0) { 670 1.1 cgd /* We have a function */ 671 1.142 kre consumetoken(TRP); 672 1.84 christos funclinno = plinno; 673 1.171 kre /* 674 1.171 kre * Make sure there are no unquoted $'s in the 675 1.171 kre * name (allowing those, not expanding them, 676 1.177 andvar * simply treating '$' as a character, is desirable 677 1.171 kre * but the parser has converted them to CTLxxx 678 1.171 kre * chars, and that's not what we want 679 1.171 kre * 680 1.171 kre * Fortunately here the user can simply quote 681 1.171 kre * the name to avoid this restriction. 682 1.171 kre */ 683 1.171 kre if (!noexpand(n->narg.text)) 684 1.171 kre synerror("Bad function name (use quotes)"); 685 1.64 christos rmescapes(n->narg.text); 686 1.118 kre if (strchr(n->narg.text, '/')) 687 1.1 cgd synerror("Bad function name"); 688 1.134 kre VTRACE(DBG_PARSE, ("Function '%s' seen @%d\n", 689 1.134 kre n->narg.text, plinno)); 690 1.1 cgd n->type = NDEFUN; 691 1.134 kre n->narg.lineno = plinno - elided_nl; 692 1.1 cgd n->narg.next = command(); 693 1.84 christos funclinno = 0; 694 1.31 christos goto checkneg; 695 1.1 cgd } else { 696 1.1 cgd tokpushback++; 697 1.1 cgd break; 698 1.1 cgd } 699 1.1 cgd } 700 1.120 kre 701 1.120 kre if (args == NULL && redir == NULL) 702 1.120 kre synexpect(-1, 0); 703 1.1 cgd *app = NULL; 704 1.1 cgd *rpp = NULL; 705 1.101 christos n = stalloc(sizeof(struct ncmd)); 706 1.1 cgd n->type = NCMD; 707 1.134 kre n->ncmd.lineno = line - elided_nl; 708 1.1 cgd n->ncmd.backgnd = 0; 709 1.1 cgd n->ncmd.args = args; 710 1.1 cgd n->ncmd.redirect = redir; 711 1.133 kre n->ncmd.lineno = startlinno; 712 1.31 christos 713 1.182 kre checkneg:; 714 1.129 kre #ifdef BOGUS_NOT_COMMAND 715 1.31 christos if (negate) { 716 1.130 kre VTRACE(DBG_PARSE, ("bogus %snegate simplecmd\n", 717 1.130 kre (negate&1) ? "" : "double ")); 718 1.101 christos n2 = stalloc(sizeof(struct nnot)); 719 1.125 kre n2->type = (negate & 1) ? NNOT : NDNOT; 720 1.31 christos n2->nnot.com = n; 721 1.31 christos return n2; 722 1.31 christos } 723 1.31 christos else 724 1.129 kre #endif 725 1.31 christos return n; 726 1.1 cgd } 727 1.1 cgd 728 1.18 jtc STATIC union node * 729 1.155 kre makeword(int lno) 730 1.54 christos { 731 1.18 jtc union node *n; 732 1.18 jtc 733 1.101 christos n = stalloc(sizeof(struct narg)); 734 1.18 jtc n->type = NARG; 735 1.18 jtc n->narg.next = NULL; 736 1.18 jtc n->narg.text = wordtext; 737 1.18 jtc n->narg.backquote = backquotelist; 738 1.142 kre n->narg.lineno = lno; 739 1.18 jtc return n; 740 1.18 jtc } 741 1.18 jtc 742 1.95 christos void 743 1.95 christos fixredir(union node *n, const char *text, int err) 744 1.95 christos { 745 1.126 kre 746 1.130 kre VTRACE(DBG_PARSE, ("Fix redir %s %d\n", text, err)); 747 1.18 jtc if (!err) 748 1.18 jtc n->ndup.vname = NULL; 749 1.18 jtc 750 1.174 kre if (is_number(text)) { 751 1.91 christos n->ndup.dupfd = number(text); 752 1.174 kre if (n->ndup.dupfd < user_fd_limit && 753 1.174 kre n->ndup.dupfd > max_user_fd) 754 1.174 kre max_user_fd = n->ndup.dupfd; 755 1.174 kre } else if (text[0] == '-' && text[1] == '\0') 756 1.18 jtc n->ndup.dupfd = -1; 757 1.18 jtc else { 758 1.30 christos 759 1.18 jtc if (err) 760 1.18 jtc synerror("Bad fd number"); 761 1.18 jtc else 762 1.155 kre n->ndup.vname = makeword(startlinno - elided_nl); 763 1.18 jtc } 764 1.18 jtc } 765 1.18 jtc 766 1.1 cgd 767 1.1 cgd STATIC void 768 1.54 christos parsefname(void) 769 1.54 christos { 770 1.1 cgd union node *n = redirnode; 771 1.1 cgd 772 1.1 cgd if (readtoken() != TWORD) 773 1.108 christos synexpect(-1, 0); 774 1.1 cgd if (n->type == NHERE) { 775 1.140 kre struct HereDoc *here = heredoc; 776 1.140 kre struct HereDoc *p; 777 1.1 cgd 778 1.1 cgd if (quoteflag == 0) 779 1.1 cgd n->type = NXHERE; 780 1.130 kre VTRACE(DBG_PARSE, ("Here document %d @%d\n", n->type, plinno)); 781 1.1 cgd if (here->striptabs) { 782 1.1 cgd while (*wordtext == '\t') 783 1.1 cgd wordtext++; 784 1.1 cgd } 785 1.111 christos 786 1.111 christos /* 787 1.111 christos * this test is not really necessary, we are not 788 1.111 christos * required to expand wordtext, but there's no reason 789 1.111 christos * it cannot be $$ or something like that - that would 790 1.111 christos * not mean the pid, but literally two '$' characters. 791 1.111 christos * There is no need for limits on what the word can be. 792 1.111 christos * However, it needs to stay literal as entered, not 793 1.111 christos * have $ converted to CTLVAR or something, which as 794 1.111 christos * the parser is, at the minute, is impossible to prevent. 795 1.111 christos * So, leave it like this until the rest of the parser is fixed. 796 1.111 christos */ 797 1.126 kre if (!noexpand(wordtext)) 798 1.178 kre synerror("Unimplemented form of eof marker" 799 1.178 kre " for << redirection"); 800 1.111 christos 801 1.1 cgd rmescapes(wordtext); 802 1.1 cgd here->eofmark = wordtext; 803 1.1 cgd here->next = NULL; 804 1.1 cgd if (heredoclist == NULL) 805 1.1 cgd heredoclist = here; 806 1.1 cgd else { 807 1.90 christos for (p = heredoclist ; p->next ; p = p->next) 808 1.90 christos continue; 809 1.1 cgd p->next = here; 810 1.1 cgd } 811 1.1 cgd } else if (n->type == NTOFD || n->type == NFROMFD) { 812 1.18 jtc fixredir(n, wordtext, 0); 813 1.1 cgd } else { 814 1.155 kre n->nfile.fname = makeword(startlinno - elided_nl); 815 1.1 cgd } 816 1.1 cgd } 817 1.1 cgd 818 1.111 christos /* 819 1.111 christos * Check to see whether we are at the end of the here document. When this 820 1.111 christos * is called, c is set to the first character of the next input line. If 821 1.111 christos * we are at the end of the here document, this routine sets the c to PEOF. 822 1.111 christos * The new value of c is returned. 823 1.111 christos */ 824 1.111 christos 825 1.111 christos static int 826 1.111 christos checkend(int c, char * const eofmark, const int striptabs) 827 1.111 christos { 828 1.126 kre 829 1.111 christos if (striptabs) { 830 1.111 christos while (c == '\t') 831 1.111 christos c = pgetc(); 832 1.111 christos } 833 1.111 christos if (c == PEOF) { 834 1.111 christos if (*eofmark == '\0') 835 1.111 christos return (c); 836 1.111 christos synerror(EOFhere); 837 1.111 christos } 838 1.111 christos if (c == *eofmark) { 839 1.111 christos int c2; 840 1.111 christos char *q; 841 1.111 christos 842 1.111 christos for (q = eofmark + 1; c2 = pgetc(), *q != '\0' && c2 == *q; q++) 843 1.138 kre if (c2 == '\n') { 844 1.138 kre plinno++; 845 1.138 kre needprompt = doprompt; 846 1.138 kre } 847 1.111 christos if ((c2 == PEOF || c2 == '\n') && *q == '\0') { 848 1.111 christos c = PEOF; 849 1.111 christos if (c2 == '\n') { 850 1.111 christos plinno++; 851 1.111 christos needprompt = doprompt; 852 1.111 christos } 853 1.111 christos } else { 854 1.111 christos pungetc(); 855 1.111 christos pushstring(eofmark + 1, q - (eofmark + 1), NULL); 856 1.111 christos } 857 1.111 christos } else if (c == '\n' && *eofmark == '\0') { 858 1.111 christos c = PEOF; 859 1.111 christos plinno++; 860 1.111 christos needprompt = doprompt; 861 1.111 christos } 862 1.111 christos return (c); 863 1.111 christos } 864 1.111 christos 865 1.1 cgd 866 1.1 cgd /* 867 1.1 cgd * Input any here documents. 868 1.1 cgd */ 869 1.1 cgd 870 1.134 kre STATIC int 871 1.115 christos slurp_heredoc(char *const eofmark, const int striptabs, const int sq) 872 1.111 christos { 873 1.111 christos int c; 874 1.111 christos char *out; 875 1.134 kre int lines = plinno; 876 1.111 christos 877 1.111 christos c = pgetc(); 878 1.111 christos 879 1.111 christos /* 880 1.111 christos * If we hit EOF on the input, and the eofmark is a null string ('') 881 1.111 christos * we consider this empty line to be the eofmark, and exit without err. 882 1.111 christos */ 883 1.111 christos if (c == PEOF && *eofmark != '\0') 884 1.111 christos synerror(EOFhere); 885 1.111 christos 886 1.111 christos STARTSTACKSTR(out); 887 1.111 christos 888 1.111 christos while ((c = checkend(c, eofmark, striptabs)) != PEOF) { 889 1.111 christos do { 890 1.111 christos if (sq) { 891 1.111 christos /* 892 1.111 christos * in single quoted mode (eofmark quoted) 893 1.111 christos * all we look for is \n so we can check 894 1.179 andvar * for the eofmark - everything saved literally. 895 1.111 christos */ 896 1.111 christos STPUTC(c, out); 897 1.122 kre if (c == '\n') { 898 1.122 kre plinno++; 899 1.111 christos break; 900 1.122 kre } 901 1.111 christos continue; 902 1.111 christos } 903 1.111 christos /* 904 1.111 christos * In double quoted (non-quoted eofmark) 905 1.111 christos * we must handle \ followed by \n here 906 1.111 christos * otherwise we can mismatch the end mark. 907 1.111 christos * All other uses of \ will be handled later 908 1.111 christos * when the here doc is expanded. 909 1.111 christos * 910 1.111 christos * This also makes sure \\ followed by \n does 911 1.111 christos * not suppress the newline (the \ quotes itself) 912 1.111 christos */ 913 1.111 christos if (c == '\\') { /* A backslash */ 914 1.138 kre STPUTC(c, out); 915 1.111 christos c = pgetc(); /* followed by */ 916 1.122 kre if (c == '\n') { /* a newline? */ 917 1.138 kre STPUTC(c, out); 918 1.122 kre plinno++; 919 1.138 kre continue; /* don't break */ 920 1.122 kre } 921 1.111 christos } 922 1.111 christos STPUTC(c, out); /* keep the char */ 923 1.122 kre if (c == '\n') { /* at end of line */ 924 1.122 kre plinno++; 925 1.111 christos break; /* look for eofmark */ 926 1.122 kre } 927 1.111 christos } while ((c = pgetc()) != PEOF); 928 1.111 christos 929 1.111 christos /* 930 1.111 christos * If we have read a line, and reached EOF, without 931 1.111 christos * finding the eofmark, whether the EOF comes before 932 1.111 christos * or immediately after the \n, that is an error. 933 1.111 christos */ 934 1.111 christos if (c == PEOF || (c = pgetc()) == PEOF) 935 1.111 christos synerror(EOFhere); 936 1.111 christos } 937 1.111 christos STPUTC('\0', out); 938 1.111 christos 939 1.111 christos c = out - stackblock(); 940 1.111 christos out = stackblock(); 941 1.111 christos grabstackblock(c); 942 1.111 christos wordtext = out; 943 1.111 christos 944 1.130 kre VTRACE(DBG_PARSE, 945 1.134 kre ("Slurped a %d line %sheredoc (to '%s')%s: len %d, \"%.*s%s\" @%d\n", 946 1.134 kre plinno - lines, sq ? "quoted " : "", eofmark, 947 1.134 kre striptabs ? " tab stripped" : "", c, (c > 16 ? 16 : c), 948 1.130 kre wordtext, (c > 16 ? "..." : ""), plinno)); 949 1.134 kre 950 1.134 kre return (plinno - lines); 951 1.134 kre } 952 1.134 kre 953 1.134 kre static char * 954 1.134 kre insert_elided_nl(char *str) 955 1.134 kre { 956 1.134 kre while (elided_nl > 0) { 957 1.134 kre STPUTC(CTLNONL, str); 958 1.134 kre elided_nl--; 959 1.134 kre } 960 1.134 kre return str; 961 1.111 christos } 962 1.111 christos 963 1.111 christos STATIC void 964 1.111 christos readheredocs(void) 965 1.54 christos { 966 1.140 kre struct HereDoc *here; 967 1.1 cgd union node *n; 968 1.134 kre int line, l; 969 1.1 cgd 970 1.134 kre line = 0; /*XXX - gcc! obviously unneeded */ 971 1.134 kre if (heredoclist) 972 1.134 kre line = heredoclist->startline + 1; 973 1.134 kre l = 0; 974 1.1 cgd while (heredoclist) { 975 1.134 kre line += l; 976 1.1 cgd here = heredoclist; 977 1.1 cgd heredoclist = here->next; 978 1.1 cgd if (needprompt) { 979 1.11 jtc setprompt(2); 980 1.1 cgd needprompt = 0; 981 1.1 cgd } 982 1.111 christos 983 1.134 kre l = slurp_heredoc(here->eofmark, here->striptabs, 984 1.111 christos here->here->nhere.type == NHERE); 985 1.111 christos 986 1.155 kre here->here->nhere.doc = n = makeword(line); 987 1.1 cgd 988 1.115 christos if (here->here->nhere.type == NHERE) 989 1.115 christos continue; 990 1.111 christos 991 1.115 christos /* 992 1.115 christos * Now "parse" here docs that have unquoted eofmarkers. 993 1.115 christos */ 994 1.134 kre setinputstring(wordtext, 1, line); 995 1.138 kre VTRACE(DBG_PARSE, ("Reprocessing %d line here doc from %d\n", 996 1.138 kre l, line)); 997 1.115 christos readtoken1(pgetc(), DQSYNTAX, 1); 998 1.115 christos n->narg.text = wordtext; 999 1.115 christos n->narg.backquote = backquotelist; 1000 1.115 christos popfile(); 1001 1.115 christos } 1002 1.111 christos } 1003 1.111 christos 1004 1.1 cgd STATIC int 1005 1.54 christos peektoken(void) 1006 1.54 christos { 1007 1.1 cgd int t; 1008 1.1 cgd 1009 1.1 cgd t = readtoken(); 1010 1.1 cgd tokpushback++; 1011 1.1 cgd return (t); 1012 1.1 cgd } 1013 1.1 cgd 1014 1.1 cgd STATIC int 1015 1.54 christos readtoken(void) 1016 1.54 christos { 1017 1.1 cgd int t; 1018 1.1 cgd #ifdef DEBUG 1019 1.1 cgd int alreadyseen = tokpushback; 1020 1.156 kre int savecheckkwd = checkkwd; 1021 1.1 cgd #endif 1022 1.48 christos struct alias *ap; 1023 1.30 christos 1024 1.182 kre top:; 1025 1.1 cgd t = xxreadtoken(); 1026 1.1 cgd 1027 1.156 kre if (checkkwd & CHKNL) { 1028 1.156 kre while (t == TNL) { 1029 1.156 kre readheredocs(); 1030 1.156 kre t = xxreadtoken(); 1031 1.156 kre } 1032 1.156 kre } 1033 1.156 kre 1034 1.156 kre /* 1035 1.156 kre * check for keywords and aliases 1036 1.156 kre */ 1037 1.156 kre if (t == TWORD && !quoteflag) { 1038 1.156 kre const char *const *pp; 1039 1.1 cgd 1040 1.156 kre if (checkkwd & CHKKWD) 1041 1.43 christos for (pp = parsekwd; *pp; pp++) { 1042 1.95 christos if (**pp == *wordtext && equal(*pp, wordtext)) { 1043 1.90 christos lasttoken = t = pp - 1044 1.43 christos parsekwd + KWDOFFSET; 1045 1.130 kre VTRACE(DBG_PARSE, 1046 1.134 kre ("keyword %s recognized @%d\n", 1047 1.134 kre tokname[t], plinno)); 1048 1.11 jtc goto out; 1049 1.1 cgd } 1050 1.1 cgd } 1051 1.156 kre 1052 1.156 kre if (checkkwd & CHKALIAS && 1053 1.156 kre (ap = lookupalias(wordtext, 1)) != NULL) { 1054 1.156 kre VTRACE(DBG_PARSE, 1055 1.156 kre ("alias '%s' recognized -> <:%s:>\n", 1056 1.156 kre wordtext, ap->val)); 1057 1.156 kre pushstring(ap->val, strlen(ap->val), ap); 1058 1.156 kre goto top; 1059 1.1 cgd } 1060 1.156 kre } 1061 1.182 kre out:; 1062 1.156 kre if (t != TNOT) 1063 1.156 kre checkkwd = 0; 1064 1.156 kre 1065 1.156 kre VTRACE(DBG_PARSE, ("%stoken %s %s @%d (chkkwd %x->%x)\n", 1066 1.156 kre alreadyseen ? "reread " : "", tokname[t], 1067 1.156 kre t == TWORD ? wordtext : "", plinno, savecheckkwd, checkkwd)); 1068 1.1 cgd return (t); 1069 1.1 cgd } 1070 1.1 cgd 1071 1.1 cgd 1072 1.1 cgd /* 1073 1.1 cgd * Read the next input token. 1074 1.1 cgd * If the token is a word, we set backquotelist to the list of cmds in 1075 1.1 cgd * backquotes. We set quoteflag to true if any part of the word was 1076 1.1 cgd * quoted. 1077 1.1 cgd * If the token is TREDIR, then we set redirnode to a structure containing 1078 1.1 cgd * the redirection. 1079 1.1 cgd * In all cases, the variable startlinno is set to the number of the line 1080 1.1 cgd * on which the token starts. 1081 1.1 cgd * 1082 1.1 cgd * [Change comment: here documents and internal procedures] 1083 1.1 cgd * [Readtoken shouldn't have any arguments. Perhaps we should make the 1084 1.1 cgd * word parsing code into a separate routine. In this case, readtoken 1085 1.1 cgd * doesn't need to have any internal procedures, but parseword does. 1086 1.1 cgd * We could also make parseoperator in essence the main routine, and 1087 1.1 cgd * have parseword (readtoken1?) handle both words and redirection.] 1088 1.1 cgd */ 1089 1.1 cgd 1090 1.164 kre #define RETURN(token) return lasttoken = (token) 1091 1.1 cgd 1092 1.1 cgd STATIC int 1093 1.54 christos xxreadtoken(void) 1094 1.54 christos { 1095 1.32 tls int c; 1096 1.1 cgd 1097 1.1 cgd if (tokpushback) { 1098 1.1 cgd tokpushback = 0; 1099 1.163 kre CTRACE(DBG_LEXER, 1100 1.163 kre ("xxreadtoken() returns %s (%d) again\n", 1101 1.163 kre tokname[lasttoken], lasttoken)); 1102 1.1 cgd return lasttoken; 1103 1.1 cgd } 1104 1.1 cgd if (needprompt) { 1105 1.11 jtc setprompt(2); 1106 1.1 cgd needprompt = 0; 1107 1.1 cgd } 1108 1.134 kre elided_nl = 0; 1109 1.1 cgd startlinno = plinno; 1110 1.1 cgd for (;;) { /* until token or start of word found */ 1111 1.1 cgd c = pgetc_macro(); 1112 1.163 kre CTRACE(DBG_LEXER, ("xxreadtoken() sees '%c' (%#.2x) ", 1113 1.163 kre c&0xFF, c&0x1FF)); 1114 1.1 cgd switch (c) { 1115 1.156 kre case ' ': case '\t': case PFAKE: 1116 1.163 kre CTRACE(DBG_LEXER, (" ignored\n")); 1117 1.1 cgd continue; 1118 1.1 cgd case '#': 1119 1.90 christos while ((c = pgetc()) != '\n' && c != PEOF) 1120 1.90 christos continue; 1121 1.163 kre CTRACE(DBG_LEXER, 1122 1.163 kre ("skipped comment to (not incl) \\n\n")); 1123 1.1 cgd pungetc(); 1124 1.1 cgd continue; 1125 1.108 christos 1126 1.1 cgd case '\n': 1127 1.1 cgd plinno++; 1128 1.163 kre CTRACE(DBG_LEXER, ("newline now @%d\n", plinno)); 1129 1.1 cgd needprompt = doprompt; 1130 1.1 cgd RETURN(TNL); 1131 1.1 cgd case PEOF: 1132 1.163 kre CTRACE(DBG_LEXER, ("EOF -> TEOF (return)\n")); 1133 1.1 cgd RETURN(TEOF); 1134 1.108 christos 1135 1.1 cgd case '&': 1136 1.163 kre if (pgetc_linecont() == '&') { 1137 1.163 kre CTRACE(DBG_LEXER, 1138 1.163 kre ("and another -> TAND (return)\n")); 1139 1.1 cgd RETURN(TAND); 1140 1.163 kre } 1141 1.1 cgd pungetc(); 1142 1.163 kre CTRACE(DBG_LEXER, (" -> TBACKGND (return)\n")); 1143 1.1 cgd RETURN(TBACKGND); 1144 1.1 cgd case '|': 1145 1.163 kre if (pgetc_linecont() == '|') { 1146 1.163 kre CTRACE(DBG_LEXER, 1147 1.163 kre ("and another -> TOR (return)\n")); 1148 1.1 cgd RETURN(TOR); 1149 1.163 kre } 1150 1.1 cgd pungetc(); 1151 1.163 kre CTRACE(DBG_LEXER, (" -> TPIPE (return)\n")); 1152 1.1 cgd RETURN(TPIPE); 1153 1.1 cgd case ';': 1154 1.123 kre switch (pgetc_linecont()) { 1155 1.123 kre case ';': 1156 1.163 kre CTRACE(DBG_LEXER, 1157 1.163 kre ("and another -> TENDCASE (return)\n")); 1158 1.1 cgd RETURN(TENDCASE); 1159 1.123 kre case '&': 1160 1.163 kre CTRACE(DBG_LEXER, 1161 1.163 kre ("and '&' -> TCASEFALL (return)\n")); 1162 1.123 kre RETURN(TCASEFALL); 1163 1.123 kre default: 1164 1.123 kre pungetc(); 1165 1.163 kre CTRACE(DBG_LEXER, (" -> TSEMI (return)\n")); 1166 1.123 kre RETURN(TSEMI); 1167 1.123 kre } 1168 1.1 cgd case '(': 1169 1.163 kre CTRACE(DBG_LEXER, (" -> TLP (return)\n")); 1170 1.1 cgd RETURN(TLP); 1171 1.1 cgd case ')': 1172 1.163 kre CTRACE(DBG_LEXER, (" -> TRP (return)\n")); 1173 1.1 cgd RETURN(TRP); 1174 1.108 christos 1175 1.108 christos case '\\': 1176 1.108 christos switch (pgetc()) { 1177 1.108 christos case '\n': 1178 1.108 christos startlinno = ++plinno; 1179 1.163 kre CTRACE(DBG_LEXER, ("\\\n ignored, now @%d\n", 1180 1.163 kre plinno)); 1181 1.108 christos if (doprompt) 1182 1.108 christos setprompt(2); 1183 1.108 christos else 1184 1.108 christos setprompt(0); 1185 1.108 christos continue; 1186 1.108 christos case PEOF: 1187 1.163 kre CTRACE(DBG_LEXER, 1188 1.163 kre ("then EOF -> TEOF (return) '\\' dropped\n")); 1189 1.108 christos RETURN(TEOF); 1190 1.108 christos default: 1191 1.163 kre CTRACE(DBG_LEXER, ("not \\\n or EOF: ")); 1192 1.108 christos pungetc(); 1193 1.108 christos break; 1194 1.108 christos } 1195 1.108 christos /* FALLTHROUGH */ 1196 1.1 cgd default: 1197 1.163 kre CTRACE(DBG_LEXER, ("getting a word\n")); 1198 1.111 christos return readtoken1(c, BASESYNTAX, 0); 1199 1.1 cgd } 1200 1.1 cgd } 1201 1.1 cgd #undef RETURN 1202 1.1 cgd } 1203 1.1 cgd 1204 1.1 cgd 1205 1.1 cgd 1206 1.1 cgd /* 1207 1.1 cgd * If eofmark is NULL, read a word or a redirection symbol. If eofmark 1208 1.1 cgd * is not NULL, read a here document. In the latter case, eofmark is the 1209 1.1 cgd * word which marks the end of the document and striptabs is true if 1210 1.1 cgd * leading tabs should be stripped from the document. The argument firstc 1211 1.1 cgd * is the first character of the input token or document. 1212 1.1 cgd * 1213 1.1 cgd * Because C does not have internal subroutines, I have simulated them 1214 1.1 cgd * using goto's to implement the subroutine linkage. The following macros 1215 1.1 cgd * will run code that appears at the end of readtoken1. 1216 1.1 cgd */ 1217 1.1 cgd 1218 1.96 christos /* 1219 1.96 christos * We used to remember only the current syntax, variable nesting level, 1220 1.102 christos * double quote state for each var nesting level, and arith nesting 1221 1.96 christos * level (unrelated to var nesting) and one prev syntax when in arith 1222 1.96 christos * syntax. This worked for simple cases, but can't handle arith inside 1223 1.96 christos * var expansion inside arith inside var with some quoted and some not. 1224 1.96 christos * 1225 1.96 christos * Inspired by FreeBSD's implementation (though it was the obvious way) 1226 1.96 christos * though implemented differently, we now have a stack that keeps track 1227 1.96 christos * of what we are doing now, and what we were doing previously. 1228 1.96 christos * Every time something changes, which will eventually end and should 1229 1.96 christos * revert to the previous state, we push this stack, and then pop it 1230 1.96 christos * again later (that is every ${} with an operator (to parse the word 1231 1.102 christos * or pattern that follows) ${x} and $x are too simple to need it) 1232 1.96 christos * $(( )) $( ) and "...". Always. Really, always! 1233 1.96 christos * 1234 1.96 christos * The stack is implemented as one static (on the C stack) base block 1235 1.96 christos * containing LEVELS_PER_BLOCK (8) stack entries, which should be 1236 1.96 christos * enough for the vast majority of cases. For torture tests, we 1237 1.96 christos * malloc more blocks as needed. All accesses through the inline 1238 1.96 christos * functions below. 1239 1.96 christos */ 1240 1.96 christos 1241 1.96 christos /* 1242 1.96 christos * varnest & arinest will typically be 0 or 1 1243 1.96 christos * (varnest can increment in usages like ${x=${y}} but probably 1244 1.96 christos * does not really need to) 1245 1.96 christos * parenlevel allows balancing parens inside a $(( )), it is reset 1246 1.96 christos * at each new nesting level ( $(( ( x + 3 ${unset-)} )) does not work. 1247 1.96 christos * quoted is special - we need to know 2 things ... are we inside "..." 1248 1.96 christos * (even if inherited from some previous nesting level) and was there 1249 1.96 christos * an opening '"' at this level (so the next will be closing). 1250 1.106 christos * "..." can span nesting levels, but cannot be opened in one and 1251 1.96 christos * closed in a different one. 1252 1.96 christos * To handle this, "quoted" has two fields, the bottom 4 (really 2) 1253 1.96 christos * bits are 0, 1, or 2, for un, single, and double quoted (single quoted 1254 1.96 christos * is really so special that this setting is not very important) 1255 1.96 christos * and 0x10 that indicates that an opening quote has been seen. 1256 1.96 christos * The bottom 4 bits are inherited, the 0x10 bit is not. 1257 1.96 christos */ 1258 1.96 christos struct tokenstate { 1259 1.96 christos const char *ts_syntax; 1260 1.96 christos unsigned short ts_parenlevel; /* counters */ 1261 1.96 christos unsigned short ts_varnest; /* 64000 levels should be enough! */ 1262 1.96 christos unsigned short ts_arinest; 1263 1.96 christos unsigned short ts_quoted; /* 1 -> single, 2 -> double */ 1264 1.164 kre unsigned short ts_magicq; /* heredoc or word expand */ 1265 1.96 christos }; 1266 1.96 christos 1267 1.106 christos #define NQ 0x00 /* Unquoted */ 1268 1.106 christos #define SQ 0x01 /* Single Quotes */ 1269 1.106 christos #define DQ 0x02 /* Double Quotes (or equivalent) */ 1270 1.144 kre #define CQ 0x03 /* C style Single Quotes */ 1271 1.106 christos #define QF 0x0F /* Mask to extract previous values */ 1272 1.106 christos #define QS 0x10 /* Quoting started at this level in stack */ 1273 1.96 christos 1274 1.96 christos #define LEVELS_PER_BLOCK 8 1275 1.103 christos #define VSS struct statestack 1276 1.96 christos 1277 1.96 christos struct statestack { 1278 1.96 christos VSS *prev; /* previous block in list */ 1279 1.96 christos int cur; /* which of our tokenstates is current */ 1280 1.96 christos struct tokenstate tokenstate[LEVELS_PER_BLOCK]; 1281 1.96 christos }; 1282 1.96 christos 1283 1.103 christos static inline struct tokenstate * 1284 1.96 christos currentstate(VSS *stack) 1285 1.96 christos { 1286 1.96 christos return &stack->tokenstate[stack->cur]; 1287 1.96 christos } 1288 1.96 christos 1289 1.158 christos #ifdef notdef 1290 1.103 christos static inline struct tokenstate * 1291 1.96 christos prevstate(VSS *stack) 1292 1.96 christos { 1293 1.96 christos if (stack->cur != 0) 1294 1.96 christos return &stack->tokenstate[stack->cur - 1]; 1295 1.96 christos if (stack->prev == NULL) /* cannot drop below base */ 1296 1.96 christos return &stack->tokenstate[0]; 1297 1.96 christos return &stack->prev->tokenstate[LEVELS_PER_BLOCK - 1]; 1298 1.96 christos } 1299 1.158 christos #endif 1300 1.96 christos 1301 1.96 christos static inline VSS * 1302 1.96 christos bump_state_level(VSS *stack) 1303 1.96 christos { 1304 1.103 christos struct tokenstate *os, *ts; 1305 1.96 christos 1306 1.96 christos os = currentstate(stack); 1307 1.96 christos 1308 1.96 christos if (++stack->cur >= LEVELS_PER_BLOCK) { 1309 1.96 christos VSS *ss; 1310 1.96 christos 1311 1.96 christos ss = (VSS *)ckmalloc(sizeof (struct statestack)); 1312 1.96 christos ss->cur = 0; 1313 1.96 christos ss->prev = stack; 1314 1.96 christos stack = ss; 1315 1.96 christos } 1316 1.96 christos 1317 1.96 christos ts = currentstate(stack); 1318 1.96 christos 1319 1.96 christos ts->ts_parenlevel = 0; /* parens inside never match outside */ 1320 1.96 christos 1321 1.96 christos ts->ts_quoted = os->ts_quoted & QF; /* these are default settings */ 1322 1.96 christos ts->ts_varnest = os->ts_varnest; 1323 1.96 christos ts->ts_arinest = os->ts_arinest; /* when appropriate */ 1324 1.96 christos ts->ts_syntax = os->ts_syntax; /* they will be altered */ 1325 1.164 kre ts->ts_magicq = os->ts_magicq; 1326 1.96 christos 1327 1.96 christos return stack; 1328 1.96 christos } 1329 1.96 christos 1330 1.96 christos static inline VSS * 1331 1.96 christos drop_state_level(VSS *stack) 1332 1.96 christos { 1333 1.96 christos if (stack->cur == 0) { 1334 1.96 christos VSS *ss; 1335 1.96 christos 1336 1.96 christos ss = stack; 1337 1.96 christos stack = ss->prev; 1338 1.96 christos if (stack == NULL) 1339 1.96 christos return ss; 1340 1.106 christos ckfree(ss); 1341 1.96 christos } 1342 1.96 christos --stack->cur; 1343 1.96 christos return stack; 1344 1.96 christos } 1345 1.96 christos 1346 1.96 christos static inline void 1347 1.96 christos cleanup_state_stack(VSS *stack) 1348 1.96 christos { 1349 1.96 christos while (stack->prev != NULL) { 1350 1.96 christos stack->cur = 0; 1351 1.96 christos stack = drop_state_level(stack); 1352 1.96 christos } 1353 1.96 christos } 1354 1.96 christos 1355 1.95 christos #define PARSESUB() {goto parsesub; parsesub_return:;} 1356 1.11 jtc #define PARSEARITH() {goto parsearith; parsearith_return:;} 1357 1.1 cgd 1358 1.52 christos /* 1359 1.176 msaitoh * The following macros all assume the existence of a local var "stack" 1360 1.96 christos * which contains a pointer to the current struct stackstate 1361 1.52 christos */ 1362 1.51 christos 1363 1.96 christos /* 1364 1.96 christos * These are macros rather than inline funcs to avoid code churn as much 1365 1.96 christos * as possible - they replace macros of the same name used previously. 1366 1.96 christos */ 1367 1.96 christos #define ISDBLQUOTE() (currentstate(stack)->ts_quoted & QS) 1368 1.96 christos #define SETDBLQUOTE() (currentstate(stack)->ts_quoted = QS | DQ) 1369 1.158 christos #ifdef notdef 1370 1.96 christos #define CLRDBLQUOTE() (currentstate(stack)->ts_quoted = \ 1371 1.96 christos stack->cur != 0 || stack->prev ? \ 1372 1.96 christos prevstate(stack)->ts_quoted & QF : 0) 1373 1.158 christos #endif 1374 1.96 christos 1375 1.96 christos /* 1376 1.96 christos * This set are just to avoid excess typing and line lengths... 1377 1.96 christos * The ones that "look like" var names must be implemented to be lvalues 1378 1.96 christos */ 1379 1.96 christos #define syntax (currentstate(stack)->ts_syntax) 1380 1.96 christos #define parenlevel (currentstate(stack)->ts_parenlevel) 1381 1.96 christos #define varnest (currentstate(stack)->ts_varnest) 1382 1.96 christos #define arinest (currentstate(stack)->ts_arinest) 1383 1.96 christos #define quoted (currentstate(stack)->ts_quoted) 1384 1.164 kre #define magicq (currentstate(stack)->ts_magicq) 1385 1.106 christos #define TS_PUSH() (stack = bump_state_level(stack)) 1386 1.106 christos #define TS_POP() (stack = drop_state_level(stack)) 1387 1.106 christos 1388 1.106 christos /* 1389 1.106 christos * Called to parse command substitutions. oldstyle is true if the command 1390 1.106 christos * is enclosed inside `` (otherwise it was enclosed in "$( )") 1391 1.106 christos * 1392 1.106 christos * Internally nlpp is a pointer to the head of the linked 1393 1.106 christos * list of commands (passed by reference), and savelen is the number of 1394 1.106 christos * characters on the top of the stack which must be preserved. 1395 1.106 christos */ 1396 1.106 christos static char * 1397 1.107 christos parsebackq(VSS *const stack, char * const in, 1398 1.164 kre struct nodelist **const pbqlist, const int oldstyle) 1399 1.106 christos { 1400 1.106 christos struct nodelist **nlpp; 1401 1.109 christos const int savepbq = parsebackquote; 1402 1.106 christos union node *n; 1403 1.107 christos char *out; 1404 1.106 christos char *str = NULL; 1405 1.106 christos char *volatile sstr = str; 1406 1.106 christos struct jmploc jmploc; 1407 1.106 christos struct jmploc *const savehandler = handler; 1408 1.160 kre struct parsefile *const savetopfile = getcurrentfile(); 1409 1.109 christos const int savelen = in - stackblock(); 1410 1.106 christos int saveprompt; 1411 1.138 kre int lno; 1412 1.106 christos 1413 1.106 christos if (setjmp(jmploc.loc)) { 1414 1.160 kre popfilesupto(savetopfile); 1415 1.106 christos if (sstr) 1416 1.106 christos ckfree(__UNVOLATILE(sstr)); 1417 1.106 christos cleanup_state_stack(stack); 1418 1.106 christos parsebackquote = 0; 1419 1.106 christos handler = savehandler; 1420 1.163 kre CTRACE(DBG_LEXER, ("parsebackq() err (%d), unwinding\n", 1421 1.163 kre exception)); 1422 1.106 christos longjmp(handler->loc, 1); 1423 1.106 christos } 1424 1.106 christos INTOFF; 1425 1.106 christos sstr = str = NULL; 1426 1.106 christos if (savelen > 0) { 1427 1.106 christos sstr = str = ckmalloc(savelen); 1428 1.106 christos memcpy(str, stackblock(), savelen); 1429 1.106 christos } 1430 1.106 christos handler = &jmploc; 1431 1.106 christos INTON; 1432 1.126 kre if (oldstyle) { 1433 1.134 kre /* 1434 1.134 kre * We must read until the closing backquote, giving special 1435 1.134 kre * treatment to some slashes, and then push the string and 1436 1.134 kre * reread it as input, interpreting it normally. 1437 1.134 kre */ 1438 1.126 kre int pc; 1439 1.126 kre int psavelen; 1440 1.126 kre char *pstr; 1441 1.134 kre int line1 = plinno; 1442 1.106 christos 1443 1.163 kre VTRACE(DBG_PARSE|DBG_LEXER, 1444 1.163 kre ("parsebackq: repackaging `` as $( )")); 1445 1.106 christos /* 1446 1.106 christos * Because the entire `...` is read here, we don't 1447 1.106 christos * need to bother the state stack. That will be used 1448 1.106 christos * (as appropriate) when the processed string is re-read. 1449 1.106 christos */ 1450 1.126 kre STARTSTACKSTR(out); 1451 1.138 kre #ifdef DEBUG 1452 1.163 kre for (psavelen = 0;;psavelen++) { /* } */ 1453 1.138 kre #else 1454 1.106 christos for (;;) { 1455 1.138 kre #endif 1456 1.106 christos if (needprompt) { 1457 1.106 christos setprompt(2); 1458 1.106 christos needprompt = 0; 1459 1.106 christos } 1460 1.138 kre pc = pgetc(); 1461 1.163 kre VTRACE(DBG_LEXER, 1462 1.163 kre ("parsebackq() got '%c'(%#.2x) in `` %s", pc&0xFF, 1463 1.163 kre pc&0x1FF, pc == '`' ? "terminator\n" : "")); 1464 1.134 kre if (pc == '`') 1465 1.134 kre break; 1466 1.134 kre switch (pc) { 1467 1.106 christos case '\\': 1468 1.138 kre pc = pgetc(); 1469 1.163 kre VTRACE(DBG_LEXER, ("then '%c'(%#.2x) ", 1470 1.163 kre pc&0xFF, pc&0x1FF)); 1471 1.138 kre #ifdef DEBUG 1472 1.138 kre psavelen++; 1473 1.138 kre #endif 1474 1.138 kre if (pc == '\n') { /* keep \ \n for later */ 1475 1.138 kre plinno++; 1476 1.163 kre VTRACE(DBG_LEXER, ("@%d ", plinno)); 1477 1.138 kre needprompt = doprompt; 1478 1.138 kre } 1479 1.126 kre if (pc != '\\' && pc != '`' && pc != '$' 1480 1.163 kre && (!ISDBLQUOTE() || pc != '"')) { 1481 1.163 kre VTRACE(DBG_LEXER, ("keep '\\' ")); 1482 1.126 kre STPUTC('\\', out); 1483 1.163 kre } 1484 1.106 christos break; 1485 1.106 christos 1486 1.106 christos case '\n': 1487 1.106 christos plinno++; 1488 1.163 kre VTRACE(DBG_LEXER, ("@%d ", plinno)); 1489 1.106 christos needprompt = doprompt; 1490 1.106 christos break; 1491 1.106 christos 1492 1.106 christos case PEOF: 1493 1.138 kre startlinno = line1; 1494 1.163 kre VTRACE(DBG_LEXER, ("EOF\n", plinno)); 1495 1.106 christos synerror("EOF in backquote substitution"); 1496 1.106 christos break; 1497 1.106 christos 1498 1.106 christos default: 1499 1.106 christos break; 1500 1.106 christos } 1501 1.163 kre VTRACE(DBG_LEXER, (".\n", plinno)); 1502 1.109 christos STPUTC(pc, out); 1503 1.126 kre } 1504 1.126 kre STPUTC('\0', out); 1505 1.163 kre VTRACE(DBG_LEXER, ("parsebackq() ``:")); 1506 1.163 kre VTRACE(DBG_PARSE|DBG_LEXER, (" read %d", psavelen)); 1507 1.126 kre psavelen = out - stackblock(); 1508 1.163 kre VTRACE(DBG_PARSE|DBG_LEXER, (" produced %d\n", psavelen)); 1509 1.126 kre if (psavelen > 0) { 1510 1.109 christos pstr = grabstackstr(out); 1511 1.180 kre CTRACE(DBG_LEXER, 1512 1.163 kre ("parsebackq() reprocessing as $(%s)\n", pstr)); 1513 1.134 kre setinputstring(pstr, 1, line1); 1514 1.126 kre } 1515 1.126 kre } 1516 1.106 christos nlpp = pbqlist; 1517 1.106 christos while (*nlpp) 1518 1.106 christos nlpp = &(*nlpp)->next; 1519 1.106 christos *nlpp = stalloc(sizeof(struct nodelist)); 1520 1.106 christos (*nlpp)->next = NULL; 1521 1.106 christos parsebackquote = oldstyle; 1522 1.106 christos 1523 1.106 christos if (oldstyle) { 1524 1.106 christos saveprompt = doprompt; 1525 1.106 christos doprompt = 0; 1526 1.106 christos } else 1527 1.106 christos saveprompt = 0; 1528 1.106 christos 1529 1.138 kre lno = -plinno; 1530 1.163 kre CTRACE(DBG_LEXER, ("parsebackq() parsing embedded command list\n")); 1531 1.142 kre n = list(0); 1532 1.163 kre CTRACE(DBG_LEXER, ("parsebackq() parsed $() (%d -> %d)\n", -lno, 1533 1.163 kre lno + plinno)); 1534 1.138 kre lno += plinno; 1535 1.106 christos 1536 1.142 kre if (oldstyle) { 1537 1.142 kre if (peektoken() != TEOF) 1538 1.142 kre synexpect(-1, 0); 1539 1.106 christos doprompt = saveprompt; 1540 1.142 kre } else 1541 1.142 kre consumetoken(TRP); 1542 1.106 christos 1543 1.106 christos (*nlpp)->n = n; 1544 1.126 kre if (oldstyle) { 1545 1.106 christos /* 1546 1.106 christos * Start reading from old file again, ignoring any pushed back 1547 1.106 christos * tokens left from the backquote parsing 1548 1.106 christos */ 1549 1.163 kre CTRACE(DBG_LEXER, ("parsebackq() back to previous input\n")); 1550 1.126 kre popfile(); 1551 1.106 christos tokpushback = 0; 1552 1.106 christos } 1553 1.109 christos 1554 1.106 christos while (stackblocksize() <= savelen) 1555 1.106 christos growstackblock(); 1556 1.109 christos STARTSTACKSTR(out); 1557 1.106 christos if (str) { 1558 1.109 christos memcpy(out, str, savelen); 1559 1.109 christos STADJUST(savelen, out); 1560 1.106 christos INTOFF; 1561 1.106 christos ckfree(str); 1562 1.106 christos sstr = str = NULL; 1563 1.106 christos INTON; 1564 1.106 christos } 1565 1.106 christos parsebackquote = savepbq; 1566 1.106 christos handler = savehandler; 1567 1.138 kre if (arinest || ISDBLQUOTE()) { 1568 1.139 kre STPUTC(CTLBACKQ | CTLQUOTE, out); 1569 1.138 kre while (--lno >= 0) 1570 1.139 kre STPUTC(CTLNONL, out); 1571 1.138 kre } else 1572 1.139 kre STPUTC(CTLBACKQ, out); 1573 1.106 christos 1574 1.109 christos return out; 1575 1.106 christos } 1576 1.94 christos 1577 1.112 christos /* 1578 1.112 christos * Parse a redirection operator. The parameter "out" points to a string 1579 1.112 christos * specifying the fd to be redirected. It is guaranteed to be either "" 1580 1.112 christos * or a numeric string (for now anyway). The parameter "c" contains the 1581 1.112 christos * first character of the redirection operator. 1582 1.112 christos * 1583 1.112 christos * Note the string "out" is on the stack, which we are about to clobber, 1584 1.112 christos * so process it first... 1585 1.112 christos */ 1586 1.112 christos 1587 1.112 christos static void 1588 1.112 christos parseredir(const char *out, int c) 1589 1.112 christos { 1590 1.112 christos union node *np; 1591 1.112 christos int fd; 1592 1.112 christos 1593 1.166 kre np = stalloc(sizeof(struct nfile)); 1594 1.166 kre 1595 1.166 kre fd = (*out == '\0') ? -1 : number(out); /* number(out) >= 0 */ 1596 1.166 kre np->nfile.fd = fd; /* do this again later with updated fd */ 1597 1.166 kre if (fd != np->nfile.fd) 1598 1.174 kre error("file descriptor (%d) out of range (max %ld)", 1599 1.174 kre fd, user_fd_limit - 1); 1600 1.174 kre if (fd < user_fd_limit && fd > max_user_fd) 1601 1.173 kre max_user_fd = fd; 1602 1.112 christos 1603 1.163 kre VTRACE(DBG_LEXER, ("parseredir after '%s%c' ", out, c)); 1604 1.112 christos if (c == '>') { 1605 1.112 christos if (fd < 0) 1606 1.112 christos fd = 1; 1607 1.121 kre c = pgetc_linecont(); 1608 1.163 kre VTRACE(DBG_LEXER, ("is '%c'(%#.2x) ", c&0xFF, c&0x1FF)); 1609 1.112 christos if (c == '>') 1610 1.112 christos np->type = NAPPEND; 1611 1.112 christos else if (c == '|') 1612 1.112 christos np->type = NCLOBBER; 1613 1.112 christos else if (c == '&') 1614 1.112 christos np->type = NTOFD; 1615 1.112 christos else { 1616 1.112 christos np->type = NTO; 1617 1.163 kre VTRACE(DBG_LEXER, ("unwanted ", c)); 1618 1.112 christos pungetc(); 1619 1.112 christos } 1620 1.112 christos } else { /* c == '<' */ 1621 1.112 christos if (fd < 0) 1622 1.112 christos fd = 0; 1623 1.163 kre c = pgetc_linecont(); 1624 1.163 kre VTRACE(DBG_LEXER, ("is '%c'(%#.2x) ", c&0xFF, c&0x1FF)); 1625 1.163 kre switch (c) { 1626 1.112 christos case '<': 1627 1.164 kre /* if sizes differ, just discard the old one */ 1628 1.164 kre if (sizeof (struct nfile) != sizeof (struct nhere)) 1629 1.112 christos np = stalloc(sizeof(struct nhere)); 1630 1.112 christos np->type = NHERE; 1631 1.164 kre np->nhere.fd = 0; 1632 1.140 kre heredoc = stalloc(sizeof(struct HereDoc)); 1633 1.112 christos heredoc->here = np; 1634 1.116 christos heredoc->startline = plinno; 1635 1.121 kre if ((c = pgetc_linecont()) == '-') { 1636 1.163 kre CTRACE(DBG_LEXER, ("and '%c'(%#.2x) ", 1637 1.163 kre c & 0xFF, c & 0x1FF)); 1638 1.112 christos heredoc->striptabs = 1; 1639 1.112 christos } else { 1640 1.112 christos heredoc->striptabs = 0; 1641 1.112 christos pungetc(); 1642 1.112 christos } 1643 1.112 christos break; 1644 1.112 christos 1645 1.112 christos case '&': 1646 1.112 christos np->type = NFROMFD; 1647 1.112 christos break; 1648 1.112 christos 1649 1.112 christos case '>': 1650 1.112 christos np->type = NFROMTO; 1651 1.112 christos break; 1652 1.112 christos 1653 1.112 christos default: 1654 1.112 christos np->type = NFROM; 1655 1.163 kre VTRACE(DBG_LEXER, ("unwanted('%c'0#.2x)", c&0xFF, 1656 1.163 kre c&0x1FF)); 1657 1.112 christos pungetc(); 1658 1.112 christos break; 1659 1.112 christos } 1660 1.112 christos } 1661 1.112 christos np->nfile.fd = fd; 1662 1.112 christos 1663 1.163 kre VTRACE(DBG_LEXER, (" ->%"PRIdsNT" fd=%d\n", NODETYPENAME(np->type),fd)); 1664 1.163 kre 1665 1.112 christos redirnode = np; /* this is the "value" of TRENODE */ 1666 1.112 christos } 1667 1.112 christos 1668 1.144 kre /* 1669 1.144 kre * Called to parse a backslash escape sequence inside $'...'. 1670 1.144 kre * The backslash has already been read. 1671 1.144 kre */ 1672 1.144 kre static char * 1673 1.144 kre readcstyleesc(char *out) 1674 1.144 kre { 1675 1.144 kre int c, vc, i, n; 1676 1.144 kre unsigned int v; 1677 1.144 kre 1678 1.144 kre c = pgetc(); 1679 1.163 kre VTRACE(DBG_LEXER, ("CSTR(\\%c)(\\%#x)", c&0xFF, c&0x1FF)); 1680 1.144 kre switch (c) { 1681 1.144 kre case '\0': 1682 1.144 kre case PEOF: 1683 1.167 kre synerror("Unterminated quoted string ($'...)"); 1684 1.144 kre case '\n': 1685 1.144 kre plinno++; 1686 1.163 kre VTRACE(DBG_LEXER, ("@%d ", plinno)); 1687 1.144 kre if (doprompt) 1688 1.144 kre setprompt(2); 1689 1.144 kre else 1690 1.144 kre setprompt(0); 1691 1.144 kre return out; 1692 1.144 kre 1693 1.144 kre case '\\': 1694 1.144 kre case '\'': 1695 1.144 kre case '"': 1696 1.144 kre v = c; 1697 1.144 kre break; 1698 1.144 kre 1699 1.144 kre case 'a': v = '\a'; break; 1700 1.144 kre case 'b': v = '\b'; break; 1701 1.144 kre case 'e': v = '\033'; break; 1702 1.144 kre case 'f': v = '\f'; break; 1703 1.144 kre case 'n': v = '\n'; break; 1704 1.144 kre case 'r': v = '\r'; break; 1705 1.144 kre case 't': v = '\t'; break; 1706 1.144 kre case 'v': v = '\v'; break; 1707 1.144 kre 1708 1.144 kre case '0': case '1': case '2': case '3': 1709 1.144 kre case '4': case '5': case '6': case '7': 1710 1.144 kre v = c - '0'; 1711 1.144 kre c = pgetc(); 1712 1.144 kre if (c >= '0' && c <= '7') { 1713 1.144 kre v <<= 3; 1714 1.144 kre v += c - '0'; 1715 1.144 kre c = pgetc(); 1716 1.144 kre if (c >= '0' && c <= '7') { 1717 1.144 kre v <<= 3; 1718 1.144 kre v += c - '0'; 1719 1.144 kre } else 1720 1.144 kre pungetc(); 1721 1.144 kre } else 1722 1.144 kre pungetc(); 1723 1.144 kre break; 1724 1.144 kre 1725 1.144 kre case 'c': 1726 1.144 kre c = pgetc(); 1727 1.144 kre if (c < 0x3f || c > 0x7a || c == 0x60) 1728 1.144 kre synerror("Bad \\c escape sequence"); 1729 1.144 kre if (c == '\\' && pgetc() != '\\') 1730 1.144 kre synerror("Bad \\c\\ escape sequence"); 1731 1.144 kre if (c == '?') 1732 1.144 kre v = 127; 1733 1.144 kre else 1734 1.144 kre v = c & 0x1f; 1735 1.144 kre break; 1736 1.144 kre 1737 1.144 kre case 'x': 1738 1.144 kre n = 2; 1739 1.144 kre goto hexval; 1740 1.144 kre case 'u': 1741 1.144 kre n = 4; 1742 1.144 kre goto hexval; 1743 1.144 kre case 'U': 1744 1.144 kre n = 8; 1745 1.182 kre hexval:; 1746 1.144 kre v = 0; 1747 1.144 kre for (i = 0; i < n; i++) { 1748 1.144 kre c = pgetc(); 1749 1.144 kre if (c >= '0' && c <= '9') 1750 1.144 kre v = (v << 4) + c - '0'; 1751 1.144 kre else if (c >= 'A' && c <= 'F') 1752 1.144 kre v = (v << 4) + c - 'A' + 10; 1753 1.144 kre else if (c >= 'a' && c <= 'f') 1754 1.144 kre v = (v << 4) + c - 'a' + 10; 1755 1.144 kre else { 1756 1.144 kre pungetc(); 1757 1.144 kre break; 1758 1.144 kre } 1759 1.144 kre } 1760 1.144 kre if (n > 2 && v > 127) { 1761 1.144 kre if (v >= 0xd800 && v <= 0xdfff) 1762 1.144 kre synerror("Invalid \\u escape sequence"); 1763 1.144 kre 1764 1.144 kre /* XXX should we use iconv here. What locale? */ 1765 1.167 kre CHECKSTRSPACE(12, out); 1766 1.144 kre 1767 1.167 kre /* 1768 1.167 kre * Add a byte to output string, while checking if it needs to 1769 1.167 kre * be escaped -- if its value happens to match the value of one 1770 1.179 andvar * of our internal CTL* chars - which would (at a minimum) be 1771 1.167 kre * summarily removed later, if not escaped. 1772 1.167 kre * 1773 1.167 kre * The current definition of ISCTL() allows the compiler to 1774 1.167 kre * optimise away either half, or all, of the test in most of 1775 1.169 kre * the cases here (0xc0 | anything) cannot be between 0x80 and 0x9f 1776 1.167 kre * for example, so there a test is not needed). 1777 1.167 kre * 1778 1.167 kre * Which tests can be removed depends upon the actual values 1779 1.167 kre * selected for the CTL* chars. 1780 1.167 kre */ 1781 1.167 kre #define ESC_USTPUTC(c, o) do { \ 1782 1.167 kre char _ch = (c); \ 1783 1.167 kre \ 1784 1.167 kre if (ISCTL(_ch)) \ 1785 1.167 kre USTPUTC(CTLESC, o); \ 1786 1.167 kre USTPUTC(_ch, o); \ 1787 1.167 kre } while (0) 1788 1.167 kre 1789 1.167 kre VTRACE(DBG_LEXER, ("CSTR(\\%c%8.8x)", n==4?'u':'U', v)); 1790 1.144 kre if (v <= 0x7ff) { 1791 1.167 kre ESC_USTPUTC(0xc0 | v >> 6, out); 1792 1.167 kre ESC_USTPUTC(0x80 | (v & 0x3f), out); 1793 1.144 kre return out; 1794 1.144 kre } else if (v <= 0xffff) { 1795 1.167 kre ESC_USTPUTC(0xe0 | v >> 12, out); 1796 1.167 kre ESC_USTPUTC(0x80 | ((v >> 6) & 0x3f), out); 1797 1.167 kre ESC_USTPUTC(0x80 | (v & 0x3f), out); 1798 1.144 kre return out; 1799 1.144 kre } else if (v <= 0x10ffff) { 1800 1.167 kre ESC_USTPUTC(0xf0 | v >> 18, out); 1801 1.167 kre ESC_USTPUTC(0x80 | ((v >> 12) & 0x3f), out); 1802 1.167 kre ESC_USTPUTC(0x80 | ((v >> 6) & 0x3f), out); 1803 1.167 kre ESC_USTPUTC(0x80 | (v & 0x3f), out); 1804 1.167 kre return out; 1805 1.167 kre 1806 1.167 kre /* these next two are not very likely, but we may as well be complete */ 1807 1.167 kre } else if (v <= 0x3FFFFFF) { 1808 1.167 kre ESC_USTPUTC(0xf8 | v >> 24, out); 1809 1.167 kre ESC_USTPUTC(0x80 | ((v >> 18) & 0x3f), out); 1810 1.167 kre ESC_USTPUTC(0x80 | ((v >> 12) & 0x3f), out); 1811 1.167 kre ESC_USTPUTC(0x80 | ((v >> 6) & 0x3f), out); 1812 1.167 kre ESC_USTPUTC(0x80 | (v & 0x3f), out); 1813 1.167 kre return out; 1814 1.167 kre } else if (v <= 0x7FFFFFFF) { 1815 1.167 kre ESC_USTPUTC(0xfC | v >> 30, out); 1816 1.167 kre ESC_USTPUTC(0x80 | ((v >> 24) & 0x3f), out); 1817 1.167 kre ESC_USTPUTC(0x80 | ((v >> 18) & 0x3f), out); 1818 1.167 kre ESC_USTPUTC(0x80 | ((v >> 12) & 0x3f), out); 1819 1.167 kre ESC_USTPUTC(0x80 | ((v >> 6) & 0x3f), out); 1820 1.167 kre ESC_USTPUTC(0x80 | (v & 0x3f), out); 1821 1.144 kre return out; 1822 1.144 kre } 1823 1.144 kre if (v > 127) 1824 1.144 kre v = '?'; 1825 1.144 kre } 1826 1.144 kre break; 1827 1.144 kre default: 1828 1.144 kre synerror("Unknown $'' escape sequence"); 1829 1.144 kre } 1830 1.144 kre vc = (char)v; 1831 1.163 kre VTRACE(DBG_LEXER, ("->%u(%#x)['%c']", v, v, vc&0xFF)); 1832 1.144 kre 1833 1.144 kre /* 1834 1.144 kre * If we managed to create a \n from a \ sequence (no matter how) 1835 1.144 kre * then we replace it with the magic CRTCNL control char, which 1836 1.144 kre * will turn into a \n again later, but in the meantime, never 1837 1.144 kre * causes LINENO increments. 1838 1.144 kre */ 1839 1.144 kre if (vc == '\n') { 1840 1.163 kre VTRACE(DBG_LEXER, ("CTLCNL.")); 1841 1.144 kre USTPUTC(CTLCNL, out); 1842 1.144 kre return out; 1843 1.144 kre } 1844 1.144 kre 1845 1.144 kre /* 1846 1.144 kre * We can't handle NUL bytes. 1847 1.144 kre * POSIX says we should skip till the closing quote. 1848 1.144 kre */ 1849 1.144 kre if (vc == '\0') { 1850 1.163 kre CTRACE(DBG_LEXER, ("\\0: skip to '", v, v, vc&0xFF)); 1851 1.144 kre while ((c = pgetc()) != '\'') { 1852 1.144 kre if (c == '\\') 1853 1.144 kre c = pgetc(); 1854 1.144 kre if (c == PEOF) 1855 1.167 kre synerror("Unterminated quoted string ($'...)"); 1856 1.144 kre if (c == '\n') { 1857 1.144 kre plinno++; 1858 1.144 kre if (doprompt) 1859 1.144 kre setprompt(2); 1860 1.144 kre else 1861 1.144 kre setprompt(0); 1862 1.144 kre } 1863 1.144 kre } 1864 1.144 kre pungetc(); 1865 1.144 kre return out; 1866 1.144 kre } 1867 1.163 kre CVTRACE(DBG_LEXER, NEEDESC(vc), ("CTLESC-")); 1868 1.163 kre VTRACE(DBG_LEXER, ("'%c'(%#.2x)", vc&0xFF, vc&0x1FF)); 1869 1.153 kre if (NEEDESC(vc)) 1870 1.144 kre USTPUTC(CTLESC, out); 1871 1.144 kre USTPUTC(vc, out); 1872 1.144 kre return out; 1873 1.144 kre } 1874 1.112 christos 1875 1.112 christos /* 1876 1.112 christos * The lowest level basic tokenizer. 1877 1.112 christos * 1878 1.112 christos * The next input byte (character) is in firstc, syn says which 1879 1.112 christos * syntax tables we are to use (basic, single or double quoted, or arith) 1880 1.112 christos * and magicq (used with sqsyntax and dqsyntax only) indicates that the 1881 1.112 christos * quote character itself is not special (used parsing here docs and similar) 1882 1.112 christos * 1883 1.112 christos * The result is the type of the next token (its value, when there is one, 1884 1.112 christos * is saved in the relevant global var - must fix that someday!) which is 1885 1.112 christos * also saved for re-reading ("lasttoken"). 1886 1.112 christos * 1887 1.112 christos * Overall, this routine does far more parsing than it is supposed to. 1888 1.112 christos * That will also need fixing, someday... 1889 1.112 christos */ 1890 1.1 cgd STATIC int 1891 1.164 kre readtoken1(int firstc, char const *syn, int oneword) 1892 1.54 christos { 1893 1.113 christos int c; 1894 1.103 christos char * out; 1895 1.1 cgd int len; 1896 1.1 cgd struct nodelist *bqlist; 1897 1.106 christos int quotef; 1898 1.96 christos VSS static_stack; 1899 1.106 christos VSS *stack = &static_stack; 1900 1.96 christos 1901 1.96 christos stack->prev = NULL; 1902 1.96 christos stack->cur = 0; 1903 1.96 christos 1904 1.96 christos syntax = syn; 1905 1.1 cgd 1906 1.163 kre #ifdef DEBUG 1907 1.163 kre #define SYNTAX ( syntax == BASESYNTAX ? "BASE" : \ 1908 1.163 kre syntax == DQSYNTAX ? "DQ" : \ 1909 1.163 kre syntax == SQSYNTAX ? "SQ" : \ 1910 1.163 kre syntax == ARISYNTAX ? "ARI" : \ 1911 1.163 kre "???" ) 1912 1.163 kre #endif 1913 1.163 kre 1914 1.1 cgd startlinno = plinno; 1915 1.51 christos varnest = 0; 1916 1.99 christos quoted = 0; 1917 1.108 christos if (syntax == DQSYNTAX) 1918 1.51 christos SETDBLQUOTE(); 1919 1.1 cgd quotef = 0; 1920 1.1 cgd bqlist = NULL; 1921 1.11 jtc arinest = 0; 1922 1.11 jtc parenlevel = 0; 1923 1.134 kre elided_nl = 0; 1924 1.164 kre magicq = oneword; 1925 1.11 jtc 1926 1.163 kre CTRACE(DBG_LEXER, ("readtoken1(%c) syntax=%s %s%s(quoted=%x)\n", 1927 1.163 kre firstc&0xFF, SYNTAX, magicq ? "magic quotes" : "", 1928 1.163 kre ISDBLQUOTE()?" ISDBLQUOTE":"", quoted)); 1929 1.163 kre 1930 1.1 cgd STARTSTACKSTR(out); 1931 1.113 christos 1932 1.113 christos for (c = firstc ;; c = pgetc_macro()) { /* until of token */ 1933 1.134 kre if (syntax == ARISYNTAX) 1934 1.134 kre out = insert_elided_nl(out); 1935 1.148 kre CHECKSTRSPACE(6, out); /* permit 6 calls to USTPUTC */ 1936 1.113 christos switch (syntax[c]) { 1937 1.156 kre case CFAKE: 1938 1.163 kre VTRACE(DBG_LEXER, ("CFAKE")); 1939 1.156 kre if (syntax == BASESYNTAX && varnest == 0) 1940 1.156 kre break; 1941 1.163 kre VTRACE(DBG_LEXER, (",")); 1942 1.156 kre continue; 1943 1.113 christos case CNL: /* '\n' */ 1944 1.163 kre VTRACE(DBG_LEXER, ("CNL")); 1945 1.146 kre if (syntax == BASESYNTAX && varnest == 0) 1946 1.113 christos break; /* exit loop */ 1947 1.113 christos USTPUTC(c, out); 1948 1.113 christos plinno++; 1949 1.163 kre VTRACE(DBG_LEXER, ("@%d,", plinno)); 1950 1.113 christos if (doprompt) 1951 1.113 christos setprompt(2); 1952 1.113 christos else 1953 1.113 christos setprompt(0); 1954 1.113 christos continue; 1955 1.113 christos 1956 1.144 kre case CSBACK: /* single quoted backslash */ 1957 1.144 kre if ((quoted & QF) == CQ) { 1958 1.144 kre out = readcstyleesc(out); 1959 1.144 kre continue; 1960 1.144 kre } 1961 1.163 kre VTRACE(DBG_LEXER, ("ESC:")); 1962 1.148 kre USTPUTC(CTLESC, out); 1963 1.144 kre /* FALLTHROUGH */ 1964 1.113 christos case CWORD: 1965 1.163 kre VTRACE(DBG_LEXER, ("'%c'", c)); 1966 1.113 christos USTPUTC(c, out); 1967 1.113 christos continue; 1968 1.144 kre 1969 1.113 christos case CCTL: 1970 1.163 kre CVTRACE(DBG_LEXER, !magicq || ISDBLQUOTE(), 1971 1.163 kre ("%s%sESC:",!magicq?"!m":"",ISDBLQUOTE()?"DQ":"")); 1972 1.113 christos if (!magicq || ISDBLQUOTE()) 1973 1.113 christos USTPUTC(CTLESC, out); 1974 1.163 kre VTRACE(DBG_LEXER, ("'%c'", c)); 1975 1.113 christos USTPUTC(c, out); 1976 1.113 christos continue; 1977 1.113 christos case CBACK: /* backslash */ 1978 1.113 christos c = pgetc(); 1979 1.163 kre VTRACE(DBG_LEXER, ("\\'%c'(%#.2x)", c&0xFF, c&0x1FF)); 1980 1.113 christos if (c == PEOF) { 1981 1.163 kre VTRACE(DBG_LEXER, ("EOF, keep \\ ")); 1982 1.113 christos USTPUTC('\\', out); 1983 1.113 christos pungetc(); 1984 1.113 christos continue; 1985 1.113 christos } 1986 1.113 christos if (c == '\n') { 1987 1.1 cgd plinno++; 1988 1.134 kre elided_nl++; 1989 1.163 kre VTRACE(DBG_LEXER, ("eli \\n (%d) @%d ", 1990 1.163 kre elided_nl, plinno)); 1991 1.11 jtc if (doprompt) 1992 1.11 jtc setprompt(2); 1993 1.11 jtc else 1994 1.11 jtc setprompt(0); 1995 1.113 christos continue; 1996 1.113 christos } 1997 1.163 kre CVTRACE(DBG_LEXER, quotef==0, (" QF=1 ")); 1998 1.113 christos quotef = 1; /* current token is quoted */ 1999 1.164 kre if (quoted && c != '\\' && c != '`' && 2000 1.168 kre (c != '}' || varnest == 0) && 2001 1.149 kre c != '$' && (c != '"' || magicq)) { 2002 1.153 kre /* 2003 1.153 kre * retain the \ (which we *know* needs CTLESC) 2004 1.153 kre * when in "..." and the following char is 2005 1.153 kre * not one of the magic few.) 2006 1.153 kre * Otherwise the \ has done its work, and 2007 1.153 kre * is dropped. 2008 1.153 kre */ 2009 1.163 kre VTRACE(DBG_LEXER, ("ESC:'\\'")); 2010 1.149 kre USTPUTC(CTLESC, out); 2011 1.113 christos USTPUTC('\\', out); 2012 1.149 kre } 2013 1.163 kre CVTRACE(DBG_LEXER, NEEDESC(c) || !magicq, 2014 1.163 kre ("%sESC:", NEEDESC(c) ? "+" : "m")); 2015 1.163 kre VTRACE(DBG_LEXER, ("'%c'(%#.2x)", c&0xFF, c&0x1FF)); 2016 1.153 kre if (NEEDESC(c)) 2017 1.113 christos USTPUTC(CTLESC, out); 2018 1.113 christos else if (!magicq) { 2019 1.157 kre USTPUTC(CTLESC, out); 2020 1.59 dsl USTPUTC(c, out); 2021 1.113 christos continue; 2022 1.113 christos } 2023 1.113 christos USTPUTC(c, out); 2024 1.113 christos continue; 2025 1.113 christos case CSQUOTE: 2026 1.113 christos if (syntax != SQSYNTAX) { 2027 1.163 kre CVTRACE(DBG_LEXER, !magicq, (" CQM ")); 2028 1.113 christos if (!magicq) 2029 1.113 christos USTPUTC(CTLQUOTEMARK, out); 2030 1.163 kre CVTRACE(DBG_LEXER, quotef==0, (" QF=1 ")); 2031 1.113 christos quotef = 1; 2032 1.113 christos TS_PUSH(); 2033 1.113 christos syntax = SQSYNTAX; 2034 1.113 christos quoted = SQ; 2035 1.163 kre VTRACE(DBG_LEXER, (" TS_PUSH(SQ)")); 2036 1.113 christos continue; 2037 1.113 christos } 2038 1.113 christos if (magicq && arinest == 0 && varnest == 0) { 2039 1.113 christos /* Ignore inside quoted here document */ 2040 1.163 kre VTRACE(DBG_LEXER, ("<<'>>")); 2041 1.1 cgd USTPUTC(c, out); 2042 1.113 christos continue; 2043 1.113 christos } 2044 1.113 christos /* End of single quotes... */ 2045 1.113 christos TS_POP(); 2046 1.163 kre VTRACE(DBG_LEXER, ("SQ TS_POP->%s ", SYNTAX)); 2047 1.163 kre CVTRACE(DBG_LEXER, syntax == BASESYNTAX, (" CQE ")); 2048 1.157 kre if (syntax == BASESYNTAX) 2049 1.113 christos USTPUTC(CTLQUOTEEND, out); 2050 1.113 christos continue; 2051 1.113 christos case CDQUOTE: 2052 1.164 kre if (magicq && arinest == 0 /* && varnest == 0 */) { 2053 1.163 kre VTRACE(DBG_LEXER, ("<<\">>")); 2054 1.113 christos /* Ignore inside here document */ 2055 1.56 dsl USTPUTC(c, out); 2056 1.113 christos continue; 2057 1.113 christos } 2058 1.163 kre CVTRACE(DBG_LEXER, quotef==0, (" QF=1 ")); 2059 1.113 christos quotef = 1; 2060 1.113 christos if (arinest) { 2061 1.56 dsl if (ISDBLQUOTE()) { 2062 1.163 kre VTRACE(DBG_LEXER, 2063 1.163 kre (" CQE ari(%d", arinest)); 2064 1.157 kre USTPUTC(CTLQUOTEEND, out); 2065 1.96 christos TS_POP(); 2066 1.163 kre VTRACE(DBG_LEXER, ("%d)TS_POP->%s ", 2067 1.163 kre arinest, SYNTAX)); 2068 1.1 cgd } else { 2069 1.163 kre VTRACE(DBG_LEXER, 2070 1.163 kre (" ari(%d) %s TS_PUSH->DQ CQM ", 2071 1.163 kre arinest, SYNTAX)); 2072 1.96 christos TS_PUSH(); 2073 1.56 dsl syntax = DQSYNTAX; 2074 1.56 dsl SETDBLQUOTE(); 2075 1.56 dsl USTPUTC(CTLQUOTEMARK, out); 2076 1.1 cgd } 2077 1.113 christos continue; 2078 1.113 christos } 2079 1.163 kre CVTRACE(DBG_LEXER, magicq, (" MQignDQ ")); 2080 1.113 christos if (magicq) 2081 1.113 christos continue; 2082 1.113 christos if (ISDBLQUOTE()) { 2083 1.113 christos TS_POP(); 2084 1.163 kre VTRACE(DBG_LEXER, 2085 1.163 kre (" DQ TS_POP->%s CQE ", SYNTAX)); 2086 1.157 kre USTPUTC(CTLQUOTEEND, out); 2087 1.113 christos } else { 2088 1.163 kre VTRACE(DBG_LEXER, 2089 1.163 kre (" %s TS_POP->DQ CQM ", SYNTAX)); 2090 1.113 christos TS_PUSH(); 2091 1.113 christos syntax = DQSYNTAX; 2092 1.113 christos SETDBLQUOTE(); 2093 1.113 christos USTPUTC(CTLQUOTEMARK, out); 2094 1.113 christos } 2095 1.113 christos continue; 2096 1.113 christos case CVAR: /* '$' */ 2097 1.163 kre VTRACE(DBG_LEXER, ("'$'...")); 2098 1.134 kre out = insert_elided_nl(out); 2099 1.113 christos PARSESUB(); /* parse substitution */ 2100 1.113 christos continue; 2101 1.113 christos case CENDVAR: /* CLOSEBRACE */ 2102 1.113 christos if (varnest > 0 && !ISDBLQUOTE()) { 2103 1.163 kre VTRACE(DBG_LEXER, ("vn=%d !DQ", varnest)); 2104 1.113 christos TS_POP(); 2105 1.163 kre VTRACE(DBG_LEXER, (" TS_POP->%s CEV ", SYNTAX)); 2106 1.113 christos USTPUTC(CTLENDVAR, out); 2107 1.113 christos } else { 2108 1.163 kre VTRACE(DBG_LEXER, ("'%c'", c)); 2109 1.113 christos USTPUTC(c, out); 2110 1.113 christos } 2111 1.134 kre out = insert_elided_nl(out); 2112 1.113 christos continue; 2113 1.113 christos case CLP: /* '(' in arithmetic */ 2114 1.113 christos parenlevel++; 2115 1.163 kre VTRACE(DBG_LEXER, ("'('(%d)", parenlevel)); 2116 1.113 christos USTPUTC(c, out); 2117 1.170 msaitoh continue; 2118 1.113 christos case CRP: /* ')' in arithmetic */ 2119 1.113 christos if (parenlevel > 0) { 2120 1.11 jtc USTPUTC(c, out); 2121 1.113 christos --parenlevel; 2122 1.163 kre VTRACE(DBG_LEXER, ("')'(%d)", parenlevel)); 2123 1.113 christos } else { 2124 1.163 kre VTRACE(DBG_LEXER, ("')'(%d)", parenlevel)); 2125 1.138 kre if (pgetc_linecont() == /*(*/ ')') { 2126 1.134 kre out = insert_elided_nl(out); 2127 1.113 christos if (--arinest == 0) { 2128 1.113 christos TS_POP(); 2129 1.113 christos USTPUTC(CTLENDARI, out); 2130 1.113 christos } else 2131 1.138 kre USTPUTC(/*(*/ ')', out); 2132 1.11 jtc } else { 2133 1.141 kre break; /* to synerror() just below */ 2134 1.141 kre #if 0 /* the old way, causes weird errors on bad input */ 2135 1.113 christos /* 2136 1.113 christos * unbalanced parens 2137 1.113 christos * (don't 2nd guess - no error) 2138 1.113 christos */ 2139 1.113 christos pungetc(); 2140 1.138 kre USTPUTC(/*(*/ ')', out); 2141 1.141 kre #endif 2142 1.11 jtc } 2143 1.1 cgd } 2144 1.113 christos continue; 2145 1.113 christos case CBQUOTE: /* '`' */ 2146 1.163 kre VTRACE(DBG_LEXER, ("'`' -> parsebackq()\n")); 2147 1.164 kre out = parsebackq(stack, out, &bqlist, 1); 2148 1.163 kre VTRACE(DBG_LEXER, ("parsebackq() -> readtoken1: ")); 2149 1.113 christos continue; 2150 1.113 christos case CEOF: /* --> c == PEOF */ 2151 1.163 kre VTRACE(DBG_LEXER, ("EOF ")); 2152 1.113 christos break; /* will exit loop */ 2153 1.113 christos default: 2154 1.163 kre VTRACE(DBG_LEXER, ("['%c'(%#.2x)]", c&0xFF, c&0x1FF)); 2155 1.113 christos if (varnest == 0 && !ISDBLQUOTE()) 2156 1.113 christos break; /* exit loop */ 2157 1.113 christos USTPUTC(c, out); 2158 1.163 kre VTRACE(DBG_LEXER, (",")); 2159 1.113 christos continue; 2160 1.1 cgd } 2161 1.163 kre VTRACE(DBG_LEXER, (" END TOKEN\n", c&0xFF, c&0x1FF)); 2162 1.113 christos break; /* break from switch -> break from for loop too */ 2163 1.1 cgd } 2164 1.113 christos 2165 1.96 christos if (syntax == ARISYNTAX) { 2166 1.96 christos cleanup_state_stack(stack); 2167 1.138 kre synerror(/*((*/ "Missing '))'"); 2168 1.96 christos } 2169 1.111 christos if (syntax != BASESYNTAX && /* ! parsebackquote && */ !magicq) { 2170 1.96 christos cleanup_state_stack(stack); 2171 1.1 cgd synerror("Unterminated quoted string"); 2172 1.96 christos } 2173 1.1 cgd if (varnest != 0) { 2174 1.96 christos cleanup_state_stack(stack); 2175 1.1 cgd startlinno = plinno; 2176 1.51 christos /* { */ 2177 1.1 cgd synerror("Missing '}'"); 2178 1.1 cgd } 2179 1.113 christos 2180 1.138 kre STPUTC('\0', out); 2181 1.1 cgd len = out - stackblock(); 2182 1.1 cgd out = stackblock(); 2183 1.113 christos 2184 1.111 christos if (!magicq) { 2185 1.111 christos if ((c == '<' || c == '>') 2186 1.113 christos && quotef == 0 && (*out == '\0' || is_number(out))) { 2187 1.112 christos parseredir(out, c); 2188 1.96 christos cleanup_state_stack(stack); 2189 1.1 cgd return lasttoken = TREDIR; 2190 1.1 cgd } else { 2191 1.1 cgd pungetc(); 2192 1.1 cgd } 2193 1.1 cgd } 2194 1.113 christos 2195 1.163 kre VTRACE(DBG_PARSE|DBG_LEXER, 2196 1.138 kre ("readtoken1 %sword \"%s\", completed%s (%d) left %d enl\n", 2197 1.138 kre (quotef ? "quoted " : ""), out, (bqlist ? " with cmdsubs" : ""), 2198 1.138 kre len, elided_nl)); 2199 1.138 kre 2200 1.1 cgd quoteflag = quotef; 2201 1.1 cgd backquotelist = bqlist; 2202 1.1 cgd grabstackblock(len); 2203 1.1 cgd wordtext = out; 2204 1.96 christos cleanup_state_stack(stack); 2205 1.1 cgd return lasttoken = TWORD; 2206 1.1 cgd /* end of readtoken routine */ 2207 1.1 cgd 2208 1.1 cgd 2209 1.1 cgd /* 2210 1.1 cgd * Parse a substitution. At this point, we have read the dollar sign 2211 1.1 cgd * and nothing else. 2212 1.1 cgd */ 2213 1.1 cgd 2214 1.1 cgd parsesub: { 2215 1.1 cgd int subtype; 2216 1.1 cgd int typeloc; 2217 1.1 cgd int flags; 2218 1.183 rillig const char *p; 2219 1.184 kre static const char types[] = "}-+?="; /* see parser.h VSXYZ defs */ 2220 1.1 cgd 2221 1.121 kre c = pgetc_linecont(); 2222 1.163 kre VTRACE(DBG_LEXER, ("\"$%c\"(%#.2x)", c&0xFF, c&0x1FF)); 2223 1.144 kre if (c == '(' /*)*/) { /* $(command) or $((arith)) */ 2224 1.134 kre if (pgetc_linecont() == '(' /*')'*/ ) { 2225 1.163 kre VTRACE(DBG_LEXER, ("\"$((\" ARITH ")); 2226 1.134 kre out = insert_elided_nl(out); 2227 1.11 jtc PARSEARITH(); 2228 1.11 jtc } else { 2229 1.163 kre VTRACE(DBG_LEXER, ("\"$(\" CSUB->parsebackq()\n")); 2230 1.134 kre out = insert_elided_nl(out); 2231 1.11 jtc pungetc(); 2232 1.164 kre out = parsebackq(stack, out, &bqlist, 0); 2233 1.163 kre VTRACE(DBG_LEXER, ("parseback()->readtoken1(): ")); 2234 1.11 jtc } 2235 1.144 kre } else if (c == OPENBRACE || is_name(c) || is_special(c)) { 2236 1.163 kre VTRACE(DBG_LEXER, (" $EXP:CTLVAR ")); 2237 1.1 cgd USTPUTC(CTLVAR, out); 2238 1.1 cgd typeloc = out - stackblock(); 2239 1.1 cgd USTPUTC(VSNORMAL, out); 2240 1.1 cgd subtype = VSNORMAL; 2241 1.84 christos flags = 0; 2242 1.51 christos if (c == OPENBRACE) { 2243 1.121 kre c = pgetc_linecont(); 2244 1.23 christos if (c == '#') { 2245 1.127 kre if ((c = pgetc_linecont()) == CLOSEBRACE) 2246 1.26 christos c = '#'; 2247 1.127 kre else if (is_name(c) || isdigit(c)) 2248 1.26 christos subtype = VSLENGTH; 2249 1.127 kre else if (is_special(c)) { 2250 1.127 kre /* 2251 1.128 kre * ${#} is $# - the number of sh params 2252 1.127 kre * ${##} is the length of ${#} 2253 1.128 kre * ${###} is ${#} with as much nothing 2254 1.128 kre * as possible removed from start 2255 1.127 kre * ${##1} is ${#} with leading 1 gone 2256 1.128 kre * ${##\#} is ${#} with leading # gone 2257 1.127 kre * 2258 1.127 kre * this stuff is UGLY! 2259 1.127 kre */ 2260 1.127 kre if (pgetc_linecont() == CLOSEBRACE) { 2261 1.127 kre pungetc(); 2262 1.127 kre subtype = VSLENGTH; 2263 1.127 kre } else { 2264 1.127 kre static char cbuf[2]; 2265 1.128 kre 2266 1.128 kre pungetc(); /* would like 2 */ 2267 1.128 kre cbuf[0] = c; /* so ... */ 2268 1.127 kre cbuf[1] = '\0'; 2269 1.127 kre pushstring(cbuf, 1, NULL); 2270 1.128 kre c = '#'; /* ${#:...} */ 2271 1.128 kre subtype = 0; /* .. or similar */ 2272 1.127 kre } 2273 1.127 kre } else { 2274 1.127 kre pungetc(); 2275 1.127 kre c = '#'; 2276 1.127 kre subtype = 0; 2277 1.127 kre } 2278 1.23 christos } 2279 1.23 christos else 2280 1.23 christos subtype = 0; 2281 1.163 kre VTRACE(DBG_LEXER, ("${ st=%d ", subtype)); 2282 1.1 cgd } 2283 1.1 cgd if (is_name(c)) { 2284 1.84 christos p = out; 2285 1.1 cgd do { 2286 1.163 kre VTRACE(DBG_LEXER, ("%c", c)); 2287 1.1 cgd STPUTC(c, out); 2288 1.121 kre c = pgetc_linecont(); 2289 1.1 cgd } while (is_in_name(c)); 2290 1.163 kre 2291 1.134 kre #if 0 2292 1.84 christos if (out - p == 6 && strncmp(p, "LINENO", 6) == 0) { 2293 1.134 kre int i; 2294 1.134 kre int linno; 2295 1.134 kre char buf[10]; 2296 1.134 kre 2297 1.134 kre /* 2298 1.134 kre * The "LINENO hack" 2299 1.134 kre * 2300 1.134 kre * Replace the variable name with the 2301 1.134 kre * current line number. 2302 1.134 kre */ 2303 1.84 christos linno = plinno; 2304 1.84 christos if (funclinno != 0) 2305 1.84 christos linno -= funclinno - 1; 2306 1.84 christos snprintf(buf, sizeof(buf), "%d", linno); 2307 1.84 christos STADJUST(-6, out); 2308 1.84 christos for (i = 0; buf[i] != '\0'; i++) 2309 1.84 christos STPUTC(buf[i], out); 2310 1.84 christos flags |= VSLINENO; 2311 1.84 christos } 2312 1.134 kre #endif 2313 1.34 christos } else if (is_digit(c)) { 2314 1.33 christos do { 2315 1.163 kre VTRACE(DBG_LEXER, ("%c", c)); 2316 1.134 kre STPUTC(c, out); 2317 1.121 kre c = pgetc_linecont(); 2318 1.114 christos } while (subtype != VSNORMAL && is_digit(c)); 2319 1.34 christos } 2320 1.34 christos else if (is_special(c)) { 2321 1.163 kre VTRACE(DBG_LEXER, ("\"$%c", c)); 2322 1.34 christos USTPUTC(c, out); 2323 1.121 kre c = pgetc_linecont(); 2324 1.1 cgd } 2325 1.96 christos else { 2326 1.184 kre VTRACE(DBG_LEXER, ("\"$%c(%#.2x)??", c&0xFF, c&0xFF)); 2327 1.184 kre subtype = VSUNKNOWN; 2328 1.96 christos } 2329 1.33 christos 2330 1.1 cgd STPUTC('=', out); 2331 1.1 cgd if (subtype == 0) { 2332 1.23 christos switch (c) { 2333 1.23 christos case ':': 2334 1.84 christos flags |= VSNUL; 2335 1.121 kre c = pgetc_linecont(); 2336 1.23 christos /*FALLTHROUGH*/ 2337 1.23 christos default: 2338 1.23 christos p = strchr(types, c); 2339 1.184 kre if (__predict_false(p == NULL)) { 2340 1.184 kre subtype = VSUNKNOWN; 2341 1.184 kre /* 2342 1.184 kre * keep the unknown modifier 2343 1.184 kre * for the error message. 2344 1.184 kre * 2345 1.184 kre * Note that if we came from 2346 1.184 kre * the case ':' above, that 2347 1.184 kre * is the unknown modifier, 2348 1.184 kre * not the following character 2349 1.184 kre * 2350 1.184 kre * It is not important that 2351 1.184 kre * we keep the remaining word 2352 1.184 kre * intact, it will never be 2353 1.184 kre * used. 2354 1.184 kre */ 2355 1.184 kre if (flags & VSNUL) 2356 1.184 kre /* (ie: lose c) */ 2357 1.184 kre STPUTC(':', out); 2358 1.184 kre else 2359 1.184 kre STPUTC(c, out); 2360 1.184 kre } else 2361 1.184 kre subtype = p - types + VSNORMAL; 2362 1.23 christos break; 2363 1.23 christos case '%': 2364 1.30 christos case '#': 2365 1.23 christos { 2366 1.23 christos int cc = c; 2367 1.23 christos subtype = c == '#' ? VSTRIMLEFT : 2368 1.23 christos VSTRIMRIGHT; 2369 1.121 kre c = pgetc_linecont(); 2370 1.23 christos if (c == cc) 2371 1.23 christos subtype++; 2372 1.23 christos else 2373 1.23 christos pungetc(); 2374 1.23 christos break; 2375 1.23 christos } 2376 1.1 cgd } 2377 1.1 cgd } else { 2378 1.184 kre if (subtype == VSLENGTH && c != /*{*/ '}') { 2379 1.184 kre STPUTC('#', out); 2380 1.184 kre subtype = VSUNKNOWN; 2381 1.184 kre } 2382 1.1 cgd pungetc(); 2383 1.1 cgd } 2384 1.157 kre if (quoted || arinest) 2385 1.1 cgd flags |= VSQUOTE; 2386 1.98 christos if (subtype >= VSTRIMLEFT && subtype <= VSTRIMRIGHTMAX) 2387 1.98 christos flags |= VSPATQ; 2388 1.163 kre VTRACE(DBG_LEXER, (" st%d:%x", subtype, flags)); 2389 1.1 cgd *(stackblock() + typeloc) = subtype | flags; 2390 1.96 christos if (subtype != VSNORMAL) { 2391 1.96 christos TS_PUSH(); 2392 1.96 christos varnest++; 2393 1.96 christos arinest = 0; 2394 1.96 christos if (subtype > VSASSIGN) { /* # ## % %% */ 2395 1.96 christos syntax = BASESYNTAX; 2396 1.157 kre quoted = 0; 2397 1.164 kre magicq = 0; 2398 1.96 christos } 2399 1.163 kre VTRACE(DBG_LEXER, (" TS_PUSH->%s vn=%d%s ", 2400 1.163 kre SYNTAX, varnest, quoted ? " Q" : "")); 2401 1.96 christos } 2402 1.144 kre } else if (c == '\'' && syntax == BASESYNTAX) { 2403 1.144 kre USTPUTC(CTLQUOTEMARK, out); 2404 1.163 kre VTRACE(DBG_LEXER, (" CSTR \"$'\" CQM ")); 2405 1.163 kre CVTRACE(DBG_LEXER, quotef==0, ("QF=1 ")); 2406 1.144 kre quotef = 1; 2407 1.144 kre TS_PUSH(); 2408 1.144 kre syntax = SQSYNTAX; 2409 1.144 kre quoted = CQ; 2410 1.163 kre VTRACE(DBG_LEXER, ("%s->TS_PUSH()->SQ ", SYNTAX)); 2411 1.144 kre } else { 2412 1.163 kre VTRACE(DBG_LEXER, ("$unk -> '$' (pushback '%c'%#.2x)", 2413 1.163 kre c & 0xFF, c & 0x1FF)); 2414 1.144 kre USTPUTC('$', out); 2415 1.144 kre pungetc(); 2416 1.1 cgd } 2417 1.1 cgd goto parsesub_return; 2418 1.1 cgd } 2419 1.1 cgd 2420 1.1 cgd 2421 1.1 cgd /* 2422 1.11 jtc * Parse an arithmetic expansion (indicate start of one and set state) 2423 1.1 cgd */ 2424 1.11 jtc parsearith: { 2425 1.1 cgd 2426 1.131 kre #if 0 2427 1.96 christos if (syntax == ARISYNTAX) { 2428 1.96 christos /* 2429 1.96 christos * we collapse embedded arithmetic expansion to 2430 1.96 christos * parentheses, which should be equivalent 2431 1.134 kre * 2432 1.134 kre * XXX It isn't, must fix, soonish... 2433 1.96 christos */ 2434 1.138 kre USTPUTC('(' /*)*/, out); 2435 1.138 kre USTPUTC('(' /*)*/, out); 2436 1.96 christos /* 2437 1.96 christos * Need 2 of them because there will (should be) 2438 1.96 christos * two closing ))'s to follow later. 2439 1.96 christos */ 2440 1.96 christos parenlevel += 2; 2441 1.131 kre } else 2442 1.131 kre #endif 2443 1.131 kre { 2444 1.163 kre VTRACE(DBG_LEXER, (" CTLARI%c ", ISDBLQUOTE()?'"':'_')); 2445 1.11 jtc USTPUTC(CTLARI, out); 2446 1.51 christos if (ISDBLQUOTE()) 2447 1.41 mycroft USTPUTC('"',out); 2448 1.41 mycroft else 2449 1.41 mycroft USTPUTC(' ',out); 2450 1.131 kre 2451 1.163 kre VTRACE(DBG_LEXER, ("%s->TS_PUSH->ARI(1)", SYNTAX)); 2452 1.132 kre TS_PUSH(); 2453 1.132 kre syntax = ARISYNTAX; 2454 1.132 kre arinest = 1; 2455 1.132 kre varnest = 0; 2456 1.164 kre magicq = 1; 2457 1.1 cgd } 2458 1.11 jtc goto parsearith_return; 2459 1.1 cgd } 2460 1.1 cgd 2461 1.11 jtc } /* end of readtoken */ 2462 1.1 cgd 2463 1.1 cgd 2464 1.1 cgd 2465 1.134 kre 2466 1.11 jtc #ifdef mkinit 2467 1.140 kre INCLUDE "parser.h" 2468 1.140 kre 2469 1.11 jtc RESET { 2470 1.140 kre psp.v_current_parser = &parse_state; 2471 1.138 kre 2472 1.140 kre parse_state.ps_tokpushback = 0; 2473 1.140 kre parse_state.ps_checkkwd = 0; 2474 1.140 kre parse_state.ps_heredoclist = NULL; 2475 1.1 cgd } 2476 1.1 cgd #endif 2477 1.1 cgd 2478 1.1 cgd /* 2479 1.1 cgd * Returns true if the text contains nothing to expand (no dollar signs 2480 1.1 cgd * or backquotes). 2481 1.1 cgd */ 2482 1.1 cgd 2483 1.1 cgd STATIC int 2484 1.54 christos noexpand(char *text) 2485 1.54 christos { 2486 1.32 tls char *p; 2487 1.32 tls char c; 2488 1.1 cgd 2489 1.1 cgd p = text; 2490 1.1 cgd while ((c = *p++) != '\0') { 2491 1.157 kre if (c == CTLQUOTEMARK || c == CTLQUOTEEND) 2492 1.41 mycroft continue; 2493 1.1 cgd if (c == CTLESC) 2494 1.1 cgd p++; 2495 1.167 kre else if (ISCTL(c)) 2496 1.1 cgd return 0; 2497 1.1 cgd } 2498 1.1 cgd return 1; 2499 1.1 cgd } 2500 1.1 cgd 2501 1.1 cgd 2502 1.1 cgd /* 2503 1.1 cgd * Return true if the argument is a legal variable name (a letter or 2504 1.1 cgd * underscore followed by zero or more letters, underscores, and digits). 2505 1.1 cgd */ 2506 1.1 cgd 2507 1.1 cgd int 2508 1.154 kre goodname(const char *name) 2509 1.108 christos { 2510 1.154 kre const char *p; 2511 1.1 cgd 2512 1.1 cgd p = name; 2513 1.1 cgd if (! is_name(*p)) 2514 1.1 cgd return 0; 2515 1.1 cgd while (*++p) { 2516 1.1 cgd if (! is_in_name(*p)) 2517 1.1 cgd return 0; 2518 1.1 cgd } 2519 1.1 cgd return 1; 2520 1.1 cgd } 2521 1.1 cgd 2522 1.156 kre int 2523 1.156 kre isassignment(const char *p) 2524 1.156 kre { 2525 1.156 kre if (!is_name(*p)) 2526 1.156 kre return 0; 2527 1.156 kre while (*++p != '=') 2528 1.156 kre if (*p == '\0' || !is_in_name(*p)) 2529 1.156 kre return 0; 2530 1.156 kre return 1; 2531 1.156 kre } 2532 1.156 kre 2533 1.142 kre /* 2534 1.142 kre * skip past any \n's, and leave lasttoken set to whatever follows 2535 1.142 kre */ 2536 1.142 kre STATIC void 2537 1.142 kre linebreak(void) 2538 1.142 kre { 2539 1.142 kre while (readtoken() == TNL) 2540 1.172 kre readheredocs(); 2541 1.142 kre } 2542 1.142 kre 2543 1.142 kre /* 2544 1.142 kre * The next token must be "token" -- check, then move past it 2545 1.142 kre */ 2546 1.142 kre STATIC void 2547 1.142 kre consumetoken(int token) 2548 1.142 kre { 2549 1.142 kre if (readtoken() != token) { 2550 1.142 kre VTRACE(DBG_PARSE, ("consumetoken(%d): expecting %s got %s", 2551 1.142 kre token, tokname[token], tokname[lasttoken])); 2552 1.142 kre CVTRACE(DBG_PARSE, (lasttoken==TWORD), (" \"%s\"", wordtext)); 2553 1.142 kre VTRACE(DBG_PARSE, ("\n")); 2554 1.142 kre synexpect(token, NULL); 2555 1.142 kre } 2556 1.142 kre } 2557 1.1 cgd 2558 1.1 cgd /* 2559 1.1 cgd * Called when an unexpected token is read during the parse. The argument 2560 1.1 cgd * is the token that is expected, or -1 if more than one type of token can 2561 1.1 cgd * occur at this point. 2562 1.1 cgd */ 2563 1.1 cgd 2564 1.1 cgd STATIC void 2565 1.108 christos synexpect(int token, const char *text) 2566 1.22 cgd { 2567 1.1 cgd char msg[64]; 2568 1.108 christos char *p; 2569 1.108 christos 2570 1.108 christos if (lasttoken == TWORD) { 2571 1.108 christos size_t len = strlen(wordtext); 2572 1.108 christos 2573 1.108 christos if (len <= 13) 2574 1.108 christos fmtstr(msg, 34, "Word \"%.13s\" unexpected", wordtext); 2575 1.108 christos else 2576 1.108 christos fmtstr(msg, 34, 2577 1.108 christos "Word \"%.10s...\" unexpected", wordtext); 2578 1.108 christos } else 2579 1.108 christos fmtstr(msg, 34, "%s unexpected", tokname[lasttoken]); 2580 1.108 christos 2581 1.108 christos p = strchr(msg, '\0'); 2582 1.108 christos if (text) 2583 1.108 christos fmtstr(p, 30, " (expecting \"%.10s\")", text); 2584 1.108 christos else if (token >= 0) 2585 1.108 christos fmtstr(p, 30, " (expecting %s)", tokname[token]); 2586 1.1 cgd 2587 1.1 cgd synerror(msg); 2588 1.39 mycroft /* NOTREACHED */ 2589 1.1 cgd } 2590 1.1 cgd 2591 1.1 cgd 2592 1.1 cgd STATIC void 2593 1.54 christos synerror(const char *msg) 2594 1.54 christos { 2595 1.124 kre error("%d: Syntax error: %s", startlinno, msg); 2596 1.39 mycroft /* NOTREACHED */ 2597 1.11 jtc } 2598 1.11 jtc 2599 1.11 jtc STATIC void 2600 1.54 christos setprompt(int which) 2601 1.54 christos { 2602 1.11 jtc whichprompt = which; 2603 1.11 jtc 2604 1.35 christos #ifndef SMALL 2605 1.11 jtc if (!el) 2606 1.14 cgd #endif 2607 1.11 jtc out2str(getprompt(NULL)); 2608 1.11 jtc } 2609 1.11 jtc 2610 1.11 jtc /* 2611 1.121 kre * handle getting the next character, while ignoring \ \n 2612 1.121 kre * (which is a little tricky as we only have one char of pushback 2613 1.121 kre * and we need that one elsewhere). 2614 1.121 kre */ 2615 1.121 kre STATIC int 2616 1.121 kre pgetc_linecont(void) 2617 1.121 kre { 2618 1.121 kre int c; 2619 1.121 kre 2620 1.161 kre while ((c = pgetc()) == '\\') { 2621 1.121 kre c = pgetc(); 2622 1.121 kre if (c == '\n') { 2623 1.121 kre plinno++; 2624 1.134 kre elided_nl++; 2625 1.163 kre VTRACE(DBG_LEXER, ("\"\\n\"drop(el=%d@%d)", 2626 1.163 kre elided_nl, plinno)); 2627 1.121 kre if (doprompt) 2628 1.121 kre setprompt(2); 2629 1.121 kre else 2630 1.121 kre setprompt(0); 2631 1.121 kre } else { 2632 1.121 kre pungetc(); 2633 1.121 kre /* Allow the backslash to be pushed back. */ 2634 1.121 kre pushstring("\\", 1, NULL); 2635 1.121 kre return (pgetc()); 2636 1.121 kre } 2637 1.121 kre } 2638 1.121 kre return (c); 2639 1.121 kre } 2640 1.121 kre 2641 1.121 kre /* 2642 1.11 jtc * called by editline -- any expansions to the prompt 2643 1.11 jtc * should be added here. 2644 1.11 jtc */ 2645 1.43 christos const char * 2646 1.45 cgd getprompt(void *unused) 2647 1.108 christos { 2648 1.140 kre char *p; 2649 1.140 kre const char *cp; 2650 1.143 kre int wp; 2651 1.140 kre 2652 1.140 kre if (!doprompt) 2653 1.140 kre return ""; 2654 1.140 kre 2655 1.140 kre VTRACE(DBG_PARSE|DBG_EXPAND, ("getprompt %d\n", whichprompt)); 2656 1.140 kre 2657 1.143 kre switch (wp = whichprompt) { 2658 1.11 jtc case 0: 2659 1.11 jtc return ""; 2660 1.11 jtc case 1: 2661 1.140 kre p = ps1val(); 2662 1.140 kre break; 2663 1.11 jtc case 2: 2664 1.140 kre p = ps2val(); 2665 1.140 kre break; 2666 1.11 jtc default: 2667 1.11 jtc return "<internal prompt error>"; 2668 1.11 jtc } 2669 1.140 kre if (p == NULL) 2670 1.140 kre return ""; 2671 1.140 kre 2672 1.140 kre VTRACE(DBG_PARSE|DBG_EXPAND, ("prompt <<%s>>\n", p)); 2673 1.140 kre 2674 1.140 kre cp = expandstr(p, plinno); 2675 1.143 kre whichprompt = wp; /* history depends on it not changing */ 2676 1.140 kre 2677 1.140 kre VTRACE(DBG_PARSE|DBG_EXPAND, ("prompt -> <<%s>>\n", cp)); 2678 1.140 kre 2679 1.140 kre return cp; 2680 1.140 kre } 2681 1.140 kre 2682 1.140 kre /* 2683 1.140 kre * Expand a string ... used for expanding prompts (PS1...) 2684 1.140 kre * 2685 1.140 kre * Never return NULL, always some string (return input string if invalid) 2686 1.145 kre * 2687 1.145 kre * The internal routine does the work, leaving the result on the 2688 1.145 kre * stack (or in a static string, or even the input string) and 2689 1.145 kre * handles parser recursion, and cleanup after an error while parsing. 2690 1.145 kre * 2691 1.145 kre * The visible interface copies the result off the stack (if it is there), 2692 1.145 kre * and handles stack management, leaving the stack in the exact same 2693 1.145 kre * state it was when expandstr() was called (so it can be used part way 2694 1.145 kre * through building a stack data structure - as in when PS2 is being 2695 1.145 kre * expanded half way through reading a "command line") 2696 1.145 kre * 2697 1.145 kre * on error, expandonstack() cleans up the parser state, but then 2698 1.179 andvar * simply jumps out through expandstr() without doing any stack cleanup, 2699 1.145 kre * which is OK, as the error handler must deal with that anyway. 2700 1.145 kre * 2701 1.145 kre * The split into two funcs is to avoid problems with setjmp/longjmp 2702 1.145 kre * and local variables which could otherwise be optimised into bizarre 2703 1.145 kre * behaviour. 2704 1.140 kre */ 2705 1.145 kre static const char * 2706 1.159 kre expandonstack(char *ps, int cmdsub, int lineno) 2707 1.140 kre { 2708 1.140 kre union node n; 2709 1.140 kre struct jmploc jmploc; 2710 1.140 kre struct jmploc *const savehandler = handler; 2711 1.140 kre struct parsefile *const savetopfile = getcurrentfile(); 2712 1.181 kre char * const save_ps = ps; 2713 1.140 kre const int save_x = xflag; 2714 1.165 kre const int save_e_s = errors_suppressed; 2715 1.140 kre struct parse_state new_state = init_parse_state; 2716 1.140 kre struct parse_state *const saveparser = psp.v_current_parser; 2717 1.140 kre const char *result = NULL; 2718 1.140 kre 2719 1.140 kre if (!setjmp(jmploc.loc)) { 2720 1.140 kre handler = &jmploc; 2721 1.165 kre errors_suppressed = 1; 2722 1.140 kre 2723 1.140 kre psp.v_current_parser = &new_state; 2724 1.140 kre setinputstring(ps, 1, lineno); 2725 1.140 kre 2726 1.140 kre readtoken1(pgetc(), DQSYNTAX, 1); 2727 1.159 kre if (backquotelist != NULL) { 2728 1.180 kre if (!cmdsub) 2729 1.159 kre result = ps; 2730 1.182 kre else if (cmdsub == 1 && !promptcmds) 2731 1.159 kre result = "-o promptcmds not set: "; 2732 1.159 kre } 2733 1.159 kre if (result == NULL) { 2734 1.140 kre n.narg.type = NARG; 2735 1.140 kre n.narg.next = NULL; 2736 1.140 kre n.narg.text = wordtext; 2737 1.140 kre n.narg.lineno = lineno; 2738 1.140 kre n.narg.backquote = backquotelist; 2739 1.140 kre 2740 1.140 kre xflag = 0; /* we might be expanding PS4 ... */ 2741 1.140 kre expandarg(&n, NULL, 0); 2742 1.140 kre result = stackblock(); 2743 1.140 kre } 2744 1.162 kre } else { 2745 1.162 kre psp.v_current_parser = saveparser; 2746 1.162 kre xflag = save_x; 2747 1.162 kre popfilesupto(savetopfile); 2748 1.162 kre handler = savehandler; 2749 1.165 kre errors_suppressed = save_e_s; 2750 1.162 kre 2751 1.162 kre if (exception == EXEXIT) 2752 1.162 kre longjmp(handler->loc, 1); 2753 1.162 kre if (exception == EXINT) 2754 1.162 kre exraise(SIGINT); 2755 1.165 kre return ""; 2756 1.140 kre } 2757 1.140 kre psp.v_current_parser = saveparser; 2758 1.140 kre xflag = save_x; 2759 1.140 kre popfilesupto(savetopfile); 2760 1.140 kre handler = savehandler; 2761 1.165 kre errors_suppressed = save_e_s; 2762 1.151 kre 2763 1.162 kre if (result == NULL) 2764 1.181 kre result = save_ps; 2765 1.140 kre 2766 1.140 kre return result; 2767 1.1 cgd } 2768 1.145 kre 2769 1.145 kre const char * 2770 1.145 kre expandstr(char *ps, int lineno) 2771 1.145 kre { 2772 1.145 kre const char *result = NULL; 2773 1.145 kre struct stackmark smark; 2774 1.145 kre static char *buffer = NULL; /* storage for prompt, never freed */ 2775 1.145 kre static size_t bufferlen = 0; 2776 1.145 kre 2777 1.145 kre setstackmark(&smark); 2778 1.145 kre /* 2779 1.145 kre * At this point we anticipate that there may be a string 2780 1.145 kre * growing on the stack, but we have no idea how big it is. 2781 1.145 kre * However we know that it cannot be bigger than the current 2782 1.145 kre * allocated stack block, so simply reserve the whole thing, 2783 1.145 kre * then we can use the stack without barfing all over what 2784 1.145 kre * is there already... (the stack mark undoes this later.) 2785 1.145 kre */ 2786 1.145 kre (void) stalloc(stackblocksize()); 2787 1.145 kre 2788 1.159 kre result = expandonstack(ps, 1, lineno); 2789 1.145 kre 2790 1.145 kre if (__predict_true(result == stackblock())) { 2791 1.145 kre size_t len = strlen(result) + 1; 2792 1.145 kre 2793 1.145 kre /* 2794 1.145 kre * the result (usual case) is on the stack, which we 2795 1.145 kre * are just about to discard (popstackmark()) so we 2796 1.145 kre * need to move it somewhere safe first. 2797 1.145 kre */ 2798 1.145 kre 2799 1.145 kre if (__predict_false(len > bufferlen)) { 2800 1.145 kre char *new; 2801 1.145 kre size_t newlen = bufferlen; 2802 1.145 kre 2803 1.145 kre if (__predict_false(len > (SIZE_MAX >> 4))) { 2804 1.145 kre result = "huge prompt: "; 2805 1.145 kre goto getout; 2806 1.145 kre } 2807 1.145 kre 2808 1.145 kre if (newlen == 0) 2809 1.145 kre newlen = 32; 2810 1.145 kre while (newlen <= len) 2811 1.145 kre newlen <<= 1; 2812 1.145 kre 2813 1.145 kre new = (char *)realloc(buffer, newlen); 2814 1.145 kre 2815 1.145 kre if (__predict_false(new == NULL)) { 2816 1.145 kre /* 2817 1.145 kre * this should rarely (if ever) happen 2818 1.145 kre * but we must do something when it does... 2819 1.145 kre */ 2820 1.145 kre result = "No mem for prompt: "; 2821 1.145 kre goto getout; 2822 1.145 kre } else { 2823 1.145 kre buffer = new; 2824 1.145 kre bufferlen = newlen; 2825 1.145 kre } 2826 1.145 kre } 2827 1.145 kre (void)memcpy(buffer, result, len); 2828 1.145 kre result = buffer; 2829 1.145 kre } 2830 1.145 kre 2831 1.145 kre getout:; 2832 1.145 kre popstackmark(&smark); 2833 1.145 kre 2834 1.145 kre return result; 2835 1.145 kre } 2836 1.159 kre 2837 1.182 kre #ifndef SMALL 2838 1.182 kre /* 2839 1.182 kre * A version of the above which isn't tailored to expanding prompts, 2840 1.182 kre * but can be used for expanding other expandable variables when 2841 1.182 kre * they need to be used. ${LINENO} will always expand to 0 in this case. 2842 1.182 kre */ 2843 1.182 kre 2844 1.182 kre const char * 2845 1.182 kre expandvar(char *var, int flags) 2846 1.182 kre { 2847 1.182 kre const char *result = NULL; 2848 1.182 kre struct stackmark smark; 2849 1.182 kre static char *buffer = NULL; /* storage for result */ 2850 1.182 kre static size_t bufferlen = 0; 2851 1.182 kre 2852 1.182 kre setstackmark(&smark); 2853 1.182 kre /* 2854 1.182 kre * At this point we anticipate that there may be a string 2855 1.182 kre * growing on the stack, [...] [see expandstr() above]. 2856 1.182 kre */ 2857 1.182 kre (void) stalloc(stackblocksize()); 2858 1.182 kre 2859 1.182 kre result = expandonstack(var, (flags & VUNSAFE ? 0 : 2), 0); 2860 1.182 kre if (__predict_false(result == NULL || *result == '\0')) { 2861 1.182 kre result = NULL; 2862 1.182 kre goto getout; 2863 1.182 kre } 2864 1.182 kre 2865 1.182 kre if (__predict_true(result == stackblock())) { 2866 1.182 kre size_t len = strlen(result) + 1; 2867 1.182 kre 2868 1.182 kre /* 2869 1.182 kre * the result is on the stack, so we 2870 1.182 kre * need to move it somewhere safe first. 2871 1.182 kre */ 2872 1.182 kre 2873 1.182 kre if (__predict_false(len > bufferlen)) { 2874 1.182 kre char *new; 2875 1.182 kre size_t newlen = bufferlen; 2876 1.182 kre 2877 1.182 kre if (__predict_false(len > (SIZE_MAX >> 4))) { 2878 1.182 kre result = ""; 2879 1.182 kre goto getout; 2880 1.182 kre } 2881 1.182 kre 2882 1.182 kre if (__predict_false(newlen == 0)) 2883 1.182 kre newlen = 32; 2884 1.182 kre while (newlen <= len) 2885 1.182 kre newlen <<= 1; 2886 1.182 kre 2887 1.182 kre new = (char *)realloc(buffer, newlen); 2888 1.182 kre 2889 1.182 kre if (__predict_false(new == NULL)) { 2890 1.182 kre /* 2891 1.182 kre * this should rarely (if ever) happen 2892 1.182 kre * but we must do something when it does... 2893 1.182 kre */ 2894 1.182 kre result = ""; 2895 1.182 kre goto getout; 2896 1.182 kre } else { 2897 1.182 kre buffer = new; 2898 1.182 kre bufferlen = newlen; 2899 1.182 kre } 2900 1.182 kre } 2901 1.182 kre (void)memcpy(buffer, result, len); 2902 1.182 kre result = buffer; 2903 1.182 kre } 2904 1.182 kre 2905 1.182 kre getout:; 2906 1.182 kre popstackmark(&smark); 2907 1.182 kre 2908 1.182 kre return result; 2909 1.182 kre } 2910 1.182 kre #endif 2911 1.182 kre 2912 1.159 kre /* 2913 1.159 kre * and a simpler version, which does no $( ) expansions, for 2914 1.159 kre * use during shell startup when we know we are not parsing, 2915 1.159 kre * and so the stack is not in use - we can do what we like, 2916 1.159 kre * and do not need to clean up (that's handled externally). 2917 1.159 kre * 2918 1.159 kre * Simply return the result, even if it is on the stack 2919 1.159 kre */ 2920 1.159 kre const char * 2921 1.159 kre expandenv(char *arg) 2922 1.159 kre { 2923 1.159 kre return expandonstack(arg, 0, 0); 2924 1.159 kre } 2925