posix mode changes for interp 1150; fix for varassign redirection; fix for nameref in ${param=value} expansion

This commit is contained in:
Chet Ramey
2023-04-11 09:56:03 -04:00
parent ec9447ce93
commit 15b199c0dd
12 changed files with 113 additions and 10 deletions
+32
View File
@@ -5969,3 +5969,35 @@ lib/readline/vi_mode.c
- _rl_domove_motion_cleanup: ditto for y/Y
- rl_domove_motion_callback: if t/T/;/, fail (return non-zero without
moving point), flag the motion command as having failed (MOVE_FAILED)
4/6
---
subst.c
- command_substitute: save the return status of the child process in
last_command_subst_status; don't assign to last_command_exit_value
in posix mode (posix interp 1150)
execute_cmd.c
- execute_null_command: a simple command without a command word but
with command substitutions now returns last_command_subst_status.
It may or may not have already modified $? depending on posix mode
redir.c
- redir_varvalue: legal_number validity check should be == 0, not < 0
From a report by Grisha Levit <grishalevit@gmail.com>
4/10
----
subst.c
- parameter_brace_expand_rhs: check for namerefs in the variable name
part of the ${name=word} expansion so we can go back and implement
the POSIX semantics of returning "the final value of parameter."
From a report by Grisha Levit <grishalevit@gmail.com>
sig.c,sig.h
- sigpipe_handler: clean up, set $?, and throw to top level on receipt
of a SIGPIPE
- termsig_handler: if the variable builtin_catch_sigpipe is set (it's
not set anywhere yet), call sigpipe_handler instead of terminating
the shell. Still need to make sure a sighandler is installed for
SIGPIPE even if initialize_terminating_signals isn't called
+7
View File
@@ -8561,6 +8561,13 @@ undergoes expansion.
That means, for example, that a backslash preceding a double quote
character will escape it and the backslash will be removed.
@item
Command substitutions don't set the @samp{?} special parameter. The exit
status of a simple command without a command word is still the exit status
of the last command substitution that occurred while evaluating the variable
assignments and redirections in that command, but that does not happen until
after all of the assignments and redirections.
@end enumerate
There is other @sc{posix} behavior that Bash does not implement by
+3 -3
View File
@@ -2,10 +2,10 @@
Copyright (C) 1988-2023 Free Software Foundation, Inc.
@end ignore
@set LASTCHANGE Tue Mar 21 11:05:49 EDT 2023
@set LASTCHANGE Thu Apr 6 11:58:41 EDT 2023
@set EDITION 5.2
@set VERSION 5.2
@set UPDATED 21 March 2023
@set UPDATED-MONTH March 2023
@set UPDATED 6 April 2023
@set UPDATED-MONTH April 2023
+1 -1
View File
@@ -4123,7 +4123,7 @@ execute_null_command (REDIRECT *redirects, int pipe_in, int pipe_out, int async)
if (r != 0)
return (EXECUTION_FAILURE);
else if (last_command_subst_pid != NO_PID)
return (last_command_exit_value);
return (last_command_subst_status);
else
return (EXECUTION_SUCCESS);
}
+3 -1
View File
@@ -5891,7 +5891,7 @@ decode_prompt_string (char *string)
WORD_LIST *list;
char *result, *t, *orig_string;
struct dstack save_dstack;
int last_exit_value, last_comsub_pid;
int last_exit_value, last_comsub_pid, last_comsub_status;
#if defined (PROMPT_STRING_DECODE)
size_t result_size;
size_t result_index;
@@ -6297,12 +6297,14 @@ not_escape:
{
last_exit_value = last_command_exit_value;
last_comsub_pid = last_command_subst_pid;
last_comsub_status = last_command_subst_status;
list = expand_prompt_string (result, Q_DOUBLE_QUOTES, 0);
free (result);
result = string_list (list);
dispose_words (list);
last_command_exit_value = last_exit_value;
last_command_subst_pid = last_comsub_pid;
last_command_subst_status = last_comsub_status;
}
else
{
+1 -1
View File
@@ -1459,7 +1459,7 @@ redir_varvalue (REDIRECT *redir)
if (val == 0 || *val == 0)
return -1;
if (legal_number (val, &vmax) < 0)
if (legal_number (val, &vmax) == 0)
return -1;
i = vmax; /* integer truncation */
+15
View File
@@ -74,6 +74,8 @@ volatile sig_atomic_t sigterm_received = 0;
/* Set to the value of any terminating signal received. */
volatile sig_atomic_t terminating_signal = 0;
volatile int builtin_catch_sigpipe = 0;
/* The environment at the top-level R-E loop. We use this in
the case of error return. */
procenv_t top_level;
@@ -591,6 +593,9 @@ termsig_handler (int sig)
handling_termsig = terminating_signal; /* for termsig_sighandler */
terminating_signal = 0; /* keep macro from re-testing true. */
if (builtin_catch_sigpipe)
sigpipe_handler (sig);
/* I don't believe this condition ever tests true. */
if (sig == SIGINT && signal_is_trapped (SIGINT))
run_interrupt_trap (0);
@@ -714,6 +719,7 @@ sigint_sighandler (int sig)
set_exit_status (128 + sig);
throw_to_top_level ();
}
#if defined (READLINE)
/* Set the event hook so readline will call it after the signal handlers
finish executing, so if this interrupted character input we can get
@@ -762,6 +768,15 @@ sigterm_sighandler (int sig)
SIGRETURN (0);
}
void
sigpipe_handler (int sig)
{
handling_termsig = 0;
builtin_catch_sigpipe = 0;
last_command_exit_value = 128 + sig;
throw_to_top_level ();
}
/* Signal functions used by the rest of the code. */
#if !defined (HAVE_POSIX_SIGNALS)
+4
View File
@@ -108,6 +108,8 @@ extern volatile sig_atomic_t sigterm_received;
extern int interrupt_immediately; /* no longer used */
extern int terminate_immediately;
extern volatile int builtin_catch_sigpipe; /* not used yet */
/* Functions from sig.c. */
extern sighandler termsig_sighandler (int);
extern void termsig_handler (int);
@@ -126,6 +128,8 @@ extern void unset_sigwinch_handler (void);
extern sighandler sigterm_sighandler (int);
extern void sigpipe_handler (int);
/* Functions defined in trap.c. */
extern SigHandler *set_sigint_handler (void);
extern SigHandler *trap_to_sighandler (int);
+28 -4
View File
@@ -149,6 +149,7 @@ typedef WORD_LIST *EXPFUNC (const char *, int);
/* Process ID of the last command executed within command substitution. */
pid_t last_command_subst_pid = NO_PID;
pid_t current_command_subst_pid = NO_PID;
int last_command_subst_status = 0;
/* Variables used to keep track of the characters in IFS. */
SHELL_VAR *ifs_var;
@@ -6723,13 +6724,16 @@ command_substitute (char *string, int quoted, int flags)
istring = optimize_cat_file (cmd->value.Simple->redirects, quoted, flags, &tflag);
if (istring == &expand_param_error)
{
last_command_exit_value = EXECUTION_FAILURE;
last_command_subst_status = EXECUTION_FAILURE;
istring = 0;
}
else
last_command_exit_value = EXECUTION_SUCCESS; /* compat */
last_command_subst_status = EXECUTION_SUCCESS; /* compat */
last_command_subst_pid = dollar_dollar_pid;
if (posixly_correct == 0) /* POSIX interp 1150 */
last_command_exit_value = last_command_subst_status; /* XXX */
dispose_command (cmd);
ret = alloc_word_desc ();
ret->word = istring;
@@ -6974,10 +6978,13 @@ command_substitute (char *string, int quoted, int flags)
UNBLOCK_SIGNAL (oset);
current_command_subst_pid = pid;
last_command_exit_value = wait_for (pid, JWAIT_NOTERM);
last_command_subst_status = wait_for (pid, JWAIT_NOTERM);
last_command_subst_pid = pid;
last_made_pid = old_pid;
if (posixly_correct == 0) /* POSIX interp 1150 */
last_command_exit_value = last_command_subst_status; /* XXX */
#if defined (JOB_CONTROL)
/* If last_command_exit_value > 128, then the substituted command
was terminated by a signal. If that signal was SIGINT, then send
@@ -7626,7 +7633,24 @@ parameter_brace_expand_rhs (char *name, char *value,
return &expand_wdesc_error;
}
}
/* We check for this here instead of letting bind_variable do it so we can
satisfy the POSIX semantics of returning the final value assigned to the
variable, even after assignment transformations (uppercase, lowercase, etc.).
We need the final name to get the right value back. */
else if ((v = find_variable_last_nameref (name, 0)) && nameref_p (v))
{
temp = nameref_cell (v);
/* shouldn't happen at this point, but... */
if (temp == 0 || *temp == 0)
{
report_error (_("%s: bad substitution"), name);
free (t1);
dispose_word (w);
return &expand_wdesc_error;
}
vname = savestring (temp);
}
arrayref = 0;
#if defined (ARRAY_VARS)
if (valid_array_reference (vname, 0))
+1
View File
@@ -350,6 +350,7 @@ extern int expanding_redir;
extern int inherit_errexit;
extern pid_t last_command_subst_pid;
extern int last_command_subst_status;
/* Evaluates to 1 if C is a character in $IFS. */
#define isifs(c) (ifs_cmap[(unsigned char)(c)] != 0)
+4
View File
@@ -92,6 +92,10 @@ expect <one>
one
expect <four>
four
expect <X>
X
expect <X>
X
errors = 0
1
2
+14
View File
@@ -228,6 +228,20 @@ echo "expect <four>"
echo $qux
ckval qux ${bar[3]}
bar=()
declare -n ref='bar[1]'
echo "expect <X>"
echo ${ref=X}
ckval ref ${bar[1]}
unset -n ref
declare -n ref
echo "expect <X>"
echo ${ref=X}
ckval ref ${ref}
# Need to add code and tests for `for' loop nameref variables
echo errors = $errors