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