command string (it was run through parse.y:parse_matched_pair())
- expand_word_internal: pass PF_BACKQUOTE to command_substitute() if
expanding a `` command substitution
+
+ 10/20
+ -----
+parse.y
+ - yylex: return YYUNDEF as current_token if read_token returns < 0.
+ Fixes parser reset issue reported by Todd Stein <toddbstein@gmail.com>
+
+subst.c
+ - ARITH_EXP_CHARS: chars that are special and trigger expansion in
+ arithmetic expressions, EXP_CHARS without `<' and `>'. Fixes bug
+ reported by Glenn Jackman <glenn.jackman@gmail.com>
+
+execute_cmd.c
+ - retain_fifos: replace executing_list (which is still present) as the
+ indicator of whether or not to save and restore the FIFO list around
+ a call to execute_command_internal/execute_command; it's more
+ descriptive and can be used elsewhere
+ - execute_for_command: set retain_fifos so we don't unlink the fifo
+ list until the for command completes. Fixes issue reported in
+ https://savannah.gnu.org/support/index.php?110743
+
+lib/readline/xmalloc.c
+ - memory_error_and_abort: add `const' qualifiers to the argument. Fix
+ from Markus Elfring <Markus.Elfring@web.de>
/* Non-zero if we are executing a command list (a;b;c, etc.) */
int executing_list = 0;
+/* Non-zero if we should defer closing process substitution FDs. */
+int retain_fifos = 0;
+
/* Non-zero if failing commands in a command substitution should not exit the
shell even if -e is set. Used to pass the CMD_IGNORE_RETURN flag down to
commands run in command substitutions by parse_and_execute. */
#if defined (PROCESS_SUBSTITUTION)
/* don't unlink fifos if we're in a shell function; wait until the function
returns. */
- if (variable_context == 0 && executing_list == 0)
+ if (variable_context == 0 && retain_fifos == 0)
unlink_fifo_list ();
#endif /* PROCESS_SUBSTITUTION */
# endif
/* XXX - also if sourcelevel != 0? */
- if (variable_context != 0 || executing_list)
+ if (variable_context != 0 || retain_fifos)
{
ofifo = num_fifos ();
ofifo_list = copy_fifo_list ((int *)&osize);
if (command->value.Connection->second)
command->value.Connection->second->flags |= CMD_IGNORE_RETURN;
}
- executing_list++;
+ executing_list++; retain_fifos++;
QUIT;
#if 1
exec_result = execute_command_internal (command->value.Connection->second,
asynchronous, pipe_in, pipe_out,
fds_to_close);
- executing_list--;
+ executing_list--; retain_fifos--;
break;
case '|':
and the connector is OR_OR, then execute the second command,
otherwise return. */
- executing_list++;
+ executing_list++; retain_fifos++;
if (command->value.Connection->first)
command->value.Connection->first->flags |= CMD_IGNORE_RETURN;
exec_result = execute_command (second);
}
- executing_list--;
+ executing_list--; retain_fifos--;
break;
default:
return (EXECUTION_FAILURE);
}
- loop_level++;
+ loop_level++; retain_fifos++;
identifier = for_command->name->word;
line_number = for_command->line; /* for expansion error messages */
{
dispose_words (releaser);
discard_unwind_frame ("for");
- loop_level--;
+ loop_level--; retain_fifos--;
return (EXECUTION_FAILURE);
}
}
}
}
- loop_level--;
+ loop_level--; retain_fifos--;
line_number = save_line_number;
#if 0
/* Make sure that the pipes are closed in the parent. */
close_pipes (pipe_in, pipe_out);
-#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
#if 0
+#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
if (variable_context == 0)
unlink_fifo_list ();
#endif
/* We're no longer inside a shell function. */
variable_context = return_catch_flag = funcnest = evalnest = sourcenest = 0;
- executing_list = 0; /* XXX */
+ executing_list = retain_fifos = 0; /* XXX */
/* If we're not interactive, close the file descriptor from which we're
reading the current shell script. */
extern int builtin_ignoring_errexit;
extern int executing_builtin;
extern int executing_list;
+extern int retain_fifos;
extern int comsub_ignore_return;
extern int subshell_level;
extern int match_ignore_case;
/* **************************************************************** */
static void
-memory_error_and_abort (char *fname)
+memory_error_and_abort (const char * const fname)
{
fprintf (stderr, "%s: out of virtual memory\n", fname);
exit (2);
#if defined (YYERRCODE) && !defined (YYUNDEF)
current_token = YYERRCODE;
#else
- current_token = YYerror;
+ current_token = YYUNDEF;
#endif
return (current_token);
shell_eof_token = ps.eof_token;
expand_aliases = ps.expand_aliases;
- /* yyparse() has already called yyerror() and reset_parser() */
+ /* yyparse() has already called yyerror() and reset_parser(), so we set
+ PST_NOERROR to avoid a redundant error message. */
+ parser_state |= PST_NOERROR;
return (&matched_pair_error);
}
else if (r != 0)
run_unwind_protects ();
loop_level = continuing = breaking = funcnest = 0;
- executing_list = comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
+ executing_list = retain_fifos = 0;
+ comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
}
/* What to do when we've been interrupted, and it is safe to handle it. */
run_unwind_protects ();
loop_level = continuing = breaking = funcnest = 0;
- executing_list = comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
+ executing_list = retain_fifos = 0;
+ comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
if (interactive && print_newline)
{
/* Reset execution context */
loop_level = continuing = breaking = funcnest = 0;
- executing_list = comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
+ executing_list = retain_fifos = 0;
+ comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
run_exit_trap (); /* XXX - run exit trap possibly in signal context? */
#define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
#endif
+/* We don't perform process substitution in arithmetic expressions, so don't
+ bother checking for it. */
+#define ARITH_EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
+
/* If there are any characters in STRING that require full expansion,
then call FUNC to expand STRING; otherwise just perform quote
removal if necessary. This returns a new string. */
i = saw_quote = 0;
while (string[i])
{
- if (EXP_CHAR (string[i]))
+ if (ARITH_EXP_CHAR (string[i]))
break;
else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
saw_quote = string[i];
argv[1] = <A>
argv[1] = <A>
./posixexp.tests: line 97: unexpected EOF while looking for matching `}'
+./posixexp.tests: line 98: syntax error: unexpected end of file