1 /* $Header: /src/pub/tcsh/sh.parse.c,v 3.10 1996/04/26 19:20:04 christos Exp $ */
3 * sh.parse.c: Interpret a list of tokens
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 RCSID("$Id: sh.parse.c,v 3.10 1996/04/26 19:20:04 christos Exp $")
44 static void asyntax __P((struct wordent *, struct wordent *));
45 static void asyn0 __P((struct wordent *, struct wordent *));
46 static void asyn3 __P((struct wordent *, struct wordent *));
47 static struct wordent *freenod __P((struct wordent *, struct wordent *));
48 static struct command *syn0 __P((struct wordent *, struct wordent *, int));
49 static struct command *syn1 __P((struct wordent *, struct wordent *, int));
50 static struct command *syn1a __P((struct wordent *, struct wordent *, int));
51 static struct command *syn1b __P((struct wordent *, struct wordent *, int));
52 static struct command *syn2 __P((struct wordent *, struct wordent *, int));
53 static struct command *syn3 __P((struct wordent *, struct wordent *, int));
55 #define ALEFT 51 /* max of 50 alias expansions */
56 #define HLEFT 11 /* max of 10 history expansions */
58 * Perform aliasing on the word list lexp
59 * Do a (very rudimentary) parse to separate into commands.
60 * If word 0 of a command has an alias, do it.
61 * Repeat a maximum of 50 times.
67 register struct wordent *lexp;
80 stderror(ERR_ALIASLOOP);
81 asyntax(lexp->next, lexp);
87 register struct wordent *p1, *p2;
90 if (any(";&\n", p1->word[0]))
101 register struct wordent *p2;
103 register struct wordent *p;
106 for (p = p1; p != p2; p = p->next)
107 switch (p->word[0]) {
116 stderror(ERR_TOOMANYRP);
120 if (p->next != p2 && eq(p->next->word, STRand))
131 asyntax(p->next, p2);
144 register struct wordent *p2;
146 register struct varent *ap;
147 struct wordent alout;
152 if (p1->word[0] == '(') {
153 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
161 ap = adrof1(p1->word, &aliases);
168 alhistp = alhistt = 0;
174 if (p1->word[0] && eq(p1->word, alout.next->word)) {
175 Char *cp = alout.next->word;
177 alout.next->word = Strspl(STRQNULL, cp);
180 p1 = freenod(p1, redid ? p2 : p1->next);
181 if (alout.next != &alout) {
182 p1->next->prev = alout.prev->prev;
183 alout.prev->prev->next = p1->next;
184 alout.next->prev = p1;
185 p1->next = alout.next;
186 xfree((ptr_t) alout.prev->word);
187 xfree((ptr_t) (alout.prev));
189 reset(); /* throw! */
192 static struct wordent *
194 register struct wordent *p1, *p2;
196 register struct wordent *retp = p1->prev;
199 xfree((ptr_t) p1->word);
201 xfree((ptr_t) (p1->prev));
219 syntax(p1, p2, flags)
220 register struct wordent *p1, *p2;
225 if (any(";&\n", p1->word[0]))
228 return (syn0(p1, p2, flags));
237 static struct command *
239 struct wordent *p1, *p2;
242 register struct wordent *p;
243 register struct command *t, *t1;
247 for (p = p1; p != p2; p = p->next)
248 switch (p->word[0]) {
257 seterror(ERR_TOOMANYRP);
261 if (p->word[1] == '|')
266 if (p->next != p2 && eq(p->next->word, STRand))
273 if (p->word[1] == '&')
275 t1 = syn1(p1, p, flags);
276 if (t1->t_dtyp == NODE_LIST ||
277 t1->t_dtyp == NODE_AND ||
278 t1->t_dtyp == NODE_OR) {
279 t = (struct command *) xcalloc(1, sizeof(*t));
280 t->t_dtyp = NODE_PAREN;
281 t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
286 t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
287 t = (struct command *) xcalloc(1, sizeof(*t));
288 t->t_dtyp = NODE_LIST;
291 t->t_dcdr = syntax(p, p2, flags);
297 return (syn1(p1, p2, flags));
298 seterror(ERR_TOOMANYLP);
307 static struct command *
309 struct wordent *p1, *p2;
312 register struct wordent *p;
313 register struct command *t;
317 for (p = p1; p != p2; p = p->next)
318 switch (p->word[0]) {
332 t = (struct command *) xcalloc(1, sizeof(*t));
333 t->t_dtyp = NODE_LIST;
334 t->t_dcar = syn1a(p1, p, flags);
335 t->t_dcdr = syntax(p->next, p2, flags);
337 t->t_dcdr = t->t_dcar, t->t_dcar = 0;
343 return (syn1a(p1, p2, flags));
351 static struct command *
353 struct wordent *p1, *p2;
356 register struct wordent *p;
357 register struct command *t;
360 for (p = p1; p != p2; p = p->next)
361 switch (p->word[0]) {
372 if (p->word[1] != '|')
375 t = (struct command *) xcalloc(1, sizeof(*t));
377 t->t_dcar = syn1b(p1, p, flags);
378 t->t_dcdr = syn1a(p->next, p2, flags);
387 return (syn1b(p1, p2, flags));
395 static struct command *
397 struct wordent *p1, *p2;
400 register struct wordent *p;
401 register struct command *t;
404 for (p = p1; p != p2; p = p->next)
405 switch (p->word[0]) {
416 if (p->word[1] == '&' && l == 0) {
417 t = (struct command *) xcalloc(1, sizeof(*t));
418 t->t_dtyp = NODE_AND;
419 t->t_dcar = syn2(p1, p, flags);
420 t->t_dcdr = syn1b(p->next, p2, flags);
429 return (syn2(p1, p2, flags));
438 static struct command *
440 struct wordent *p1, *p2;
443 register struct wordent *p, *pn;
444 register struct command *t;
448 for (p = p1; p != p2; p = p->next)
449 switch (p->word[0]) {
462 t = (struct command *) xcalloc(1, sizeof(*t));
465 if (pn != p2 && pn->word[0] == '&') {
467 t->t_dflg |= F_STDERR;
469 t->t_dtyp = NODE_PIPE;
470 t->t_dcar = syn3(p1, p, f);
471 if (pn != p2 && pn->word[0] == '&')
473 t->t_dcdr = syn2(p->next, p2, flags | P_IN);
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;
497 register struct wordent *p;
498 struct wordent *lp, *rp;
499 register struct command *t;
508 switch (srchx(p->word)) {
531 for (p = p1; p != p2; p = p->next)
532 switch (p->word[0]) {
555 if (any(RELPAR, p->next->word[0]))
561 if (!specp && l != 0)
568 t = (struct command *) xcalloc(1, sizeof(*t));
569 av = (Char **) xcalloc((size_t) (n + 1), sizeof(Char **));
572 if (p2->word[0] == ')')
573 t->t_dflg = F_NOFORK;
577 for (p = p1; p != p2; p = p->next) {
583 if (lp != 0 && !specp)
584 seterror(ERR_BADPLP);
599 if (p->word[1] == '>')
600 t->t_dflg |= F_APPEND;
601 if (p->next != p2 && eq(p->next->word, STRand)) {
602 t->t_dflg |= F_STDERR, p = p->next;
603 if (flags & (P_OUT | P_DIAG)) {
604 seterror(ERR_OUTRED);
608 if (p->next != p2 && eq(p->next->word, STRbang))
609 t->t_dflg |= F_OVERWRITE, p = p->next;
611 seterror(ERR_MISRED);
615 if (any(RELPAR, p->word[0])) {
616 seterror(ERR_MISRED);
619 if (((flags & P_OUT) && (flags & P_DIAG) == 0) || t->t_drit)
620 seterror(ERR_OUTRED);
622 t->t_drit = Strsave(p->word);
628 if (p->word[1] == '<')
631 seterror(ERR_MISRED);
635 if (any(RELPAR, p->word[0])) {
636 seterror(ERR_MISRED);
639 if ((flags & P_HERE) && (t->t_dflg & F_READ))
640 seterror(ERR_REDPAR);
641 else if ((flags & P_IN) || t->t_dlef)
644 t->t_dlef = Strsave(p->word);
651 if (l != 0 && !specp)
654 av[n] = Strsave(p->word);
659 if (lp != 0 && !specp) {
661 seterror(ERR_BADPLPS);
662 t->t_dtyp = NODE_PAREN;
663 t->t_dspr = syn0(lp, rp, P_HERE);
667 seterror(ERR_NULLCOM);
668 t->t_dtyp = NODE_COMMAND;
675 register struct command *t;
684 for (v = t->t_dcom; *v; v++)
686 xfree((ptr_t) (t->t_dcom));
687 xfree((ptr_t) t->t_dlef);
688 xfree((ptr_t) t->t_drit);
692 xfree((ptr_t) t->t_dlef);
693 xfree((ptr_t) t->t_drit);
700 freesyn(t->t_dcar), freesyn(t->t_dcdr);