2 * shell parser (C version)
10 struct nesting_state
{
11 int start_token
; /* token than began nesting (eg, FOR) */
12 int start_line
; /* line nesting began on */
15 static void yyparse
ARGS((void));
16 static struct op
*pipeline
ARGS((int cf
));
17 static struct op
*andor
ARGS((void));
18 static struct op
*c_list
ARGS((int multi
));
19 static struct ioword
*synio
ARGS((int cf
));
20 static struct op
*nested
ARGS((int type
, int smark
, int emark
));
21 static struct op
*get_command
ARGS((int cf
));
22 static struct op
*dogroup
ARGS((void));
23 static struct op
*thenpart
ARGS((void));
24 static struct op
*elsepart
ARGS((void));
25 static struct op
*caselist
ARGS((void));
26 static struct op
*casepart
ARGS((int endtok
));
27 static struct op
*function_body
ARGS((char *name
));
28 static char ** wordlist
ARGS((void));
29 static struct op
*block
ARGS((int type
, struct op
*t1
, struct op
*t2
,
31 static struct op
*newtp
ARGS((int type
));
32 static void syntaxerr
ARGS((const char *what
))
33 GCC_FUNC_ATTR(noreturn
);
34 static void nesting_push
ARGS((struct nesting_state
*save
, int tok
));
35 static void nesting_pop
ARGS((struct nesting_state
*saved
));
36 static int assign_command
ARGS((char *s
));
37 static int inalias
ARGS((struct source
*s
));
39 static int dbtestp_isa
ARGS((Test_env
*te
, Test_meta meta
));
40 static const char *dbtestp_getopnd
ARGS((Test_env
*te
, Test_op op
,
42 static int dbtestp_eval
ARGS((Test_env
*te
, Test_op op
, const char *opnd1
,
43 const char *opnd2
, int do_eval
));
44 static void dbtestp_error
ARGS((Test_env
*te
, int offset
, const char *msg
));
47 static struct op
*outtree
; /* yyparse output */
49 static struct nesting_state nesting
; /* \n changed to ; */
51 static int reject
; /* token(cf) gets symbol again */
52 static int symbol
; /* yylex value */
54 #define REJECT (reject = 1)
55 #define ACCEPT (reject = 0)
56 #define token(cf) ((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf)))
57 #define tpeek(cf) ((reject) ? (symbol) : (REJECT, symbol = yylex(cf)))
58 #define musthave(c,cf) do { if (token(cf) != (c)) syntaxerr(NULL); } while (0)
67 outtree
= c_list(source
->type
== SSTRING
);
69 if (c
== 0 && !outtree
)
70 outtree
= newtp(TEOF
);
71 else if (c
!= '\n' && c
!= 0)
78 struct op
*t
, *p
, *tl
= NULL
;
82 while (token(0) == '|') {
83 if ((p
= get_command(CONTIN
)) == NULL
)
86 t
= tl
= block(TPIPE
, t
, p
, NOWORDS
);
88 tl
= tl
->right
= block(TPIPE
, tl
->right
, p
, NOWORDS
);
103 while ((c
= token(0)) == LOGAND
|| c
== LOGOR
) {
104 if ((p
= pipeline(CONTIN
)) == NULL
)
106 t
= block(c
== LOGAND
? TAND
: TOR
, t
, p
, NOWORDS
);
116 struct op
*t
= NULL
, *p
, *tl
= NULL
;
121 /* Token has always been read/rejected at this point, so
122 * we don't worry about what flags to pass token()
126 if (c
== '\n' && (multi
|| inalias(source
))) {
127 if (!p
) /* ignore blank lines */
131 else if (c
== '&' || c
== COPROC
)
132 p
= block(c
== '&' ? TASYNC
: TCOPROC
,
133 p
, NOBLOCK
, NOWORDS
);
139 t
= tl
= block(TLIST
, t
, p
, NOWORDS
);
141 tl
= tl
->right
= block(TLIST
, tl
->right
, p
, NOWORDS
);
149 static struct ioword
*
153 static struct ioword
*nextiop
= NULL
;
156 if (nextiop
!= NULL
) {
162 if (tpeek(cf
) != REDIR
)
166 ishere
= (iop
->flag
&IOTYPE
) == IOHERE
;
167 musthave(LWORD
, ishere
? HEREDELIM
: 0);
169 iop
->delim
= yylval
.cp
;
170 if (*ident
!= 0) /* unquoted */
172 if (herep
> &heres
[HERES
- 1])
173 yyerror("too many <<'s\n");
176 iop
->name
= yylval
.cp
;
182 nested(int type
, int smark
, int emark
)
185 struct nesting_state old_nesting
;
187 nesting_push(&old_nesting
, smark
);
189 musthave(emark
, KEYWORD
|ALIAS
);
190 nesting_pop(&old_nesting
);
191 return (block(type
, t
, NOBLOCK
, NOWORDS
));
198 int c
, iopn
= 0, syniocf
;
199 struct ioword
*iop
, **iops
;
201 struct nesting_state old_nesting
;
203 iops
= (struct ioword
**) alloc(sizeofN(struct ioword
*, NUFILE
+1),
208 syniocf
= KEYWORD
|ALIAS
;
209 switch (c
= token(cf
|KEYWORD
|ALIAS
|VARASN
)) {
212 afree((void*) iops
, ATEMP
);
215 return (NULL
); /* empty line */
220 syniocf
&= ~(KEYWORD
|ALIAS
);
222 t
->lineno
= source
->line
;
224 cf
= (t
->evalflags
? ARRAYVAR
: 0) |
225 (XPsize(args
) == 0 ? ALIAS
|VARASN
: CMDWORD
);
229 yyerror("too many redirections\n");
230 iops
[iopn
++] = synio(cf
);
235 /* the iopn == 0 and XPsize(vars) == 0 are
236 * dubious but AT&T ksh acts this way
238 if (iopn
== 0 && XPsize(vars
) == 0 &&
240 assign_command(ident
))
241 t
->evalflags
= DOVACHECK
;
242 if ((XPsize(args
) == 0) &&
243 is_wdvarassign(yylval
.cp
))
244 XPput(vars
, yylval
.cp
);
246 XPput(args
, yylval
.cp
);
250 /* Check for "> foo (echo hi)" which AT&T ksh
251 * allows (not POSIX, but not disallowed)
254 if (XPsize(args
) == 0 && XPsize(vars
) == 0) {
258 /* Must be a function */
259 if (iopn
!= 0 || XPsize(args
) != 1 ||
265 t
= function_body(XPptrv(args
)[0]);
277 t
= nested(TPAREN
, '(', ')');
281 t
= nested(TBRACE
, '{', '}');
284 #ifdef SILLY_FEATURES
287 static const char let_cmd
[] = { CHAR
, 'l', CHAR
, 'e',
289 /* Leave KEYWORD in syniocf (allow if (( 1 )) then ...) */
291 t
->lineno
= source
->line
;
293 XPput(args
, wdcopy(let_cmd
, ATEMP
));
294 musthave(LWORD
,LETEXPR
);
295 XPput(args
, yylval
.cp
);
300 #ifdef SILLY_FEATURES
301 case DBRACKET
: /* [[ .. ]] */
302 /* Leave KEYWORD in syniocf (allow if [[ -n 1 ]] then ...) */
303 t
= newtp(TDBRACKET
);
308 te
.flags
= TEF_DBRACKET
;
310 te
.isa
= dbtestp_isa
;
311 te
.getopnd
= dbtestp_getopnd
;
312 te
.eval
= dbtestp_eval
;
313 te
.error
= dbtestp_error
;
322 t
= newtp((c
== FOR
) ? TFOR
: TSELECT
);
323 musthave(LWORD
, ARRAYVAR
);
324 if (!is_wdvarname(yylval
.cp
, TRUE
))
325 yyerror("%s: bad identifier\n",
326 c
== FOR
? "for" : "select");
327 t
->str
= str_save(ident
, ATEMP
);
328 nesting_push(&old_nesting
, c
);
329 t
->vars
= wordlist();
331 nesting_pop(&old_nesting
);
336 nesting_push(&old_nesting
, c
);
337 t
= newtp((c
== WHILE
) ? TWHILE
: TUNTIL
);
338 t
->left
= c_list(TRUE
);
339 t
->right
= dogroup();
340 nesting_pop(&old_nesting
);
347 nesting_push(&old_nesting
, c
);
348 t
->left
= caselist();
349 nesting_pop(&old_nesting
);
353 nesting_push(&old_nesting
, c
);
355 t
->left
= c_list(TRUE
);
356 t
->right
= thenpart();
357 musthave(FI
, KEYWORD
|ALIAS
);
358 nesting_pop(&old_nesting
);
362 syniocf
&= ~(KEYWORD
|ALIAS
);
366 t
= block(TBANG
, NOBLOCK
, t
, NOWORDS
);
369 #ifdef SILLY_FEATURES
371 syniocf
&= ~(KEYWORD
|ALIAS
);
374 t
->str
= alloc(2, ATEMP
);
375 t
->str
[0] = '\0'; /* TF_* flags */
378 t
= block(TTIME
, t
, NOBLOCK
, NOWORDS
);
383 t
= function_body(yylval
.cp
, TRUE
);
385 #endif /* SILLY_FEATURES */
388 while ((iop
= synio(syniocf
)) != NULL
) {
390 yyerror("too many redirections\n");
399 iops
= (struct ioword
**) aresize((void*) iops
,
400 sizeofN(struct ioword
*, iopn
), ATEMP
);
404 if (t
->type
== TCOM
|| t
->type
== TDBRACKET
) {
406 t
->args
= (char **) XPclose(args
);
408 t
->vars
= (char **) XPclose(vars
);
423 c
= token(CONTIN
|KEYWORD
|ALIAS
);
424 /* A {...} can be used instead of do...done for for/select loops
425 * but not for while/until loops - we don't need to check if it
426 * is a while loop because it would have been parsed as part of
427 * the conditional command list...
436 musthave(c
, KEYWORD
|ALIAS
);
445 musthave(THEN
, KEYWORD
|ALIAS
);
447 t
->left
= c_list(TRUE
);
450 t
->right
= elsepart();
459 switch (token(KEYWORD
|ALIAS
|VARASN
)) {
461 if ((t
= c_list(TRUE
)) == NULL
)
467 t
->left
= c_list(TRUE
);
468 t
->right
= thenpart();
483 c
= token(CONTIN
|KEYWORD
|ALIAS
);
484 /* A {...} can be used instead of in...esac for case statements */
492 while ((tpeek(CONTIN
|KEYWORD
|ESACONLY
)) != c
) { /* no ALIAS here */
493 struct op
*tc
= casepart(c
);
495 t
= tl
= tc
, tl
->right
= NULL
;
497 tl
->right
= tc
, tl
= tc
;
499 musthave(c
, KEYWORD
|ALIAS
);
512 if (token(CONTIN
| KEYWORD
) != '(')
516 XPput(ptns
, yylval
.cp
);
517 } while (token(0) == '|');
520 t
->vars
= (char **) XPclose(ptns
);
523 t
->left
= c_list(TRUE
);
524 /* Note: Posix requires the ;; */
525 if ((tpeek(CONTIN
|KEYWORD
|ALIAS
)) != endtok
)
526 musthave(BREAK
, CONTIN
|KEYWORD
|ALIAS
);
531 function_body(char *name
)
537 sname
= wdstrip(name
);
538 /* Check for valid characters in name. only allow [a-zA-Z_0-9]
540 for (p
= sname
; *p
; p
++)
541 if (!isalnum(*p
) && (*p
!='_'))
542 yyerror("%s: invalid function name\n", sname
);
546 t
->lineno
= source
->line
;
548 /* Note that POSIX allows only compound statements after foo(), sh and
549 * at&t ksh allow any command, go with the later since it shouldn't
550 * break anything. However, for function foo, at&t ksh only accepts
554 old_func_parse
= e
->flags
& EF_FUNC_PARSE
;
555 e
->flags
|= EF_FUNC_PARSE
;
556 if ((t
->left
= get_command(CONTIN
)) == (struct op
*) 0) {
558 * Probably something like foo() followed by eof or ;.
559 * This is accepted by sh and ksh88.
560 * To make "typset -f foo" work reliably (so its output can
561 * be used as input), we pretend there is a colon here.
563 t
->left
= newtp(TCOM
);
564 t
->left
->args
= (char **) alloc(sizeof(char *) * 2, ATEMP
);
565 t
->left
->args
[0] = alloc(sizeof(char) * 3, ATEMP
);
566 t
->left
->args
[0][0] = CHAR
;
567 t
->left
->args
[0][1] = ':';
568 t
->left
->args
[0][2] = EOS
;
569 t
->left
->args
[1] = (char *) 0;
570 t
->left
->vars
= (char **) alloc(sizeof(char *), ATEMP
);
571 t
->left
->vars
[0] = (char *) 0;
575 e
->flags
&= ~EF_FUNC_PARSE
;
587 /* Posix does not do alias expansion here... */
588 if ((c
= token(CONTIN
|KEYWORD
|ALIAS
)) != IN
) {
589 if (c
!= ';') /* non-POSIX, but at&t ksh accepts a ; here */
593 while ((c
= token(0)) == LWORD
)
594 XPput(args
, yylval
.cp
);
595 if (c
!= '\n' && c
!= ';')
597 if (XPsize(args
) == 0) {
602 return ((char **)XPclose(args
));
607 * supporting functions
611 block(int type
, struct op
*t1
, struct op
*t2
, char **wp
)
622 const struct tokeninfo
{
629 { "then", THEN
, TRUE
},
630 { "else", ELSE
, TRUE
},
631 { "elif", ELIF
, TRUE
},
633 { "case", CASE
, TRUE
},
634 { "esac", ESAC
, TRUE
},
635 { "for", FOR
, TRUE
},
637 { "select", SELECT
, TRUE
},
639 { "while", WHILE
, TRUE
},
640 { "until", UNTIL
, TRUE
},
642 { "done", DONE
, TRUE
},
644 #ifdef SILLY_FEATURES
645 { "function", FUNCTION
, TRUE
},
646 { "time", TIME
, TRUE
},
647 #endif /* SILLY_FEATURES */
652 { "[[", DBRACKET
, TRUE
},
654 /* Lexical tokens (0[EOF], LWORD and REDIR handled specially) */
655 { "&&", LOGAND
, FALSE
},
656 { "||", LOGOR
, FALSE
},
657 { ";;", BREAK
, FALSE
},
659 { "((", MDPAREN
, FALSE
},
660 { "|&", COPROC
, FALSE
},
662 /* and some special cases... */
663 { "newline", '\n', FALSE
},
670 struct tokeninfo
const *tt
;
673 transitional_tinit(&keywords
, APERM
); /* must be 2^n (currently 20 keywords) */
674 for (tt
= tokentab
; tt
->name
; tt
++) {
676 p
= transitional_tenter(&keywords
.root
, tt
->name
, APERM
);
677 p
->flag
|= DEFINED
|ISSET
;
688 char redir
[6]; /* 2<<- is the longest redirection, I think */
690 struct tokeninfo
const *tt
;
700 if (nesting
.start_token
) {
701 c
= nesting
.start_token
;
702 source
->errline
= nesting
.start_line
;
706 /* don't quote the EOF */
707 yyerror("syntax error: unexpected EOF\n");
711 s
= snptreef(NULL
, 32, "%S", yylval
.cp
);
715 s
= snptreef(redir
, sizeof(redir
), "%R", yylval
.iop
);
719 for (tt
= tokentab
; tt
->name
; tt
++)
725 if (c
> 0 && c
< 256) {
729 snprintf(redir
, sizeof(redir
),
734 yyerror("syntax error: `%s' %s\n", s
, what
);
738 nesting_push(struct nesting_state
*save
, int tok
)
741 nesting
.start_token
= tok
;
742 nesting
.start_line
= source
->line
;
746 nesting_pop(struct nesting_state
*saved
)
756 t
= (struct op
*) alloc(sizeof(*t
), ATEMP
);
759 t
->args
= t
->vars
= NULL
;
761 t
->left
= t
->right
= NULL
;
769 nesting
.start_token
= 0;
770 nesting
.start_line
= 0;
777 /* This kludge exists to take care of sh/at&t ksh oddity in which
778 * the arguments of alias/export/readonly/typeset have no field
779 * splitting, file globbing, or (normal) tilde expansion done.
780 * at&t ksh seems to do something similar to this since
781 * $ touch a=a; typeset a=[ab]; echo "$a"
783 * $ x=typeset; $x a=[ab]; echo "$a"
788 assign_command(char UNUSED(*s
))
791 #ifdef SILLY_FEATURES
794 return (c
== 'a' && strcmp(s
, "alias") == 0)
795 || (c
== 'e' && strcmp(s
, "export") == 0)
796 || (c
== 'r' && strcmp(s
, "readonly") == 0)
797 || (c
== 't' && strcmp(s
, "typeset") == 0);
798 #endif /* SILLY_FEATURES */
801 /* Check if we are in the middle of reading an alias */
803 inalias(struct source
*s
)
805 for (; s
&& s
->type
== SALIAS
; s
= s
->next
)
806 if (!(s
->flags
& SF_ALIASEND
))
813 /* Order important - indexed by Test_meta values
814 * Note that ||, &&, ( and ) can't appear in as unquoted strings
815 * in normal shell input, so these can be interpreted unambiguously
816 * in the evaluation pass.
818 static const char dbtest_or
[] = { CHAR
, '|', CHAR
, '|', EOS
};
819 static const char dbtest_and
[] = { CHAR
, '&', CHAR
, '&', EOS
};
820 static const char dbtest_not
[] = { CHAR
, '!', EOS
};
821 static const char dbtest_oparen
[] = { CHAR
, '(', EOS
};
822 static const char dbtest_cparen
[] = { CHAR
, ')', EOS
};
823 const char *const dbtest_tokens
[] = {
824 dbtest_or
, dbtest_and
, dbtest_not
,
825 dbtest_oparen
, dbtest_cparen
827 const char db_close
[] = { CHAR
, ']', CHAR
, ']', EOS
};
828 const char db_lthan
[] = { CHAR
, '<', EOS
};
829 const char db_gthan
[] = { CHAR
, '>', EOS
};
831 /* Test if the current token is a whatever. Accepts the current token if
832 * it is. Returns 0 if it is not, non-zero if it is (in the case of
833 * TM_UNOP and TM_BINOP, the returned value is a Test_op).
836 dbtestp_isa(Test_env
*te
, Test_meta meta
)
838 int c
= tpeek(ARRAYVAR
| (meta
== TM_BINOP
? 0 : CONTIN
));
844 uqword
= c
== LWORD
&& *ident
;
848 else if (meta
== TM_AND
)
850 else if (meta
== TM_NOT
)
851 ret
= uqword
&& strcmp(yylval
.cp
, dbtest_tokens
[(int) TM_NOT
]) == 0;
852 else if (meta
== TM_OPAREN
)
853 ret
= c
== '(' /*)*/;
854 else if (meta
== TM_CPAREN
)
855 ret
= c
== /*(*/ ')';
856 else if (meta
== TM_UNOP
|| meta
== TM_BINOP
) {
857 if (meta
== TM_BINOP
&& c
== REDIR
&&
858 (yylval
.iop
->flag
== IOREAD
|| yylval
.iop
->flag
== IOWRITE
)) {
860 save
= wdcopy(yylval
.iop
->flag
== IOREAD
?
861 db_lthan
: db_gthan
, ATEMP
);
862 } else if (uqword
&& (ret
= test_isop(meta
, ident
)))
864 } else /* meta == TM_END */
865 ret
= uqword
&& strcmp(yylval
.cp
, db_close
) == 0;
868 if (meta
< NELEM(dbtest_tokens
))
869 save
= wdcopy(dbtest_tokens
[(int)meta
], ATEMP
);
871 XPput(*te
->pos
.av
, save
);
877 dbtestp_getopnd(Test_env
*te
, Test_op
UNUSED(op
), int UNUSED(do_eval
))
879 int c
= tpeek(ARRAYVAR
);
885 XPput(*te
->pos
.av
, yylval
.cp
);
891 dbtestp_eval(Test_env
*te __unused
, Test_op op __unused
,
892 const char *opnd1 __unused
, const char *opnd2 __unused
,
899 dbtestp_error(Test_env
*te
, int offset
, const char *msg
)
901 te
->flags
|= TEF_ERROR
;
905 /* Kludgy to say the least... */
907 yylval
.cp
= *(XPptrv(*te
->pos
.av
) + XPsize(*te
->pos
.av
) +