1 /* $Header: /src/pub/tcsh/sh.parse.c,v 3.11 2002/03/08 17:36:46 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("$Id: sh.parse.c,v 3.11 2002/03/08 17:36:46 christos Exp $")
40 static void asyntax
__P((struct wordent
*, struct wordent
*));
41 static void asyn0
__P((struct wordent
*, struct wordent
*));
42 static void asyn3
__P((struct wordent
*, struct wordent
*));
43 static struct wordent
*freenod
__P((struct wordent
*, struct wordent
*));
44 static struct command
*syn0
__P((struct wordent
*, struct wordent
*, int));
45 static struct command
*syn1
__P((struct wordent
*, struct wordent
*, int));
46 static struct command
*syn1a
__P((struct wordent
*, struct wordent
*, int));
47 static struct command
*syn1b
__P((struct wordent
*, struct wordent
*, int));
48 static struct command
*syn2
__P((struct wordent
*, struct wordent
*, int));
49 static struct command
*syn3
__P((struct wordent
*, 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.
63 register struct wordent
*lexp
;
76 stderror(ERR_ALIASLOOP
);
77 asyntax(lexp
->next
, lexp
);
83 register struct wordent
*p1
, *p2
;
86 if (any(";&\n", p1
->word
[0]))
97 register struct wordent
*p2
;
99 register struct wordent
*p
;
102 for (p
= p1
; p
!= p2
; p
= p
->next
)
103 switch (p
->word
[0]) {
112 stderror(ERR_TOOMANYRP
);
116 if (p
->next
!= p2
&& eq(p
->next
->word
, STRand
))
127 asyntax(p
->next
, p2
);
140 register struct wordent
*p2
;
142 register struct varent
*ap
;
143 struct wordent alout
;
148 if (p1
->word
[0] == '(') {
149 for (p2
= p2
->prev
; p2
->word
[0] != ')'; p2
= p2
->prev
)
157 ap
= adrof1(p1
->word
, &aliases
);
164 alhistp
= alhistt
= 0;
170 if (p1
->word
[0] && eq(p1
->word
, alout
.next
->word
)) {
171 Char
*cp
= alout
.next
->word
;
173 alout
.next
->word
= Strspl(STRQNULL
, cp
);
176 p1
= freenod(p1
, redid
? p2
: p1
->next
);
177 if (alout
.next
!= &alout
) {
178 p1
->next
->prev
= alout
.prev
->prev
;
179 alout
.prev
->prev
->next
= p1
->next
;
180 alout
.next
->prev
= p1
;
181 p1
->next
= alout
.next
;
182 xfree((ptr_t
) alout
.prev
->word
);
183 xfree((ptr_t
) (alout
.prev
));
185 reset(); /* throw! */
188 static struct wordent
*
190 register struct wordent
*p1
, *p2
;
192 register struct wordent
*retp
= p1
->prev
;
195 xfree((ptr_t
) p1
->word
);
197 xfree((ptr_t
) (p1
->prev
));
215 syntax(p1
, p2
, flags
)
216 register struct wordent
*p1
, *p2
;
221 if (any(";&\n", p1
->word
[0]))
224 return (syn0(p1
, p2
, flags
));
233 static struct command
*
235 struct wordent
*p1
, *p2
;
238 register struct wordent
*p
;
239 register struct command
*t
, *t1
;
243 for (p
= p1
; p
!= p2
; p
= p
->next
)
244 switch (p
->word
[0]) {
253 seterror(ERR_TOOMANYRP
);
257 if (p
->word
[1] == '|')
262 if (p
->next
!= p2
&& eq(p
->next
->word
, STRand
))
269 if (p
->word
[1] == '&')
271 t1
= syn1(p1
, p
, flags
);
272 if (t1
->t_dtyp
== NODE_LIST
||
273 t1
->t_dtyp
== NODE_AND
||
274 t1
->t_dtyp
== NODE_OR
) {
275 t
= (struct command
*) xcalloc(1, sizeof(*t
));
276 t
->t_dtyp
= NODE_PAREN
;
277 t
->t_dflg
= F_AMPERSAND
| F_NOINTERRUPT
;
282 t1
->t_dflg
|= F_AMPERSAND
| F_NOINTERRUPT
;
283 t
= (struct command
*) xcalloc(1, sizeof(*t
));
284 t
->t_dtyp
= NODE_LIST
;
287 t
->t_dcdr
= syntax(p
, p2
, flags
);
293 return (syn1(p1
, p2
, flags
));
294 seterror(ERR_TOOMANYLP
);
303 static struct command
*
305 struct wordent
*p1
, *p2
;
308 register struct wordent
*p
;
309 register struct command
*t
;
313 for (p
= p1
; p
!= p2
; p
= p
->next
)
314 switch (p
->word
[0]) {
328 t
= (struct command
*) xcalloc(1, sizeof(*t
));
329 t
->t_dtyp
= NODE_LIST
;
330 t
->t_dcar
= syn1a(p1
, p
, flags
);
331 t
->t_dcdr
= syntax(p
->next
, p2
, flags
);
333 t
->t_dcdr
= t
->t_dcar
, t
->t_dcar
= 0;
339 return (syn1a(p1
, p2
, flags
));
347 static struct command
*
349 struct wordent
*p1
, *p2
;
352 register struct wordent
*p
;
353 register struct command
*t
;
356 for (p
= p1
; p
!= p2
; p
= p
->next
)
357 switch (p
->word
[0]) {
368 if (p
->word
[1] != '|')
371 t
= (struct command
*) xcalloc(1, sizeof(*t
));
373 t
->t_dcar
= syn1b(p1
, p
, flags
);
374 t
->t_dcdr
= syn1a(p
->next
, p2
, flags
);
383 return (syn1b(p1
, p2
, flags
));
391 static struct command
*
393 struct wordent
*p1
, *p2
;
396 register struct wordent
*p
;
397 register struct command
*t
;
400 for (p
= p1
; p
!= p2
; p
= p
->next
)
401 switch (p
->word
[0]) {
412 if (p
->word
[1] == '&' && l
== 0) {
413 t
= (struct command
*) xcalloc(1, sizeof(*t
));
414 t
->t_dtyp
= NODE_AND
;
415 t
->t_dcar
= syn2(p1
, p
, flags
);
416 t
->t_dcdr
= syn1b(p
->next
, p2
, flags
);
425 return (syn2(p1
, p2
, flags
));
434 static struct command
*
436 struct wordent
*p1
, *p2
;
439 register struct wordent
*p
, *pn
;
440 register struct command
*t
;
444 for (p
= p1
; p
!= p2
; p
= p
->next
)
445 switch (p
->word
[0]) {
458 t
= (struct command
*) xcalloc(1, sizeof(*t
));
461 if (pn
!= p2
&& pn
->word
[0] == '&') {
463 t
->t_dflg
|= F_STDERR
;
465 t
->t_dtyp
= NODE_PIPE
;
466 t
->t_dcar
= syn3(p1
, p
, f
);
467 if (pn
!= p2
&& pn
->word
[0] == '&')
469 t
->t_dcdr
= syn2(p
->next
, p2
, flags
| P_IN
);
475 return (syn3(p1
, p2
, flags
));
478 static char RELPAR
[] = {'<', '>', '(', ')', '\0'};
482 * ( syn0 ) [ < in ] [ > out ]
483 * word word* [ < in ] [ > out ]
484 * KEYWORD ( word* ) word* [ < in ] [ > out ]
486 * KEYWORD = (@ exit foreach if set switch test while)
488 static struct command
*
490 struct wordent
*p1
, *p2
;
493 register struct wordent
*p
;
494 struct wordent
*lp
, *rp
;
495 register struct command
*t
;
504 switch (srchx(p
->word
)) {
527 for (p
= p1
; p
!= p2
; p
= p
->next
)
528 switch (p
->word
[0]) {
551 if (any(RELPAR
, p
->next
->word
[0]))
557 if (!specp
&& l
!= 0)
564 t
= (struct command
*) xcalloc(1, sizeof(*t
));
565 av
= (Char
**) xcalloc((size_t) (n
+ 1), sizeof(Char
**));
568 if (p2
->word
[0] == ')')
569 t
->t_dflg
= F_NOFORK
;
573 for (p
= p1
; p
!= p2
; p
= p
->next
) {
579 if (lp
!= 0 && !specp
)
580 seterror(ERR_BADPLP
);
595 if (p
->word
[1] == '>')
596 t
->t_dflg
|= F_APPEND
;
597 if (p
->next
!= p2
&& eq(p
->next
->word
, STRand
)) {
598 t
->t_dflg
|= F_STDERR
, p
= p
->next
;
599 if (flags
& (P_OUT
| P_DIAG
)) {
600 seterror(ERR_OUTRED
);
604 if (p
->next
!= p2
&& eq(p
->next
->word
, STRbang
))
605 t
->t_dflg
|= F_OVERWRITE
, p
= p
->next
;
607 seterror(ERR_MISRED
);
611 if (any(RELPAR
, p
->word
[0])) {
612 seterror(ERR_MISRED
);
615 if (((flags
& P_OUT
) && (flags
& P_DIAG
) == 0) || t
->t_drit
)
616 seterror(ERR_OUTRED
);
618 t
->t_drit
= Strsave(p
->word
);
624 if (p
->word
[1] == '<')
627 seterror(ERR_MISRED
);
631 if (any(RELPAR
, p
->word
[0])) {
632 seterror(ERR_MISRED
);
635 if ((flags
& P_HERE
) && (t
->t_dflg
& F_READ
))
636 seterror(ERR_REDPAR
);
637 else if ((flags
& P_IN
) || t
->t_dlef
)
640 t
->t_dlef
= Strsave(p
->word
);
647 if (l
!= 0 && !specp
)
650 av
[n
] = Strsave(p
->word
);
655 if (lp
!= 0 && !specp
) {
657 seterror(ERR_BADPLPS
);
658 t
->t_dtyp
= NODE_PAREN
;
659 t
->t_dspr
= syn0(lp
, rp
, P_HERE
);
663 seterror(ERR_NULLCOM
);
664 t
->t_dtyp
= NODE_COMMAND
;
671 register struct command
*t
;
680 for (v
= t
->t_dcom
; *v
; v
++)
682 xfree((ptr_t
) (t
->t_dcom
));
683 xfree((ptr_t
) t
->t_dlef
);
684 xfree((ptr_t
) t
->t_drit
);
688 xfree((ptr_t
) t
->t_dlef
);
689 xfree((ptr_t
) t
->t_drit
);
696 freesyn(t
->t_dcar
), freesyn(t
->t_dcdr
);