parser.c revision 1.133 1 1.133 kre /* $NetBSD: parser.c,v 1.133 2017/06/07 04:44:17 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.133 kre __RCSID("$NetBSD: parser.c,v 1.133 2017/06/07 04:44:17 kre Exp $");
41 1.24 cgd #endif
42 1.1 cgd #endif /* not lint */
43 1.1 cgd
44 1.85 christos #include <stdio.h>
45 1.25 christos #include <stdlib.h>
46 1.82 christos #include <limits.h>
47 1.25 christos
48 1.1 cgd #include "shell.h"
49 1.1 cgd #include "parser.h"
50 1.1 cgd #include "nodes.h"
51 1.1 cgd #include "expand.h" /* defines rmescapes() */
52 1.46 christos #include "eval.h" /* defines commandname */
53 1.1 cgd #include "syntax.h"
54 1.1 cgd #include "options.h"
55 1.1 cgd #include "input.h"
56 1.1 cgd #include "output.h"
57 1.1 cgd #include "var.h"
58 1.1 cgd #include "error.h"
59 1.1 cgd #include "memalloc.h"
60 1.1 cgd #include "mystring.h"
61 1.11 jtc #include "alias.h"
62 1.25 christos #include "show.h"
63 1.35 christos #ifndef SMALL
64 1.11 jtc #include "myhistedit.h"
65 1.14 cgd #endif
66 1.1 cgd
67 1.1 cgd /*
68 1.1 cgd * Shell command parser.
69 1.1 cgd */
70 1.1 cgd
71 1.1 cgd /* values returned by readtoken */
72 1.30 christos #include "token.h"
73 1.1 cgd
74 1.51 christos #define OPENBRACE '{'
75 1.51 christos #define CLOSEBRACE '}'
76 1.1 cgd
77 1.1 cgd
78 1.1 cgd struct heredoc {
79 1.1 cgd struct heredoc *next; /* next here document in list */
80 1.1 cgd union node *here; /* redirection node */
81 1.1 cgd char *eofmark; /* string indicating end of input */
82 1.1 cgd int striptabs; /* if set, strip leading tabs */
83 1.116 christos int startline; /* line number where << seen */
84 1.1 cgd };
85 1.1 cgd
86 1.1 cgd
87 1.1 cgd
88 1.48 christos static int noalias = 0; /* when set, don't handle aliases */
89 1.1 cgd struct heredoc *heredoclist; /* list of here documents to read */
90 1.1 cgd int parsebackquote; /* nonzero if we are inside backquotes */
91 1.1 cgd int doprompt; /* if set, prompt the user */
92 1.1 cgd int needprompt; /* true if interactive and at start of line */
93 1.1 cgd int lasttoken; /* last token read */
94 1.1 cgd MKINIT int tokpushback; /* last token pushed back */
95 1.1 cgd char *wordtext; /* text of last word returned by readtoken */
96 1.67 dsl MKINIT int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
97 1.1 cgd struct nodelist *backquotelist;
98 1.1 cgd union node *redirnode;
99 1.1 cgd struct heredoc *heredoc;
100 1.1 cgd int quoteflag; /* set if (part of) last token was quoted */
101 1.1 cgd int startlinno; /* line # where last token started */
102 1.84 christos int funclinno; /* line # where the current function started */
103 1.1 cgd
104 1.1 cgd
105 1.73 christos STATIC union node *list(int, int);
106 1.54 christos STATIC union node *andor(void);
107 1.54 christos STATIC union node *pipeline(void);
108 1.54 christos STATIC union node *command(void);
109 1.54 christos STATIC union node *simplecmd(union node **, union node *);
110 1.54 christos STATIC union node *makename(void);
111 1.54 christos STATIC void parsefname(void);
112 1.115 christos STATIC void slurp_heredoc(char *const, const int, const int);
113 1.111 christos STATIC void readheredocs(void);
114 1.54 christos STATIC int peektoken(void);
115 1.54 christos STATIC int readtoken(void);
116 1.54 christos STATIC int xxreadtoken(void);
117 1.111 christos STATIC int readtoken1(int, char const *, int);
118 1.54 christos STATIC int noexpand(char *);
119 1.108 christos STATIC void synexpect(int, const char *) __dead;
120 1.66 perry STATIC void synerror(const char *) __dead;
121 1.54 christos STATIC void setprompt(int);
122 1.121 kre STATIC int pgetc_linecont(void);
123 1.1 cgd
124 1.22 cgd
125 1.102 christos static const char EOFhere[] = "EOF reading here (<<) document";
126 1.102 christos
127 1.108 christos
128 1.1 cgd /*
129 1.1 cgd * Read and parse a command. Returns NEOF on end of file. (NULL is a
130 1.1 cgd * valid parse tree indicating a blank line.)
131 1.1 cgd */
132 1.1 cgd
133 1.1 cgd union node *
134 1.45 cgd parsecmd(int interact)
135 1.22 cgd {
136 1.1 cgd int t;
137 1.116 christos union node *n;
138 1.1 cgd
139 1.47 christos tokpushback = 0;
140 1.1 cgd doprompt = interact;
141 1.1 cgd if (doprompt)
142 1.11 jtc setprompt(1);
143 1.11 jtc else
144 1.11 jtc setprompt(0);
145 1.1 cgd needprompt = 0;
146 1.11 jtc t = readtoken();
147 1.11 jtc if (t == TEOF)
148 1.1 cgd return NEOF;
149 1.1 cgd if (t == TNL)
150 1.1 cgd return NULL;
151 1.1 cgd tokpushback++;
152 1.116 christos n = list(1, 0);
153 1.116 christos if (heredoclist)
154 1.116 christos error("%d: Here document (<<%s) expected but not present",
155 1.116 christos heredoclist->startline, heredoclist->eofmark);
156 1.116 christos return n;
157 1.1 cgd }
158 1.1 cgd
159 1.1 cgd
160 1.1 cgd STATIC union node *
161 1.73 christos list(int nlflag, int erflag)
162 1.22 cgd {
163 1.1 cgd union node *n1, *n2, *n3;
164 1.12 jtc int tok;
165 1.126 kre
166 1.130 kre CTRACE(DBG_PARSE, ("list(%d,%d): entered @%d\n",nlflag,erflag,plinno));
167 1.1 cgd
168 1.1 cgd checkkwd = 2;
169 1.1 cgd if (nlflag == 0 && tokendlist[peektoken()])
170 1.1 cgd return NULL;
171 1.12 jtc n1 = NULL;
172 1.1 cgd for (;;) {
173 1.12 jtc n2 = andor();
174 1.12 jtc tok = readtoken();
175 1.12 jtc if (tok == TBACKGND) {
176 1.12 jtc if (n2->type == NCMD || n2->type == NPIPE) {
177 1.12 jtc n2->ncmd.backgnd = 1;
178 1.12 jtc } else if (n2->type == NREDIR) {
179 1.12 jtc n2->type = NBACKGND;
180 1.1 cgd } else {
181 1.101 christos n3 = stalloc(sizeof(struct nredir));
182 1.1 cgd n3->type = NBACKGND;
183 1.12 jtc n3->nredir.n = n2;
184 1.1 cgd n3->nredir.redirect = NULL;
185 1.12 jtc n2 = n3;
186 1.1 cgd }
187 1.12 jtc }
188 1.12 jtc if (n1 == NULL) {
189 1.12 jtc n1 = n2;
190 1.12 jtc }
191 1.12 jtc else {
192 1.101 christos n3 = stalloc(sizeof(struct nbinary));
193 1.12 jtc n3->type = NSEMI;
194 1.12 jtc n3->nbinary.ch1 = n1;
195 1.12 jtc n3->nbinary.ch2 = n2;
196 1.12 jtc n1 = n3;
197 1.12 jtc }
198 1.12 jtc switch (tok) {
199 1.12 jtc case TBACKGND:
200 1.12 jtc case TSEMI:
201 1.12 jtc tok = readtoken();
202 1.108 christos /* FALLTHROUGH */
203 1.1 cgd case TNL:
204 1.12 jtc if (tok == TNL) {
205 1.111 christos readheredocs();
206 1.1 cgd if (nlflag)
207 1.1 cgd return n1;
208 1.1 cgd } else {
209 1.1 cgd tokpushback++;
210 1.1 cgd }
211 1.1 cgd checkkwd = 2;
212 1.1 cgd if (tokendlist[peektoken()])
213 1.1 cgd return n1;
214 1.1 cgd break;
215 1.1 cgd case TEOF:
216 1.116 christos pungetc(); /* push back EOF on input */
217 1.1 cgd return n1;
218 1.1 cgd default:
219 1.73 christos if (nlflag || erflag)
220 1.108 christos synexpect(-1, 0);
221 1.1 cgd tokpushback++;
222 1.1 cgd return n1;
223 1.1 cgd }
224 1.1 cgd }
225 1.1 cgd }
226 1.1 cgd
227 1.1 cgd STATIC union node *
228 1.54 christos andor(void)
229 1.54 christos {
230 1.1 cgd union node *n1, *n2, *n3;
231 1.1 cgd int t;
232 1.1 cgd
233 1.130 kre CTRACE(DBG_PARSE, ("andor: entered @%d\n", plinno));
234 1.126 kre
235 1.1 cgd n1 = pipeline();
236 1.1 cgd for (;;) {
237 1.1 cgd if ((t = readtoken()) == TAND) {
238 1.1 cgd t = NAND;
239 1.1 cgd } else if (t == TOR) {
240 1.1 cgd t = NOR;
241 1.1 cgd } else {
242 1.1 cgd tokpushback++;
243 1.1 cgd return n1;
244 1.1 cgd }
245 1.1 cgd n2 = pipeline();
246 1.101 christos n3 = stalloc(sizeof(struct nbinary));
247 1.1 cgd n3->type = t;
248 1.1 cgd n3->nbinary.ch1 = n1;
249 1.1 cgd n3->nbinary.ch2 = n2;
250 1.1 cgd n1 = n3;
251 1.1 cgd }
252 1.1 cgd }
253 1.1 cgd
254 1.1 cgd STATIC union node *
255 1.54 christos pipeline(void)
256 1.54 christos {
257 1.44 christos union node *n1, *n2, *pipenode;
258 1.1 cgd struct nodelist *lp, *prev;
259 1.44 christos int negate;
260 1.1 cgd
261 1.130 kre CTRACE(DBG_PARSE, ("pipeline: entered @%d\n", plinno));
262 1.65 dsl
263 1.44 christos negate = 0;
264 1.65 dsl checkkwd = 2;
265 1.65 dsl while (readtoken() == TNOT) {
266 1.130 kre CTRACE(DBG_PARSE, ("pipeline: TNOT recognized\n"));
267 1.129 kre #ifndef BOGUS_NOT_COMMAND
268 1.129 kre if (posix && negate)
269 1.129 kre synerror("2nd \"!\" unexpected");
270 1.129 kre #endif
271 1.125 kre negate++;
272 1.65 dsl }
273 1.44 christos tokpushback++;
274 1.1 cgd n1 = command();
275 1.1 cgd if (readtoken() == TPIPE) {
276 1.101 christos pipenode = stalloc(sizeof(struct npipe));
277 1.1 cgd pipenode->type = NPIPE;
278 1.1 cgd pipenode->npipe.backgnd = 0;
279 1.101 christos lp = stalloc(sizeof(struct nodelist));
280 1.1 cgd pipenode->npipe.cmdlist = lp;
281 1.1 cgd lp->n = n1;
282 1.1 cgd do {
283 1.1 cgd prev = lp;
284 1.101 christos lp = stalloc(sizeof(struct nodelist));
285 1.1 cgd lp->n = command();
286 1.1 cgd prev->next = lp;
287 1.1 cgd } while (readtoken() == TPIPE);
288 1.1 cgd lp->next = NULL;
289 1.1 cgd n1 = pipenode;
290 1.1 cgd }
291 1.1 cgd tokpushback++;
292 1.44 christos if (negate) {
293 1.130 kre CTRACE(DBG_PARSE, ("%snegate pipeline\n",
294 1.130 kre (negate&1) ? "" : "double "));
295 1.101 christos n2 = stalloc(sizeof(struct nnot));
296 1.125 kre n2->type = (negate & 1) ? NNOT : NDNOT;
297 1.44 christos n2->nnot.com = n1;
298 1.44 christos return n2;
299 1.44 christos } else
300 1.44 christos return n1;
301 1.1 cgd }
302 1.1 cgd
303 1.1 cgd
304 1.1 cgd
305 1.1 cgd STATIC union node *
306 1.54 christos command(void)
307 1.54 christos {
308 1.1 cgd union node *n1, *n2;
309 1.1 cgd union node *ap, **app;
310 1.1 cgd union node *cp, **cpp;
311 1.1 cgd union node *redir, **rpp;
312 1.129 kre int t;
313 1.129 kre #ifdef BOGUS_NOT_COMMAND
314 1.129 kre int negate = 0;
315 1.129 kre #endif
316 1.1 cgd
317 1.130 kre CTRACE(DBG_PARSE, ("command: entered @%d\n", plinno));
318 1.65 dsl
319 1.1 cgd checkkwd = 2;
320 1.25 christos redir = NULL;
321 1.25 christos n1 = NULL;
322 1.5 sef rpp = &redir;
323 1.31 christos
324 1.5 sef /* Check for redirection which may precede command */
325 1.5 sef while (readtoken() == TREDIR) {
326 1.5 sef *rpp = n2 = redirnode;
327 1.5 sef rpp = &n2->nfile.next;
328 1.5 sef parsefname();
329 1.5 sef }
330 1.5 sef tokpushback++;
331 1.5 sef
332 1.129 kre #ifdef BOGUS_NOT_COMMAND /* only in pileline() */
333 1.31 christos while (readtoken() == TNOT) {
334 1.130 kre CTRACE(DBG_PARSE, ("command: TNOT (bogus) recognized\n"));
335 1.125 kre negate++;
336 1.31 christos }
337 1.31 christos tokpushback++;
338 1.129 kre #endif
339 1.31 christos
340 1.1 cgd switch (readtoken()) {
341 1.1 cgd case TIF:
342 1.101 christos n1 = stalloc(sizeof(struct nif));
343 1.1 cgd n1->type = NIF;
344 1.73 christos n1->nif.test = list(0, 0);
345 1.1 cgd if (readtoken() != TTHEN)
346 1.108 christos synexpect(TTHEN, 0);
347 1.73 christos n1->nif.ifpart = list(0, 0);
348 1.1 cgd n2 = n1;
349 1.1 cgd while (readtoken() == TELIF) {
350 1.101 christos n2->nif.elsepart = stalloc(sizeof(struct nif));
351 1.1 cgd n2 = n2->nif.elsepart;
352 1.1 cgd n2->type = NIF;
353 1.73 christos n2->nif.test = list(0, 0);
354 1.1 cgd if (readtoken() != TTHEN)
355 1.108 christos synexpect(TTHEN, 0);
356 1.73 christos n2->nif.ifpart = list(0, 0);
357 1.1 cgd }
358 1.1 cgd if (lasttoken == TELSE)
359 1.73 christos n2->nif.elsepart = list(0, 0);
360 1.1 cgd else {
361 1.1 cgd n2->nif.elsepart = NULL;
362 1.1 cgd tokpushback++;
363 1.1 cgd }
364 1.1 cgd if (readtoken() != TFI)
365 1.108 christos synexpect(TFI, 0);
366 1.1 cgd checkkwd = 1;
367 1.1 cgd break;
368 1.1 cgd case TWHILE:
369 1.1 cgd case TUNTIL: {
370 1.1 cgd int got;
371 1.126 kre
372 1.101 christos n1 = stalloc(sizeof(struct nbinary));
373 1.1 cgd n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
374 1.73 christos n1->nbinary.ch1 = list(0, 0);
375 1.1 cgd if ((got=readtoken()) != TDO) {
376 1.130 kre VTRACE(DBG_PARSE, ("expecting DO got %s %s\n",
377 1.130 kre tokname[got], got == TWORD ? wordtext : ""));
378 1.108 christos synexpect(TDO, 0);
379 1.1 cgd }
380 1.73 christos n1->nbinary.ch2 = list(0, 0);
381 1.1 cgd if (readtoken() != TDONE)
382 1.108 christos synexpect(TDONE, 0);
383 1.1 cgd checkkwd = 1;
384 1.1 cgd break;
385 1.1 cgd }
386 1.1 cgd case TFOR:
387 1.1 cgd if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
388 1.1 cgd synerror("Bad for loop variable");
389 1.101 christos n1 = stalloc(sizeof(struct nfor));
390 1.1 cgd n1->type = NFOR;
391 1.1 cgd n1->nfor.var = wordtext;
392 1.133 kre n1->nfor.lineno = startlinno;
393 1.126 kre if (readtoken()==TWORD && !quoteflag && equal(wordtext,"in")) {
394 1.1 cgd app = ≈
395 1.1 cgd while (readtoken() == TWORD) {
396 1.101 christos n2 = stalloc(sizeof(struct narg));
397 1.1 cgd n2->type = NARG;
398 1.1 cgd n2->narg.text = wordtext;
399 1.1 cgd n2->narg.backquote = backquotelist;
400 1.1 cgd *app = n2;
401 1.1 cgd app = &n2->narg.next;
402 1.1 cgd }
403 1.1 cgd *app = NULL;
404 1.1 cgd n1->nfor.args = ap;
405 1.5 sef if (lasttoken != TNL && lasttoken != TSEMI)
406 1.108 christos synexpect(-1, 0);
407 1.1 cgd } else {
408 1.95 christos static char argvars[5] = {
409 1.95 christos CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
410 1.95 christos };
411 1.126 kre
412 1.101 christos n2 = stalloc(sizeof(struct narg));
413 1.1 cgd n2->type = NARG;
414 1.43 christos n2->narg.text = argvars;
415 1.1 cgd n2->narg.backquote = NULL;
416 1.1 cgd n2->narg.next = NULL;
417 1.1 cgd n1->nfor.args = n2;
418 1.11 jtc /*
419 1.11 jtc * Newline or semicolon here is optional (but note
420 1.11 jtc * that the original Bourne shell only allowed NL).
421 1.11 jtc */
422 1.11 jtc if (lasttoken != TNL && lasttoken != TSEMI)
423 1.11 jtc tokpushback++;
424 1.1 cgd }
425 1.1 cgd checkkwd = 2;
426 1.1 cgd if ((t = readtoken()) == TDO)
427 1.1 cgd t = TDONE;
428 1.1 cgd else if (t == TBEGIN)
429 1.1 cgd t = TEND;
430 1.1 cgd else
431 1.108 christos synexpect(-1, 0);
432 1.73 christos n1->nfor.body = list(0, 0);
433 1.1 cgd if (readtoken() != t)
434 1.108 christos synexpect(t, 0);
435 1.1 cgd checkkwd = 1;
436 1.1 cgd break;
437 1.1 cgd case TCASE:
438 1.101 christos n1 = stalloc(sizeof(struct ncase));
439 1.1 cgd n1->type = NCASE;
440 1.133 kre n1->ncase.lineno = startlinno;
441 1.1 cgd if (readtoken() != TWORD)
442 1.108 christos synexpect(TWORD, 0);
443 1.101 christos n1->ncase.expr = n2 = stalloc(sizeof(struct narg));
444 1.1 cgd n2->type = NARG;
445 1.1 cgd n2->narg.text = wordtext;
446 1.1 cgd n2->narg.backquote = backquotelist;
447 1.1 cgd n2->narg.next = NULL;
448 1.1 cgd while (readtoken() == TNL);
449 1.1 cgd if (lasttoken != TWORD || ! equal(wordtext, "in"))
450 1.108 christos synexpect(-1, "in");
451 1.1 cgd cpp = &n1->ncase.cases;
452 1.48 christos noalias = 1;
453 1.15 jtc checkkwd = 2, readtoken();
454 1.87 christos /*
455 1.88 christos * Both ksh and bash accept 'case x in esac'
456 1.87 christos * so configure scripts started taking advantage of this.
457 1.88 christos * The page: http://pubs.opengroup.org/onlinepubs/\
458 1.88 christos * 009695399/utilities/xcu_chap02.html contradicts itself,
459 1.88 christos * as to if this is legal; the "Case Conditional Format"
460 1.88 christos * paragraph shows one case is required, but the "Grammar"
461 1.88 christos * section shows a grammar that explicitly allows the no
462 1.88 christos * case option.
463 1.87 christos */
464 1.87 christos while (lasttoken != TESAC) {
465 1.101 christos *cpp = cp = stalloc(sizeof(struct nclist));
466 1.61 christos if (lasttoken == TLP)
467 1.61 christos readtoken();
468 1.1 cgd cp->type = NCLIST;
469 1.1 cgd app = &cp->nclist.pattern;
470 1.1 cgd for (;;) {
471 1.101 christos *app = ap = stalloc(sizeof(struct narg));
472 1.1 cgd ap->type = NARG;
473 1.1 cgd ap->narg.text = wordtext;
474 1.1 cgd ap->narg.backquote = backquotelist;
475 1.15 jtc if (checkkwd = 2, readtoken() != TPIPE)
476 1.1 cgd break;
477 1.1 cgd app = &ap->narg.next;
478 1.16 jtc readtoken();
479 1.1 cgd }
480 1.1 cgd ap->narg.next = NULL;
481 1.48 christos noalias = 0;
482 1.48 christos if (lasttoken != TRP) {
483 1.108 christos synexpect(TRP, 0);
484 1.48 christos }
485 1.73 christos cp->nclist.body = list(0, 0);
486 1.15 jtc
487 1.15 jtc checkkwd = 2;
488 1.15 jtc if ((t = readtoken()) != TESAC) {
489 1.123 kre if (t != TENDCASE && t != TCASEFALL) {
490 1.48 christos noalias = 0;
491 1.108 christos synexpect(TENDCASE, 0);
492 1.48 christos } else {
493 1.123 kre if (t == TCASEFALL)
494 1.123 kre cp->type = NCLISTCONT;
495 1.48 christos noalias = 1;
496 1.48 christos checkkwd = 2;
497 1.48 christos readtoken();
498 1.48 christos }
499 1.15 jtc }
500 1.1 cgd cpp = &cp->nclist.next;
501 1.86 christos }
502 1.48 christos noalias = 0;
503 1.1 cgd *cpp = NULL;
504 1.1 cgd checkkwd = 1;
505 1.1 cgd break;
506 1.1 cgd case TLP:
507 1.101 christos n1 = stalloc(sizeof(struct nredir));
508 1.1 cgd n1->type = NSUBSHELL;
509 1.73 christos n1->nredir.n = list(0, 0);
510 1.1 cgd n1->nredir.redirect = NULL;
511 1.120 kre if (n1->nredir.n == NULL)
512 1.120 kre synexpect(-1, 0);
513 1.1 cgd if (readtoken() != TRP)
514 1.108 christos synexpect(TRP, 0);
515 1.1 cgd checkkwd = 1;
516 1.1 cgd break;
517 1.1 cgd case TBEGIN:
518 1.73 christos n1 = list(0, 0);
519 1.120 kre if (posix && n1 == NULL)
520 1.120 kre synexpect(-1, 0);
521 1.1 cgd if (readtoken() != TEND)
522 1.108 christos synexpect(TEND, 0);
523 1.1 cgd checkkwd = 1;
524 1.1 cgd break;
525 1.119 kre
526 1.19 mycroft case TSEMI:
527 1.119 kre case TAND:
528 1.119 kre case TOR:
529 1.119 kre case TPIPE:
530 1.119 kre case TNL:
531 1.119 kre case TEOF:
532 1.119 kre case TRP:
533 1.19 mycroft /*
534 1.119 kre * simple commands must have something in them,
535 1.119 kre * either a word (which at this point includes a=b)
536 1.119 kre * or a redirection. If we reached the end of the
537 1.119 kre * command (which one of these tokens indicates)
538 1.119 kre * when we are just starting, and have not had a
539 1.119 kre * redirect, then ...
540 1.119 kre *
541 1.119 kre * nb: it is still possible to end up with empty
542 1.119 kre * simple commands, if the "command" is a var
543 1.119 kre * expansion that produces nothing
544 1.119 kre * X= ; $X && $X
545 1.119 kre * --> &&
546 1.119 kre * I am not sure if this is intended to be legal or not.
547 1.19 mycroft */
548 1.19 mycroft if (!redir)
549 1.108 christos synexpect(-1, 0);
550 1.1 cgd case TWORD:
551 1.1 cgd tokpushback++;
552 1.31 christos n1 = simplecmd(rpp, redir);
553 1.31 christos goto checkneg;
554 1.97 christos case TENDCASE:
555 1.97 christos if (redir) {
556 1.97 christos tokpushback++;
557 1.97 christos goto checkneg;
558 1.97 christos }
559 1.97 christos /* FALLTHROUGH */
560 1.1 cgd default:
561 1.108 christos synexpect(-1, 0);
562 1.39 mycroft /* NOTREACHED */
563 1.1 cgd }
564 1.1 cgd
565 1.1 cgd /* Now check for redirection which may follow command */
566 1.1 cgd while (readtoken() == TREDIR) {
567 1.1 cgd *rpp = n2 = redirnode;
568 1.1 cgd rpp = &n2->nfile.next;
569 1.1 cgd parsefname();
570 1.1 cgd }
571 1.1 cgd tokpushback++;
572 1.1 cgd *rpp = NULL;
573 1.1 cgd if (redir) {
574 1.1 cgd if (n1->type != NSUBSHELL) {
575 1.101 christos n2 = stalloc(sizeof(struct nredir));
576 1.1 cgd n2->type = NREDIR;
577 1.1 cgd n2->nredir.n = n1;
578 1.1 cgd n1 = n2;
579 1.1 cgd }
580 1.1 cgd n1->nredir.redirect = redir;
581 1.1 cgd }
582 1.31 christos
583 1.126 kre checkneg:
584 1.129 kre #ifdef BOGUS_NOT_COMMAND
585 1.31 christos if (negate) {
586 1.130 kre VTRACE(DBG_PARSE, ("bogus %snegate command\n",
587 1.130 kre (negate&1) ? "" : "double "));
588 1.101 christos n2 = stalloc(sizeof(struct nnot));
589 1.125 kre n2->type = (negate & 1) ? NNOT : NDNOT;
590 1.31 christos n2->nnot.com = n1;
591 1.31 christos return n2;
592 1.31 christos }
593 1.31 christos else
594 1.129 kre #endif
595 1.31 christos return n1;
596 1.1 cgd }
597 1.1 cgd
598 1.1 cgd
599 1.1 cgd STATIC union node *
600 1.54 christos simplecmd(union node **rpp, union node *redir)
601 1.54 christos {
602 1.1 cgd union node *args, **app;
603 1.129 kre union node *n = NULL;
604 1.129 kre #ifdef BOGUS_NOT_COMMAND
605 1.129 kre union node *n2;
606 1.31 christos int negate = 0;
607 1.129 kre #endif
608 1.1 cgd
609 1.130 kre CTRACE(DBG_PARSE, ("simple command with%s redir already @%d\n",
610 1.130 kre redir ? "" : "out", plinno));
611 1.130 kre
612 1.11 jtc /* If we don't have any redirections already, then we must reset */
613 1.11 jtc /* rpp to be the address of the local redir variable. */
614 1.5 sef if (redir == 0)
615 1.5 sef rpp = &redir;
616 1.5 sef
617 1.1 cgd args = NULL;
618 1.1 cgd app = &args;
619 1.11 jtc
620 1.129 kre #ifdef BOGUS_NOT_COMMAND /* pipelines get negated, commands do not */
621 1.31 christos while (readtoken() == TNOT) {
622 1.130 kre VTRACE(DBG_PARSE, ("simplcmd: bogus TNOT recognized\n"));
623 1.125 kre negate++;
624 1.31 christos }
625 1.31 christos tokpushback++;
626 1.129 kre #endif
627 1.31 christos
628 1.1 cgd for (;;) {
629 1.1 cgd if (readtoken() == TWORD) {
630 1.101 christos n = stalloc(sizeof(struct narg));
631 1.1 cgd n->type = NARG;
632 1.1 cgd n->narg.text = wordtext;
633 1.1 cgd n->narg.backquote = backquotelist;
634 1.1 cgd *app = n;
635 1.1 cgd app = &n->narg.next;
636 1.1 cgd } else if (lasttoken == TREDIR) {
637 1.1 cgd *rpp = n = redirnode;
638 1.1 cgd rpp = &n->nfile.next;
639 1.1 cgd parsefname(); /* read name of redirection file */
640 1.1 cgd } else if (lasttoken == TLP && app == &args->narg.next
641 1.110 christos && redir == 0) {
642 1.1 cgd /* We have a function */
643 1.1 cgd if (readtoken() != TRP)
644 1.108 christos synexpect(TRP, 0);
645 1.84 christos funclinno = plinno;
646 1.64 christos rmescapes(n->narg.text);
647 1.118 kre if (strchr(n->narg.text, '/'))
648 1.1 cgd synerror("Bad function name");
649 1.1 cgd n->type = NDEFUN;
650 1.1 cgd n->narg.next = command();
651 1.84 christos funclinno = 0;
652 1.31 christos goto checkneg;
653 1.1 cgd } else {
654 1.1 cgd tokpushback++;
655 1.1 cgd break;
656 1.1 cgd }
657 1.1 cgd }
658 1.120 kre
659 1.120 kre if (args == NULL && redir == NULL)
660 1.120 kre synexpect(-1, 0);
661 1.1 cgd *app = NULL;
662 1.1 cgd *rpp = NULL;
663 1.101 christos n = stalloc(sizeof(struct ncmd));
664 1.1 cgd n->type = NCMD;
665 1.1 cgd n->ncmd.backgnd = 0;
666 1.1 cgd n->ncmd.args = args;
667 1.1 cgd n->ncmd.redirect = redir;
668 1.133 kre n->ncmd.lineno = startlinno;
669 1.31 christos
670 1.126 kre checkneg:
671 1.129 kre #ifdef BOGUS_NOT_COMMAND
672 1.31 christos if (negate) {
673 1.130 kre VTRACE(DBG_PARSE, ("bogus %snegate simplecmd\n",
674 1.130 kre (negate&1) ? "" : "double "));
675 1.101 christos n2 = stalloc(sizeof(struct nnot));
676 1.125 kre n2->type = (negate & 1) ? NNOT : NDNOT;
677 1.31 christos n2->nnot.com = n;
678 1.31 christos return n2;
679 1.31 christos }
680 1.31 christos else
681 1.129 kre #endif
682 1.31 christos return n;
683 1.1 cgd }
684 1.1 cgd
685 1.18 jtc STATIC union node *
686 1.54 christos makename(void)
687 1.54 christos {
688 1.18 jtc union node *n;
689 1.18 jtc
690 1.101 christos n = stalloc(sizeof(struct narg));
691 1.18 jtc n->type = NARG;
692 1.18 jtc n->narg.next = NULL;
693 1.18 jtc n->narg.text = wordtext;
694 1.18 jtc n->narg.backquote = backquotelist;
695 1.18 jtc return n;
696 1.18 jtc }
697 1.18 jtc
698 1.95 christos void
699 1.95 christos fixredir(union node *n, const char *text, int err)
700 1.95 christos {
701 1.126 kre
702 1.130 kre VTRACE(DBG_PARSE, ("Fix redir %s %d\n", text, err));
703 1.18 jtc if (!err)
704 1.18 jtc n->ndup.vname = NULL;
705 1.18 jtc
706 1.91 christos if (is_number(text))
707 1.91 christos n->ndup.dupfd = number(text);
708 1.18 jtc else if (text[0] == '-' && text[1] == '\0')
709 1.18 jtc n->ndup.dupfd = -1;
710 1.18 jtc else {
711 1.30 christos
712 1.18 jtc if (err)
713 1.18 jtc synerror("Bad fd number");
714 1.18 jtc else
715 1.18 jtc n->ndup.vname = makename();
716 1.18 jtc }
717 1.18 jtc }
718 1.18 jtc
719 1.1 cgd
720 1.1 cgd STATIC void
721 1.54 christos parsefname(void)
722 1.54 christos {
723 1.1 cgd union node *n = redirnode;
724 1.1 cgd
725 1.1 cgd if (readtoken() != TWORD)
726 1.108 christos synexpect(-1, 0);
727 1.1 cgd if (n->type == NHERE) {
728 1.1 cgd struct heredoc *here = heredoc;
729 1.1 cgd struct heredoc *p;
730 1.1 cgd
731 1.1 cgd if (quoteflag == 0)
732 1.1 cgd n->type = NXHERE;
733 1.130 kre VTRACE(DBG_PARSE, ("Here document %d @%d\n", n->type, plinno));
734 1.1 cgd if (here->striptabs) {
735 1.1 cgd while (*wordtext == '\t')
736 1.1 cgd wordtext++;
737 1.1 cgd }
738 1.111 christos
739 1.111 christos /*
740 1.111 christos * this test is not really necessary, we are not
741 1.111 christos * required to expand wordtext, but there's no reason
742 1.111 christos * it cannot be $$ or something like that - that would
743 1.111 christos * not mean the pid, but literally two '$' characters.
744 1.111 christos * There is no need for limits on what the word can be.
745 1.111 christos * However, it needs to stay literal as entered, not
746 1.111 christos * have $ converted to CTLVAR or something, which as
747 1.111 christos * the parser is, at the minute, is impossible to prevent.
748 1.111 christos * So, leave it like this until the rest of the parser is fixed.
749 1.111 christos */
750 1.126 kre if (!noexpand(wordtext))
751 1.1 cgd synerror("Illegal eof marker for << redirection");
752 1.111 christos
753 1.1 cgd rmescapes(wordtext);
754 1.1 cgd here->eofmark = wordtext;
755 1.1 cgd here->next = NULL;
756 1.1 cgd if (heredoclist == NULL)
757 1.1 cgd heredoclist = here;
758 1.1 cgd else {
759 1.90 christos for (p = heredoclist ; p->next ; p = p->next)
760 1.90 christos continue;
761 1.1 cgd p->next = here;
762 1.1 cgd }
763 1.1 cgd } else if (n->type == NTOFD || n->type == NFROMFD) {
764 1.18 jtc fixredir(n, wordtext, 0);
765 1.1 cgd } else {
766 1.18 jtc n->nfile.fname = makename();
767 1.1 cgd }
768 1.1 cgd }
769 1.1 cgd
770 1.111 christos /*
771 1.111 christos * Check to see whether we are at the end of the here document. When this
772 1.111 christos * is called, c is set to the first character of the next input line. If
773 1.111 christos * we are at the end of the here document, this routine sets the c to PEOF.
774 1.111 christos * The new value of c is returned.
775 1.111 christos */
776 1.111 christos
777 1.111 christos static int
778 1.111 christos checkend(int c, char * const eofmark, const int striptabs)
779 1.111 christos {
780 1.126 kre
781 1.111 christos if (striptabs) {
782 1.111 christos while (c == '\t')
783 1.111 christos c = pgetc();
784 1.111 christos }
785 1.111 christos if (c == PEOF) {
786 1.111 christos if (*eofmark == '\0')
787 1.111 christos return (c);
788 1.111 christos synerror(EOFhere);
789 1.111 christos }
790 1.111 christos if (c == *eofmark) {
791 1.111 christos int c2;
792 1.111 christos char *q;
793 1.111 christos
794 1.111 christos for (q = eofmark + 1; c2 = pgetc(), *q != '\0' && c2 == *q; q++)
795 1.111 christos ;
796 1.111 christos if ((c2 == PEOF || c2 == '\n') && *q == '\0') {
797 1.111 christos c = PEOF;
798 1.111 christos if (c2 == '\n') {
799 1.111 christos plinno++;
800 1.111 christos needprompt = doprompt;
801 1.111 christos }
802 1.111 christos } else {
803 1.111 christos pungetc();
804 1.111 christos pushstring(eofmark + 1, q - (eofmark + 1), NULL);
805 1.111 christos }
806 1.111 christos } else if (c == '\n' && *eofmark == '\0') {
807 1.111 christos c = PEOF;
808 1.111 christos plinno++;
809 1.111 christos needprompt = doprompt;
810 1.111 christos }
811 1.111 christos return (c);
812 1.111 christos }
813 1.111 christos
814 1.1 cgd
815 1.1 cgd /*
816 1.1 cgd * Input any here documents.
817 1.1 cgd */
818 1.1 cgd
819 1.1 cgd STATIC void
820 1.115 christos slurp_heredoc(char *const eofmark, const int striptabs, const int sq)
821 1.111 christos {
822 1.111 christos int c;
823 1.111 christos char *out;
824 1.111 christos
825 1.111 christos c = pgetc();
826 1.111 christos
827 1.111 christos /*
828 1.111 christos * If we hit EOF on the input, and the eofmark is a null string ('')
829 1.111 christos * we consider this empty line to be the eofmark, and exit without err.
830 1.111 christos */
831 1.111 christos if (c == PEOF && *eofmark != '\0')
832 1.111 christos synerror(EOFhere);
833 1.111 christos
834 1.111 christos STARTSTACKSTR(out);
835 1.111 christos
836 1.111 christos while ((c = checkend(c, eofmark, striptabs)) != PEOF) {
837 1.111 christos do {
838 1.111 christos if (sq) {
839 1.111 christos /*
840 1.111 christos * in single quoted mode (eofmark quoted)
841 1.111 christos * all we look for is \n so we can check
842 1.111 christos * for the epfmark - everything saved literally.
843 1.111 christos */
844 1.111 christos STPUTC(c, out);
845 1.122 kre if (c == '\n') {
846 1.122 kre plinno++;
847 1.111 christos break;
848 1.122 kre }
849 1.111 christos continue;
850 1.111 christos }
851 1.111 christos /*
852 1.111 christos * In double quoted (non-quoted eofmark)
853 1.111 christos * we must handle \ followed by \n here
854 1.111 christos * otherwise we can mismatch the end mark.
855 1.111 christos * All other uses of \ will be handled later
856 1.111 christos * when the here doc is expanded.
857 1.111 christos *
858 1.111 christos * This also makes sure \\ followed by \n does
859 1.111 christos * not suppress the newline (the \ quotes itself)
860 1.111 christos */
861 1.111 christos if (c == '\\') { /* A backslash */
862 1.111 christos c = pgetc(); /* followed by */
863 1.122 kre if (c == '\n') { /* a newline? */
864 1.122 kre plinno++;
865 1.122 kre continue; /* :drop both */
866 1.122 kre }
867 1.111 christos STPUTC('\\', out); /* else keep \ */
868 1.111 christos }
869 1.111 christos STPUTC(c, out); /* keep the char */
870 1.122 kre if (c == '\n') { /* at end of line */
871 1.122 kre plinno++;
872 1.111 christos break; /* look for eofmark */
873 1.122 kre }
874 1.111 christos } while ((c = pgetc()) != PEOF);
875 1.111 christos
876 1.111 christos /*
877 1.111 christos * If we have read a line, and reached EOF, without
878 1.111 christos * finding the eofmark, whether the EOF comes before
879 1.111 christos * or immediately after the \n, that is an error.
880 1.111 christos */
881 1.111 christos if (c == PEOF || (c = pgetc()) == PEOF)
882 1.111 christos synerror(EOFhere);
883 1.111 christos }
884 1.111 christos STPUTC('\0', out);
885 1.111 christos
886 1.111 christos c = out - stackblock();
887 1.111 christos out = stackblock();
888 1.111 christos grabstackblock(c);
889 1.111 christos wordtext = out;
890 1.111 christos
891 1.130 kre VTRACE(DBG_PARSE,
892 1.130 kre ("Slurped a heredoc (to '%s')%s: len %d, \"%.*s%s\" @%d\n",
893 1.130 kre eofmark, striptabs ? " tab stripped" : "", c, (c > 16 ? 16 : c),
894 1.130 kre wordtext, (c > 16 ? "..." : ""), plinno));
895 1.111 christos }
896 1.111 christos
897 1.111 christos STATIC void
898 1.111 christos readheredocs(void)
899 1.54 christos {
900 1.1 cgd struct heredoc *here;
901 1.1 cgd union node *n;
902 1.1 cgd
903 1.1 cgd while (heredoclist) {
904 1.1 cgd here = heredoclist;
905 1.1 cgd heredoclist = here->next;
906 1.1 cgd if (needprompt) {
907 1.11 jtc setprompt(2);
908 1.1 cgd needprompt = 0;
909 1.1 cgd }
910 1.111 christos
911 1.111 christos slurp_heredoc(here->eofmark, here->striptabs,
912 1.111 christos here->here->nhere.type == NHERE);
913 1.111 christos
914 1.101 christos n = stalloc(sizeof(struct narg));
915 1.1 cgd n->narg.type = NARG;
916 1.1 cgd n->narg.next = NULL;
917 1.1 cgd n->narg.text = wordtext;
918 1.1 cgd n->narg.backquote = backquotelist;
919 1.1 cgd here->here->nhere.doc = n;
920 1.1 cgd
921 1.115 christos if (here->here->nhere.type == NHERE)
922 1.115 christos continue;
923 1.111 christos
924 1.115 christos /*
925 1.115 christos * Now "parse" here docs that have unquoted eofmarkers.
926 1.115 christos */
927 1.133 kre setinputstring(wordtext, 1, startlinno);
928 1.115 christos readtoken1(pgetc(), DQSYNTAX, 1);
929 1.115 christos n->narg.text = wordtext;
930 1.115 christos n->narg.backquote = backquotelist;
931 1.115 christos popfile();
932 1.115 christos }
933 1.111 christos }
934 1.111 christos
935 1.1 cgd STATIC int
936 1.54 christos peektoken(void)
937 1.54 christos {
938 1.1 cgd int t;
939 1.1 cgd
940 1.1 cgd t = readtoken();
941 1.1 cgd tokpushback++;
942 1.1 cgd return (t);
943 1.1 cgd }
944 1.1 cgd
945 1.1 cgd STATIC int
946 1.54 christos readtoken(void)
947 1.54 christos {
948 1.1 cgd int t;
949 1.11 jtc int savecheckkwd = checkkwd;
950 1.1 cgd #ifdef DEBUG
951 1.1 cgd int alreadyseen = tokpushback;
952 1.1 cgd #endif
953 1.48 christos struct alias *ap;
954 1.30 christos
955 1.11 jtc top:
956 1.1 cgd t = xxreadtoken();
957 1.1 cgd
958 1.1 cgd if (checkkwd) {
959 1.1 cgd /*
960 1.1 cgd * eat newlines
961 1.1 cgd */
962 1.1 cgd if (checkkwd == 2) {
963 1.1 cgd checkkwd = 0;
964 1.1 cgd while (t == TNL) {
965 1.111 christos readheredocs();
966 1.1 cgd t = xxreadtoken();
967 1.1 cgd }
968 1.1 cgd } else
969 1.1 cgd checkkwd = 0;
970 1.1 cgd /*
971 1.11 jtc * check for keywords and aliases
972 1.1 cgd */
973 1.95 christos if (t == TWORD && !quoteflag) {
974 1.43 christos const char *const *pp;
975 1.1 cgd
976 1.43 christos for (pp = parsekwd; *pp; pp++) {
977 1.95 christos if (**pp == *wordtext && equal(*pp, wordtext)) {
978 1.90 christos lasttoken = t = pp -
979 1.43 christos parsekwd + KWDOFFSET;
980 1.130 kre VTRACE(DBG_PARSE,
981 1.130 kre ("keyword %s recognized\n",
982 1.126 kre tokname[t]));
983 1.11 jtc goto out;
984 1.1 cgd }
985 1.1 cgd }
986 1.90 christos if (!noalias &&
987 1.48 christos (ap = lookupalias(wordtext, 1)) != NULL) {
988 1.11 jtc pushstring(ap->val, strlen(ap->val), ap);
989 1.11 jtc checkkwd = savecheckkwd;
990 1.11 jtc goto top;
991 1.11 jtc }
992 1.1 cgd }
993 1.126 kre out:
994 1.31 christos checkkwd = (t == TNOT) ? savecheckkwd : 0;
995 1.1 cgd }
996 1.130 kre VTRACE(DBG_PARSE, ("%stoken %s %s\n", alreadyseen ? "reread " : "",
997 1.126 kre tokname[t], t == TWORD ? wordtext : ""));
998 1.1 cgd return (t);
999 1.1 cgd }
1000 1.1 cgd
1001 1.1 cgd
1002 1.1 cgd /*
1003 1.1 cgd * Read the next input token.
1004 1.1 cgd * If the token is a word, we set backquotelist to the list of cmds in
1005 1.1 cgd * backquotes. We set quoteflag to true if any part of the word was
1006 1.1 cgd * quoted.
1007 1.1 cgd * If the token is TREDIR, then we set redirnode to a structure containing
1008 1.1 cgd * the redirection.
1009 1.1 cgd * In all cases, the variable startlinno is set to the number of the line
1010 1.1 cgd * on which the token starts.
1011 1.1 cgd *
1012 1.1 cgd * [Change comment: here documents and internal procedures]
1013 1.1 cgd * [Readtoken shouldn't have any arguments. Perhaps we should make the
1014 1.1 cgd * word parsing code into a separate routine. In this case, readtoken
1015 1.1 cgd * doesn't need to have any internal procedures, but parseword does.
1016 1.1 cgd * We could also make parseoperator in essence the main routine, and
1017 1.1 cgd * have parseword (readtoken1?) handle both words and redirection.]
1018 1.1 cgd */
1019 1.1 cgd
1020 1.1 cgd #define RETURN(token) return lasttoken = token
1021 1.1 cgd
1022 1.1 cgd STATIC int
1023 1.54 christos xxreadtoken(void)
1024 1.54 christos {
1025 1.32 tls int c;
1026 1.1 cgd
1027 1.1 cgd if (tokpushback) {
1028 1.1 cgd tokpushback = 0;
1029 1.1 cgd return lasttoken;
1030 1.1 cgd }
1031 1.1 cgd if (needprompt) {
1032 1.11 jtc setprompt(2);
1033 1.1 cgd needprompt = 0;
1034 1.1 cgd }
1035 1.1 cgd startlinno = plinno;
1036 1.1 cgd for (;;) { /* until token or start of word found */
1037 1.1 cgd c = pgetc_macro();
1038 1.1 cgd switch (c) {
1039 1.1 cgd case ' ': case '\t':
1040 1.1 cgd continue;
1041 1.1 cgd case '#':
1042 1.90 christos while ((c = pgetc()) != '\n' && c != PEOF)
1043 1.90 christos continue;
1044 1.1 cgd pungetc();
1045 1.1 cgd continue;
1046 1.108 christos
1047 1.1 cgd case '\n':
1048 1.1 cgd plinno++;
1049 1.1 cgd needprompt = doprompt;
1050 1.1 cgd RETURN(TNL);
1051 1.1 cgd case PEOF:
1052 1.1 cgd RETURN(TEOF);
1053 1.108 christos
1054 1.1 cgd case '&':
1055 1.121 kre if (pgetc_linecont() == '&')
1056 1.1 cgd RETURN(TAND);
1057 1.1 cgd pungetc();
1058 1.1 cgd RETURN(TBACKGND);
1059 1.1 cgd case '|':
1060 1.121 kre if (pgetc_linecont() == '|')
1061 1.1 cgd RETURN(TOR);
1062 1.1 cgd pungetc();
1063 1.1 cgd RETURN(TPIPE);
1064 1.1 cgd case ';':
1065 1.123 kre switch (pgetc_linecont()) {
1066 1.123 kre case ';':
1067 1.1 cgd RETURN(TENDCASE);
1068 1.123 kre case '&':
1069 1.123 kre RETURN(TCASEFALL);
1070 1.123 kre default:
1071 1.123 kre pungetc();
1072 1.123 kre RETURN(TSEMI);
1073 1.123 kre }
1074 1.1 cgd case '(':
1075 1.1 cgd RETURN(TLP);
1076 1.1 cgd case ')':
1077 1.1 cgd RETURN(TRP);
1078 1.108 christos
1079 1.108 christos case '\\':
1080 1.108 christos switch (pgetc()) {
1081 1.108 christos case '\n':
1082 1.108 christos startlinno = ++plinno;
1083 1.108 christos if (doprompt)
1084 1.108 christos setprompt(2);
1085 1.108 christos else
1086 1.108 christos setprompt(0);
1087 1.108 christos continue;
1088 1.108 christos case PEOF:
1089 1.108 christos RETURN(TEOF);
1090 1.108 christos default:
1091 1.108 christos pungetc();
1092 1.108 christos break;
1093 1.108 christos }
1094 1.108 christos /* FALLTHROUGH */
1095 1.1 cgd default:
1096 1.111 christos return readtoken1(c, BASESYNTAX, 0);
1097 1.1 cgd }
1098 1.1 cgd }
1099 1.1 cgd #undef RETURN
1100 1.1 cgd }
1101 1.1 cgd
1102 1.1 cgd
1103 1.1 cgd
1104 1.1 cgd /*
1105 1.1 cgd * If eofmark is NULL, read a word or a redirection symbol. If eofmark
1106 1.1 cgd * is not NULL, read a here document. In the latter case, eofmark is the
1107 1.1 cgd * word which marks the end of the document and striptabs is true if
1108 1.1 cgd * leading tabs should be stripped from the document. The argument firstc
1109 1.1 cgd * is the first character of the input token or document.
1110 1.1 cgd *
1111 1.1 cgd * Because C does not have internal subroutines, I have simulated them
1112 1.1 cgd * using goto's to implement the subroutine linkage. The following macros
1113 1.1 cgd * will run code that appears at the end of readtoken1.
1114 1.1 cgd */
1115 1.1 cgd
1116 1.96 christos /*
1117 1.96 christos * We used to remember only the current syntax, variable nesting level,
1118 1.102 christos * double quote state for each var nesting level, and arith nesting
1119 1.96 christos * level (unrelated to var nesting) and one prev syntax when in arith
1120 1.96 christos * syntax. This worked for simple cases, but can't handle arith inside
1121 1.96 christos * var expansion inside arith inside var with some quoted and some not.
1122 1.96 christos *
1123 1.96 christos * Inspired by FreeBSD's implementation (though it was the obvious way)
1124 1.96 christos * though implemented differently, we now have a stack that keeps track
1125 1.96 christos * of what we are doing now, and what we were doing previously.
1126 1.96 christos * Every time something changes, which will eventually end and should
1127 1.96 christos * revert to the previous state, we push this stack, and then pop it
1128 1.96 christos * again later (that is every ${} with an operator (to parse the word
1129 1.102 christos * or pattern that follows) ${x} and $x are too simple to need it)
1130 1.96 christos * $(( )) $( ) and "...". Always. Really, always!
1131 1.96 christos *
1132 1.96 christos * The stack is implemented as one static (on the C stack) base block
1133 1.96 christos * containing LEVELS_PER_BLOCK (8) stack entries, which should be
1134 1.96 christos * enough for the vast majority of cases. For torture tests, we
1135 1.96 christos * malloc more blocks as needed. All accesses through the inline
1136 1.96 christos * functions below.
1137 1.96 christos */
1138 1.96 christos
1139 1.96 christos /*
1140 1.96 christos * varnest & arinest will typically be 0 or 1
1141 1.96 christos * (varnest can increment in usages like ${x=${y}} but probably
1142 1.96 christos * does not really need to)
1143 1.96 christos * parenlevel allows balancing parens inside a $(( )), it is reset
1144 1.96 christos * at each new nesting level ( $(( ( x + 3 ${unset-)} )) does not work.
1145 1.96 christos * quoted is special - we need to know 2 things ... are we inside "..."
1146 1.96 christos * (even if inherited from some previous nesting level) and was there
1147 1.96 christos * an opening '"' at this level (so the next will be closing).
1148 1.106 christos * "..." can span nesting levels, but cannot be opened in one and
1149 1.96 christos * closed in a different one.
1150 1.96 christos * To handle this, "quoted" has two fields, the bottom 4 (really 2)
1151 1.96 christos * bits are 0, 1, or 2, for un, single, and double quoted (single quoted
1152 1.96 christos * is really so special that this setting is not very important)
1153 1.96 christos * and 0x10 that indicates that an opening quote has been seen.
1154 1.96 christos * The bottom 4 bits are inherited, the 0x10 bit is not.
1155 1.96 christos */
1156 1.96 christos struct tokenstate {
1157 1.96 christos const char *ts_syntax;
1158 1.96 christos unsigned short ts_parenlevel; /* counters */
1159 1.96 christos unsigned short ts_varnest; /* 64000 levels should be enough! */
1160 1.96 christos unsigned short ts_arinest;
1161 1.96 christos unsigned short ts_quoted; /* 1 -> single, 2 -> double */
1162 1.96 christos };
1163 1.96 christos
1164 1.106 christos #define NQ 0x00 /* Unquoted */
1165 1.106 christos #define SQ 0x01 /* Single Quotes */
1166 1.106 christos #define DQ 0x02 /* Double Quotes (or equivalent) */
1167 1.106 christos #define QF 0x0F /* Mask to extract previous values */
1168 1.106 christos #define QS 0x10 /* Quoting started at this level in stack */
1169 1.96 christos
1170 1.96 christos #define LEVELS_PER_BLOCK 8
1171 1.103 christos #define VSS struct statestack
1172 1.96 christos
1173 1.96 christos struct statestack {
1174 1.96 christos VSS *prev; /* previous block in list */
1175 1.96 christos int cur; /* which of our tokenstates is current */
1176 1.96 christos struct tokenstate tokenstate[LEVELS_PER_BLOCK];
1177 1.96 christos };
1178 1.96 christos
1179 1.103 christos static inline struct tokenstate *
1180 1.96 christos currentstate(VSS *stack)
1181 1.96 christos {
1182 1.96 christos return &stack->tokenstate[stack->cur];
1183 1.96 christos }
1184 1.96 christos
1185 1.103 christos static inline struct tokenstate *
1186 1.96 christos prevstate(VSS *stack)
1187 1.96 christos {
1188 1.96 christos if (stack->cur != 0)
1189 1.96 christos return &stack->tokenstate[stack->cur - 1];
1190 1.96 christos if (stack->prev == NULL) /* cannot drop below base */
1191 1.96 christos return &stack->tokenstate[0];
1192 1.96 christos return &stack->prev->tokenstate[LEVELS_PER_BLOCK - 1];
1193 1.96 christos }
1194 1.96 christos
1195 1.96 christos static inline VSS *
1196 1.96 christos bump_state_level(VSS *stack)
1197 1.96 christos {
1198 1.103 christos struct tokenstate *os, *ts;
1199 1.96 christos
1200 1.96 christos os = currentstate(stack);
1201 1.96 christos
1202 1.96 christos if (++stack->cur >= LEVELS_PER_BLOCK) {
1203 1.96 christos VSS *ss;
1204 1.96 christos
1205 1.96 christos ss = (VSS *)ckmalloc(sizeof (struct statestack));
1206 1.96 christos ss->cur = 0;
1207 1.96 christos ss->prev = stack;
1208 1.96 christos stack = ss;
1209 1.96 christos }
1210 1.96 christos
1211 1.96 christos ts = currentstate(stack);
1212 1.96 christos
1213 1.96 christos ts->ts_parenlevel = 0; /* parens inside never match outside */
1214 1.96 christos
1215 1.96 christos ts->ts_quoted = os->ts_quoted & QF; /* these are default settings */
1216 1.96 christos ts->ts_varnest = os->ts_varnest;
1217 1.96 christos ts->ts_arinest = os->ts_arinest; /* when appropriate */
1218 1.96 christos ts->ts_syntax = os->ts_syntax; /* they will be altered */
1219 1.96 christos
1220 1.96 christos return stack;
1221 1.96 christos }
1222 1.96 christos
1223 1.96 christos static inline VSS *
1224 1.96 christos drop_state_level(VSS *stack)
1225 1.96 christos {
1226 1.96 christos if (stack->cur == 0) {
1227 1.96 christos VSS *ss;
1228 1.96 christos
1229 1.96 christos ss = stack;
1230 1.96 christos stack = ss->prev;
1231 1.96 christos if (stack == NULL)
1232 1.96 christos return ss;
1233 1.106 christos ckfree(ss);
1234 1.96 christos }
1235 1.96 christos --stack->cur;
1236 1.96 christos return stack;
1237 1.96 christos }
1238 1.96 christos
1239 1.96 christos static inline void
1240 1.96 christos cleanup_state_stack(VSS *stack)
1241 1.96 christos {
1242 1.96 christos while (stack->prev != NULL) {
1243 1.96 christos stack->cur = 0;
1244 1.96 christos stack = drop_state_level(stack);
1245 1.96 christos }
1246 1.96 christos }
1247 1.96 christos
1248 1.95 christos #define PARSESUB() {goto parsesub; parsesub_return:;}
1249 1.11 jtc #define PARSEARITH() {goto parsearith; parsearith_return:;}
1250 1.1 cgd
1251 1.52 christos /*
1252 1.96 christos * The following macros all assume the existance of a local var "stack"
1253 1.96 christos * which contains a pointer to the current struct stackstate
1254 1.52 christos */
1255 1.51 christos
1256 1.96 christos /*
1257 1.96 christos * These are macros rather than inline funcs to avoid code churn as much
1258 1.96 christos * as possible - they replace macros of the same name used previously.
1259 1.96 christos */
1260 1.96 christos #define ISDBLQUOTE() (currentstate(stack)->ts_quoted & QS)
1261 1.96 christos #define SETDBLQUOTE() (currentstate(stack)->ts_quoted = QS | DQ)
1262 1.96 christos #define CLRDBLQUOTE() (currentstate(stack)->ts_quoted = \
1263 1.96 christos stack->cur != 0 || stack->prev ? \
1264 1.96 christos prevstate(stack)->ts_quoted & QF : 0)
1265 1.96 christos
1266 1.96 christos /*
1267 1.96 christos * This set are just to avoid excess typing and line lengths...
1268 1.96 christos * The ones that "look like" var names must be implemented to be lvalues
1269 1.96 christos */
1270 1.96 christos #define syntax (currentstate(stack)->ts_syntax)
1271 1.96 christos #define parenlevel (currentstate(stack)->ts_parenlevel)
1272 1.96 christos #define varnest (currentstate(stack)->ts_varnest)
1273 1.96 christos #define arinest (currentstate(stack)->ts_arinest)
1274 1.96 christos #define quoted (currentstate(stack)->ts_quoted)
1275 1.106 christos #define TS_PUSH() (stack = bump_state_level(stack))
1276 1.106 christos #define TS_POP() (stack = drop_state_level(stack))
1277 1.106 christos
1278 1.106 christos /*
1279 1.106 christos * Called to parse command substitutions. oldstyle is true if the command
1280 1.106 christos * is enclosed inside `` (otherwise it was enclosed in "$( )")
1281 1.106 christos *
1282 1.106 christos * Internally nlpp is a pointer to the head of the linked
1283 1.106 christos * list of commands (passed by reference), and savelen is the number of
1284 1.106 christos * characters on the top of the stack which must be preserved.
1285 1.106 christos */
1286 1.106 christos static char *
1287 1.107 christos parsebackq(VSS *const stack, char * const in,
1288 1.106 christos struct nodelist **const pbqlist, const int oldstyle)
1289 1.106 christos {
1290 1.106 christos struct nodelist **nlpp;
1291 1.109 christos const int savepbq = parsebackquote;
1292 1.106 christos union node *n;
1293 1.107 christos char *out;
1294 1.106 christos char *str = NULL;
1295 1.106 christos char *volatile sstr = str;
1296 1.106 christos struct jmploc jmploc;
1297 1.106 christos struct jmploc *const savehandler = handler;
1298 1.109 christos const int savelen = in - stackblock();
1299 1.106 christos int saveprompt;
1300 1.106 christos
1301 1.106 christos if (setjmp(jmploc.loc)) {
1302 1.106 christos if (sstr)
1303 1.106 christos ckfree(__UNVOLATILE(sstr));
1304 1.106 christos cleanup_state_stack(stack);
1305 1.106 christos parsebackquote = 0;
1306 1.106 christos handler = savehandler;
1307 1.106 christos longjmp(handler->loc, 1);
1308 1.106 christos }
1309 1.106 christos INTOFF;
1310 1.106 christos sstr = str = NULL;
1311 1.106 christos if (savelen > 0) {
1312 1.106 christos sstr = str = ckmalloc(savelen);
1313 1.106 christos memcpy(str, stackblock(), savelen);
1314 1.106 christos }
1315 1.106 christos handler = &jmploc;
1316 1.106 christos INTON;
1317 1.126 kre if (oldstyle) {
1318 1.126 kre /* We must read until the closing backquote, giving special
1319 1.126 kre treatment to some slashes, and then push the string and
1320 1.126 kre reread it as input, interpreting it normally. */
1321 1.126 kre int pc;
1322 1.126 kre int psavelen;
1323 1.126 kre char *pstr;
1324 1.106 christos
1325 1.106 christos /*
1326 1.106 christos * Because the entire `...` is read here, we don't
1327 1.106 christos * need to bother the state stack. That will be used
1328 1.106 christos * (as appropriate) when the processed string is re-read.
1329 1.106 christos */
1330 1.126 kre STARTSTACKSTR(out);
1331 1.106 christos for (;;) {
1332 1.106 christos if (needprompt) {
1333 1.106 christos setprompt(2);
1334 1.106 christos needprompt = 0;
1335 1.106 christos }
1336 1.121 kre switch (pc = pgetc_linecont()) {
1337 1.106 christos case '`':
1338 1.106 christos goto done;
1339 1.106 christos
1340 1.106 christos case '\\':
1341 1.126 kre if ((pc = pgetc()) == '\n') {
1342 1.106 christos plinno++;
1343 1.106 christos if (doprompt)
1344 1.106 christos setprompt(2);
1345 1.106 christos else
1346 1.106 christos setprompt(0);
1347 1.106 christos /*
1348 1.106 christos * If eating a newline, avoid putting
1349 1.106 christos * the newline into the new character
1350 1.106 christos * stream (via the STPUTC after the
1351 1.106 christos * switch).
1352 1.106 christos */
1353 1.106 christos continue;
1354 1.106 christos }
1355 1.126 kre if (pc != '\\' && pc != '`' && pc != '$'
1356 1.126 kre && (!ISDBLQUOTE() || pc != '"'))
1357 1.126 kre STPUTC('\\', out);
1358 1.106 christos break;
1359 1.106 christos
1360 1.106 christos case '\n':
1361 1.106 christos plinno++;
1362 1.106 christos needprompt = doprompt;
1363 1.106 christos break;
1364 1.106 christos
1365 1.106 christos case PEOF:
1366 1.106 christos startlinno = plinno;
1367 1.106 christos synerror("EOF in backquote substitution");
1368 1.106 christos break;
1369 1.106 christos
1370 1.106 christos default:
1371 1.106 christos break;
1372 1.106 christos }
1373 1.109 christos STPUTC(pc, out);
1374 1.126 kre }
1375 1.126 kre done:
1376 1.126 kre STPUTC('\0', out);
1377 1.126 kre psavelen = out - stackblock();
1378 1.126 kre if (psavelen > 0) {
1379 1.109 christos pstr = grabstackstr(out);
1380 1.133 kre setinputstring(pstr, 1, startlinno);
1381 1.126 kre }
1382 1.126 kre }
1383 1.106 christos nlpp = pbqlist;
1384 1.106 christos while (*nlpp)
1385 1.106 christos nlpp = &(*nlpp)->next;
1386 1.106 christos *nlpp = stalloc(sizeof(struct nodelist));
1387 1.106 christos (*nlpp)->next = NULL;
1388 1.106 christos parsebackquote = oldstyle;
1389 1.106 christos
1390 1.106 christos if (oldstyle) {
1391 1.106 christos saveprompt = doprompt;
1392 1.106 christos doprompt = 0;
1393 1.106 christos } else
1394 1.106 christos saveprompt = 0;
1395 1.106 christos
1396 1.106 christos n = list(0, oldstyle);
1397 1.106 christos
1398 1.106 christos if (oldstyle)
1399 1.106 christos doprompt = saveprompt;
1400 1.106 christos else {
1401 1.106 christos if (readtoken() != TRP) {
1402 1.106 christos cleanup_state_stack(stack);
1403 1.108 christos synexpect(TRP, 0);
1404 1.106 christos }
1405 1.106 christos }
1406 1.106 christos
1407 1.106 christos (*nlpp)->n = n;
1408 1.126 kre if (oldstyle) {
1409 1.106 christos /*
1410 1.106 christos * Start reading from old file again, ignoring any pushed back
1411 1.106 christos * tokens left from the backquote parsing
1412 1.106 christos */
1413 1.126 kre popfile();
1414 1.106 christos tokpushback = 0;
1415 1.106 christos }
1416 1.109 christos
1417 1.106 christos while (stackblocksize() <= savelen)
1418 1.106 christos growstackblock();
1419 1.109 christos STARTSTACKSTR(out);
1420 1.106 christos if (str) {
1421 1.109 christos memcpy(out, str, savelen);
1422 1.109 christos STADJUST(savelen, out);
1423 1.106 christos INTOFF;
1424 1.106 christos ckfree(str);
1425 1.106 christos sstr = str = NULL;
1426 1.106 christos INTON;
1427 1.106 christos }
1428 1.106 christos parsebackquote = savepbq;
1429 1.106 christos handler = savehandler;
1430 1.106 christos if (arinest || ISDBLQUOTE())
1431 1.109 christos USTPUTC(CTLBACKQ | CTLQUOTE, out);
1432 1.106 christos else
1433 1.109 christos USTPUTC(CTLBACKQ, out);
1434 1.106 christos
1435 1.109 christos return out;
1436 1.106 christos }
1437 1.94 christos
1438 1.112 christos /*
1439 1.112 christos * Parse a redirection operator. The parameter "out" points to a string
1440 1.112 christos * specifying the fd to be redirected. It is guaranteed to be either ""
1441 1.112 christos * or a numeric string (for now anyway). The parameter "c" contains the
1442 1.112 christos * first character of the redirection operator.
1443 1.112 christos *
1444 1.112 christos * Note the string "out" is on the stack, which we are about to clobber,
1445 1.112 christos * so process it first...
1446 1.112 christos */
1447 1.112 christos
1448 1.112 christos static void
1449 1.112 christos parseredir(const char *out, int c)
1450 1.112 christos {
1451 1.112 christos union node *np;
1452 1.112 christos int fd;
1453 1.112 christos
1454 1.112 christos fd = (*out == '\0') ? -1 : atoi(out);
1455 1.112 christos
1456 1.112 christos np = stalloc(sizeof(struct nfile));
1457 1.112 christos if (c == '>') {
1458 1.112 christos if (fd < 0)
1459 1.112 christos fd = 1;
1460 1.121 kre c = pgetc_linecont();
1461 1.112 christos if (c == '>')
1462 1.112 christos np->type = NAPPEND;
1463 1.112 christos else if (c == '|')
1464 1.112 christos np->type = NCLOBBER;
1465 1.112 christos else if (c == '&')
1466 1.112 christos np->type = NTOFD;
1467 1.112 christos else {
1468 1.112 christos np->type = NTO;
1469 1.112 christos pungetc();
1470 1.112 christos }
1471 1.112 christos } else { /* c == '<' */
1472 1.112 christos if (fd < 0)
1473 1.112 christos fd = 0;
1474 1.121 kre switch (c = pgetc_linecont()) {
1475 1.112 christos case '<':
1476 1.112 christos if (sizeof (struct nfile) != sizeof (struct nhere)) {
1477 1.112 christos np = stalloc(sizeof(struct nhere));
1478 1.112 christos np->nfile.fd = 0;
1479 1.112 christos }
1480 1.112 christos np->type = NHERE;
1481 1.112 christos heredoc = stalloc(sizeof(struct heredoc));
1482 1.112 christos heredoc->here = np;
1483 1.116 christos heredoc->startline = plinno;
1484 1.121 kre if ((c = pgetc_linecont()) == '-') {
1485 1.112 christos heredoc->striptabs = 1;
1486 1.112 christos } else {
1487 1.112 christos heredoc->striptabs = 0;
1488 1.112 christos pungetc();
1489 1.112 christos }
1490 1.112 christos break;
1491 1.112 christos
1492 1.112 christos case '&':
1493 1.112 christos np->type = NFROMFD;
1494 1.112 christos break;
1495 1.112 christos
1496 1.112 christos case '>':
1497 1.112 christos np->type = NFROMTO;
1498 1.112 christos break;
1499 1.112 christos
1500 1.112 christos default:
1501 1.112 christos np->type = NFROM;
1502 1.112 christos pungetc();
1503 1.112 christos break;
1504 1.112 christos }
1505 1.112 christos }
1506 1.112 christos np->nfile.fd = fd;
1507 1.112 christos
1508 1.112 christos redirnode = np; /* this is the "value" of TRENODE */
1509 1.112 christos }
1510 1.112 christos
1511 1.112 christos
1512 1.112 christos /*
1513 1.112 christos * The lowest level basic tokenizer.
1514 1.112 christos *
1515 1.112 christos * The next input byte (character) is in firstc, syn says which
1516 1.112 christos * syntax tables we are to use (basic, single or double quoted, or arith)
1517 1.112 christos * and magicq (used with sqsyntax and dqsyntax only) indicates that the
1518 1.112 christos * quote character itself is not special (used parsing here docs and similar)
1519 1.112 christos *
1520 1.112 christos * The result is the type of the next token (its value, when there is one,
1521 1.112 christos * is saved in the relevant global var - must fix that someday!) which is
1522 1.112 christos * also saved for re-reading ("lasttoken").
1523 1.112 christos *
1524 1.112 christos * Overall, this routine does far more parsing than it is supposed to.
1525 1.112 christos * That will also need fixing, someday...
1526 1.112 christos */
1527 1.1 cgd STATIC int
1528 1.111 christos readtoken1(int firstc, char const *syn, int magicq)
1529 1.54 christos {
1530 1.113 christos int c;
1531 1.103 christos char * out;
1532 1.1 cgd int len;
1533 1.1 cgd struct nodelist *bqlist;
1534 1.106 christos int quotef;
1535 1.96 christos VSS static_stack;
1536 1.106 christos VSS *stack = &static_stack;
1537 1.96 christos
1538 1.96 christos stack->prev = NULL;
1539 1.96 christos stack->cur = 0;
1540 1.96 christos
1541 1.96 christos syntax = syn;
1542 1.1 cgd
1543 1.1 cgd startlinno = plinno;
1544 1.51 christos varnest = 0;
1545 1.99 christos quoted = 0;
1546 1.108 christos if (syntax == DQSYNTAX)
1547 1.51 christos SETDBLQUOTE();
1548 1.1 cgd quotef = 0;
1549 1.1 cgd bqlist = NULL;
1550 1.11 jtc arinest = 0;
1551 1.11 jtc parenlevel = 0;
1552 1.11 jtc
1553 1.1 cgd STARTSTACKSTR(out);
1554 1.113 christos
1555 1.113 christos for (c = firstc ;; c = pgetc_macro()) { /* until of token */
1556 1.113 christos CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
1557 1.113 christos switch (syntax[c]) {
1558 1.113 christos case CNL: /* '\n' */
1559 1.113 christos if (syntax == BASESYNTAX)
1560 1.113 christos break; /* exit loop */
1561 1.113 christos USTPUTC(c, out);
1562 1.113 christos plinno++;
1563 1.113 christos if (doprompt)
1564 1.113 christos setprompt(2);
1565 1.113 christos else
1566 1.113 christos setprompt(0);
1567 1.113 christos continue;
1568 1.113 christos
1569 1.113 christos case CWORD:
1570 1.113 christos USTPUTC(c, out);
1571 1.113 christos continue;
1572 1.113 christos case CCTL:
1573 1.113 christos if (!magicq || ISDBLQUOTE())
1574 1.113 christos USTPUTC(CTLESC, out);
1575 1.113 christos USTPUTC(c, out);
1576 1.113 christos continue;
1577 1.113 christos case CBACK: /* backslash */
1578 1.113 christos c = pgetc();
1579 1.113 christos if (c == PEOF) {
1580 1.113 christos USTPUTC('\\', out);
1581 1.113 christos pungetc();
1582 1.113 christos continue;
1583 1.113 christos }
1584 1.113 christos if (c == '\n') {
1585 1.1 cgd plinno++;
1586 1.11 jtc if (doprompt)
1587 1.11 jtc setprompt(2);
1588 1.11 jtc else
1589 1.11 jtc setprompt(0);
1590 1.113 christos continue;
1591 1.113 christos }
1592 1.113 christos quotef = 1; /* current token is quoted */
1593 1.113 christos if (ISDBLQUOTE() && c != '\\' && c != '`' &&
1594 1.113 christos c != '$' && (c != '"' || magicq))
1595 1.113 christos USTPUTC('\\', out);
1596 1.113 christos if (SQSYNTAX[c] == CCTL)
1597 1.113 christos USTPUTC(CTLESC, out);
1598 1.113 christos else if (!magicq) {
1599 1.113 christos USTPUTC(CTLQUOTEMARK, out);
1600 1.59 dsl USTPUTC(c, out);
1601 1.113 christos if (varnest != 0)
1602 1.113 christos USTPUTC(CTLQUOTEEND, out);
1603 1.113 christos continue;
1604 1.113 christos }
1605 1.113 christos USTPUTC(c, out);
1606 1.113 christos continue;
1607 1.113 christos case CSQUOTE:
1608 1.113 christos if (syntax != SQSYNTAX) {
1609 1.113 christos if (!magicq)
1610 1.113 christos USTPUTC(CTLQUOTEMARK, out);
1611 1.113 christos quotef = 1;
1612 1.113 christos TS_PUSH();
1613 1.113 christos syntax = SQSYNTAX;
1614 1.113 christos quoted = SQ;
1615 1.113 christos continue;
1616 1.113 christos }
1617 1.113 christos if (magicq && arinest == 0 && varnest == 0) {
1618 1.113 christos /* Ignore inside quoted here document */
1619 1.1 cgd USTPUTC(c, out);
1620 1.113 christos continue;
1621 1.113 christos }
1622 1.113 christos /* End of single quotes... */
1623 1.113 christos TS_POP();
1624 1.113 christos if (syntax == BASESYNTAX && varnest != 0)
1625 1.113 christos USTPUTC(CTLQUOTEEND, out);
1626 1.113 christos continue;
1627 1.113 christos case CDQUOTE:
1628 1.113 christos if (magicq && arinest == 0 && varnest == 0) {
1629 1.113 christos /* Ignore inside here document */
1630 1.56 dsl USTPUTC(c, out);
1631 1.113 christos continue;
1632 1.113 christos }
1633 1.113 christos quotef = 1;
1634 1.113 christos if (arinest) {
1635 1.56 dsl if (ISDBLQUOTE()) {
1636 1.96 christos TS_POP();
1637 1.1 cgd } else {
1638 1.96 christos TS_PUSH();
1639 1.56 dsl syntax = DQSYNTAX;
1640 1.56 dsl SETDBLQUOTE();
1641 1.56 dsl USTPUTC(CTLQUOTEMARK, out);
1642 1.1 cgd }
1643 1.113 christos continue;
1644 1.113 christos }
1645 1.113 christos if (magicq)
1646 1.113 christos continue;
1647 1.113 christos if (ISDBLQUOTE()) {
1648 1.113 christos TS_POP();
1649 1.113 christos if (varnest != 0)
1650 1.113 christos USTPUTC(CTLQUOTEEND, out);
1651 1.113 christos } else {
1652 1.113 christos TS_PUSH();
1653 1.113 christos syntax = DQSYNTAX;
1654 1.113 christos SETDBLQUOTE();
1655 1.113 christos USTPUTC(CTLQUOTEMARK, out);
1656 1.113 christos }
1657 1.113 christos continue;
1658 1.113 christos case CVAR: /* '$' */
1659 1.113 christos PARSESUB(); /* parse substitution */
1660 1.113 christos continue;
1661 1.113 christos case CENDVAR: /* CLOSEBRACE */
1662 1.113 christos if (varnest > 0 && !ISDBLQUOTE()) {
1663 1.113 christos TS_POP();
1664 1.113 christos USTPUTC(CTLENDVAR, out);
1665 1.113 christos } else {
1666 1.113 christos USTPUTC(c, out);
1667 1.113 christos }
1668 1.113 christos continue;
1669 1.113 christos case CLP: /* '(' in arithmetic */
1670 1.113 christos parenlevel++;
1671 1.113 christos USTPUTC(c, out);
1672 1.113 christos continue;;
1673 1.113 christos case CRP: /* ')' in arithmetic */
1674 1.113 christos if (parenlevel > 0) {
1675 1.11 jtc USTPUTC(c, out);
1676 1.113 christos --parenlevel;
1677 1.113 christos } else {
1678 1.121 kre if (pgetc_linecont() == ')') {
1679 1.113 christos if (--arinest == 0) {
1680 1.113 christos TS_POP();
1681 1.113 christos USTPUTC(CTLENDARI, out);
1682 1.113 christos } else
1683 1.113 christos USTPUTC(')', out);
1684 1.11 jtc } else {
1685 1.113 christos /*
1686 1.113 christos * unbalanced parens
1687 1.113 christos * (don't 2nd guess - no error)
1688 1.113 christos */
1689 1.113 christos pungetc();
1690 1.113 christos USTPUTC(')', out);
1691 1.11 jtc }
1692 1.1 cgd }
1693 1.113 christos continue;
1694 1.113 christos case CBQUOTE: /* '`' */
1695 1.113 christos out = parsebackq(stack, out, &bqlist, 1);
1696 1.113 christos continue;
1697 1.113 christos case CEOF: /* --> c == PEOF */
1698 1.113 christos break; /* will exit loop */
1699 1.113 christos default:
1700 1.113 christos if (varnest == 0 && !ISDBLQUOTE())
1701 1.113 christos break; /* exit loop */
1702 1.113 christos USTPUTC(c, out);
1703 1.113 christos continue;
1704 1.1 cgd }
1705 1.113 christos break; /* break from switch -> break from for loop too */
1706 1.1 cgd }
1707 1.113 christos
1708 1.96 christos if (syntax == ARISYNTAX) {
1709 1.96 christos cleanup_state_stack(stack);
1710 1.11 jtc synerror("Missing '))'");
1711 1.96 christos }
1712 1.111 christos if (syntax != BASESYNTAX && /* ! parsebackquote && */ !magicq) {
1713 1.96 christos cleanup_state_stack(stack);
1714 1.1 cgd synerror("Unterminated quoted string");
1715 1.96 christos }
1716 1.1 cgd if (varnest != 0) {
1717 1.96 christos cleanup_state_stack(stack);
1718 1.1 cgd startlinno = plinno;
1719 1.51 christos /* { */
1720 1.1 cgd synerror("Missing '}'");
1721 1.1 cgd }
1722 1.113 christos
1723 1.1 cgd USTPUTC('\0', out);
1724 1.1 cgd len = out - stackblock();
1725 1.1 cgd out = stackblock();
1726 1.113 christos
1727 1.111 christos if (!magicq) {
1728 1.111 christos if ((c == '<' || c == '>')
1729 1.113 christos && quotef == 0 && (*out == '\0' || is_number(out))) {
1730 1.112 christos parseredir(out, c);
1731 1.96 christos cleanup_state_stack(stack);
1732 1.1 cgd return lasttoken = TREDIR;
1733 1.1 cgd } else {
1734 1.1 cgd pungetc();
1735 1.1 cgd }
1736 1.1 cgd }
1737 1.113 christos
1738 1.1 cgd quoteflag = quotef;
1739 1.1 cgd backquotelist = bqlist;
1740 1.1 cgd grabstackblock(len);
1741 1.1 cgd wordtext = out;
1742 1.96 christos cleanup_state_stack(stack);
1743 1.1 cgd return lasttoken = TWORD;
1744 1.1 cgd /* end of readtoken routine */
1745 1.1 cgd
1746 1.1 cgd
1747 1.1 cgd /*
1748 1.1 cgd * Parse a substitution. At this point, we have read the dollar sign
1749 1.1 cgd * and nothing else.
1750 1.1 cgd */
1751 1.1 cgd
1752 1.1 cgd parsesub: {
1753 1.84 christos char buf[10];
1754 1.1 cgd int subtype;
1755 1.1 cgd int typeloc;
1756 1.1 cgd int flags;
1757 1.1 cgd char *p;
1758 1.1 cgd static const char types[] = "}-+?=";
1759 1.84 christos int i;
1760 1.84 christos int linno;
1761 1.1 cgd
1762 1.121 kre c = pgetc_linecont();
1763 1.51 christos if (c != '(' && c != OPENBRACE && !is_name(c) && !is_special(c)) {
1764 1.1 cgd USTPUTC('$', out);
1765 1.1 cgd pungetc();
1766 1.11 jtc } else if (c == '(') { /* $(command) or $((arith)) */
1767 1.121 kre if (pgetc_linecont() == '(') {
1768 1.11 jtc PARSEARITH();
1769 1.11 jtc } else {
1770 1.11 jtc pungetc();
1771 1.106 christos out = parsebackq(stack, out, &bqlist, 0);
1772 1.11 jtc }
1773 1.1 cgd } else {
1774 1.1 cgd USTPUTC(CTLVAR, out);
1775 1.1 cgd typeloc = out - stackblock();
1776 1.1 cgd USTPUTC(VSNORMAL, out);
1777 1.1 cgd subtype = VSNORMAL;
1778 1.84 christos flags = 0;
1779 1.51 christos if (c == OPENBRACE) {
1780 1.121 kre c = pgetc_linecont();
1781 1.23 christos if (c == '#') {
1782 1.127 kre if ((c = pgetc_linecont()) == CLOSEBRACE)
1783 1.26 christos c = '#';
1784 1.127 kre else if (is_name(c) || isdigit(c))
1785 1.26 christos subtype = VSLENGTH;
1786 1.127 kre else if (is_special(c)) {
1787 1.127 kre /*
1788 1.128 kre * ${#} is $# - the number of sh params
1789 1.127 kre * ${##} is the length of ${#}
1790 1.128 kre * ${###} is ${#} with as much nothing
1791 1.128 kre * as possible removed from start
1792 1.127 kre * ${##1} is ${#} with leading 1 gone
1793 1.128 kre * ${##\#} is ${#} with leading # gone
1794 1.127 kre *
1795 1.127 kre * this stuff is UGLY!
1796 1.127 kre */
1797 1.127 kre if (pgetc_linecont() == CLOSEBRACE) {
1798 1.127 kre pungetc();
1799 1.127 kre subtype = VSLENGTH;
1800 1.127 kre } else {
1801 1.127 kre static char cbuf[2];
1802 1.128 kre
1803 1.128 kre pungetc(); /* would like 2 */
1804 1.128 kre cbuf[0] = c; /* so ... */
1805 1.127 kre cbuf[1] = '\0';
1806 1.127 kre pushstring(cbuf, 1, NULL);
1807 1.128 kre c = '#'; /* ${#:...} */
1808 1.128 kre subtype = 0; /* .. or similar */
1809 1.127 kre }
1810 1.127 kre } else {
1811 1.127 kre pungetc();
1812 1.127 kre c = '#';
1813 1.127 kre subtype = 0;
1814 1.127 kre }
1815 1.23 christos }
1816 1.23 christos else
1817 1.23 christos subtype = 0;
1818 1.1 cgd }
1819 1.1 cgd if (is_name(c)) {
1820 1.84 christos p = out;
1821 1.1 cgd do {
1822 1.1 cgd STPUTC(c, out);
1823 1.121 kre c = pgetc_linecont();
1824 1.1 cgd } while (is_in_name(c));
1825 1.84 christos if (out - p == 6 && strncmp(p, "LINENO", 6) == 0) {
1826 1.84 christos /* Replace the variable name with the
1827 1.84 christos * current line number. */
1828 1.84 christos linno = plinno;
1829 1.84 christos if (funclinno != 0)
1830 1.84 christos linno -= funclinno - 1;
1831 1.84 christos snprintf(buf, sizeof(buf), "%d", linno);
1832 1.84 christos STADJUST(-6, out);
1833 1.84 christos for (i = 0; buf[i] != '\0'; i++)
1834 1.84 christos STPUTC(buf[i], out);
1835 1.84 christos flags |= VSLINENO;
1836 1.84 christos }
1837 1.34 christos } else if (is_digit(c)) {
1838 1.33 christos do {
1839 1.33 christos USTPUTC(c, out);
1840 1.121 kre c = pgetc_linecont();
1841 1.114 christos } while (subtype != VSNORMAL && is_digit(c));
1842 1.34 christos }
1843 1.34 christos else if (is_special(c)) {
1844 1.34 christos USTPUTC(c, out);
1845 1.121 kre c = pgetc_linecont();
1846 1.1 cgd }
1847 1.96 christos else {
1848 1.126 kre badsub:
1849 1.96 christos cleanup_state_stack(stack);
1850 1.96 christos synerror("Bad substitution");
1851 1.96 christos }
1852 1.33 christos
1853 1.1 cgd STPUTC('=', out);
1854 1.1 cgd if (subtype == 0) {
1855 1.23 christos switch (c) {
1856 1.23 christos case ':':
1857 1.84 christos flags |= VSNUL;
1858 1.121 kre c = pgetc_linecont();
1859 1.23 christos /*FALLTHROUGH*/
1860 1.23 christos default:
1861 1.23 christos p = strchr(types, c);
1862 1.23 christos if (p == NULL)
1863 1.23 christos goto badsub;
1864 1.23 christos subtype = p - types + VSNORMAL;
1865 1.23 christos break;
1866 1.23 christos case '%':
1867 1.30 christos case '#':
1868 1.23 christos {
1869 1.23 christos int cc = c;
1870 1.23 christos subtype = c == '#' ? VSTRIMLEFT :
1871 1.23 christos VSTRIMRIGHT;
1872 1.121 kre c = pgetc_linecont();
1873 1.23 christos if (c == cc)
1874 1.23 christos subtype++;
1875 1.23 christos else
1876 1.23 christos pungetc();
1877 1.23 christos break;
1878 1.23 christos }
1879 1.1 cgd }
1880 1.1 cgd } else {
1881 1.127 kre if (subtype == VSLENGTH && c != /*{*/ '}')
1882 1.127 kre synerror("no modifiers allowed with ${#var}");
1883 1.1 cgd pungetc();
1884 1.1 cgd }
1885 1.51 christos if (ISDBLQUOTE() || arinest)
1886 1.1 cgd flags |= VSQUOTE;
1887 1.98 christos if (subtype >= VSTRIMLEFT && subtype <= VSTRIMRIGHTMAX)
1888 1.98 christos flags |= VSPATQ;
1889 1.1 cgd *(stackblock() + typeloc) = subtype | flags;
1890 1.96 christos if (subtype != VSNORMAL) {
1891 1.96 christos TS_PUSH();
1892 1.96 christos varnest++;
1893 1.96 christos arinest = 0;
1894 1.96 christos if (subtype > VSASSIGN) { /* # ## % %% */
1895 1.96 christos syntax = BASESYNTAX;
1896 1.96 christos CLRDBLQUOTE();
1897 1.96 christos }
1898 1.96 christos }
1899 1.1 cgd }
1900 1.1 cgd goto parsesub_return;
1901 1.1 cgd }
1902 1.1 cgd
1903 1.1 cgd
1904 1.1 cgd /*
1905 1.11 jtc * Parse an arithmetic expansion (indicate start of one and set state)
1906 1.1 cgd */
1907 1.11 jtc parsearith: {
1908 1.1 cgd
1909 1.131 kre #if 0
1910 1.96 christos if (syntax == ARISYNTAX) {
1911 1.96 christos /*
1912 1.96 christos * we collapse embedded arithmetic expansion to
1913 1.96 christos * parentheses, which should be equivalent
1914 1.96 christos */
1915 1.96 christos USTPUTC('(', out);
1916 1.96 christos USTPUTC('(', out);
1917 1.96 christos /*
1918 1.96 christos * Need 2 of them because there will (should be)
1919 1.96 christos * two closing ))'s to follow later.
1920 1.96 christos */
1921 1.96 christos parenlevel += 2;
1922 1.131 kre } else
1923 1.131 kre #endif
1924 1.131 kre {
1925 1.11 jtc USTPUTC(CTLARI, out);
1926 1.51 christos if (ISDBLQUOTE())
1927 1.41 mycroft USTPUTC('"',out);
1928 1.41 mycroft else
1929 1.41 mycroft USTPUTC(' ',out);
1930 1.131 kre
1931 1.132 kre TS_PUSH();
1932 1.132 kre syntax = ARISYNTAX;
1933 1.132 kre arinest = 1;
1934 1.132 kre varnest = 0;
1935 1.1 cgd }
1936 1.11 jtc goto parsearith_return;
1937 1.1 cgd }
1938 1.1 cgd
1939 1.11 jtc } /* end of readtoken */
1940 1.1 cgd
1941 1.1 cgd
1942 1.1 cgd
1943 1.11 jtc #ifdef mkinit
1944 1.11 jtc RESET {
1945 1.11 jtc tokpushback = 0;
1946 1.11 jtc checkkwd = 0;
1947 1.1 cgd }
1948 1.1 cgd #endif
1949 1.1 cgd
1950 1.1 cgd /*
1951 1.1 cgd * Returns true if the text contains nothing to expand (no dollar signs
1952 1.1 cgd * or backquotes).
1953 1.1 cgd */
1954 1.1 cgd
1955 1.1 cgd STATIC int
1956 1.54 christos noexpand(char *text)
1957 1.54 christos {
1958 1.32 tls char *p;
1959 1.32 tls char c;
1960 1.1 cgd
1961 1.1 cgd p = text;
1962 1.1 cgd while ((c = *p++) != '\0') {
1963 1.41 mycroft if (c == CTLQUOTEMARK)
1964 1.41 mycroft continue;
1965 1.1 cgd if (c == CTLESC)
1966 1.1 cgd p++;
1967 1.38 mrg else if (BASESYNTAX[(int)c] == CCTL)
1968 1.1 cgd return 0;
1969 1.1 cgd }
1970 1.1 cgd return 1;
1971 1.1 cgd }
1972 1.1 cgd
1973 1.1 cgd
1974 1.1 cgd /*
1975 1.1 cgd * Return true if the argument is a legal variable name (a letter or
1976 1.1 cgd * underscore followed by zero or more letters, underscores, and digits).
1977 1.1 cgd */
1978 1.1 cgd
1979 1.1 cgd int
1980 1.45 cgd goodname(char *name)
1981 1.108 christos {
1982 1.32 tls char *p;
1983 1.1 cgd
1984 1.1 cgd p = name;
1985 1.1 cgd if (! is_name(*p))
1986 1.1 cgd return 0;
1987 1.1 cgd while (*++p) {
1988 1.1 cgd if (! is_in_name(*p))
1989 1.1 cgd return 0;
1990 1.1 cgd }
1991 1.1 cgd return 1;
1992 1.1 cgd }
1993 1.1 cgd
1994 1.1 cgd
1995 1.1 cgd /*
1996 1.1 cgd * Called when an unexpected token is read during the parse. The argument
1997 1.1 cgd * is the token that is expected, or -1 if more than one type of token can
1998 1.1 cgd * occur at this point.
1999 1.1 cgd */
2000 1.1 cgd
2001 1.1 cgd STATIC void
2002 1.108 christos synexpect(int token, const char *text)
2003 1.22 cgd {
2004 1.1 cgd char msg[64];
2005 1.108 christos char *p;
2006 1.108 christos
2007 1.108 christos if (lasttoken == TWORD) {
2008 1.108 christos size_t len = strlen(wordtext);
2009 1.108 christos
2010 1.108 christos if (len <= 13)
2011 1.108 christos fmtstr(msg, 34, "Word \"%.13s\" unexpected", wordtext);
2012 1.108 christos else
2013 1.108 christos fmtstr(msg, 34,
2014 1.108 christos "Word \"%.10s...\" unexpected", wordtext);
2015 1.108 christos } else
2016 1.108 christos fmtstr(msg, 34, "%s unexpected", tokname[lasttoken]);
2017 1.108 christos
2018 1.108 christos p = strchr(msg, '\0');
2019 1.108 christos if (text)
2020 1.108 christos fmtstr(p, 30, " (expecting \"%.10s\")", text);
2021 1.108 christos else if (token >= 0)
2022 1.108 christos fmtstr(p, 30, " (expecting %s)", tokname[token]);
2023 1.1 cgd
2024 1.1 cgd synerror(msg);
2025 1.39 mycroft /* NOTREACHED */
2026 1.1 cgd }
2027 1.1 cgd
2028 1.1 cgd
2029 1.1 cgd STATIC void
2030 1.54 christos synerror(const char *msg)
2031 1.54 christos {
2032 1.124 kre error("%d: Syntax error: %s", startlinno, msg);
2033 1.39 mycroft /* NOTREACHED */
2034 1.11 jtc }
2035 1.11 jtc
2036 1.11 jtc STATIC void
2037 1.54 christos setprompt(int which)
2038 1.54 christos {
2039 1.11 jtc whichprompt = which;
2040 1.11 jtc
2041 1.35 christos #ifndef SMALL
2042 1.11 jtc if (!el)
2043 1.14 cgd #endif
2044 1.11 jtc out2str(getprompt(NULL));
2045 1.11 jtc }
2046 1.11 jtc
2047 1.11 jtc /*
2048 1.121 kre * handle getting the next character, while ignoring \ \n
2049 1.121 kre * (which is a little tricky as we only have one char of pushback
2050 1.121 kre * and we need that one elsewhere).
2051 1.121 kre */
2052 1.121 kre STATIC int
2053 1.121 kre pgetc_linecont(void)
2054 1.121 kre {
2055 1.121 kre int c;
2056 1.121 kre
2057 1.121 kre while ((c = pgetc_macro()) == '\\') {
2058 1.121 kre c = pgetc();
2059 1.121 kre if (c == '\n') {
2060 1.121 kre plinno++;
2061 1.121 kre if (doprompt)
2062 1.121 kre setprompt(2);
2063 1.121 kre else
2064 1.121 kre setprompt(0);
2065 1.121 kre } else {
2066 1.121 kre pungetc();
2067 1.121 kre /* Allow the backslash to be pushed back. */
2068 1.121 kre pushstring("\\", 1, NULL);
2069 1.121 kre return (pgetc());
2070 1.121 kre }
2071 1.121 kre }
2072 1.121 kre return (c);
2073 1.121 kre }
2074 1.121 kre
2075 1.121 kre /*
2076 1.11 jtc * called by editline -- any expansions to the prompt
2077 1.11 jtc * should be added here.
2078 1.11 jtc */
2079 1.43 christos const char *
2080 1.45 cgd getprompt(void *unused)
2081 1.108 christos {
2082 1.11 jtc switch (whichprompt) {
2083 1.11 jtc case 0:
2084 1.11 jtc return "";
2085 1.11 jtc case 1:
2086 1.11 jtc return ps1val();
2087 1.11 jtc case 2:
2088 1.11 jtc return ps2val();
2089 1.11 jtc default:
2090 1.11 jtc return "<internal prompt error>";
2091 1.11 jtc }
2092 1.1 cgd }
2093