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
);
625 if (l
!= 0 && !specp
)
628 av
[n
] = Strsave(p
->word
);
633 if (lp
!= 0 && !specp
) {
635 seterror(ERR_BADPLPS
);
636 t
->t_dtyp
= NODE_PAREN
;
637 t
->t_dspr
= syn0(lp
, rp
, P_HERE
);
641 seterror(ERR_NULLCOM
);
642 t
->t_dtyp
= NODE_COMMAND
;
648 freesyn(struct command
*t
)
657 for (v
= t
->t_dcom
; *v
; v
++)
673 freesyn(t
->t_dcar
), freesyn(t
->t_dcdr
);
679 memset(t
, 0, sizeof(*t
));
685 syntax_cleanup(void *xt
)