mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-28 16:09:51 +02:00
fix recogniation of IN token in for command nested within case command
This commit is contained in:
+22
-1
@@ -9155,4 +9155,25 @@ redir.c
|
||||
get expanded again.
|
||||
Fixes bug reported by squeaky <q7d9y9muja@liamekaens.com>
|
||||
|
||||
|
||||
4/12
|
||||
----
|
||||
parse.y
|
||||
- expecting_in_command: new variable, set to FOR or CASE depending on
|
||||
which command is expecting the IN token to follow it
|
||||
- {save,restore}_parser_state: save and restore expecting_in_command
|
||||
in `incmd' member
|
||||
- special_case_tokens: for POSIX rule 6, check expecting_in_token
|
||||
instead of last_read_token/token_before_that for case/for command
|
||||
and whether we should return IN and maybe set PST_CASEPAT
|
||||
- special_case_tokens: reset expecting_in_command before returning DO
|
||||
- read_token_word: set expecting_in_command if last_read_token was
|
||||
CASE or FOR and we are returning a WORD
|
||||
- reset_parser: reset expecting_in_command
|
||||
- parse_comsub,parse_compound_assignment: reset expecting_in_command
|
||||
Fixes bug reported by nbowler@draconx.ca
|
||||
|
||||
parser.h
|
||||
- incmd: new member of parser_state, saves and restores the value of
|
||||
expecting_in_command
|
||||
- PST_FORCMD: new parser state, used to say if we're parsing a `for'
|
||||
command and waiting for an IN token (not used yet)
|
||||
|
||||
@@ -1042,12 +1042,12 @@ getconf_all (WORD_LIST *list)
|
||||
int r;
|
||||
|
||||
r = EXECUTION_SUCCESS;
|
||||
path = list ? list->word->word : 0;
|
||||
path = list ? list->word->word : "/";
|
||||
for (c = vars; c->name != NULL; ++c)
|
||||
{
|
||||
#if 0
|
||||
if (c->call == PATHCONF && path == 0)
|
||||
continue; /* Don't print pathconf vars if no path supplied */
|
||||
#if 0
|
||||
if (c->call != PATHCONF && path)
|
||||
continue; /* Only print pathconf vars if path supplied */
|
||||
#endif
|
||||
|
||||
@@ -3035,6 +3035,7 @@ static int esacs_needed_count;
|
||||
/* When non-zero, we can read IN as an acceptable token, regardless of how
|
||||
many newlines we read. */
|
||||
static int expecting_in_token;
|
||||
static int expecting_in_command; /* XXX - maybe save previous? */
|
||||
|
||||
static void
|
||||
push_heredoc (REDIRECT *r)
|
||||
@@ -3119,12 +3120,15 @@ static int open_brace_count;
|
||||
if (word_token_alist[i].token == ESAC) { \
|
||||
parser_state &= ~(PST_CASEPAT|PST_CASESTMT); \
|
||||
esacs_needed_count--; \
|
||||
} else if (word_token_alist[i].token == CASE) \
|
||||
} else if (word_token_alist[i].token == CASE) { \
|
||||
parser_state |= PST_CASESTMT; \
|
||||
else if (word_token_alist[i].token == COND_END) \
|
||||
expecting_in_command = CASE; \
|
||||
} else if (word_token_alist[i].token == COND_END) \
|
||||
parser_state &= ~(PST_CONDCMD|PST_CONDEXPR); \
|
||||
else if (word_token_alist[i].token == COND_START) \
|
||||
parser_state |= PST_CONDCMD; \
|
||||
else if (word_token_alist[i].token == FOR) \
|
||||
expecting_in_command = FOR; \
|
||||
else if (word_token_alist[i].token == '{') \
|
||||
open_brace_count++; \
|
||||
else if (word_token_alist[i].token == '}' && open_brace_count) \
|
||||
@@ -3300,19 +3304,20 @@ special_case_tokens (const char *tokstr)
|
||||
/* Posix grammar rule 6 */
|
||||
if ((last_read_token == WORD) &&
|
||||
#if defined (SELECT_COMMAND)
|
||||
((token_before_that == FOR) || (token_before_that == CASE) || (token_before_that == SELECT)) &&
|
||||
(token_before_that == FOR || token_before_that == CASE || token_before_that == SELECT) &&
|
||||
#else
|
||||
((token_before_that == FOR) || (token_before_that == CASE)) &&
|
||||
(token_before_that == FOR || token_before_that == CASE) &&
|
||||
#endif
|
||||
(tokstr[0] == 'i' && tokstr[1] == 'n' && tokstr[2] == 0))
|
||||
{
|
||||
if (token_before_that == CASE)
|
||||
if (expecting_in_command == CASE)
|
||||
{
|
||||
parser_state |= PST_CASEPAT;
|
||||
esacs_needed_count++;
|
||||
}
|
||||
if (expecting_in_token)
|
||||
expecting_in_token--;
|
||||
expecting_in_command = 0;
|
||||
return (IN);
|
||||
}
|
||||
|
||||
@@ -3322,12 +3327,13 @@ special_case_tokens (const char *tokstr)
|
||||
if (expecting_in_token && (last_read_token == WORD || last_read_token == '\n') &&
|
||||
(tokstr[0] == 'i' && tokstr[1] == 'n' && tokstr[2] == 0))
|
||||
{
|
||||
if (parser_state & PST_CASESTMT)
|
||||
if (expecting_in_command == CASE && (parser_state & PST_CASESTMT))
|
||||
{
|
||||
parser_state |= PST_CASEPAT;
|
||||
esacs_needed_count++;
|
||||
}
|
||||
expecting_in_token--;
|
||||
expecting_in_command = 0;
|
||||
return (IN);
|
||||
}
|
||||
/* Posix grammar rule 6, third word in FOR: for i; do command-list; done */
|
||||
@@ -3335,6 +3341,7 @@ special_case_tokens (const char *tokstr)
|
||||
(tokstr[0] == 'd' && tokstr[1] == 'o' && tokstr[2] == '\0'))
|
||||
{
|
||||
expecting_in_token--;
|
||||
expecting_in_command = 0;
|
||||
return (DO);
|
||||
}
|
||||
|
||||
@@ -3349,6 +3356,7 @@ special_case_tokens (const char *tokstr)
|
||||
{
|
||||
if (expecting_in_token)
|
||||
expecting_in_token--;
|
||||
expecting_in_command = 0;
|
||||
return (DO);
|
||||
}
|
||||
|
||||
@@ -3457,6 +3465,7 @@ reset_parser (void)
|
||||
need_here_doc = 0;
|
||||
redir_stack[0] = 0;
|
||||
esacs_needed_count = expecting_in_token = 0;
|
||||
expecting_in_command = 0;
|
||||
|
||||
simplecmd_lineno = line_number;
|
||||
|
||||
@@ -4422,8 +4431,9 @@ parse_comsub (int qc, int open, int close, size_t *lenp, int flags)
|
||||
|
||||
/* State flags we don't want to persist into command substitutions. */
|
||||
parser_state &= ~(PST_REGEXP|PST_EXTPAT|PST_CONDCMD|PST_CONDEXPR|PST_COMPASSIGN);
|
||||
/* Could do PST_CASESTMT too, but that also affects history. Setting
|
||||
expecting_in_token below should take care of the parsing requirements.
|
||||
/* Could do PST_CASESTMT too, but that also affects history. Ditto for
|
||||
PST_FORCMD. Setting expecting_in_token and expecting_in_command below
|
||||
should take care of the parsing requirements.
|
||||
Unsetting PST_REDIRLIST isn't strictly necessary because of how we set
|
||||
token_to_read below, but we do it anyway. */
|
||||
parser_state &= ~(PST_CASEPAT|PST_ALEXPNEXT|PST_SUBSHELL|PST_REDIRLIST);
|
||||
@@ -4442,6 +4452,7 @@ parse_comsub (int qc, int open, int close, size_t *lenp, int flags)
|
||||
/* These are reset by reset_parser() */
|
||||
need_here_doc = 0;
|
||||
esacs_needed_count = expecting_in_token = 0;
|
||||
expecting_in_command = 0;
|
||||
|
||||
/* We want to expand aliases on this pass if we're in posix mode, since the
|
||||
standard says you have to take aliases into account when looking for the
|
||||
@@ -5763,8 +5774,9 @@ got_token:
|
||||
function_dstart = line_number;
|
||||
break;
|
||||
case CASE:
|
||||
case SELECT:
|
||||
case FOR:
|
||||
expecting_in_command = last_read_token;
|
||||
case SELECT:
|
||||
expecting_in_token++;
|
||||
break;
|
||||
}
|
||||
@@ -6996,6 +7008,7 @@ parse_compound_assignment (size_t *retlenp)
|
||||
parser_state |= PST_COMPASSIGN;
|
||||
|
||||
esacs_needed_count = expecting_in_token = 0;
|
||||
expecting_in_command = 0;
|
||||
|
||||
/* We're not pushing any new input here, we're reading from the current input
|
||||
source. If that's an alias, we have to be prepared for the alias to get
|
||||
@@ -7126,6 +7139,7 @@ save_parser_state (sh_parser_state_t *ps)
|
||||
|
||||
ps->esacs_needed = esacs_needed_count;
|
||||
ps->expecting_in = expecting_in_token;
|
||||
ps->incmd = expecting_in_command;
|
||||
|
||||
if (need_here_doc == 0)
|
||||
ps->redir_stack[0] = 0;
|
||||
@@ -7190,6 +7204,7 @@ restore_parser_state (sh_parser_state_t *ps)
|
||||
|
||||
esacs_needed_count = ps->esacs_needed;
|
||||
expecting_in_token = ps->expecting_in;
|
||||
expecting_in_command = ps->incmd;
|
||||
|
||||
#if 0
|
||||
for (i = 0; i < HEREDOC_MAX; i++)
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#define PST_STRING 0x1000000 /* parsing a string to a command or word list */
|
||||
#define PST_CMDBLTIN 0x2000000 /* last token was the `command' builtin */
|
||||
#define PST_FUNSUBST 0x4000000 /* parsing a foreground command substitution */
|
||||
#define PST_FORCMD 0x8000000 /* parsing for command -- not used yet */
|
||||
|
||||
/* Definition of the delimiter stack. Needed by parse.y and bashhist.c. */
|
||||
struct dstack {
|
||||
|
||||
@@ -215,6 +215,7 @@ typedef struct _sh_parser_state_t
|
||||
|
||||
int esacs_needed;
|
||||
int expecting_in;
|
||||
int incmd;
|
||||
|
||||
/* structures affecting the parser */
|
||||
void *pushed_strings;
|
||||
|
||||
@@ -15,3 +15,6 @@ bash5: -c: line 1: `for()'
|
||||
in
|
||||
done
|
||||
ok 1
|
||||
x
|
||||
x
|
||||
x
|
||||
|
||||
@@ -63,4 +63,39 @@ in
|
||||
foo) echo "ok 1";;
|
||||
esac' $bashname
|
||||
|
||||
# POSIX grammar rule 6 with <linebreak> consisting of multiple newlines and
|
||||
# nested case and for commands
|
||||
|
||||
case x in x)
|
||||
for x
|
||||
in x
|
||||
do
|
||||
echo $x
|
||||
done
|
||||
esac
|
||||
|
||||
# need to recognize IN here
|
||||
case x in x)
|
||||
for x
|
||||
|
||||
|
||||
in x
|
||||
do
|
||||
echo $x
|
||||
done
|
||||
esac
|
||||
|
||||
# recognize both IN and DO
|
||||
case x in x)
|
||||
for x
|
||||
|
||||
|
||||
in x
|
||||
|
||||
|
||||
|
||||
do
|
||||
echo $x
|
||||
done
|
||||
esac
|
||||
|
||||
|
||||
Reference in New Issue
Block a user