1 /* $NetBSD: parse.c,v 1.16 2007/07/16 14:07:01 christos Exp $ */
4 * Copyright (c) 1980, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)parse.c 8.1 (Berkeley) 5/31/93";
37 __RCSID("$NetBSD: parse.c,v 1.16 2007/07/16 14:07:01 christos Exp $");
41 #include <sys/types.h>
50 static void asyntax(struct wordent
*, struct wordent
*);
51 static void asyn0(struct wordent
*, struct wordent
*);
52 static void asyn3(struct wordent
*, struct wordent
*);
53 static struct wordent
*freenod(struct wordent
*, struct wordent
*);
54 static struct command
*syn0(struct wordent
*, struct wordent
*, int);
55 static struct command
*syn1(struct wordent
*, struct wordent
*, int);
56 static struct command
*syn1a(struct wordent
*, struct wordent
*, int);
57 static struct command
*syn1b(struct wordent
*, struct wordent
*, int);
58 static struct command
*syn2(struct wordent
*, struct wordent
*, int);
59 static struct command
*syn3(struct wordent
*, struct wordent
*, int);
61 #define ALEFT 21 /* max of 20 alias expansions */
62 #define HLEFT 11 /* max of 10 history expansions */
64 * Perform aliasing on the word list lex
65 * Do a (very rudimentary) parse to separate into commands.
66 * If word 0 of a command has an alias, do it.
67 * Repeat a maximum of 20 times.
73 alias(struct wordent
*lexp
)
86 stderror(ERR_ALIASLOOP
);
87 asyntax(lexp
->next
, lexp
);
92 asyntax(struct wordent
*p1
, struct wordent
*p2
)
95 if (any(";&\n", p1
->word
[0]))
104 asyn0(struct wordent
*p1
, struct wordent
*p2
)
110 for (p
= p1
; p
!= p2
; p
= p
->next
)
111 switch (p
->word
[0]) {
118 stderror(ERR_TOOMANYRP
);
121 if (p
->next
!= p2
&& eq(p
->next
->word
, STRand
))
131 asyntax(p
->next
, p2
);
139 asyn3(struct wordent
*p1
, struct wordent
*p2
)
142 struct wordent alout
;
147 if (p1
->word
[0] == '(') {
148 for (p2
= p2
->prev
; p2
->word
[0] != ')'; p2
= p2
->prev
)
156 ap
= adrof1(p1
->word
, &aliases
);
163 alhistp
= alhistt
= 0;
169 if (p1
->word
[0] && eq(p1
->word
, alout
.next
->word
)) {
172 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
*
189 freenod(struct wordent
*p1
, struct wordent
*p2
)
191 struct wordent
*retp
;
195 xfree((ptr_t
)p1
->word
);
197 xfree((ptr_t
) (p1
->prev
));
215 syntax(struct wordent
*p1
, struct wordent
*p2
, int flags
)
218 if (any(";&\n", p1
->word
[0]))
221 return (syn0(p1
, p2
, flags
));
230 static struct command
*
231 syn0(struct wordent
*p1
, struct wordent
*p2
, int flags
)
234 struct command
*t
, *t1
;
238 for (p
= p1
; p
!= p2
; p
= p
->next
)
239 switch (p
->word
[0]) {
246 seterror(ERR_TOOMANYRP
);
249 if (p
->word
[1] == '|')
253 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
= (struct command
*)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
= (struct command
*)xcalloc(1, sizeof(*t
));
274 t
->t_dtyp
= NODE_LIST
;
277 t
->t_dcdr
= syntax(p
, p2
, flags
);
281 return (syn1(p1
, p2
, flags
));
282 seterror(ERR_TOOMANYLP
);
291 static struct command
*
292 syn1(struct wordent
*p1
, struct wordent
*p2
, int flags
)
299 for (p
= p1
; p
!= p2
; p
= p
->next
)
300 switch (p
->word
[0]) {
311 t
= (struct command
*) xcalloc(1, sizeof(*t
));
312 t
->t_dtyp
= NODE_LIST
;
313 t
->t_dcar
= syn1a(p1
, p
, flags
);
314 t
->t_dcdr
= syntax(p
->next
, p2
, flags
);
316 t
->t_dcdr
= t
->t_dcar
, t
->t_dcar
= 0;
319 return (syn1a(p1
, p2
, flags
));
327 static struct command
*
328 syn1a(struct wordent
*p1
, struct wordent
*p2
, int flags
)
335 for (p
= p1
; p
!= p2
; p
= p
->next
)
336 switch (p
->word
[0]) {
344 if (p
->word
[1] != '|')
347 t
= (struct command
*)xcalloc(1, sizeof(*t
));
349 t
->t_dcar
= syn1b(p1
, p
, flags
);
350 t
->t_dcdr
= syn1a(p
->next
, p2
, flags
);
356 return (syn1b(p1
, p2
, flags
));
364 static struct command
*
365 syn1b(struct wordent
*p1
, struct wordent
*p2
, int flags
)
372 for (p
= p1
; p
!= p2
; p
= p
->next
)
373 switch (p
->word
[0]) {
381 if (p
->word
[1] == '&' && l
== 0) {
382 t
= (struct command
*)xcalloc(1, sizeof(*t
));
383 t
->t_dtyp
= NODE_AND
;
384 t
->t_dcar
= syn2(p1
, p
, flags
);
385 t
->t_dcdr
= syn1b(p
->next
, p2
, flags
);
391 return (syn2(p1
, p2
, flags
));
400 static struct command
*
401 syn2(struct wordent
*p1
, struct wordent
*p2
, int flags
)
403 struct wordent
*p
, *pn
;
408 for (p
= p1
; p
!= p2
; p
= p
->next
)
409 switch (p
->word
[0]) {
419 t
= (struct command
*)xcalloc(1, sizeof(*t
));
422 if (pn
!= p2
&& pn
->word
[0] == '&') {
424 t
->t_dflg
|= F_STDERR
;
426 t
->t_dtyp
= NODE_PIPE
;
427 t
->t_dcar
= syn3(p1
, p
, f
);
428 if (pn
!= p2
&& pn
->word
[0] == '&')
430 t
->t_dcdr
= syn2(p
->next
, p2
, flags
| PIN
);
433 return (syn3(p1
, p2
, flags
));
436 static char RELPAR
[] = {'<', '>', '(', ')', '\0'};
440 * ( syn0 ) [ < in ] [ > out ]
441 * word word* [ < in ] [ > out ]
442 * KEYWORD ( word* ) word* [ < in ] [ > out ]
444 * KEYWORD = (@ exit foreach if set switch test while)
446 static struct command
*
447 syn3(struct wordent
*p1
, struct wordent
*p2
, int flags
)
449 struct wordent
*lp
, *p
, *rp
;
459 switch (srchx(p
->word
)) {
478 for (p
= p1
; p
!= p2
; p
= p
->next
)
479 switch (p
->word
[0]) {
499 if (any(RELPAR
, p
->next
->word
[0]))
504 if (!specp
&& l
!= 0)
511 t
= (struct command
*)xcalloc(1, sizeof(*t
));
512 av
= (Char
**)xcalloc((size_t)(n
+ 1), sizeof(Char
**));
515 if (p2
->word
[0] == ')')
516 t
->t_dflg
= F_NOFORK
;
520 for (p
= p1
; p
!= p2
; p
= p
->next
) {
525 if (lp
!= 0 && !specp
)
526 seterror(ERR_BADPLP
);
539 if (p
->word
[1] == '>')
540 t
->t_dflg
|= F_APPEND
;
541 if (p
->next
!= p2
&& eq(p
->next
->word
, STRand
)) {
542 t
->t_dflg
|= F_STDERR
, p
= p
->next
;
543 if (flags
& (POUT
| PERR
)) {
544 seterror(ERR_OUTRED
);
548 if (p
->next
!= p2
&& eq(p
->next
->word
, STRbang
))
549 t
->t_dflg
|= F_OVERWRITE
, p
= p
->next
;
551 seterror(ERR_MISRED
);
555 if (any(RELPAR
, p
->word
[0])) {
556 seterror(ERR_MISRED
);
559 if ((flags
& POUT
) && ((flags
& PERR
) == 0 || t
->t_drit
))
560 seterror(ERR_OUTRED
);
562 t
->t_drit
= Strsave(p
->word
);
567 if (p
->word
[1] == '<')
570 seterror(ERR_MISRED
);
574 if (any(RELPAR
, p
->word
[0])) {
575 seterror(ERR_MISRED
);
578 if ((flags
& PHERE
) && (t
->t_dflg
& F_READ
))
579 seterror(ERR_REDPAR
);
580 else if ((flags
& PIN
) || t
->t_dlef
)
583 t
->t_dlef
= Strsave(p
->word
);
590 if (l
!= 0 && !specp
)
593 av
[n
] = Strsave(p
->word
);
598 if (lp
!= 0 && !specp
) {
600 seterror(ERR_BADPLPS
);
601 t
->t_dtyp
= NODE_PAREN
;
602 t
->t_dspr
= syn0(lp
, rp
, PHERE
);
606 seterror(ERR_NULLCOM
);
607 t
->t_dtyp
= NODE_COMMAND
;
613 freesyn(struct command
*t
)
621 for (v
= t
->t_dcom
; *v
; v
++)
623 xfree((ptr_t
)(t
->t_dcom
));
624 xfree((ptr_t
)t
->t_dlef
);
625 xfree((ptr_t
)t
->t_drit
);
629 xfree((ptr_t
)t
->t_dlef
);
630 xfree((ptr_t
)t
->t_drit
);
636 freesyn(t
->t_dcar
), freesyn(t
->t_dcdr
);