1 /* $Header: /p/tcsh/cvsroot/tcsh/sh.parse.c,v 3.18 2006/03/02 18:46:44 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. 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
35 RCSID("$tcsh: sh.parse.c,v 3.18 2006/03/02 18:46:44 christos Exp $")
40 static int asyntax (struct wordent *, struct wordent *);
41 static int asyn0 (struct wordent *, struct wordent *);
42 static int asyn3 (struct wordent *, struct wordent *);
43 static struct wordent *freenod (struct wordent *, struct wordent *);
44 static struct command *syn0 (const struct wordent *, const struct wordent *, int);
45 static struct command *syn1 (const struct wordent *, const struct wordent *, int);
46 static struct command *syn1a (const struct wordent *, const struct wordent *, int);
47 static struct command *syn1b (const struct wordent *, const struct wordent *, int);
48 static struct command *syn2 (const struct wordent *, const struct wordent *, int);
49 static struct command *syn3 (const struct wordent *, const struct wordent *, int);
51 #define ALEFT 51 /* max of 50 alias expansions */
52 #define HLEFT 11 /* max of 10 history expansions */
54 * Perform aliasing on the word list lexp
55 * Do a (very rudimentary) parse to separate into commands.
56 * If word 0 of a command has an alias, do it.
57 * Repeat a maximum of 50 times.
61 alias(struct wordent *lexp)
69 stderror(ERR_ALIASLOOP);
70 } while (asyntax(lexp->next, lexp) != 0);
74 asyntax(struct wordent *p1, struct wordent *p2)
77 if (!any(";&\n", p1->word[0]))
85 asyn0(struct wordent *p1, struct wordent *p2)
90 for (p = p1; p != p2; p = p->next)
100 stderror(ERR_TOOMANYRP);
104 if (p->next != p2 && eq(p->next->word, STRand))
114 if (asyn3(p1, p) != 0)
116 return asyntax(p->next, p2);
122 return asyn3(p1, p2);
127 alvec_cleanup(void *dummy)
136 asyn3(struct wordent *p1, struct wordent *p2)
139 struct wordent alout;
144 if (p1->word[0] == '(') {
145 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
150 return asyn0(p1->next, p2);
152 ap = adrof1(p1->word, &aliases);
158 cleanup_push(&alvec, alvec_cleanup);
160 cleanup_until(&alvec);
165 if (p1->word[0] && eq(p1->word, alout.next->word)) {
166 Char *cp = alout.next->word;
168 alout.next->word = Strspl(STRQNULL, cp);
171 p1 = freenod(p1, redid ? p2 : p1->next);
172 if (alout.next != &alout) {
173 p1->next->prev = alout.prev->prev;
174 alout.prev->prev->next = p1->next;
175 alout.next->prev = p1;
176 p1->next = alout.next;
177 xfree(alout.prev->word);
183 static struct wordent *
184 freenod(struct wordent *p1, struct wordent *p2)
186 struct wordent *retp = p1->prev;
209 syntax(const struct wordent *p1, const struct wordent *p2, int flags)
213 if (any(";&\n", p1->word[0]))
216 return (syn0(p1, p2, flags));
225 static struct command *
226 syn0(const struct wordent *p1, const struct wordent *p2, int flags)
228 const struct wordent *p;
229 struct command *t, *t1;
233 for (p = p1; p != p2; p = p->next)
234 switch (p->word[0]) {
243 seterror(ERR_TOOMANYRP);
247 if (p->word[1] == '|')
252 if (p->next != p2 && eq(p->next->word, STRand))
259 if (p->word[1] == '&')
261 t1 = syn1(p1, p, flags);
262 if (t1->t_dtyp == NODE_LIST ||
263 t1->t_dtyp == NODE_AND ||
264 t1->t_dtyp == NODE_OR) {
265 t = xcalloc(1, sizeof(*t));
266 t->t_dtyp = NODE_PAREN;
267 t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
272 t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
273 t = xcalloc(1, sizeof(*t));
274 t->t_dtyp = NODE_LIST;
277 t->t_dcdr = syntax(p, p2, flags);
283 return (syn1(p1, p2, flags));
284 seterror(ERR_TOOMANYLP);
293 static struct command *
294 syn1(const struct wordent *p1, const struct wordent *p2, int flags)
296 const struct wordent *p;
301 for (p = p1; p != p2; p = p->next)
302 switch (p->word[0]) {
316 t = xcalloc(1, sizeof(*t));
317 t->t_dtyp = NODE_LIST;
318 t->t_dcar = syn1a(p1, p, flags);
319 t->t_dcdr = syntax(p->next, p2, flags);
321 t->t_dcdr = t->t_dcar, t->t_dcar = 0;
327 return (syn1a(p1, p2, flags));
335 static struct command *
336 syn1a(const struct wordent *p1, const struct wordent *p2, int flags)
338 const struct wordent *p;
342 for (p = p1; p != p2; p = p->next)
343 switch (p->word[0]) {
354 if (p->word[1] != '|')
357 t = xcalloc(1, sizeof(*t));
359 t->t_dcar = syn1b(p1, p, flags);
360 t->t_dcdr = syn1a(p->next, p2, flags);
369 return (syn1b(p1, p2, flags));
377 static struct command *
378 syn1b(const struct wordent *p1, const struct wordent *p2, int flags)
380 const struct wordent *p;
384 for (p = p1; p != p2; p = p->next)
385 switch (p->word[0]) {
396 if (p->word[1] == '&' && l == 0) {
397 t = xcalloc(1, sizeof(*t));
398 t->t_dtyp = NODE_AND;
399 t->t_dcar = syn2(p1, p, flags);
400 t->t_dcdr = syn1b(p->next, p2, flags);
409 return (syn2(p1, p2, flags));
418 static struct command *
419 syn2(const struct wordent *p1, const struct wordent *p2, int flags)
421 const struct wordent *p, *pn;
426 for (p = p1; p != p2; p = p->next)
427 switch (p->word[0]) {
440 t = xcalloc(1, sizeof(*t));
443 if (pn != p2 && pn->word[0] == '&') {
445 t->t_dflg |= F_STDERR;
447 t->t_dtyp = NODE_PIPE;
448 t->t_dcar = syn3(p1, p, f);
449 if (pn != p2 && pn->word[0] == '&')
451 t->t_dcdr = syn2(p->next, p2, flags | P_IN);
457 return (syn3(p1, p2, flags));
460 static const char RELPAR[] = {'<', '>', '(', ')', '\0'};
464 * ( syn0 ) [ < in ] [ > out ]
465 * word word* [ < in ] [ > out ]
466 * KEYWORD ( word* ) word* [ < in ] [ > out ]
468 * KEYWORD = (@ exit foreach if set switch test while)
470 static struct command *
471 syn3(const struct wordent *p1, const struct wordent *p2, int flags)
473 const struct wordent *p;
474 const struct wordent *lp, *rp;
484 switch (srchx(p->word)) {
507 for (p = p1; p != p2; p = p->next)
508 switch (p->word[0]) {
531 if (any(RELPAR, p->next->word[0]))
537 if (!specp && l != 0)
544 t = xcalloc(1, sizeof(*t));
545 av = xcalloc(n + 1, sizeof(Char **));
548 if (p2->word[0] == ')')
549 t->t_dflg = F_NOFORK;
553 for (p = p1; p != p2; p = p->next) {
559 if (lp != 0 && !specp)
560 seterror(ERR_BADPLP);
575 if (p->word[1] == '>')
576 t->t_dflg |= F_APPEND;
577 if (p->next != p2 && eq(p->next->word, STRand)) {
578 t->t_dflg |= F_STDERR, p = p->next;
579 if (flags & (P_OUT | P_DIAG)) {
580 seterror(ERR_OUTRED);
584 if (p->next != p2 && eq(p->next->word, STRbang))
585 t->t_dflg |= F_OVERWRITE, p = p->next;
587 seterror(ERR_MISRED);
591 if (any(RELPAR, p->word[0])) {
592 seterror(ERR_MISRED);
595 if (((flags & P_OUT) && (flags & P_DIAG) == 0) || t->t_drit)
596 seterror(ERR_OUTRED);
598 t->t_drit = Strsave(p->word);
604 if (p->word[1] == '<')
607 seterror(ERR_MISRED);
611 if (any(RELPAR, p->word[0])) {
612 seterror(ERR_MISRED);
615 if ((flags & P_HERE) && (t->t_dflg & F_READ))
616 seterror(ERR_REDPAR);
617 else if ((flags & P_IN) || t->t_dlef)
620 t->t_dlef = Strsave(p->word);
627 if (l != 0 && !specp)
630 av[n] = Strsave(p->word);
635 if (lp != 0 && !specp) {
637 seterror(ERR_BADPLPS);
638 t->t_dtyp = NODE_PAREN;
639 t->t_dspr = syn0(lp, rp, P_HERE);
643 seterror(ERR_NULLCOM);
644 t->t_dtyp = NODE_COMMAND;
650 freesyn(struct command *t)
659 for (v = t->t_dcom; *v; v++)
675 freesyn(t->t_dcar), freesyn(t->t_dcdr);
684 syntax_cleanup(void *xt)