parser.c revision 1.30 1 1.30 christos /* $NetBSD: parser.c,v 1.30 1996/10/16 14:53:23 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.1 cgd * 3. All advertising materials mentioning features or use of this software
19 1.1 cgd * must display the following acknowledgement:
20 1.1 cgd * This product includes software developed by the University of
21 1.1 cgd * California, Berkeley and its contributors.
22 1.1 cgd * 4. Neither the name of the University nor the names of its contributors
23 1.1 cgd * may be used to endorse or promote products derived from this software
24 1.1 cgd * without specific prior written permission.
25 1.1 cgd *
26 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 1.1 cgd * SUCH DAMAGE.
37 1.1 cgd */
38 1.1 cgd
39 1.1 cgd #ifndef lint
40 1.24 cgd #if 0
41 1.26 christos static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95";
42 1.24 cgd #else
43 1.30 christos static char rcsid[] = "$NetBSD: parser.c,v 1.30 1996/10/16 14:53:23 christos Exp $";
44 1.24 cgd #endif
45 1.1 cgd #endif /* not lint */
46 1.1 cgd
47 1.25 christos #include <stdlib.h>
48 1.25 christos
49 1.1 cgd #include "shell.h"
50 1.1 cgd #include "parser.h"
51 1.1 cgd #include "nodes.h"
52 1.1 cgd #include "expand.h" /* defines rmescapes() */
53 1.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.14 cgd #ifndef NO_HISTORY
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.1 cgd
78 1.1 cgd
79 1.1 cgd struct heredoc {
80 1.1 cgd struct heredoc *next; /* next here document in list */
81 1.1 cgd union node *here; /* redirection node */
82 1.1 cgd char *eofmark; /* string indicating end of input */
83 1.1 cgd int striptabs; /* if set, strip leading tabs */
84 1.1 cgd };
85 1.1 cgd
86 1.1 cgd
87 1.1 cgd
88 1.1 cgd struct heredoc *heredoclist; /* list of here documents to read */
89 1.1 cgd int parsebackquote; /* nonzero if we are inside backquotes */
90 1.1 cgd int doprompt; /* if set, prompt the user */
91 1.1 cgd int needprompt; /* true if interactive and at start of line */
92 1.1 cgd int lasttoken; /* last token read */
93 1.1 cgd MKINIT int tokpushback; /* last token pushed back */
94 1.1 cgd char *wordtext; /* text of last word returned by readtoken */
95 1.11 jtc MKINIT int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
96 1.1 cgd struct nodelist *backquotelist;
97 1.1 cgd union node *redirnode;
98 1.1 cgd struct heredoc *heredoc;
99 1.1 cgd int quoteflag; /* set if (part of) last token was quoted */
100 1.1 cgd int startlinno; /* line # where last token started */
101 1.1 cgd
102 1.1 cgd
103 1.1 cgd #define GDB_HACK 1 /* avoid local declarations which gdb can't handle */
104 1.1 cgd #ifdef GDB_HACK
105 1.1 cgd static const char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'};
106 1.1 cgd static const char types[] = "}-+?=";
107 1.1 cgd #endif
108 1.1 cgd
109 1.1 cgd
110 1.1 cgd STATIC union node *list __P((int));
111 1.1 cgd STATIC union node *andor __P((void));
112 1.1 cgd STATIC union node *pipeline __P((void));
113 1.1 cgd STATIC union node *command __P((void));
114 1.5 sef STATIC union node *simplecmd __P((union node **, union node *));
115 1.18 jtc STATIC union node *makename __P((void));
116 1.1 cgd STATIC void parsefname __P((void));
117 1.1 cgd STATIC void parseheredoc __P((void));
118 1.25 christos STATIC int peektoken __P((void));
119 1.1 cgd STATIC int readtoken __P((void));
120 1.25 christos STATIC int xxreadtoken __P((void));
121 1.1 cgd STATIC int readtoken1 __P((int, char const *, char *, int));
122 1.1 cgd STATIC int noexpand __P((char *));
123 1.1 cgd STATIC void synexpect __P((int));
124 1.1 cgd STATIC void synerror __P((char *));
125 1.30 christos STATIC void setprompt __P((int));
126 1.1 cgd
127 1.22 cgd
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.30 christos parsecmd(interact)
135 1.22 cgd int interact;
136 1.22 cgd {
137 1.1 cgd int t;
138 1.1 cgd
139 1.1 cgd doprompt = interact;
140 1.1 cgd if (doprompt)
141 1.11 jtc setprompt(1);
142 1.11 jtc else
143 1.11 jtc setprompt(0);
144 1.1 cgd needprompt = 0;
145 1.11 jtc t = readtoken();
146 1.11 jtc if (t == TEOF)
147 1.1 cgd return NEOF;
148 1.1 cgd if (t == TNL)
149 1.1 cgd return NULL;
150 1.1 cgd tokpushback++;
151 1.1 cgd return list(1);
152 1.1 cgd }
153 1.1 cgd
154 1.1 cgd
155 1.1 cgd STATIC union node *
156 1.30 christos list(nlflag)
157 1.22 cgd int nlflag;
158 1.22 cgd {
159 1.1 cgd union node *n1, *n2, *n3;
160 1.12 jtc int tok;
161 1.1 cgd
162 1.1 cgd checkkwd = 2;
163 1.1 cgd if (nlflag == 0 && tokendlist[peektoken()])
164 1.1 cgd return NULL;
165 1.12 jtc n1 = NULL;
166 1.1 cgd for (;;) {
167 1.12 jtc n2 = andor();
168 1.12 jtc tok = readtoken();
169 1.12 jtc if (tok == TBACKGND) {
170 1.12 jtc if (n2->type == NCMD || n2->type == NPIPE) {
171 1.12 jtc n2->ncmd.backgnd = 1;
172 1.12 jtc } else if (n2->type == NREDIR) {
173 1.12 jtc n2->type = NBACKGND;
174 1.1 cgd } else {
175 1.1 cgd n3 = (union node *)stalloc(sizeof (struct nredir));
176 1.1 cgd n3->type = NBACKGND;
177 1.12 jtc n3->nredir.n = n2;
178 1.1 cgd n3->nredir.redirect = NULL;
179 1.12 jtc n2 = n3;
180 1.1 cgd }
181 1.12 jtc }
182 1.12 jtc if (n1 == NULL) {
183 1.12 jtc n1 = n2;
184 1.12 jtc }
185 1.12 jtc else {
186 1.12 jtc n3 = (union node *)stalloc(sizeof (struct nbinary));
187 1.12 jtc n3->type = NSEMI;
188 1.12 jtc n3->nbinary.ch1 = n1;
189 1.12 jtc n3->nbinary.ch2 = n2;
190 1.12 jtc n1 = n3;
191 1.12 jtc }
192 1.12 jtc switch (tok) {
193 1.12 jtc case TBACKGND:
194 1.12 jtc case TSEMI:
195 1.12 jtc tok = readtoken();
196 1.12 jtc /* fall through */
197 1.1 cgd case TNL:
198 1.12 jtc if (tok == TNL) {
199 1.1 cgd parseheredoc();
200 1.1 cgd if (nlflag)
201 1.1 cgd return n1;
202 1.1 cgd } else {
203 1.1 cgd tokpushback++;
204 1.1 cgd }
205 1.1 cgd checkkwd = 2;
206 1.1 cgd if (tokendlist[peektoken()])
207 1.1 cgd return n1;
208 1.1 cgd break;
209 1.1 cgd case TEOF:
210 1.1 cgd if (heredoclist)
211 1.1 cgd parseheredoc();
212 1.1 cgd else
213 1.1 cgd pungetc(); /* push back EOF on input */
214 1.1 cgd return n1;
215 1.1 cgd default:
216 1.1 cgd if (nlflag)
217 1.1 cgd synexpect(-1);
218 1.1 cgd tokpushback++;
219 1.1 cgd return n1;
220 1.1 cgd }
221 1.1 cgd }
222 1.1 cgd }
223 1.1 cgd
224 1.1 cgd
225 1.1 cgd
226 1.1 cgd STATIC union node *
227 1.1 cgd andor() {
228 1.1 cgd union node *n1, *n2, *n3;
229 1.1 cgd int t;
230 1.1 cgd
231 1.1 cgd n1 = pipeline();
232 1.1 cgd for (;;) {
233 1.1 cgd if ((t = readtoken()) == TAND) {
234 1.1 cgd t = NAND;
235 1.1 cgd } else if (t == TOR) {
236 1.1 cgd t = NOR;
237 1.1 cgd } else {
238 1.1 cgd tokpushback++;
239 1.1 cgd return n1;
240 1.1 cgd }
241 1.1 cgd n2 = pipeline();
242 1.1 cgd n3 = (union node *)stalloc(sizeof (struct nbinary));
243 1.1 cgd n3->type = t;
244 1.1 cgd n3->nbinary.ch1 = n1;
245 1.1 cgd n3->nbinary.ch2 = n2;
246 1.1 cgd n1 = n3;
247 1.1 cgd }
248 1.1 cgd }
249 1.1 cgd
250 1.1 cgd
251 1.1 cgd
252 1.1 cgd STATIC union node *
253 1.1 cgd pipeline() {
254 1.11 jtc union node *n1, *pipenode, *notnode;
255 1.1 cgd struct nodelist *lp, *prev;
256 1.11 jtc int negate = 0;
257 1.1 cgd
258 1.11 jtc TRACE(("pipeline: entered\n"));
259 1.11 jtc while (readtoken() == TNOT) {
260 1.11 jtc TRACE(("pipeline: TNOT recognized\n"));
261 1.11 jtc negate = !negate;
262 1.11 jtc }
263 1.11 jtc tokpushback++;
264 1.1 cgd n1 = command();
265 1.1 cgd if (readtoken() == TPIPE) {
266 1.1 cgd pipenode = (union node *)stalloc(sizeof (struct npipe));
267 1.1 cgd pipenode->type = NPIPE;
268 1.1 cgd pipenode->npipe.backgnd = 0;
269 1.1 cgd lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
270 1.1 cgd pipenode->npipe.cmdlist = lp;
271 1.1 cgd lp->n = n1;
272 1.1 cgd do {
273 1.1 cgd prev = lp;
274 1.1 cgd lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
275 1.1 cgd lp->n = command();
276 1.1 cgd prev->next = lp;
277 1.1 cgd } while (readtoken() == TPIPE);
278 1.1 cgd lp->next = NULL;
279 1.1 cgd n1 = pipenode;
280 1.1 cgd }
281 1.1 cgd tokpushback++;
282 1.11 jtc if (negate) {
283 1.11 jtc notnode = (union node *)stalloc(sizeof (struct nnot));
284 1.11 jtc notnode->type = NNOT;
285 1.11 jtc notnode->nnot.com = n1;
286 1.11 jtc n1 = notnode;
287 1.11 jtc }
288 1.1 cgd return n1;
289 1.1 cgd }
290 1.1 cgd
291 1.1 cgd
292 1.1 cgd
293 1.1 cgd STATIC union node *
294 1.1 cgd command() {
295 1.1 cgd union node *n1, *n2;
296 1.1 cgd union node *ap, **app;
297 1.1 cgd union node *cp, **cpp;
298 1.1 cgd union node *redir, **rpp;
299 1.1 cgd int t;
300 1.1 cgd
301 1.1 cgd checkkwd = 2;
302 1.25 christos redir = NULL;
303 1.25 christos n1 = NULL;
304 1.5 sef rpp = &redir;
305 1.5 sef /* Check for redirection which may precede command */
306 1.5 sef while (readtoken() == TREDIR) {
307 1.5 sef *rpp = n2 = redirnode;
308 1.5 sef rpp = &n2->nfile.next;
309 1.5 sef parsefname();
310 1.5 sef }
311 1.5 sef tokpushback++;
312 1.5 sef
313 1.1 cgd switch (readtoken()) {
314 1.1 cgd case TIF:
315 1.1 cgd n1 = (union node *)stalloc(sizeof (struct nif));
316 1.1 cgd n1->type = NIF;
317 1.1 cgd n1->nif.test = list(0);
318 1.1 cgd if (readtoken() != TTHEN)
319 1.1 cgd synexpect(TTHEN);
320 1.1 cgd n1->nif.ifpart = list(0);
321 1.1 cgd n2 = n1;
322 1.1 cgd while (readtoken() == TELIF) {
323 1.1 cgd n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
324 1.1 cgd n2 = n2->nif.elsepart;
325 1.1 cgd n2->type = NIF;
326 1.1 cgd n2->nif.test = list(0);
327 1.1 cgd if (readtoken() != TTHEN)
328 1.1 cgd synexpect(TTHEN);
329 1.1 cgd n2->nif.ifpart = list(0);
330 1.1 cgd }
331 1.1 cgd if (lasttoken == TELSE)
332 1.1 cgd n2->nif.elsepart = list(0);
333 1.1 cgd else {
334 1.1 cgd n2->nif.elsepart = NULL;
335 1.1 cgd tokpushback++;
336 1.1 cgd }
337 1.1 cgd if (readtoken() != TFI)
338 1.1 cgd synexpect(TFI);
339 1.1 cgd checkkwd = 1;
340 1.1 cgd break;
341 1.1 cgd case TWHILE:
342 1.1 cgd case TUNTIL: {
343 1.1 cgd int got;
344 1.1 cgd n1 = (union node *)stalloc(sizeof (struct nbinary));
345 1.1 cgd n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
346 1.1 cgd n1->nbinary.ch1 = list(0);
347 1.1 cgd if ((got=readtoken()) != TDO) {
348 1.1 cgd TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
349 1.1 cgd synexpect(TDO);
350 1.1 cgd }
351 1.1 cgd n1->nbinary.ch2 = list(0);
352 1.1 cgd if (readtoken() != TDONE)
353 1.1 cgd synexpect(TDONE);
354 1.1 cgd checkkwd = 1;
355 1.1 cgd break;
356 1.1 cgd }
357 1.1 cgd case TFOR:
358 1.1 cgd if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
359 1.1 cgd synerror("Bad for loop variable");
360 1.1 cgd n1 = (union node *)stalloc(sizeof (struct nfor));
361 1.1 cgd n1->type = NFOR;
362 1.1 cgd n1->nfor.var = wordtext;
363 1.1 cgd if (readtoken() == TWORD && ! quoteflag && equal(wordtext, "in")) {
364 1.1 cgd app = ≈
365 1.1 cgd while (readtoken() == TWORD) {
366 1.1 cgd n2 = (union node *)stalloc(sizeof (struct narg));
367 1.1 cgd n2->type = NARG;
368 1.1 cgd n2->narg.text = wordtext;
369 1.1 cgd n2->narg.backquote = backquotelist;
370 1.1 cgd *app = n2;
371 1.1 cgd app = &n2->narg.next;
372 1.1 cgd }
373 1.1 cgd *app = NULL;
374 1.1 cgd n1->nfor.args = ap;
375 1.5 sef if (lasttoken != TNL && lasttoken != TSEMI)
376 1.5 sef synexpect(-1);
377 1.1 cgd } else {
378 1.1 cgd #ifndef GDB_HACK
379 1.1 cgd static const char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
380 1.1 cgd '@', '=', '\0'};
381 1.1 cgd #endif
382 1.1 cgd n2 = (union node *)stalloc(sizeof (struct narg));
383 1.1 cgd n2->type = NARG;
384 1.1 cgd n2->narg.text = (char *)argvars;
385 1.1 cgd n2->narg.backquote = NULL;
386 1.1 cgd n2->narg.next = NULL;
387 1.1 cgd n1->nfor.args = n2;
388 1.11 jtc /*
389 1.11 jtc * Newline or semicolon here is optional (but note
390 1.11 jtc * that the original Bourne shell only allowed NL).
391 1.11 jtc */
392 1.11 jtc if (lasttoken != TNL && lasttoken != TSEMI)
393 1.11 jtc tokpushback++;
394 1.1 cgd }
395 1.1 cgd checkkwd = 2;
396 1.1 cgd if ((t = readtoken()) == TDO)
397 1.1 cgd t = TDONE;
398 1.1 cgd else if (t == TBEGIN)
399 1.1 cgd t = TEND;
400 1.1 cgd else
401 1.1 cgd synexpect(-1);
402 1.1 cgd n1->nfor.body = list(0);
403 1.1 cgd if (readtoken() != t)
404 1.1 cgd synexpect(t);
405 1.1 cgd checkkwd = 1;
406 1.1 cgd break;
407 1.1 cgd case TCASE:
408 1.1 cgd n1 = (union node *)stalloc(sizeof (struct ncase));
409 1.1 cgd n1->type = NCASE;
410 1.1 cgd if (readtoken() != TWORD)
411 1.1 cgd synexpect(TWORD);
412 1.1 cgd n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
413 1.1 cgd n2->type = NARG;
414 1.1 cgd n2->narg.text = wordtext;
415 1.1 cgd n2->narg.backquote = backquotelist;
416 1.1 cgd n2->narg.next = NULL;
417 1.1 cgd while (readtoken() == TNL);
418 1.1 cgd if (lasttoken != TWORD || ! equal(wordtext, "in"))
419 1.1 cgd synerror("expecting \"in\"");
420 1.1 cgd cpp = &n1->ncase.cases;
421 1.15 jtc checkkwd = 2, readtoken();
422 1.15 jtc do {
423 1.1 cgd *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
424 1.1 cgd cp->type = NCLIST;
425 1.1 cgd app = &cp->nclist.pattern;
426 1.1 cgd for (;;) {
427 1.1 cgd *app = ap = (union node *)stalloc(sizeof (struct narg));
428 1.1 cgd ap->type = NARG;
429 1.1 cgd ap->narg.text = wordtext;
430 1.1 cgd ap->narg.backquote = backquotelist;
431 1.15 jtc if (checkkwd = 2, readtoken() != TPIPE)
432 1.1 cgd break;
433 1.1 cgd app = &ap->narg.next;
434 1.16 jtc readtoken();
435 1.1 cgd }
436 1.1 cgd ap->narg.next = NULL;
437 1.1 cgd if (lasttoken != TRP)
438 1.1 cgd synexpect(TRP);
439 1.1 cgd cp->nclist.body = list(0);
440 1.15 jtc
441 1.15 jtc checkkwd = 2;
442 1.15 jtc if ((t = readtoken()) != TESAC) {
443 1.15 jtc if (t != TENDCASE)
444 1.15 jtc synexpect(TENDCASE);
445 1.15 jtc else
446 1.15 jtc checkkwd = 2, readtoken();
447 1.15 jtc }
448 1.1 cgd cpp = &cp->nclist.next;
449 1.15 jtc } while(lasttoken != TESAC);
450 1.1 cgd *cpp = NULL;
451 1.1 cgd checkkwd = 1;
452 1.1 cgd break;
453 1.1 cgd case TLP:
454 1.1 cgd n1 = (union node *)stalloc(sizeof (struct nredir));
455 1.1 cgd n1->type = NSUBSHELL;
456 1.1 cgd n1->nredir.n = list(0);
457 1.1 cgd n1->nredir.redirect = NULL;
458 1.1 cgd if (readtoken() != TRP)
459 1.1 cgd synexpect(TRP);
460 1.1 cgd checkkwd = 1;
461 1.1 cgd break;
462 1.1 cgd case TBEGIN:
463 1.1 cgd n1 = list(0);
464 1.1 cgd if (readtoken() != TEND)
465 1.1 cgd synexpect(TEND);
466 1.1 cgd checkkwd = 1;
467 1.1 cgd break;
468 1.5 sef /* Handle an empty command like other simple commands. */
469 1.19 mycroft case TSEMI:
470 1.19 mycroft /*
471 1.19 mycroft * An empty command before a ; doesn't make much sense, and
472 1.19 mycroft * should certainly be disallowed in the case of `if ;'.
473 1.19 mycroft */
474 1.19 mycroft if (!redir)
475 1.19 mycroft synexpect(-1);
476 1.30 christos case TAND:
477 1.30 christos case TOR:
478 1.5 sef case TNL:
479 1.20 mycroft case TEOF:
480 1.1 cgd case TWORD:
481 1.19 mycroft case TRP:
482 1.1 cgd tokpushback++;
483 1.5 sef return simplecmd(rpp, redir);
484 1.1 cgd default:
485 1.1 cgd synexpect(-1);
486 1.1 cgd }
487 1.1 cgd
488 1.1 cgd /* Now check for redirection which may follow command */
489 1.1 cgd while (readtoken() == TREDIR) {
490 1.1 cgd *rpp = n2 = redirnode;
491 1.1 cgd rpp = &n2->nfile.next;
492 1.1 cgd parsefname();
493 1.1 cgd }
494 1.1 cgd tokpushback++;
495 1.1 cgd *rpp = NULL;
496 1.1 cgd if (redir) {
497 1.1 cgd if (n1->type != NSUBSHELL) {
498 1.1 cgd n2 = (union node *)stalloc(sizeof (struct nredir));
499 1.1 cgd n2->type = NREDIR;
500 1.1 cgd n2->nredir.n = n1;
501 1.1 cgd n1 = n2;
502 1.1 cgd }
503 1.1 cgd n1->nredir.redirect = redir;
504 1.1 cgd }
505 1.1 cgd return n1;
506 1.1 cgd }
507 1.1 cgd
508 1.1 cgd
509 1.1 cgd STATIC union node *
510 1.30 christos simplecmd(rpp, redir)
511 1.5 sef union node **rpp, *redir;
512 1.5 sef {
513 1.1 cgd union node *args, **app;
514 1.5 sef union node **orig_rpp = rpp;
515 1.30 christos union node *n = NULL;
516 1.1 cgd
517 1.11 jtc /* If we don't have any redirections already, then we must reset */
518 1.11 jtc /* rpp to be the address of the local redir variable. */
519 1.5 sef if (redir == 0)
520 1.5 sef rpp = &redir;
521 1.5 sef
522 1.1 cgd args = NULL;
523 1.1 cgd app = &args;
524 1.30 christos /*
525 1.11 jtc * We save the incoming value, because we need this for shell
526 1.11 jtc * functions. There can not be a redirect or an argument between
527 1.30 christos * the function name and the open parenthesis.
528 1.11 jtc */
529 1.5 sef orig_rpp = rpp;
530 1.11 jtc
531 1.1 cgd for (;;) {
532 1.1 cgd if (readtoken() == TWORD) {
533 1.1 cgd n = (union node *)stalloc(sizeof (struct narg));
534 1.1 cgd n->type = NARG;
535 1.1 cgd n->narg.text = wordtext;
536 1.1 cgd n->narg.backquote = backquotelist;
537 1.1 cgd *app = n;
538 1.1 cgd app = &n->narg.next;
539 1.1 cgd } else if (lasttoken == TREDIR) {
540 1.1 cgd *rpp = n = redirnode;
541 1.1 cgd rpp = &n->nfile.next;
542 1.1 cgd parsefname(); /* read name of redirection file */
543 1.1 cgd } else if (lasttoken == TLP && app == &args->narg.next
544 1.5 sef && rpp == orig_rpp) {
545 1.1 cgd /* We have a function */
546 1.1 cgd if (readtoken() != TRP)
547 1.1 cgd synexpect(TRP);
548 1.1 cgd #ifdef notdef
549 1.1 cgd if (! goodname(n->narg.text))
550 1.1 cgd synerror("Bad function name");
551 1.1 cgd #endif
552 1.1 cgd n->type = NDEFUN;
553 1.1 cgd n->narg.next = command();
554 1.1 cgd return n;
555 1.1 cgd } else {
556 1.1 cgd tokpushback++;
557 1.1 cgd break;
558 1.1 cgd }
559 1.1 cgd }
560 1.1 cgd *app = NULL;
561 1.1 cgd *rpp = NULL;
562 1.1 cgd n = (union node *)stalloc(sizeof (struct ncmd));
563 1.1 cgd n->type = NCMD;
564 1.1 cgd n->ncmd.backgnd = 0;
565 1.1 cgd n->ncmd.args = args;
566 1.1 cgd n->ncmd.redirect = redir;
567 1.1 cgd return n;
568 1.1 cgd }
569 1.1 cgd
570 1.18 jtc STATIC union node *
571 1.18 jtc makename() {
572 1.18 jtc union node *n;
573 1.18 jtc
574 1.18 jtc n = (union node *)stalloc(sizeof (struct narg));
575 1.18 jtc n->type = NARG;
576 1.18 jtc n->narg.next = NULL;
577 1.18 jtc n->narg.text = wordtext;
578 1.18 jtc n->narg.backquote = backquotelist;
579 1.18 jtc return n;
580 1.18 jtc }
581 1.18 jtc
582 1.18 jtc void fixredir(n, text, err)
583 1.18 jtc union node *n;
584 1.18 jtc const char *text;
585 1.18 jtc int err;
586 1.18 jtc {
587 1.18 jtc TRACE(("Fix redir %s %d\n", text, err));
588 1.18 jtc if (!err)
589 1.18 jtc n->ndup.vname = NULL;
590 1.18 jtc
591 1.18 jtc if (is_digit(text[0]) && text[1] == '\0')
592 1.18 jtc n->ndup.dupfd = digit_val(text[0]);
593 1.18 jtc else if (text[0] == '-' && text[1] == '\0')
594 1.18 jtc n->ndup.dupfd = -1;
595 1.18 jtc else {
596 1.30 christos
597 1.18 jtc if (err)
598 1.18 jtc synerror("Bad fd number");
599 1.18 jtc else
600 1.18 jtc n->ndup.vname = makename();
601 1.18 jtc }
602 1.18 jtc }
603 1.18 jtc
604 1.1 cgd
605 1.1 cgd STATIC void
606 1.1 cgd parsefname() {
607 1.1 cgd union node *n = redirnode;
608 1.1 cgd
609 1.1 cgd if (readtoken() != TWORD)
610 1.1 cgd synexpect(-1);
611 1.1 cgd if (n->type == NHERE) {
612 1.1 cgd struct heredoc *here = heredoc;
613 1.1 cgd struct heredoc *p;
614 1.1 cgd int i;
615 1.1 cgd
616 1.1 cgd if (quoteflag == 0)
617 1.1 cgd n->type = NXHERE;
618 1.1 cgd TRACE(("Here document %d\n", n->type));
619 1.1 cgd if (here->striptabs) {
620 1.1 cgd while (*wordtext == '\t')
621 1.1 cgd wordtext++;
622 1.1 cgd }
623 1.1 cgd if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
624 1.1 cgd synerror("Illegal eof marker for << redirection");
625 1.1 cgd rmescapes(wordtext);
626 1.1 cgd here->eofmark = wordtext;
627 1.1 cgd here->next = NULL;
628 1.1 cgd if (heredoclist == NULL)
629 1.1 cgd heredoclist = here;
630 1.1 cgd else {
631 1.1 cgd for (p = heredoclist ; p->next ; p = p->next);
632 1.1 cgd p->next = here;
633 1.1 cgd }
634 1.1 cgd } else if (n->type == NTOFD || n->type == NFROMFD) {
635 1.18 jtc fixredir(n, wordtext, 0);
636 1.1 cgd } else {
637 1.18 jtc n->nfile.fname = makename();
638 1.1 cgd }
639 1.1 cgd }
640 1.1 cgd
641 1.1 cgd
642 1.1 cgd /*
643 1.1 cgd * Input any here documents.
644 1.1 cgd */
645 1.1 cgd
646 1.1 cgd STATIC void
647 1.1 cgd parseheredoc() {
648 1.1 cgd struct heredoc *here;
649 1.1 cgd union node *n;
650 1.1 cgd
651 1.1 cgd while (heredoclist) {
652 1.1 cgd here = heredoclist;
653 1.1 cgd heredoclist = here->next;
654 1.1 cgd if (needprompt) {
655 1.11 jtc setprompt(2);
656 1.1 cgd needprompt = 0;
657 1.1 cgd }
658 1.1 cgd readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
659 1.1 cgd here->eofmark, here->striptabs);
660 1.1 cgd n = (union node *)stalloc(sizeof (struct narg));
661 1.1 cgd n->narg.type = NARG;
662 1.1 cgd n->narg.next = NULL;
663 1.1 cgd n->narg.text = wordtext;
664 1.1 cgd n->narg.backquote = backquotelist;
665 1.1 cgd here->here->nhere.doc = n;
666 1.1 cgd }
667 1.1 cgd }
668 1.1 cgd
669 1.1 cgd STATIC int
670 1.1 cgd peektoken() {
671 1.1 cgd int t;
672 1.1 cgd
673 1.1 cgd t = readtoken();
674 1.1 cgd tokpushback++;
675 1.1 cgd return (t);
676 1.1 cgd }
677 1.1 cgd
678 1.1 cgd STATIC int xxreadtoken();
679 1.1 cgd
680 1.1 cgd STATIC int
681 1.1 cgd readtoken() {
682 1.1 cgd int t;
683 1.11 jtc int savecheckkwd = checkkwd;
684 1.11 jtc struct alias *ap;
685 1.1 cgd #ifdef DEBUG
686 1.1 cgd int alreadyseen = tokpushback;
687 1.1 cgd #endif
688 1.30 christos
689 1.11 jtc top:
690 1.1 cgd t = xxreadtoken();
691 1.1 cgd
692 1.1 cgd if (checkkwd) {
693 1.1 cgd /*
694 1.1 cgd * eat newlines
695 1.1 cgd */
696 1.1 cgd if (checkkwd == 2) {
697 1.1 cgd checkkwd = 0;
698 1.1 cgd while (t == TNL) {
699 1.1 cgd parseheredoc();
700 1.1 cgd t = xxreadtoken();
701 1.1 cgd }
702 1.1 cgd } else
703 1.1 cgd checkkwd = 0;
704 1.1 cgd /*
705 1.11 jtc * check for keywords and aliases
706 1.1 cgd */
707 1.30 christos if (t == TWORD && !quoteflag)
708 1.22 cgd {
709 1.22 cgd register char * const *pp;
710 1.1 cgd
711 1.11 jtc for (pp = (char **)parsekwd; *pp; pp++) {
712 1.30 christos if (**pp == *wordtext && equal(*pp, wordtext))
713 1.22 cgd {
714 1.1 cgd lasttoken = t = pp - parsekwd + KWDOFFSET;
715 1.1 cgd TRACE(("keyword %s recognized\n", tokname[t]));
716 1.11 jtc goto out;
717 1.1 cgd }
718 1.1 cgd }
719 1.25 christos if ((ap = lookupalias(wordtext, 1)) != NULL) {
720 1.11 jtc pushstring(ap->val, strlen(ap->val), ap);
721 1.11 jtc checkkwd = savecheckkwd;
722 1.11 jtc goto top;
723 1.11 jtc }
724 1.1 cgd }
725 1.11 jtc out:
726 1.11 jtc checkkwd = 0;
727 1.1 cgd }
728 1.1 cgd #ifdef DEBUG
729 1.1 cgd if (!alreadyseen)
730 1.1 cgd TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
731 1.1 cgd else
732 1.1 cgd TRACE(("reread token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
733 1.1 cgd #endif
734 1.1 cgd return (t);
735 1.1 cgd }
736 1.1 cgd
737 1.1 cgd
738 1.1 cgd /*
739 1.1 cgd * Read the next input token.
740 1.1 cgd * If the token is a word, we set backquotelist to the list of cmds in
741 1.1 cgd * backquotes. We set quoteflag to true if any part of the word was
742 1.1 cgd * quoted.
743 1.1 cgd * If the token is TREDIR, then we set redirnode to a structure containing
744 1.1 cgd * the redirection.
745 1.1 cgd * In all cases, the variable startlinno is set to the number of the line
746 1.1 cgd * on which the token starts.
747 1.1 cgd *
748 1.1 cgd * [Change comment: here documents and internal procedures]
749 1.1 cgd * [Readtoken shouldn't have any arguments. Perhaps we should make the
750 1.1 cgd * word parsing code into a separate routine. In this case, readtoken
751 1.1 cgd * doesn't need to have any internal procedures, but parseword does.
752 1.1 cgd * We could also make parseoperator in essence the main routine, and
753 1.1 cgd * have parseword (readtoken1?) handle both words and redirection.]
754 1.1 cgd */
755 1.1 cgd
756 1.1 cgd #define RETURN(token) return lasttoken = token
757 1.1 cgd
758 1.1 cgd STATIC int
759 1.1 cgd xxreadtoken() {
760 1.1 cgd register c;
761 1.1 cgd
762 1.1 cgd if (tokpushback) {
763 1.1 cgd tokpushback = 0;
764 1.1 cgd return lasttoken;
765 1.1 cgd }
766 1.1 cgd if (needprompt) {
767 1.11 jtc setprompt(2);
768 1.1 cgd needprompt = 0;
769 1.1 cgd }
770 1.1 cgd startlinno = plinno;
771 1.1 cgd for (;;) { /* until token or start of word found */
772 1.1 cgd c = pgetc_macro();
773 1.1 cgd if (c == ' ' || c == '\t')
774 1.1 cgd continue; /* quick check for white space first */
775 1.1 cgd switch (c) {
776 1.1 cgd case ' ': case '\t':
777 1.1 cgd continue;
778 1.1 cgd case '#':
779 1.1 cgd while ((c = pgetc()) != '\n' && c != PEOF);
780 1.1 cgd pungetc();
781 1.1 cgd continue;
782 1.1 cgd case '\\':
783 1.1 cgd if (pgetc() == '\n') {
784 1.1 cgd startlinno = ++plinno;
785 1.1 cgd if (doprompt)
786 1.11 jtc setprompt(2);
787 1.11 jtc else
788 1.11 jtc setprompt(0);
789 1.1 cgd continue;
790 1.1 cgd }
791 1.1 cgd pungetc();
792 1.1 cgd goto breakloop;
793 1.1 cgd case '\n':
794 1.1 cgd plinno++;
795 1.1 cgd needprompt = doprompt;
796 1.1 cgd RETURN(TNL);
797 1.1 cgd case PEOF:
798 1.1 cgd RETURN(TEOF);
799 1.1 cgd case '&':
800 1.1 cgd if (pgetc() == '&')
801 1.1 cgd RETURN(TAND);
802 1.1 cgd pungetc();
803 1.1 cgd RETURN(TBACKGND);
804 1.1 cgd case '|':
805 1.1 cgd if (pgetc() == '|')
806 1.1 cgd RETURN(TOR);
807 1.1 cgd pungetc();
808 1.1 cgd RETURN(TPIPE);
809 1.1 cgd case ';':
810 1.1 cgd if (pgetc() == ';')
811 1.1 cgd RETURN(TENDCASE);
812 1.1 cgd pungetc();
813 1.1 cgd RETURN(TSEMI);
814 1.1 cgd case '(':
815 1.1 cgd RETURN(TLP);
816 1.1 cgd case ')':
817 1.1 cgd RETURN(TRP);
818 1.1 cgd default:
819 1.1 cgd goto breakloop;
820 1.1 cgd }
821 1.1 cgd }
822 1.1 cgd breakloop:
823 1.1 cgd return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
824 1.1 cgd #undef RETURN
825 1.1 cgd }
826 1.1 cgd
827 1.1 cgd
828 1.1 cgd
829 1.1 cgd /*
830 1.1 cgd * If eofmark is NULL, read a word or a redirection symbol. If eofmark
831 1.1 cgd * is not NULL, read a here document. In the latter case, eofmark is the
832 1.1 cgd * word which marks the end of the document and striptabs is true if
833 1.1 cgd * leading tabs should be stripped from the document. The argument firstc
834 1.1 cgd * is the first character of the input token or document.
835 1.1 cgd *
836 1.1 cgd * Because C does not have internal subroutines, I have simulated them
837 1.1 cgd * using goto's to implement the subroutine linkage. The following macros
838 1.1 cgd * will run code that appears at the end of readtoken1.
839 1.1 cgd */
840 1.1 cgd
841 1.1 cgd #define CHECKEND() {goto checkend; checkend_return:;}
842 1.1 cgd #define PARSEREDIR() {goto parseredir; parseredir_return:;}
843 1.1 cgd #define PARSESUB() {goto parsesub; parsesub_return:;}
844 1.1 cgd #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
845 1.1 cgd #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
846 1.11 jtc #define PARSEARITH() {goto parsearith; parsearith_return:;}
847 1.1 cgd
848 1.1 cgd STATIC int
849 1.1 cgd readtoken1(firstc, syntax, eofmark, striptabs)
850 1.1 cgd int firstc;
851 1.1 cgd char const *syntax;
852 1.1 cgd char *eofmark;
853 1.1 cgd int striptabs;
854 1.1 cgd {
855 1.25 christos int c = firstc;
856 1.25 christos char *out;
857 1.1 cgd int len;
858 1.1 cgd char line[EOFMARKLEN + 1];
859 1.1 cgd struct nodelist *bqlist;
860 1.1 cgd int quotef;
861 1.1 cgd int dblquote;
862 1.11 jtc int varnest; /* levels of variables expansion */
863 1.11 jtc int arinest; /* levels of arithmetic expansion */
864 1.11 jtc int parenlevel; /* levels of parens in arithmetic */
865 1.1 cgd int oldstyle;
866 1.11 jtc char const *prevsyntax; /* syntax before arithmetic */
867 1.25 christos #if __GNUC__
868 1.25 christos /* Avoid longjmp clobbering */
869 1.25 christos (void) &out;
870 1.25 christos (void) "ef;
871 1.25 christos (void) &dblquote;
872 1.25 christos (void) &varnest;
873 1.25 christos (void) &arinest;
874 1.25 christos (void) &parenlevel;
875 1.25 christos (void) &oldstyle;
876 1.25 christos (void) &prevsyntax;
877 1.25 christos (void) &syntax;
878 1.25 christos #endif
879 1.1 cgd
880 1.1 cgd startlinno = plinno;
881 1.1 cgd dblquote = 0;
882 1.1 cgd if (syntax == DQSYNTAX)
883 1.1 cgd dblquote = 1;
884 1.1 cgd quotef = 0;
885 1.1 cgd bqlist = NULL;
886 1.1 cgd varnest = 0;
887 1.11 jtc arinest = 0;
888 1.11 jtc parenlevel = 0;
889 1.11 jtc
890 1.1 cgd STARTSTACKSTR(out);
891 1.1 cgd loop: { /* for each line, until end of word */
892 1.1 cgd #if ATTY
893 1.1 cgd if (c == '\034' && doprompt
894 1.1 cgd && attyset() && ! equal(termval(), "emacs")) {
895 1.1 cgd attyline();
896 1.1 cgd if (syntax == BASESYNTAX)
897 1.1 cgd return readtoken();
898 1.1 cgd c = pgetc();
899 1.1 cgd goto loop;
900 1.1 cgd }
901 1.1 cgd #endif
902 1.1 cgd CHECKEND(); /* set c to PEOF if at end of here document */
903 1.1 cgd for (;;) { /* until end of line or end of word */
904 1.1 cgd CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */
905 1.1 cgd switch(syntax[c]) {
906 1.1 cgd case CNL: /* '\n' */
907 1.1 cgd if (syntax == BASESYNTAX)
908 1.1 cgd goto endword; /* exit outer loop */
909 1.1 cgd USTPUTC(c, out);
910 1.1 cgd plinno++;
911 1.11 jtc if (doprompt)
912 1.11 jtc setprompt(2);
913 1.11 jtc else
914 1.11 jtc setprompt(0);
915 1.1 cgd c = pgetc();
916 1.1 cgd goto loop; /* continue outer loop */
917 1.1 cgd case CWORD:
918 1.1 cgd USTPUTC(c, out);
919 1.1 cgd break;
920 1.1 cgd case CCTL:
921 1.1 cgd if (eofmark == NULL || dblquote)
922 1.1 cgd USTPUTC(CTLESC, out);
923 1.1 cgd USTPUTC(c, out);
924 1.1 cgd break;
925 1.1 cgd case CBACK: /* backslash */
926 1.1 cgd c = pgetc();
927 1.1 cgd if (c == PEOF) {
928 1.1 cgd USTPUTC('\\', out);
929 1.1 cgd pungetc();
930 1.1 cgd } else if (c == '\n') {
931 1.1 cgd if (doprompt)
932 1.11 jtc setprompt(2);
933 1.11 jtc else
934 1.11 jtc setprompt(0);
935 1.1 cgd } else {
936 1.1 cgd if (dblquote && c != '\\' && c != '`' && c != '$'
937 1.1 cgd && (c != '"' || eofmark != NULL))
938 1.1 cgd USTPUTC('\\', out);
939 1.1 cgd if (SQSYNTAX[c] == CCTL)
940 1.1 cgd USTPUTC(CTLESC, out);
941 1.1 cgd USTPUTC(c, out);
942 1.1 cgd quotef++;
943 1.1 cgd }
944 1.1 cgd break;
945 1.1 cgd case CSQUOTE:
946 1.1 cgd syntax = SQSYNTAX;
947 1.1 cgd break;
948 1.1 cgd case CDQUOTE:
949 1.1 cgd syntax = DQSYNTAX;
950 1.1 cgd dblquote = 1;
951 1.1 cgd break;
952 1.1 cgd case CENDQUOTE:
953 1.1 cgd if (eofmark) {
954 1.1 cgd USTPUTC(c, out);
955 1.1 cgd } else {
956 1.11 jtc if (arinest)
957 1.11 jtc syntax = ARISYNTAX;
958 1.11 jtc else
959 1.11 jtc syntax = BASESYNTAX;
960 1.1 cgd quotef++;
961 1.1 cgd dblquote = 0;
962 1.1 cgd }
963 1.1 cgd break;
964 1.1 cgd case CVAR: /* '$' */
965 1.1 cgd PARSESUB(); /* parse substitution */
966 1.1 cgd break;
967 1.1 cgd case CENDVAR: /* '}' */
968 1.1 cgd if (varnest > 0) {
969 1.1 cgd varnest--;
970 1.1 cgd USTPUTC(CTLENDVAR, out);
971 1.1 cgd } else {
972 1.1 cgd USTPUTC(c, out);
973 1.1 cgd }
974 1.1 cgd break;
975 1.11 jtc case CLP: /* '(' in arithmetic */
976 1.11 jtc parenlevel++;
977 1.11 jtc USTPUTC(c, out);
978 1.11 jtc break;
979 1.11 jtc case CRP: /* ')' in arithmetic */
980 1.11 jtc if (parenlevel > 0) {
981 1.11 jtc USTPUTC(c, out);
982 1.11 jtc --parenlevel;
983 1.11 jtc } else {
984 1.11 jtc if (pgetc() == ')') {
985 1.11 jtc if (--arinest == 0) {
986 1.11 jtc USTPUTC(CTLENDARI, out);
987 1.11 jtc syntax = prevsyntax;
988 1.11 jtc } else
989 1.11 jtc USTPUTC(')', out);
990 1.11 jtc } else {
991 1.30 christos /*
992 1.11 jtc * unbalanced parens
993 1.11 jtc * (don't 2nd guess - no error)
994 1.11 jtc */
995 1.11 jtc pungetc();
996 1.11 jtc USTPUTC(')', out);
997 1.11 jtc }
998 1.11 jtc }
999 1.11 jtc break;
1000 1.1 cgd case CBQUOTE: /* '`' */
1001 1.1 cgd PARSEBACKQOLD();
1002 1.1 cgd break;
1003 1.1 cgd case CEOF:
1004 1.1 cgd goto endword; /* exit outer loop */
1005 1.1 cgd default:
1006 1.1 cgd if (varnest == 0)
1007 1.1 cgd goto endword; /* exit outer loop */
1008 1.1 cgd USTPUTC(c, out);
1009 1.1 cgd }
1010 1.1 cgd c = pgetc_macro();
1011 1.1 cgd }
1012 1.1 cgd }
1013 1.1 cgd endword:
1014 1.11 jtc if (syntax == ARISYNTAX)
1015 1.11 jtc synerror("Missing '))'");
1016 1.5 sef if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
1017 1.1 cgd synerror("Unterminated quoted string");
1018 1.1 cgd if (varnest != 0) {
1019 1.1 cgd startlinno = plinno;
1020 1.1 cgd synerror("Missing '}'");
1021 1.1 cgd }
1022 1.1 cgd USTPUTC('\0', out);
1023 1.1 cgd len = out - stackblock();
1024 1.1 cgd out = stackblock();
1025 1.1 cgd if (eofmark == NULL) {
1026 1.1 cgd if ((c == '>' || c == '<')
1027 1.1 cgd && quotef == 0
1028 1.1 cgd && len <= 2
1029 1.1 cgd && (*out == '\0' || is_digit(*out))) {
1030 1.1 cgd PARSEREDIR();
1031 1.1 cgd return lasttoken = TREDIR;
1032 1.1 cgd } else {
1033 1.1 cgd pungetc();
1034 1.1 cgd }
1035 1.1 cgd }
1036 1.1 cgd quoteflag = quotef;
1037 1.1 cgd backquotelist = bqlist;
1038 1.1 cgd grabstackblock(len);
1039 1.1 cgd wordtext = out;
1040 1.1 cgd return lasttoken = TWORD;
1041 1.1 cgd /* end of readtoken routine */
1042 1.1 cgd
1043 1.1 cgd
1044 1.1 cgd
1045 1.1 cgd /*
1046 1.1 cgd * Check to see whether we are at the end of the here document. When this
1047 1.1 cgd * is called, c is set to the first character of the next input line. If
1048 1.1 cgd * we are at the end of the here document, this routine sets the c to PEOF.
1049 1.1 cgd */
1050 1.1 cgd
1051 1.1 cgd checkend: {
1052 1.1 cgd if (eofmark) {
1053 1.1 cgd if (striptabs) {
1054 1.1 cgd while (c == '\t')
1055 1.1 cgd c = pgetc();
1056 1.1 cgd }
1057 1.1 cgd if (c == *eofmark) {
1058 1.1 cgd if (pfgets(line, sizeof line) != NULL) {
1059 1.1 cgd register char *p, *q;
1060 1.1 cgd
1061 1.1 cgd p = line;
1062 1.1 cgd for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
1063 1.1 cgd if (*p == '\n' && *q == '\0') {
1064 1.1 cgd c = PEOF;
1065 1.1 cgd plinno++;
1066 1.1 cgd needprompt = doprompt;
1067 1.1 cgd } else {
1068 1.11 jtc pushstring(line, strlen(line), NULL);
1069 1.1 cgd }
1070 1.1 cgd }
1071 1.1 cgd }
1072 1.1 cgd }
1073 1.1 cgd goto checkend_return;
1074 1.1 cgd }
1075 1.1 cgd
1076 1.1 cgd
1077 1.1 cgd /*
1078 1.1 cgd * Parse a redirection operator. The variable "out" points to a string
1079 1.1 cgd * specifying the fd to be redirected. The variable "c" contains the
1080 1.1 cgd * first character of the redirection operator.
1081 1.1 cgd */
1082 1.1 cgd
1083 1.1 cgd parseredir: {
1084 1.1 cgd char fd = *out;
1085 1.1 cgd union node *np;
1086 1.1 cgd
1087 1.1 cgd np = (union node *)stalloc(sizeof (struct nfile));
1088 1.1 cgd if (c == '>') {
1089 1.1 cgd np->nfile.fd = 1;
1090 1.1 cgd c = pgetc();
1091 1.1 cgd if (c == '>')
1092 1.1 cgd np->type = NAPPEND;
1093 1.1 cgd else if (c == '&')
1094 1.1 cgd np->type = NTOFD;
1095 1.1 cgd else {
1096 1.1 cgd np->type = NTO;
1097 1.1 cgd pungetc();
1098 1.1 cgd }
1099 1.1 cgd } else { /* c == '<' */
1100 1.1 cgd np->nfile.fd = 0;
1101 1.1 cgd c = pgetc();
1102 1.1 cgd if (c == '<') {
1103 1.1 cgd if (sizeof (struct nfile) != sizeof (struct nhere)) {
1104 1.1 cgd np = (union node *)stalloc(sizeof (struct nhere));
1105 1.1 cgd np->nfile.fd = 0;
1106 1.1 cgd }
1107 1.1 cgd np->type = NHERE;
1108 1.1 cgd heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
1109 1.1 cgd heredoc->here = np;
1110 1.1 cgd if ((c = pgetc()) == '-') {
1111 1.1 cgd heredoc->striptabs = 1;
1112 1.1 cgd } else {
1113 1.1 cgd heredoc->striptabs = 0;
1114 1.1 cgd pungetc();
1115 1.1 cgd }
1116 1.1 cgd } else if (c == '&')
1117 1.1 cgd np->type = NFROMFD;
1118 1.1 cgd else {
1119 1.1 cgd np->type = NFROM;
1120 1.1 cgd pungetc();
1121 1.1 cgd }
1122 1.1 cgd }
1123 1.1 cgd if (fd != '\0')
1124 1.1 cgd np->nfile.fd = digit_val(fd);
1125 1.1 cgd redirnode = np;
1126 1.1 cgd goto parseredir_return;
1127 1.1 cgd }
1128 1.1 cgd
1129 1.1 cgd
1130 1.1 cgd /*
1131 1.1 cgd * Parse a substitution. At this point, we have read the dollar sign
1132 1.1 cgd * and nothing else.
1133 1.1 cgd */
1134 1.1 cgd
1135 1.1 cgd parsesub: {
1136 1.1 cgd int subtype;
1137 1.1 cgd int typeloc;
1138 1.1 cgd int flags;
1139 1.1 cgd char *p;
1140 1.1 cgd #ifndef GDB_HACK
1141 1.1 cgd static const char types[] = "}-+?=";
1142 1.1 cgd #endif
1143 1.1 cgd
1144 1.1 cgd c = pgetc();
1145 1.1 cgd if (c != '(' && c != '{' && !is_name(c) && !is_special(c)) {
1146 1.1 cgd USTPUTC('$', out);
1147 1.1 cgd pungetc();
1148 1.11 jtc } else if (c == '(') { /* $(command) or $((arith)) */
1149 1.11 jtc if (pgetc() == '(') {
1150 1.11 jtc PARSEARITH();
1151 1.11 jtc } else {
1152 1.11 jtc pungetc();
1153 1.11 jtc PARSEBACKQNEW();
1154 1.11 jtc }
1155 1.1 cgd } else {
1156 1.1 cgd USTPUTC(CTLVAR, out);
1157 1.1 cgd typeloc = out - stackblock();
1158 1.1 cgd USTPUTC(VSNORMAL, out);
1159 1.1 cgd subtype = VSNORMAL;
1160 1.1 cgd if (c == '{') {
1161 1.1 cgd c = pgetc();
1162 1.23 christos if (c == '#') {
1163 1.26 christos if ((c = pgetc()) == '}')
1164 1.26 christos c = '#';
1165 1.26 christos else
1166 1.26 christos subtype = VSLENGTH;
1167 1.23 christos }
1168 1.23 christos else
1169 1.23 christos subtype = 0;
1170 1.1 cgd }
1171 1.1 cgd if (is_name(c)) {
1172 1.1 cgd do {
1173 1.1 cgd STPUTC(c, out);
1174 1.1 cgd c = pgetc();
1175 1.1 cgd } while (is_in_name(c));
1176 1.1 cgd } else {
1177 1.1 cgd if (! is_special(c))
1178 1.1 cgd badsub: synerror("Bad substitution");
1179 1.1 cgd USTPUTC(c, out);
1180 1.1 cgd c = pgetc();
1181 1.1 cgd }
1182 1.1 cgd STPUTC('=', out);
1183 1.1 cgd flags = 0;
1184 1.1 cgd if (subtype == 0) {
1185 1.23 christos switch (c) {
1186 1.23 christos case ':':
1187 1.1 cgd flags = VSNUL;
1188 1.1 cgd c = pgetc();
1189 1.23 christos /*FALLTHROUGH*/
1190 1.23 christos default:
1191 1.23 christos p = strchr(types, c);
1192 1.23 christos if (p == NULL)
1193 1.23 christos goto badsub;
1194 1.23 christos subtype = p - types + VSNORMAL;
1195 1.23 christos break;
1196 1.23 christos case '%':
1197 1.30 christos case '#':
1198 1.23 christos {
1199 1.23 christos int cc = c;
1200 1.23 christos subtype = c == '#' ? VSTRIMLEFT :
1201 1.23 christos VSTRIMRIGHT;
1202 1.23 christos c = pgetc();
1203 1.23 christos if (c == cc)
1204 1.23 christos subtype++;
1205 1.23 christos else
1206 1.23 christos pungetc();
1207 1.23 christos break;
1208 1.23 christos }
1209 1.1 cgd }
1210 1.1 cgd } else {
1211 1.1 cgd pungetc();
1212 1.1 cgd }
1213 1.11 jtc if (dblquote || arinest)
1214 1.1 cgd flags |= VSQUOTE;
1215 1.1 cgd *(stackblock() + typeloc) = subtype | flags;
1216 1.1 cgd if (subtype != VSNORMAL)
1217 1.1 cgd varnest++;
1218 1.1 cgd }
1219 1.1 cgd goto parsesub_return;
1220 1.1 cgd }
1221 1.1 cgd
1222 1.1 cgd
1223 1.1 cgd /*
1224 1.1 cgd * Called to parse command substitutions. Newstyle is set if the command
1225 1.1 cgd * is enclosed inside $(...); nlpp is a pointer to the head of the linked
1226 1.1 cgd * list of commands (passed by reference), and savelen is the number of
1227 1.1 cgd * characters on the top of the stack which must be preserved.
1228 1.1 cgd */
1229 1.1 cgd
1230 1.1 cgd parsebackq: {
1231 1.1 cgd struct nodelist **nlpp;
1232 1.1 cgd int savepbq;
1233 1.1 cgd union node *n;
1234 1.1 cgd char *volatile str;
1235 1.1 cgd struct jmploc jmploc;
1236 1.1 cgd struct jmploc *volatile savehandler;
1237 1.1 cgd int savelen;
1238 1.28 christos int saveprompt;
1239 1.1 cgd
1240 1.1 cgd savepbq = parsebackquote;
1241 1.1 cgd if (setjmp(jmploc.loc)) {
1242 1.1 cgd if (str)
1243 1.1 cgd ckfree(str);
1244 1.1 cgd parsebackquote = 0;
1245 1.1 cgd handler = savehandler;
1246 1.4 dpassage longjmp(handler->loc, 1);
1247 1.1 cgd }
1248 1.1 cgd INTOFF;
1249 1.1 cgd str = NULL;
1250 1.1 cgd savelen = out - stackblock();
1251 1.1 cgd if (savelen > 0) {
1252 1.1 cgd str = ckmalloc(savelen);
1253 1.21 mycroft memcpy(str, stackblock(), savelen);
1254 1.1 cgd }
1255 1.1 cgd savehandler = handler;
1256 1.1 cgd handler = &jmploc;
1257 1.1 cgd INTON;
1258 1.11 jtc if (oldstyle) {
1259 1.11 jtc /* We must read until the closing backquote, giving special
1260 1.11 jtc treatment to some slashes, and then push the string and
1261 1.11 jtc reread it as input, interpreting it normally. */
1262 1.11 jtc register char *out;
1263 1.11 jtc register c;
1264 1.11 jtc int savelen;
1265 1.11 jtc char *str;
1266 1.28 christos
1267 1.30 christos
1268 1.11 jtc STARTSTACKSTR(out);
1269 1.28 christos for (;;) {
1270 1.28 christos if (needprompt) {
1271 1.28 christos setprompt(2);
1272 1.28 christos needprompt = 0;
1273 1.28 christos }
1274 1.28 christos switch (c = pgetc()) {
1275 1.28 christos case '`':
1276 1.28 christos goto done;
1277 1.28 christos
1278 1.28 christos case '\\':
1279 1.28 christos if ((c = pgetc()) == '\n') {
1280 1.28 christos plinno++;
1281 1.28 christos if (doprompt)
1282 1.28 christos setprompt(2);
1283 1.28 christos else
1284 1.28 christos setprompt(0);
1285 1.29 christos /*
1286 1.29 christos * If eating a newline, avoid putting
1287 1.29 christos * the newline into the new character
1288 1.29 christos * stream (via the STPUTC after the
1289 1.29 christos * switch).
1290 1.29 christos */
1291 1.29 christos continue;
1292 1.28 christos }
1293 1.11 jtc if (c != '\\' && c != '`' && c != '$'
1294 1.11 jtc && (!dblquote || c != '"'))
1295 1.11 jtc STPUTC('\\', out);
1296 1.28 christos break;
1297 1.28 christos
1298 1.28 christos case '\n':
1299 1.28 christos plinno++;
1300 1.28 christos needprompt = doprompt;
1301 1.28 christos break;
1302 1.28 christos
1303 1.30 christos case PEOF:
1304 1.30 christos startlinno = plinno;
1305 1.30 christos synerror("EOF in backquote substitution");
1306 1.30 christos break;
1307 1.30 christos
1308 1.28 christos default:
1309 1.28 christos break;
1310 1.28 christos }
1311 1.28 christos STPUTC(c, out);
1312 1.11 jtc }
1313 1.28 christos done:
1314 1.11 jtc STPUTC('\0', out);
1315 1.11 jtc savelen = out - stackblock();
1316 1.11 jtc if (savelen > 0) {
1317 1.11 jtc str = ckmalloc(savelen);
1318 1.21 mycroft memcpy(str, stackblock(), savelen);
1319 1.25 christos setinputstring(str, 1);
1320 1.11 jtc }
1321 1.11 jtc }
1322 1.1 cgd nlpp = &bqlist;
1323 1.1 cgd while (*nlpp)
1324 1.1 cgd nlpp = &(*nlpp)->next;
1325 1.1 cgd *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
1326 1.1 cgd (*nlpp)->next = NULL;
1327 1.1 cgd parsebackquote = oldstyle;
1328 1.28 christos
1329 1.28 christos if (oldstyle) {
1330 1.28 christos saveprompt = doprompt;
1331 1.28 christos doprompt = 0;
1332 1.28 christos }
1333 1.28 christos
1334 1.1 cgd n = list(0);
1335 1.28 christos
1336 1.28 christos if (oldstyle)
1337 1.28 christos doprompt = saveprompt;
1338 1.28 christos else {
1339 1.28 christos if (readtoken() != TRP)
1340 1.28 christos synexpect(TRP);
1341 1.28 christos }
1342 1.28 christos
1343 1.1 cgd (*nlpp)->n = n;
1344 1.27 christos if (oldstyle) {
1345 1.27 christos /*
1346 1.27 christos * Start reading from old file again, ignoring any pushed back
1347 1.27 christos * tokens left from the backquote parsing
1348 1.27 christos */
1349 1.11 jtc popfile();
1350 1.27 christos tokpushback = 0;
1351 1.27 christos }
1352 1.1 cgd while (stackblocksize() <= savelen)
1353 1.1 cgd growstackblock();
1354 1.1 cgd STARTSTACKSTR(out);
1355 1.1 cgd if (str) {
1356 1.21 mycroft memcpy(out, str, savelen);
1357 1.1 cgd STADJUST(savelen, out);
1358 1.1 cgd INTOFF;
1359 1.1 cgd ckfree(str);
1360 1.1 cgd str = NULL;
1361 1.1 cgd INTON;
1362 1.1 cgd }
1363 1.1 cgd parsebackquote = savepbq;
1364 1.1 cgd handler = savehandler;
1365 1.11 jtc if (arinest || dblquote)
1366 1.11 jtc USTPUTC(CTLBACKQ | CTLQUOTE, out);
1367 1.11 jtc else
1368 1.11 jtc USTPUTC(CTLBACKQ, out);
1369 1.1 cgd if (oldstyle)
1370 1.1 cgd goto parsebackq_oldreturn;
1371 1.1 cgd else
1372 1.1 cgd goto parsebackq_newreturn;
1373 1.1 cgd }
1374 1.1 cgd
1375 1.1 cgd /*
1376 1.11 jtc * Parse an arithmetic expansion (indicate start of one and set state)
1377 1.1 cgd */
1378 1.11 jtc parsearith: {
1379 1.1 cgd
1380 1.11 jtc if (++arinest == 1) {
1381 1.11 jtc prevsyntax = syntax;
1382 1.11 jtc syntax = ARISYNTAX;
1383 1.11 jtc USTPUTC(CTLARI, out);
1384 1.11 jtc } else {
1385 1.11 jtc /*
1386 1.11 jtc * we collapse embedded arithmetic expansion to
1387 1.11 jtc * parenthesis, which should be equivalent
1388 1.11 jtc */
1389 1.11 jtc USTPUTC('(', out);
1390 1.1 cgd }
1391 1.11 jtc goto parsearith_return;
1392 1.1 cgd }
1393 1.1 cgd
1394 1.11 jtc } /* end of readtoken */
1395 1.1 cgd
1396 1.1 cgd
1397 1.1 cgd
1398 1.11 jtc #ifdef mkinit
1399 1.11 jtc RESET {
1400 1.11 jtc tokpushback = 0;
1401 1.11 jtc checkkwd = 0;
1402 1.1 cgd }
1403 1.1 cgd #endif
1404 1.1 cgd
1405 1.1 cgd /*
1406 1.1 cgd * Returns true if the text contains nothing to expand (no dollar signs
1407 1.1 cgd * or backquotes).
1408 1.1 cgd */
1409 1.1 cgd
1410 1.1 cgd STATIC int
1411 1.1 cgd noexpand(text)
1412 1.1 cgd char *text;
1413 1.1 cgd {
1414 1.1 cgd register char *p;
1415 1.1 cgd register char c;
1416 1.1 cgd
1417 1.1 cgd p = text;
1418 1.1 cgd while ((c = *p++) != '\0') {
1419 1.1 cgd if (c == CTLESC)
1420 1.1 cgd p++;
1421 1.1 cgd else if (BASESYNTAX[c] == CCTL)
1422 1.1 cgd return 0;
1423 1.1 cgd }
1424 1.1 cgd return 1;
1425 1.1 cgd }
1426 1.1 cgd
1427 1.1 cgd
1428 1.1 cgd /*
1429 1.1 cgd * Return true if the argument is a legal variable name (a letter or
1430 1.1 cgd * underscore followed by zero or more letters, underscores, and digits).
1431 1.1 cgd */
1432 1.1 cgd
1433 1.1 cgd int
1434 1.1 cgd goodname(name)
1435 1.1 cgd char *name;
1436 1.1 cgd {
1437 1.1 cgd register char *p;
1438 1.1 cgd
1439 1.1 cgd p = name;
1440 1.1 cgd if (! is_name(*p))
1441 1.1 cgd return 0;
1442 1.1 cgd while (*++p) {
1443 1.1 cgd if (! is_in_name(*p))
1444 1.1 cgd return 0;
1445 1.1 cgd }
1446 1.1 cgd return 1;
1447 1.1 cgd }
1448 1.1 cgd
1449 1.1 cgd
1450 1.1 cgd /*
1451 1.1 cgd * Called when an unexpected token is read during the parse. The argument
1452 1.1 cgd * is the token that is expected, or -1 if more than one type of token can
1453 1.1 cgd * occur at this point.
1454 1.1 cgd */
1455 1.1 cgd
1456 1.1 cgd STATIC void
1457 1.30 christos synexpect(token)
1458 1.22 cgd int token;
1459 1.22 cgd {
1460 1.1 cgd char msg[64];
1461 1.1 cgd
1462 1.1 cgd if (token >= 0) {
1463 1.1 cgd fmtstr(msg, 64, "%s unexpected (expecting %s)",
1464 1.1 cgd tokname[lasttoken], tokname[token]);
1465 1.1 cgd } else {
1466 1.1 cgd fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]);
1467 1.1 cgd }
1468 1.1 cgd synerror(msg);
1469 1.1 cgd }
1470 1.1 cgd
1471 1.1 cgd
1472 1.1 cgd STATIC void
1473 1.1 cgd synerror(msg)
1474 1.1 cgd char *msg;
1475 1.1 cgd {
1476 1.1 cgd if (commandname)
1477 1.1 cgd outfmt(&errout, "%s: %d: ", commandname, startlinno);
1478 1.1 cgd outfmt(&errout, "Syntax error: %s\n", msg);
1479 1.1 cgd error((char *)NULL);
1480 1.11 jtc }
1481 1.11 jtc
1482 1.11 jtc STATIC void
1483 1.11 jtc setprompt(which)
1484 1.11 jtc int which;
1485 1.11 jtc {
1486 1.11 jtc whichprompt = which;
1487 1.11 jtc
1488 1.14 cgd #ifndef NO_HISTORY
1489 1.11 jtc if (!el)
1490 1.14 cgd #endif
1491 1.11 jtc out2str(getprompt(NULL));
1492 1.11 jtc }
1493 1.11 jtc
1494 1.11 jtc /*
1495 1.11 jtc * called by editline -- any expansions to the prompt
1496 1.11 jtc * should be added here.
1497 1.11 jtc */
1498 1.11 jtc char *
1499 1.11 jtc getprompt(unused)
1500 1.11 jtc void *unused;
1501 1.11 jtc {
1502 1.11 jtc switch (whichprompt) {
1503 1.11 jtc case 0:
1504 1.11 jtc return "";
1505 1.11 jtc case 1:
1506 1.11 jtc return ps1val();
1507 1.11 jtc case 2:
1508 1.11 jtc return ps2val();
1509 1.11 jtc default:
1510 1.11 jtc return "<internal prompt error>";
1511 1.11 jtc }
1512 1.1 cgd }
1513