From: Chet Ramey Date: Wed, 28 Apr 2021 15:30:31 +0000 (-0400) Subject: allow builtins to assign to associative arrays using @ or * as keys; fixes to glob... X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=046d0cc93bc163b0d7dadf7c7512e2696a1f948e;p=thirdparty%2Fbash.git allow builtins to assign to associative arrays using @ or * as keys; fixes to glob completion of command words --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index b719bef6b..bbfbd5e86 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -10057,7 +10057,7 @@ lib/readline/search.c subst.h - ASS_ALLOWALLSUB: new assignment flag value, means to allow @ and * as - array subscripts when assigning to existing associative arrays + valid array subscripts when assigning to existing associative arrays arrayfunc.c - assign_array_element: allow assignment of key `@' to an existing @@ -10068,9 +10068,43 @@ arrayfunc.c builtins/declare.def - declare_internal: allow assignment of key `@' to an existing associative array by passing ASS_ALLOWALLSUB to assign_array_element - as part of local_aflags + as part of local_aflags. This affects declare, local, and typeset subst.c - do_assignment_internal: allow a[@]=value to an existing associative array by passing ASS_ALLOWALLSUB to assign_array_element + 4/27 + ---- +builtins/common.[ch] + - builtin_bind_var_to_int: wrapper for bind_var_to_int to be used by + builtin commands; placeholder for future work + +builtins/wait.def + - builtin_bind_var_to_int: use instead of bind_var_to_int + +builtins/common.c + - builtin_bind_variable: allow assignment of key `@' to an existing + associative array by passing ASS_ALLOWALLSUB to assign_array_element. + This affects printf and read + +builtins/variables.[ch] + - bind_var_to_int: add third `flags' argument to pass to bind_variable + instead of always passing 0 + +redir.c,builtins/common.c,builtins/printf.def + - bind_var_to_int: change callers, add third flags argument + +builtins/common.c + - builtin_bind_var_to_int: pass ASS_ALLOWALLSUB to bind_var_to_int so + builtins like wait can assign to assoc[@] and assoc[*] + + 4/28 + ---- +bashline.c + - command_word_completion_function: make sure to initialize + old_glob_ignore_case before trying to restore from it + - command_word_completion_function: if we are completing a glob + pattern, make sure to set rl_filename_completion_desired, so we get + quoting and appending -- we are completing a filename, after all. + From a report from Manuel Boni diff --git a/bashline.c b/bashline.c index f0fbe5386..87fbfdda2 100644 --- a/bashline.c +++ b/bashline.c @@ -1939,7 +1939,7 @@ executable_completion (filename, searching_path) f = savestring (filename); #else c = 0; - f = bash_quote_filename (filename, SINGLE_MATCH, &c); + f = bash_quote_filename ((char *)filename, SINGLE_MATCH, &c); #endif bash_directory_completion_hook (&f); @@ -1992,6 +1992,8 @@ command_word_completion_function (hint_text, state) temp = rl_variable_value ("completion-ignore-case"); igncase = RL_BOOLEAN_VARIABLE_VALUE (temp); + old_glob_ignore_case = glob_ignore_case; + if (glob_matches) { free (glob_matches); @@ -2177,6 +2179,8 @@ globword: { if (state == 0) { + rl_filename_completion_desired = 1; + glob_ignore_case = igncase; glob_matches = shell_glob_filename (hint, 0); glob_ignore_case = old_glob_ignore_case; diff --git a/builtins/common.c b/builtins/common.c index 063ddac2a..9459900e4 100644 --- a/builtins/common.c +++ b/builtins/common.c @@ -1,6 +1,6 @@ /* common.c - utility functions for all builtins */ -/* Copyright (C) 1987-2020 Free Software Foundation, Inc. +/* Copyright (C) 1987-2021 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -983,7 +983,7 @@ builtin_bind_variable (name, value, flags) if (valid_array_reference (name, assoc_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0) == 0) v = bind_variable (name, value, flags); else - v = assign_array_element (name, value, flags | (assoc_expand_once ? ASS_NOEXPAND : 0)); + v = assign_array_element (name, value, flags | (assoc_expand_once ? ASS_NOEXPAND : 0) | ASS_ALLOWALLSUB); #else /* !ARRAY_VARS */ v = bind_variable (name, value, flags); #endif /* !ARRAY_VARS */ @@ -994,6 +994,17 @@ builtin_bind_variable (name, value, flags) return v; } +SHELL_VAR * +builtin_bind_var_to_int (name, val) + char *name; + intmax_t val; +{ + SHELL_VAR *v; + + v = bind_var_to_int (name, val, ASS_ALLOWALLSUB); /* XXX */ + return v; +} + /* Like check_unbind_variable, but for use by builtins (only matters for error messages). */ int diff --git a/builtins/common.h b/builtins/common.h index d4ad0407e..a4b07f811 100644 --- a/builtins/common.h +++ b/builtins/common.h @@ -226,6 +226,7 @@ extern sh_builtin_func_t *this_shell_builtin; extern sh_builtin_func_t *last_shell_builtin; extern SHELL_VAR *builtin_bind_variable PARAMS((char *, char *, int)); +extern SHELL_VAR *builtin_bind_var_to_int PARAMS((char *, intmax_t)); extern int builtin_unbind_variable PARAMS((const char *)); /* variables from evalfile.c */ diff --git a/builtins/printf.def b/builtins/printf.def index b6f2b4f1d..9343b3677 100644 --- a/builtins/printf.def +++ b/builtins/printf.def @@ -535,7 +535,7 @@ printf_builtin (list) if (var && *var) { if (legal_identifier (var)) - bind_var_to_int (var, tw); + bind_var_to_int (var, tw, 0); else { sh_invalidid (var); diff --git a/builtins/wait.def b/builtins/wait.def index 824c83fe1..6e134fb25 100644 --- a/builtins/wait.def +++ b/builtins/wait.def @@ -214,7 +214,7 @@ wait_builtin (list) status = wait_for_any_job (wflags, &pstat); if (vname && status >= 0) - bind_var_to_int (vname, pstat.pid); + builtin_bind_var_to_int (vname, pstat.pid); if (status < 0) status = 127; @@ -230,7 +230,7 @@ wait_builtin (list) { wait_for_background_pids (&pstat); if (vname) - bind_var_to_int (vname, pstat.pid); + builtin_bind_var_to_int (vname, pstat.pid); WAIT_RETURN (EXECUTION_SUCCESS); } diff --git a/redir.c b/redir.c index fa92b4d41..815c14315 100644 --- a/redir.c +++ b/redir.c @@ -1434,7 +1434,7 @@ redir_varassign (redir, fd) SHELL_VAR *v; w = redir->redirector.filename; - v = bind_var_to_int (w->word, fd); + v = bind_var_to_int (w->word, fd, 0); if (v == 0 || readonly_p (v) || noassign_p (v)) return BADVAR_REDIRECT; diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index c8bef8dd1..0b0638107 100755 --- a/tests/RUN-ONE-TEST +++ b/tests/RUN-ONE-TEST @@ -1,4 +1,4 @@ -BUILD_DIR=/usr/local/build/bash/bash-current +BUILD_DIR=/usr/local/build/chet/bash/bash-current THIS_SH=$BUILD_DIR/bash PATH=$PATH:$BUILD_DIR diff --git a/variables.c b/variables.c index eedf7f6f5..d581acd8d 100644 --- a/variables.c +++ b/variables.c @@ -3488,14 +3488,15 @@ bind_int_variable (lhs, rhs, flags) } SHELL_VAR * -bind_var_to_int (var, val) +bind_var_to_int (var, val, flags) char *var; intmax_t val; + int flags; { char ibuf[INT_STRLEN_BOUND (intmax_t) + 1], *p; p = fmtulong (val, 10, ibuf, sizeof (ibuf), 0); - return (bind_int_variable (var, p, 0)); + return (bind_int_variable (var, p, flags)); } /* Do a function binding to a variable. You pass the name and diff --git a/variables.h b/variables.h index c73eb4e52..8511ab052 100644 --- a/variables.h +++ b/variables.h @@ -320,7 +320,7 @@ extern char *make_variable_value PARAMS((SHELL_VAR *, char *, int)); extern SHELL_VAR *bind_variable_value PARAMS((SHELL_VAR *, char *, int)); extern SHELL_VAR *bind_int_variable PARAMS((char *, char *, int)); -extern SHELL_VAR *bind_var_to_int PARAMS((char *, intmax_t)); +extern SHELL_VAR *bind_var_to_int PARAMS((char *, intmax_t, int)); extern int assign_in_env PARAMS((WORD_DESC *, int));