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)
/* 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)
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) \
/* 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);
}
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 */
(tokstr[0] == 'd' && tokstr[1] == 'o' && tokstr[2] == '\0'))
{
expecting_in_token--;
+ expecting_in_command = 0;
return (DO);
}
{
if (expecting_in_token)
expecting_in_token--;
+ expecting_in_command = 0;
return (DO);
}
need_here_doc = 0;
redir_stack[0] = 0;
esacs_needed_count = expecting_in_token = 0;
+ expecting_in_command = 0;
simplecmd_lineno = line_number;
/* 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);
/* 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
function_dstart = line_number;
break;
case CASE:
- case SELECT:
case FOR:
+ expecting_in_command = last_read_token;
+ case SELECT:
expecting_in_token++;
break;
}
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
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;
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++)