mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 15:43:18 +02:00
posix mode changes for interp 1150; fix for varassign redirection; fix for nameref in ${param=value} expansion
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -92,6 +92,10 @@ expect <one>
|
||||
one
|
||||
expect <four>
|
||||
four
|
||||
expect <X>
|
||||
X
|
||||
expect <X>
|
||||
X
|
||||
errors = 0
|
||||
1
|
||||
2
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user