2 * Copyright (c) 1980, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 5/31/93";
38 static const char rcsid[] =
39 "$Id: parse.c,v 1.7 1998/05/06 06:50:56 charnier Exp $";
43 #include <sys/types.h>
54 static void asyntax __P((struct wordent *, struct wordent *));
55 static void asyn0 __P((struct wordent *, struct wordent *));
56 static void asyn3 __P((struct wordent *, struct wordent *));
58 *freenod __P((struct wordent *, struct wordent *));
60 *syn0 __P((struct wordent *, struct wordent *, int));
62 *syn1 __P((struct wordent *, struct wordent *, int));
64 *syn1a __P((struct wordent *, struct wordent *, int));
66 *syn1b __P((struct wordent *, struct wordent *, int));
68 *syn2 __P((struct wordent *, struct wordent *, int));
70 *syn3 __P((struct wordent *, struct wordent *, int));
72 #define ALEFT 21 /* max of 20 alias expansions */
73 #define HLEFT 11 /* max of 10 history expansions */
75 * Perform aliasing on the word list lex
76 * Do a (very rudimentary) parse to separate into commands.
77 * If word 0 of a command has an alias, do it.
78 * Repeat a maximum of 20 times.
97 stderror(ERR_ALIASLOOP);
98 asyntax(lex->next, lex);
104 struct wordent *p1, *p2;
107 if (any(";&\n", p1->word[0]))
123 for (p = p1; p != p2; p = p->next)
124 switch (p->word[0]) {
133 stderror(ERR_TOOMANYRP);
137 if (p->next != p2 && eq(p->next->word, STRand))
148 asyntax(p->next, p2);
161 struct wordent alout;
166 if (p1->word[0] == '(') {
167 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
175 ap = adrof1(p1->word, &aliases);
182 alhistp = alhistt = 0;
188 if (p1->word[0] && eq(p1->word, alout.next->word)) {
189 Char *cp = alout.next->word;
191 alout.next->word = Strspl(STRQNULL, cp);
194 p1 = freenod(p1, redid ? p2 : p1->next);
195 if (alout.next != &alout) {
196 p1->next->prev = alout.prev->prev;
197 alout.prev->prev->next = p1->next;
198 alout.next->prev = p1;
199 p1->next = alout.next;
200 xfree((ptr_t) alout.prev->word);
201 xfree((ptr_t) (alout.prev));
203 reset(); /* throw! */
206 static struct wordent *
208 struct wordent *p1, *p2;
210 struct wordent *retp = p1->prev;
213 xfree((ptr_t) p1->word);
215 xfree((ptr_t) (p1->prev));
233 syntax(p1, p2, flags)
234 struct wordent *p1, *p2;
239 if (any(";&\n", p1->word[0]))
242 return (syn0(p1, p2, flags));
251 static struct command *
253 struct wordent *p1, *p2;
257 struct command *t, *t1;
261 for (p = p1; p != p2; p = p->next)
262 switch (p->word[0]) {
271 seterror(ERR_TOOMANYRP);
275 if (p->word[1] == '|')
280 if (p->next != p2 && eq(p->next->word, STRand))
287 if (p->word[1] == '&')
289 t1 = syn1(p1, p, flags);
290 if (t1->t_dtyp == NODE_LIST ||
291 t1->t_dtyp == NODE_AND ||
292 t1->t_dtyp == NODE_OR) {
293 t = (struct command *) xcalloc(1, sizeof(*t));
294 t->t_dtyp = NODE_PAREN;
295 t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
300 t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
301 t = (struct command *) xcalloc(1, sizeof(*t));
302 t->t_dtyp = NODE_LIST;
305 t->t_dcdr = syntax(p, p2, flags);
309 return (syn1(p1, p2, flags));
310 seterror(ERR_TOOMANYLP);
319 static struct command *
321 struct wordent *p1, *p2;
329 for (p = p1; p != p2; p = p->next)
330 switch (p->word[0]) {
344 t = (struct command *) xcalloc(1, sizeof(*t));
345 t->t_dtyp = NODE_LIST;
346 t->t_dcar = syn1a(p1, p, flags);
347 t->t_dcdr = syntax(p->next, p2, flags);
349 t->t_dcdr = t->t_dcar, t->t_dcar = 0;
352 return (syn1a(p1, p2, flags));
360 static struct command *
362 struct wordent *p1, *p2;
369 for (p = p1; p != p2; p = p->next)
370 switch (p->word[0]) {
381 if (p->word[1] != '|')
384 t = (struct command *) xcalloc(1, sizeof(*t));
386 t->t_dcar = syn1b(p1, p, flags);
387 t->t_dcdr = syn1a(p->next, p2, flags);
393 return (syn1b(p1, p2, flags));
401 static struct command *
403 struct wordent *p1, *p2;
410 for (p = p1; p != p2; p = p->next)
411 switch (p->word[0]) {
422 if (p->word[1] == '&' && l == 0) {
423 t = (struct command *) xcalloc(1, sizeof(*t));
424 t->t_dtyp = NODE_AND;
425 t->t_dcar = syn2(p1, p, flags);
426 t->t_dcdr = syn1b(p->next, p2, flags);
432 return (syn2(p1, p2, flags));
441 static struct command *
443 struct wordent *p1, *p2;
446 struct wordent *p, *pn;
451 for (p = p1; p != p2; p = p->next)
452 switch (p->word[0]) {
465 t = (struct command *) xcalloc(1, sizeof(*t));
468 if (pn != p2 && pn->word[0] == '&') {
470 t->t_dflg |= F_STDERR;
472 t->t_dtyp = NODE_PIPE;
473 t->t_dcar = syn3(p1, p, f);
474 if (pn != p2 && pn->word[0] == '&')
476 t->t_dcdr = syn2(p->next, p2, flags | PIN);
479 return (syn3(p1, p2, flags));
482 static char RELPAR[] = {'<', '>', '(', ')', '\0'};
486 * ( syn0 ) [ < in ] [ > out ]
487 * word word* [ < in ] [ > out ]
488 * KEYWORD ( word* ) word* [ < in ] [ > out ]
490 * KEYWORD = (@ exit foreach if set switch test while)
492 static struct command *
494 struct wordent *p1, *p2;
498 struct wordent *lp, *rp;
508 switch (srchx(p->word)) {
529 for (p = p1; p != p2; p = p->next)
530 switch (p->word[0]) {
553 if (any(RELPAR, p->next->word[0]))
559 if (!specp && l != 0)
566 t = (struct command *) xcalloc(1, sizeof(*t));
567 av = (Char **) xcalloc((size_t) (n + 1), sizeof(Char **));
570 if (p2->word[0] == ')')
571 t->t_dflg = F_NOFORK;
575 for (p = p1; p != p2; p = p->next) {
581 if (lp != 0 && !specp)
582 seterror(ERR_BADPLP);
597 if (p->word[1] == '>')
598 t->t_dflg |= F_APPEND;
599 if (p->next != p2 && eq(p->next->word, STRand)) {
600 t->t_dflg |= F_STDERR, p = p->next;
601 if (flags & (POUT | PERR)) {
602 seterror(ERR_OUTRED);
606 if (p->next != p2 && eq(p->next->word, STRbang))
607 t->t_dflg |= F_OVERWRITE, p = p->next;
609 seterror(ERR_MISRED);
613 if (any(RELPAR, p->word[0])) {
614 seterror(ERR_MISRED);
617 if ((flags & POUT) && ((flags & PERR) == 0 || t->t_drit))
618 seterror(ERR_OUTRED);
620 t->t_drit = Strsave(p->word);
626 if (p->word[1] == '<')
629 seterror(ERR_MISRED);
633 if (any(RELPAR, p->word[0])) {
634 seterror(ERR_MISRED);
637 if ((flags & PHERE) && (t->t_dflg & F_READ))
638 seterror(ERR_REDPAR);
639 else if ((flags & PIN) || t->t_dlef)
642 t->t_dlef = Strsave(p->word);
649 if (l != 0 && !specp)
652 av[n] = Strsave(p->word);
657 if (lp != 0 && !specp) {
659 seterror(ERR_BADPLPS);
660 t->t_dtyp = NODE_PAREN;
661 t->t_dspr = syn0(lp, rp, PHERE);
665 seterror(ERR_NULLCOM);
666 t->t_dtyp = NODE_COMMAND;
682 for (v = t->t_dcom; *v; v++)
684 xfree((ptr_t) (t->t_dcom));
685 xfree((ptr_t) t->t_dlef);
686 xfree((ptr_t) t->t_drit);
690 xfree((ptr_t) t->t_dlef);
691 xfree((ptr_t) t->t_drit);
698 freesyn(t->t_dcar), freesyn(t->t_dcdr);