2 * sh.parse.c: Interpret a list of tokens
5 * Copyright (c) 1980, 1991 The Regents of the University of California.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 static int asyntax (struct wordent *, struct wordent *);
38 static int asyn0 (struct wordent *, struct wordent *);
39 static int asyn3 (struct wordent *, struct wordent *);
40 static struct wordent *freenod (struct wordent *, struct wordent *);
41 static struct command *syn0 (const struct wordent *, const struct wordent *, int);
42 static struct command *syn1 (const struct wordent *, const struct wordent *, int);
43 static struct command *syn1a (const struct wordent *, const struct wordent *, int);
44 static struct command *syn1b (const struct wordent *, const struct wordent *, int);
45 static struct command *syn2 (const struct wordent *, const struct wordent *, int);
46 static struct command *syn3 (const struct wordent *, const struct wordent *, int);
48 #define ALEFT 51 /* max of 50 alias expansions */
49 #define HLEFT 11 /* max of 10 history expansions */
51 * Perform aliasing on the word list lexp
52 * Do a (very rudimentary) parse to separate into commands.
53 * If word 0 of a command has an alias, do it.
54 * Repeat a maximum of 50 times.
58 alias(struct wordent *lexp)
66 stderror(ERR_ALIASLOOP);
67 } while (asyntax(lexp->next, lexp) != 0);
71 asyntax(struct wordent *p1, struct wordent *p2)
74 if (!any(";&\n", p1->word[0]))
82 asyn0(struct wordent *p1, struct wordent *p2)
87 for (p = p1; p != p2; p = p->next)
97 stderror(ERR_TOOMANYRP);
101 if (p->next != p2 && eq(p->next->word, STRand))
111 if (asyn3(p1, p) != 0)
113 return asyntax(p->next, p2);
119 return asyn3(p1, p2);
124 alvec_cleanup(void *dummy)
133 asyn3(struct wordent *p1, struct wordent *p2)
136 struct wordent alout;
141 if (p1->word[0] == '(') {
142 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
147 return asyn0(p1->next, p2);
149 ap = adrof1(p1->word, &aliases);
155 cleanup_push(&alvec, alvec_cleanup);
157 cleanup_until(&alvec);
162 if (p1->word[0] && eq(p1->word, alout.next->word)) {
163 Char *cp = alout.next->word;
165 alout.next->word = Strspl(STRQNULL, cp);
168 p1 = freenod(p1, redid ? p2 : p1->next);
169 if (alout.next != &alout) {
170 p1->next->prev = alout.prev->prev;
171 alout.prev->prev->next = p1->next;
172 alout.next->prev = p1;
173 p1->next = alout.next;
174 xfree(alout.prev->word);
180 static struct wordent *
181 freenod(struct wordent *p1, struct wordent *p2)
183 struct wordent *retp = p1->prev;
206 syntax(const struct wordent *p1, const struct wordent *p2, int flags)
210 if (any(";&\n", p1->word[0]))
213 return (syn0(p1, p2, flags));
222 static struct command *
223 syn0(const struct wordent *p1, const struct wordent *p2, int flags)
225 const struct wordent *p;
226 struct command *t, *t1;
230 for (p = p1; p != p2; p = p->next)
231 switch (p->word[0]) {
240 seterror(ERR_TOOMANYRP);
244 if (p->word[1] == '|')
249 if (p->next != p2 && eq(p->next->word, STRand))
256 if (p->word[1] == '&')
258 t1 = syn1(p1, p, flags);
259 if (t1->t_dtyp == NODE_LIST ||
260 t1->t_dtyp == NODE_AND ||
261 t1->t_dtyp == NODE_OR) {
262 t = xcalloc(1, sizeof(*t));
263 t->t_dtyp = NODE_PAREN;
264 t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
269 t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
270 t = xcalloc(1, sizeof(*t));
271 t->t_dtyp = NODE_LIST;
274 t->t_dcdr = syntax(p, p2, flags);
280 return (syn1(p1, p2, flags));
281 seterror(ERR_TOOMANYLP);
290 static struct command *
291 syn1(const struct wordent *p1, const struct wordent *p2, int flags)
293 const struct wordent *p;
298 for (p = p1; p != p2; p = p->next)
299 switch (p->word[0]) {
313 t = xcalloc(1, sizeof(*t));
314 t->t_dtyp = NODE_LIST;
315 t->t_dcar = syn1a(p1, p, flags);
316 t->t_dcdr = syntax(p->next, p2, flags);
318 t->t_dcdr = t->t_dcar, t->t_dcar = 0;
324 return (syn1a(p1, p2, flags));
332 static struct command *
333 syn1a(const struct wordent *p1, const struct wordent *p2, int flags)
335 const struct wordent *p;
339 for (p = p1; p != p2; p = p->next)
340 switch (p->word[0]) {
351 if (p->word[1] != '|')
354 t = xcalloc(1, sizeof(*t));
356 t->t_dcar = syn1b(p1, p, flags);
357 t->t_dcdr = syn1a(p->next, p2, flags);
366 return (syn1b(p1, p2, flags));
374 static struct command *
375 syn1b(const struct wordent *p1, const struct wordent *p2, int flags)
377 const struct wordent *p;
381 for (p = p1; p != p2; p = p->next)
382 switch (p->word[0]) {
393 if (p->word[1] == '&' && l == 0) {
394 t = xcalloc(1, sizeof(*t));
395 t->t_dtyp = NODE_AND;
396 t->t_dcar = syn2(p1, p, flags);
397 t->t_dcdr = syn1b(p->next, p2, flags);
406 return (syn2(p1, p2, flags));
415 static struct command *
416 syn2(const struct wordent *p1, const struct wordent *p2, int flags)
418 const struct wordent *p, *pn;
423 for (p = p1; p != p2; p = p->next)
424 switch (p->word[0]) {
437 t = xcalloc(1, sizeof(*t));
440 if (pn != p2 && pn->word[0] == '&') {
442 t->t_dflg |= F_STDERR;
444 t->t_dtyp = NODE_PIPE;
445 t->t_dcar = syn3(p1, p, f);
446 if (pn != p2 && pn->word[0] == '&')
448 t->t_dcdr = syn2(p->next, p2, flags | P_IN);
454 return (syn3(p1, p2, flags));
457 static const char RELPAR[] = {'<', '>', '(', ')', '\0'};
461 * ( syn0 ) [ < in ] [ > out ]
462 * word word* [ < in ] [ > out ]
463 * KEYWORD ( word* ) word* [ < in ] [ > out ]
465 * KEYWORD = (@ exit foreach if set switch test while)
467 static struct command *
468 syn3(const struct wordent *p1, const struct wordent *p2, int flags)
470 const struct wordent *p;
471 const struct wordent *lp, *rp;
481 switch (srchx(p->word)) {
504 for (p = p1; p != p2; p = p->next)
505 switch (p->word[0]) {
528 if (any(RELPAR, p->next->word[0]))
534 if (!specp && l != 0)
541 t = xcalloc(1, sizeof(*t));
542 av = xcalloc(n + 1, sizeof(Char **));
545 if (p2->word[0] == ')')
546 t->t_dflg = F_NOFORK;
550 for (p = p1; p != p2; p = p->next) {
556 if (lp != 0 && !specp)
557 seterror(ERR_BADPLP);
572 if (p->word[1] == '>')
573 t->t_dflg |= F_APPEND;
574 if (p->next != p2 && eq(p->next->word, STRand)) {
575 t->t_dflg |= F_STDERR, p = p->next;
576 if (flags & (P_OUT | P_DIAG)) {
577 seterror(ERR_OUTRED);
581 if (p->next != p2 && eq(p->next->word, STRbang))
582 t->t_dflg |= F_OVERWRITE, p = p->next;
584 seterror(ERR_MISRED);
588 if (any(RELPAR, p->word[0])) {
589 seterror(ERR_MISRED);
592 if (((flags & P_OUT) && (flags & P_DIAG) == 0) || t->t_drit)
593 seterror(ERR_OUTRED);
595 t->t_drit = Strsave(p->word);
601 if (p->word[1] == '<')
604 seterror(ERR_MISRED);
608 if (any(RELPAR, p->word[0])) {
609 seterror(ERR_MISRED);
612 if ((flags & P_HERE) && (t->t_dflg & F_READ))
613 seterror(ERR_REDPAR);
614 else if ((flags & P_IN) || t->t_dlef)
617 t->t_dlef = Strsave(p->word);
624 if (l != 0 && !specp)
627 av[n] = Strsave(p->word);
632 if (lp != 0 && !specp) {
634 seterror(ERR_BADPLPS);
635 t->t_dtyp = NODE_PAREN;
636 t->t_dspr = syn0(lp, rp, P_HERE);
640 seterror(ERR_NULLCOM);
641 t->t_dtyp = NODE_COMMAND;
647 freesyn(struct command *t)
656 for (v = t->t_dcom; *v; v++)
672 freesyn(t->t_dcar), freesyn(t->t_dcdr);
678 memset(t, 0, sizeof(*t));
684 syntax_cleanup(void *xt)