2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
10 * Copyright (c) 1980 Regents of the University of California.
11 * All rights reserved. The Berkeley Software License Agreement
12 * specifies the terms and conditions for redistribution.
15 #pragma ident "%Z%%M% %I% %E% SMI"
18 #include "sh.tconst.h"
24 void asyntax(struct wordent
*, struct wordent
*);
25 void asyn0(struct wordent
*, struct wordent
*);
26 void asyn3(struct wordent
*, struct wordent
*);
27 void chr_blkfree(char **);
28 struct command
*syn0(struct wordent
*, struct wordent
*, int);
29 struct command
*syn1(struct wordent
*, struct wordent
*, int);
30 struct command
*syn1a(struct wordent
*, struct wordent
*, int);
31 struct command
*syn1b(struct wordent
*, struct wordent
*, int);
32 struct command
*syn2(struct wordent
*, struct wordent
*, int);
33 struct command
*syn3(struct wordent
*, struct wordent
*, int);
34 struct wordent
*freenod(struct wordent
*, struct wordent
*);
37 * Perform aliasing on the word list lex
38 * Do a (very rudimentary) parse to separate into commands.
39 * If word 0 of a command has an alias, do it.
40 * Repeat a maximum of 20 times.
43 alias(struct wordent
*lex
)
49 tprintf("TRACE- alias()\n");
59 asyntax(lex
->next
, lex
);
64 asyntax(struct wordent
*p1
, struct wordent
*p2
)
67 tprintf("TRACE- asyntax()\n");
71 /* if (any(p1->word[0], ";&\n")) */ /* For char -> tchar */
72 if (p1
->word
[0] == ';' ||
83 asyn0(struct wordent
*p1
, struct wordent
*p2
)
89 tprintf("TRACE- asyn0()\n");
91 for (p
= p1
; p
!= p2
; p
= p
->next
)
101 error("Too many )'s");
105 if (p
->next
!= p2
&& eq(p
->next
->word
, S_AND
/* "&"*/))
116 asyntax(p
->next
, p2
);
124 asyn3(struct wordent
*p1
, struct wordent
*p2
)
127 struct wordent alout
;
131 tprintf("TRACE- asyn3()\n");
135 if (p1
->word
[0] == '(') {
136 for (p2
= p2
->prev
; p2
->word
[0] != ')'; p2
= p2
->prev
)
144 ap
= adrof1(p1
->word
, &aliases
);
151 alhistp
= alhistt
= 0;
155 error("%s", gettext(err
));
157 if (p1
->word
[0] && eq(p1
->word
, alout
.next
->word
)) {
158 tchar
*cp
= alout
.next
->word
;
160 alout
.next
->word
= strspl(S_TOPBIT
/* "\200" */, cp
);
163 p1
= freenod(p1
, redid
? p2
: p1
->next
);
164 if (alout
.next
!= &alout
) {
165 p1
->next
->prev
= alout
.prev
->prev
;
166 alout
.prev
->prev
->next
= p1
->next
;
167 alout
.next
->prev
= p1
;
168 p1
->next
= alout
.next
;
169 xfree(alout
.prev
->word
);
172 reset(); /* throw! */
176 freenod(struct wordent
*p1
, struct wordent
*p2
)
178 struct wordent
*retp
= p1
->prev
;
181 tprintf("TRACE- freenod()\n");
204 syntax(struct wordent
*p1
, struct wordent
*p2
, int flags
)
207 tprintf("TRACE- syntax()\n");
211 /* if (any(p1->word[0], ";&\n")) */ /* for char -> tchar */
212 if (p1
->word
[0] == ';' ||
213 p1
->word
[0] == '&' ||
217 return (syn0(p1
, p2
, flags
));
227 syn0(struct wordent
*p1
, struct wordent
*p2
, int flags
)
230 struct command
*t
, *t1
;
234 tprintf("TRACE- syn0()\n");
237 for (p
= p1
; p
!= p2
; p
= p
->next
)
238 switch (p
->word
[0]) {
247 seterr("Too many )'s");
251 if (p
->word
[1] == '|')
256 if (p
->next
!= p2
&& eq(p
->next
->word
, S_AND
/* "&" */))
263 if (p
->word
[1] == '&')
265 t1
= syn1(p1
, p
, flags
);
266 if (t1
->t_dtyp
== TLST
||
267 t1
->t_dtyp
== TAND
||
269 t
= (struct command
*)xcalloc(1, sizeof (*t
));
271 t
->t_dflg
= FAND
|FINT
;
275 t1
->t_dflg
|= FAND
|FINT
;
276 t
= (struct command
*)xcalloc(1, sizeof (*t
));
280 t
->t_dcdr
= syntax(p
, p2
, flags
);
284 return (syn1(p1
, p2
, flags
));
285 seterr("Too many ('s");
295 syn1(struct wordent
*p1
, struct wordent
*p2
, int flags
)
302 tprintf("TRACE- syn1()\n");
305 for (p
= p1
; p
!= p2
; p
= p
->next
)
306 switch (p
->word
[0]) {
320 t
= (struct command
*)xcalloc(1, sizeof (*t
));
322 t
->t_dcar
= syn1a(p1
, p
, flags
);
323 t
->t_dcdr
= syntax(p
->next
, p2
, flags
);
325 t
->t_dcdr
= t
->t_dcar
, t
->t_dcar
= 0;
328 return (syn1a(p1
, p2
, flags
));
337 syn1a(struct wordent
*p1
, struct wordent
*p2
, int flags
)
344 tprintf("TRACE- syn1a()\n");
346 for (p
= p1
; p
!= p2
; p
= p
->next
)
347 switch (p
->word
[0]) {
358 if (p
->word
[1] != '|')
361 t
= (struct command
*)xcalloc(1, sizeof (*t
));
363 t
->t_dcar
= syn1b(p1
, p
, flags
);
364 t
->t_dcdr
= syn1a(p
->next
, p2
, flags
);
370 return (syn1b(p1
, p2
, flags
));
379 syn1b(struct wordent
*p1
, struct wordent
*p2
, int flags
)
386 tprintf("TRACE- syn1b()\n");
389 for (p
= p1
; p
!= p2
; p
= p
->next
)
390 switch (p
->word
[0]) {
401 if (p
->word
[1] == '&' && l
== 0) {
402 t
= (struct command
*)xcalloc(1, sizeof (*t
));
404 t
->t_dcar
= syn2(p1
, p
, flags
);
405 t
->t_dcdr
= syn1b(p
->next
, p2
, flags
);
411 return (syn2(p1
, p2
, flags
));
421 syn2(struct wordent
*p1
, struct wordent
*p2
, int flags
)
423 struct wordent
*p
, *pn
;
429 tprintf("TRACE- syn2()\n");
431 for (p
= p1
; p
!= p2
; p
= p
->next
)
432 switch (p
->word
[0]) {
445 t
= (struct command
*)xcalloc(1, sizeof (*t
));
448 if (pn
!= p2
&& pn
->word
[0] == '&') {
453 t
->t_dcar
= syn3(p1
, p
, f
);
454 if (pn
!= p2
&& pn
->word
[0] == '&')
456 t
->t_dcdr
= syn2(p
->next
, p2
, flags
| PIN
);
459 return (syn3(p1
, p2
, flags
));
462 tchar RELPAR
[] = {'<', '>', '(', ')', 0}; /* "<>()" */
466 * ( syn0 ) [ < in ] [ > out ]
467 * word word* [ < in ] [ > out ]
468 * KEYWORD ( word* ) word* [ < in ] [ > out ]
470 * KEYWORD = (@ exit foreach if set switch test while)
473 syn3(struct wordent
*p1
, struct wordent
*p2
, int flags
)
476 struct wordent
*lp
, *rp
;
484 tprintf("TRACE- syn3()\n");
489 switch (srchx(p
->word
)) {
510 for (p
= p1
; p
!= p2
; p
= p
->next
)
511 switch (p
->word
[0]) {
534 if (any(p
->next
->word
[0], RELPAR
))
540 if (!specp
&& l
!= 0)
547 t
= (struct command
*)xcalloc(1, sizeof (*t
));
548 av
= (tchar
**)xcalloc((unsigned)(n
+ 1), sizeof (tchar
**));
551 if (p2
->word
[0] == ')')
556 for (p
= p1
; p
!= p2
; p
= p
->next
) {
562 if (lp
!= 0 && !specp
)
563 seterr("Badly placed (");
578 if (p
->word
[1] == '>')
580 if (p
->next
!= p2
&& eq(p
->next
->word
, S_AND
/* "&" */)) {
581 t
->t_dflg
|= FDIAG
, p
= p
->next
;
582 if (flags
& (POUT
|PDIAG
))
585 if (p
->next
!= p2
&& eq(p
->next
->word
, S_EXAS
/* "!" */))
586 t
->t_dflg
|= FANY
, p
= p
->next
;
589 seterr("Missing name for redirect");
593 if (any(p
->word
[0], RELPAR
))
595 if ((flags
& POUT
) && (flags
& PDIAG
) == 0 || t
->t_drit
)
597 seterr("Ambiguous output redirect");
599 t
->t_drit
= savestr(p
->word
);
605 if (p
->word
[1] == '<')
610 if (any(p
->word
[0], RELPAR
))
612 if ((flags
& PHERE
) && (t
->t_dflg
& FHERE
))
613 seterr("Can't << within ()'s");
614 else if ((flags
& PIN
) || t
->t_dlef
)
615 seterr("Ambiguous input redirect");
617 t
->t_dlef
= savestr(p
->word
);
624 if (l
!= 0 && !specp
)
627 av
[n
] = savestr(p
->word
);
632 if (lp
!= 0 && !specp
) {
634 seterr("Badly placed ()'s");
636 t
->t_dspr
= syn0(lp
, rp
, PHERE
);
639 seterr("Invalid null command");
646 freesyn(struct command
*t
)
649 tprintf("TRACE- freesyn()\n");
660 chr_blkfree(t
->cargs
);
676 freesyn(t
->t_dcar
), freesyn(t
->t_dcdr
);
684 chr_blkfree(char **vec
)
688 for (av
= vec
; *av
; av
++)