From: Chet Ramey Date: Wed, 25 Mar 2015 14:08:06 +0000 (-0400) Subject: commit bash-20150320 snapshot X-Git-Tag: bash-4.4-alpha~17 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=06c3a57511953d09ac9ea262bc18bfdbcff23fc4;p=thirdparty%2Fbash.git commit bash-20150320 snapshot --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index cc3261401..79b06c6c5 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -8134,3 +8134,77 @@ arrayfunc.c one round of word expansion before calling the unset builtin. (This function is only called by the unset builtin). Fixes bug reported by + + 3/17 + ---- +jobs.c + - waitchld: move code that adds the last process substitution pid to the + bgpids array from waitchld (where it can call malloc in a signal handler + context) to cleanup_dead_jobs + + 3/19 + ---- +subst.c + - parameter_brace_expand: if expanding an array in a context where word + splitting will not take place (W_ASSIGNRHS only for now), make sure to + pass the double-quoted flag to chk_atstar so we don't get the unquoted + $* behavior, which will cause unwanted word splitting. Fixes bug + reported by isabella parakiss + +arrayfunc.c + - unbind_array_element: don't assume that caller will check and pass only + array variables; don't allow non-array variables to be unset using the + `@' or `*' subscripts and don't allow any subscripts other than 0; + return -2 in those cases + - unbind_array_element: unset a non-array variable if passed a subscript + of `0' (e.g., `unbind "scalar[0]"'). This is new functionality that + parallels the ${scalar[0]} expansion + +builtins/set.def + - unset_builtin: don't check whether a variable is an array if it's + referenced using array syntax (scalar[0]); pass it to + unbind_array_element anyway and check the result. This means that + `unset scalar' and `unset scalar[0]' are equivalent + + 3/20 + ---- +builtins/set.def + - set_builtin: make `-i' an invalid option, unconditionally for now. + From a bug-bash discussion started by Peng Yu + + 3/21 + ---- +lib/readline/colors.c + - _rl_print_color_indicator: handle dangling symlinks (C_ORPHAN) and + the `target' specifier for links (dereference S_ISLNK if the target + exists). Bug report and fix from andreas@stapelspeicher.org + +{arrayfunc,subst}.c + - add code to save and restore this_command_name in places that set + this_command_name to NULL to prevent error messages from arithmetic + evaluation. Fixes bug reported by brian.carpenter@gmail.com + +builtins/mapfile.def + - do_chop: remove a new DELIM argument from the line, instead of + unconditionally removing newline + - mapfile: if -d delim is supplied and we are breaking fields at DELIM, + remove DELIM if the -t option is supplied by passing DELIM to do_chop(). + Suggested by Geir Hauge + +doc/{bash.1,bashref.texi} + - mapfile: document new -t option behavior, defaults are the same + +builtins/alias.def + - print_alias: if the first character of an alias name is `-', add a + `-- ' after `alias' to avoid option errors when trying to reuse the + output. Bug report and fix on savannah from Pasha Bolokhov + + + 3/22 + ---- +builtins/declare.def + - declare_internal: if creating a variable does not return a valid + variable in VAR, check for null variable before dereferencing it. + This happens with nameref variables referencing variables set to + the empty string. + Fixes bug reported by Arthur200000 diff --git a/MANIFEST b/MANIFEST index cef374f8f..c3e003bb4 100644 --- a/MANIFEST +++ b/MANIFEST @@ -834,6 +834,8 @@ tests/array16.sub f tests/array17.sub f tests/array18.sub f tests/array19.sub f +tests/array20.sub f +tests/array21.sub f tests/array-at-star f tests/array2.right f tests/assoc.tests f @@ -853,6 +855,7 @@ tests/builtins1.sub f tests/builtins2.sub f tests/builtins3.sub f tests/builtins4.sub f +tests/builtins5.sub f tests/source1.sub f tests/source2.sub f tests/source3.sub f @@ -1006,6 +1009,7 @@ tests/input.right f tests/intl.tests f tests/intl1.sub f tests/intl2.sub f +tests/intl3.sub f tests/intl.right f tests/iquote.tests f tests/iquote.right f @@ -1115,6 +1119,7 @@ tests/redir8.sub f tests/redir9.sub f tests/redir10.sub f tests/redir11.sub f +tests/redir12.sub f tests/rhs-exp.tests f tests/rhs-exp.right f tests/rhs-exp1.sub f diff --git a/arrayfunc.c b/arrayfunc.c index d917bad88..6479aaaf8 100644 --- a/arrayfunc.c +++ b/arrayfunc.c @@ -479,7 +479,7 @@ assign_compound_array_list (var, nlist, flags) ARRAY *a; HASH_TABLE *h; WORD_LIST *list; - char *w, *val, *nval; + char *w, *val, *nval, *savecmd; int len, iflags, free_val; arrayind_t ind, last_ind; char *akey; @@ -614,10 +614,12 @@ assign_compound_array_list (var, nlist, flags) free_val = 1; } + savecmd = this_command_name; if (integer_p (var)) this_command_name = (char *)NULL; /* no command name for errors */ bind_array_var_internal (var, ind, akey, val, iflags); last_ind++; + this_command_name = savecmd; if (free_val) free (val); @@ -747,8 +749,13 @@ unbind_array_element (var, sub) if (ALL_ELEMENT_SUB (sub[0]) && sub[1] == 0) { - unbind_variable (var->name); - return (0); + if (array_p (var) || assoc_p (var)) + { + unbind_variable (var->name); /* XXX -- {array,assoc}_flush ? */ + return (0); + } + else + return -2; /* don't allow this to unset scalar variables */ } if (assoc_p (var)) @@ -763,7 +770,7 @@ unbind_array_element (var, sub) assoc_remove (assoc_cell (var), akey); free (akey); } - else + else if (array_p (var)) { ind = array_expand_index (var, sub, len+1); /* negative subscripts to indexed arrays count back from end */ @@ -778,6 +785,19 @@ unbind_array_element (var, sub) if (ae) array_dispose_element (ae); } + else /* array_p (var) == 0 && assoc_p (var) == 0 */ + { + akey = this_command_name; + ind = array_expand_index (var, sub, len+1); + this_command_name = akey; + if (ind == 0) + { + unbind_variable (var->name); + return (0); + } + else + return -2; /* any subscript other than 0 is invalid with scalar variables */ + } return 0; } @@ -864,7 +884,7 @@ array_expand_index (var, s, len) char *s; int len; { - char *exp, *t; + char *exp, *t, *savecmd; int expok; arrayind_t val; @@ -872,8 +892,10 @@ array_expand_index (var, s, len) strncpy (exp, s, len - 1); exp[len - 1] = '\0'; t = expand_arith_string (exp, Q_DOUBLE_QUOTES|Q_ARITH|Q_ARRAYSUB); /* XXX - Q_ARRAYSUB for future use */ + savecmd = this_command_name; this_command_name = (char *)NULL; val = evalexp (t, &expok); + this_command_name = savecmd; free (t); free (exp); if (expok == 0) diff --git a/arrayfunc.h b/arrayfunc.h index 5b755329f..3a29a594e 100644 --- a/arrayfunc.h +++ b/arrayfunc.h @@ -29,6 +29,7 @@ #define AV_ALLOWALL 0x001 #define AV_QUOTED 0x002 #define AV_USEIND 0x004 +#define AV_USEVAL 0x008 /* XXX - should move this */ extern SHELL_VAR *convert_var_to_array __P((SHELL_VAR *)); extern SHELL_VAR *convert_var_to_assoc __P((SHELL_VAR *)); diff --git a/builtins/alias.def b/builtins/alias.def index d720ee4b5..d2f6319f3 100644 --- a/builtins/alias.def +++ b/builtins/alias.def @@ -232,7 +232,7 @@ print_alias (alias, flags) value = sh_single_quote (alias->value); if (flags & AL_REUSABLE) - printf ("alias "); + printf ("alias %s", (alias->name && alias->name[0] == '-') ? "-- " : ""); printf ("%s=%s\n", alias->name, value); free (value); diff --git a/builtins/declare.def b/builtins/declare.def index 69c4703df..5ed83a01d 100644 --- a/builtins/declare.def +++ b/builtins/declare.def @@ -506,13 +506,13 @@ declare_internal (list, local_var) if (flags_on & att_assoc) { var = make_new_assoc_variable (name); - if (offset == 0 && no_invisible_vars == 0) + if (var && offset == 0 && no_invisible_vars == 0) VSETATTR (var, att_invisible); } else if ((flags_on & att_array) || making_array_special) { var = make_new_array_variable (name); - if (offset == 0 && no_invisible_vars == 0) + if (var && offset == 0 && no_invisible_vars == 0) VSETATTR (var, att_invisible); } else @@ -522,9 +522,11 @@ declare_internal (list, local_var) else { var = mkglobal ? bind_global_variable (name, (char *)NULL, 0) : bind_variable (name, (char *)NULL, 0); - if (no_invisible_vars == 0) + if (var && no_invisible_vars == 0) VSETATTR (var, att_invisible); } + if (var == 0) + NEXT_VARIABLE (); } /* Can't take an existing array variable and make it a nameref */ else if ((array_p (var) || assoc_p (var)) && (flags_on & att_nameref)) diff --git a/builtins/mapfile.def b/builtins/mapfile.def index 6eae23f8d..03f0b480d 100644 --- a/builtins/mapfile.def +++ b/builtins/mapfile.def @@ -2,7 +2,7 @@ This file is mapfile.def, from which is created mapfile.c. It implements the builtin "mapfile" in Bash. Copyright (C) 2005-2006 Rocky Bernstein for Free Software Foundation, Inc. -Copyright (C) 2008-2012 Free Software Foundation, Inc. +Copyright (C) 2008-2015 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -23,7 +23,7 @@ $PRODUCES mapfile.c $BUILTIN mapfile $FUNCTION mapfile_builtin -$SHORT_DOC mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array] +$SHORT_DOC mapfile [-d delim] [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array] Read lines from the standard input into an indexed array variable. Read lines from the standard input into the indexed array variable ARRAY, or @@ -31,10 +31,11 @@ from file descriptor FD if the -u option is supplied. The variable MAPFILE is the default ARRAY. Options: + -d delim Use DELIM to terminate lines, instead of newline -n count Copy at most COUNT lines. If COUNT is 0, all lines are copied -O origin Begin assigning to ARRAY at index ORIGIN. The default index is 0 -s count Discard the first COUNT lines read - -t Remove a trailing newline from each line read + -t Remove a trailing DELIM from each line read (default newline) -u fd Read lines from file descriptor FD instead of the standard input -C callback Evaluate CALLBACK each time QUANTUM lines are read -c quantum Specify the number of lines read between each call to @@ -132,13 +133,14 @@ run_callback (callback, curindex, curline) } static void -do_chop(line) - char * line; +do_chop(line, delim) + char *line; + unsigned char delim; { int length; length = strlen (line); - if (length && line[length-1] == '\n') + if (length && line[length-1] == delim) line[length-1] = '\0'; } @@ -208,7 +210,7 @@ mapfile (fd, line_count_goal, origin, nskip, callback_quantum, callback, array_n { /* Remove trailing newlines? */ if (flags & MAPF_CHOP) - do_chop (line); + do_chop (line, delim); /* Has a callback been registered and if so is it time to call it? */ if (callback && line_count && (line_count % callback_quantum) == 0) diff --git a/builtins/set.def b/builtins/set.def index 87632a720..35b2025ca 100644 --- a/builtins/set.def +++ b/builtins/set.def @@ -653,6 +653,13 @@ set_builtin (list) { switch (flag_name) { + case 'i': /* don't allow set -i */ + s[0] = list_opttype; + s[1] = 'i'; + s[2] = '\0'; + sh_invalidopt (s); + builtin_usage (); + return (EX_USAGE); case '?': builtin_usage (); return (list_optopt == '?' ? EXECUTION_SUCCESS : EX_USAGE); @@ -887,17 +894,15 @@ unset_builtin (list) #if defined (ARRAY_VARS) if (var && unset_array) { - if (array_p (var) == 0 && assoc_p (var) == 0) + /* Let unbind_array_element decide what to do with non-array vars */ + tem = unbind_array_element (var, t); + if (tem == -2 && array_p (var) == 0 && assoc_p (var) == 0) { builtin_error (_("%s: not an array variable"), var->name); NEXT_VARIABLE (); } - else - { - tem = unbind_array_element (var, t); - if (tem == -1) - any_failed++; - } + else if (tem < 0) + any_failed++; } else #endif /* ARRAY_VARS */ diff --git a/doc/bash.1 b/doc/bash.1 index 72b47761b..f8deeb841 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -5,12 +5,12 @@ .\" Case Western Reserve University .\" chet.ramey@case.edu .\" -.\" Last Change: Mon Jan 19 14:47:31 EST 2015 +.\" Last Change: Sat Mar 21 20:10:48 EDT 2015 .\" .\" bash_builtins, strip all but Built-Ins section .if \n(zZ=1 .ig zZ .if \n(zY=1 .ig zY -.TH BASH 1 "2015 January 19" "GNU Bash 4.4" +.TH BASH 1 "2015 March 21" "GNU Bash 4.4" .\" .\" There's some problem with having a `@' .\" in a tagged paragraph with the BSD man macros. @@ -277,6 +277,7 @@ or one started with the option. .PP An \fIinteractive\fP shell is one started without non-option arguments +(unless \fB\-s\fP is specified) and without the .B \-c option @@ -8494,7 +8495,7 @@ The default index is 0. Discard the first \fIcount\fP lines read. .TP .B \-t -Remove a trailing newline from each line read. +Remove a trailing \fIdelim\fP (default newline) from each line read. .TP .B \-u Read lines from file descriptor \fIfd\fP instead of the standard input. diff --git a/doc/bashref.texi b/doc/bashref.texi index 0f17a9055..397e1d657 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -4254,7 +4254,7 @@ The default index is 0. @item -s Discard the first @var{count} lines read. @item -t -Remove a trailing newline from each line read. +Remove a trailing @var{delim} (default newline) from each line read. @item -u Read lines from file descriptor @var{fd} instead of the standard input. @item -C diff --git a/doc/version.texi b/doc/version.texi index 15447f969..987d57d2a 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -2,10 +2,10 @@ Copyright (C) 1988-2015 Free Software Foundation, Inc. @end ignore -@set LASTCHANGE Mon Jan 19 14:47:45 EST 2015 +@set LASTCHANGE Sat Mar 21 20:10:48 EDT 2015 @set EDITION 4.4 @set VERSION 4.4 -@set UPDATED 19 January 2015 -@set UPDATED-MONTH January 2015 +@set UPDATED 21 March 2015 +@set UPDATED-MONTH March 2015 diff --git a/jobs.c b/jobs.c index 3ce9d2d4e..ec014d1f0 100644 --- a/jobs.c +++ b/jobs.c @@ -866,6 +866,15 @@ cleanup_dead_jobs () delete_job (i, 0); } +#if defined (PROCESS_SUBSTITUTION) + if (last_procsub_child && last_procsub_child->running == PS_DONE) + { + bgp_add (last_procsub_child->pid, process_exit_status (last_procsub_child->status)); /* XXX */ + discard_pipeline (last_procsub_child); + last_procsub_child = (PROCESS *)NULL; + } +#endif + #if defined (COPROCESS_SUPPORT) coproc_reap (); #endif @@ -3381,12 +3390,6 @@ itrace("waitchld: waitpid returns %d block = %d children_exited = %d", pid, bloc if (job != NO_JOB) js.c_reaped++; } - -#if defined (PROCESS_SUBSTITUTION) - /* XXX - should we make this unconditional and not depend on last procsub? */ - if (child && child == last_procsub_child && child->running == PS_DONE) - bgp_add (child->pid, process_exit_status (child->status)); /* XXX */ -#endif if (job == NO_JOB) continue; diff --git a/lib/readline/colors.c b/lib/readline/colors.c index ba570b5b6..963dc12e6 100644 --- a/lib/readline/colors.c +++ b/lib/readline/colors.c @@ -128,10 +128,9 @@ _rl_print_color_indicator (char *f) const char* name; char *filename; - struct stat astat; + struct stat astat, linkstat; mode_t mode; - int linkok; - + int linkok; /* 1 == ok, 0 == dangling symlink, -1 == missing */ int stat_ok; name = f; @@ -150,10 +149,20 @@ _rl_print_color_indicator (char *f) #else stat_ok = stat(name, &astat); #endif - if( stat_ok == 0 ) { - mode = astat.st_mode; - linkok = 1; //f->linkok; - } + if (stat_ok == 0) + { + mode = astat.st_mode; +#if defined (HAVE_LSTAT) + if (S_ISLNK (mode)) + { + linkok = stat (name, &linkstat) == 0; + if (linkok && strncmp (_rl_color_indicator[C_LINK].string, "target", 6) == 0) + mode = linkstat.st_mode; + } + else +#endif + linkok = 1; + } else linkok = -1; @@ -161,6 +170,8 @@ _rl_print_color_indicator (char *f) if (linkok == -1 && _rl_color_indicator[C_MISSING].string != NULL) colored_filetype = C_MISSING; + else if (linkok == 0 && S_ISLNK(mode) && _rl_color_indicator[C_ORPHAN].string != NULL) + colored_filetype = C_ORPHAN; /* dangling symlink */ else if(stat_ok != 0) { static enum indicator_no filetype_indicator[] = FILETYPE_INDICATORS; @@ -201,10 +212,7 @@ _rl_print_color_indicator (char *f) #endif } else if (S_ISLNK (mode)) - colored_filetype = ((linkok == 0 - && (!strncmp (_rl_color_indicator[C_LINK].string, "target", 6) - || _rl_color_indicator[C_ORPHAN].string)) - ? C_ORPHAN : C_LINK); + colored_filetype = C_LINK; else if (S_ISFIFO (mode)) colored_filetype = C_FIFO; else if (S_ISSOCK (mode)) diff --git a/lib/readline/doc/readline.3 b/lib/readline/doc/readline.3 index 8230ce698..765c8fae9 100644 --- a/lib/readline/doc/readline.3 +++ b/lib/readline/doc/readline.3 @@ -354,7 +354,7 @@ readline equivalents. .TP .B blink\-matching\-paren (Off) If set to \fBOn\fP, readline attempts to briefly move the cursor to an -opening parenthesis when a closing parenthsis is inserted. +opening parenthesis when a closing parenthesis is inserted. .TP .B colored\-completion\-prefix (Off) If set to \fBOn\fP, when listing completions, readline displays the diff --git a/lib/readline/doc/rluser.texi b/lib/readline/doc/rluser.texi index 284f46657..6465895ab 100644 --- a/lib/readline/doc/rluser.texi +++ b/lib/readline/doc/rluser.texi @@ -430,7 +430,7 @@ Readline equivalents. @item blink-matching-paren @vindex blink-matching-paren If set to @samp{on}, Readline attempts to briefly move the cursor to an -opening parenthesis when a closing parenthsis is inserted. The default +opening parenthesis when a closing parenthesis is inserted. The default is @samp{off}. @item colored-completion-prefix diff --git a/redir.c b/redir.c index e490bbb3c..467f73afe 100644 --- a/redir.c +++ b/redir.c @@ -52,6 +52,7 @@ extern int errno; #include "flags.h" #include "execute_cmd.h" #include "redir.h" +#include "trap.h" #if defined (BUFFERED_INPUT) # include "input.h" diff --git a/shell.h b/shell.h index 3cf25df0b..c9affdf20 100644 --- a/shell.h +++ b/shell.h @@ -82,7 +82,8 @@ extern int EOF_Reached; #define MATCH_GLOBREP 0x010 #define MATCH_QUOTED 0x020 -#define MATCH_STARSUB 0x040 +#define MATCH_ASSIGNRHS 0x040 +#define MATCH_STARSUB 0x080 /* Some needed external declarations. */ extern char **shell_environment; diff --git a/subst.c b/subst.c index 7f6528495..ba551d30e 100644 --- a/subst.c +++ b/subst.c @@ -321,7 +321,7 @@ static int shouldexp_replacement __P((char *)); static char *pos_params_pat_subst __P((char *, char *, char *, int)); -static char *parameter_brace_patsub __P((char *, char *, int, char *, int, int)); +static char *parameter_brace_patsub __P((char *, char *, int, char *, int, int, int)); static char *pos_params_casemod __P((char *, char *, int, int)); static char *parameter_brace_casemod __P((char *, char *, int, int, char *, int, int)); @@ -7172,11 +7172,11 @@ pos_params_pat_subst (string, pat, rep, mflags) and the string to substitute. QUOTED is a flags word containing the type of quoting currently in effect. */ static char * -parameter_brace_patsub (varname, value, ind, patsub, quoted, flags) +parameter_brace_patsub (varname, value, ind, patsub, quoted, pflags, flags) char *varname, *value; int ind; char *patsub; - int quoted, flags; + int quoted, pflags, flags; { int vtype, mflags, starsub, delim; char *val, *temp, *pat, *rep, *p, *lpatsub, *tt; @@ -7212,6 +7212,9 @@ parameter_brace_patsub (varname, value, ind, patsub, quoted, flags) if (starsub) mflags |= MATCH_STARSUB; + if (pflags & PF_ASSIGNRHS) + mflags |= MATCH_ASSIGNRHS; + /* If the pattern starts with a `/', make sure we skip over it when looking for the replacement delimiter. */ delim = skip_to_delim (lpatsub, ((*patsub == '/') ? 1 : 0), "/", 0); @@ -7812,7 +7815,16 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta #if defined (ARRAY_VARS) if (valid_array_reference (name, 0)) - chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at); + { + int qflags; + + qflags = quoted; + /* If in a context where word splitting will not take place, treat as + if double-quoted. Has effects with $* and ${array[*]} */ + if (pflags & PF_ASSIGNRHS) + qflags |= Q_DOUBLE_QUOTES; + chk_atstar (name, qflags, quoted_dollar_atp, contains_dollar_at); + } #endif var_is_set = temp != (char *)0; @@ -7879,7 +7891,7 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta } else if (want_patsub) { - temp1 = parameter_brace_patsub (name, temp, ind, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0); + temp1 = parameter_brace_patsub (name, temp, ind, value, quoted, pflags, (tflag & W_ARRAYIND) ? AV_USEIND : 0); FREE (name); FREE (value); FREE (temp); @@ -8077,7 +8089,7 @@ param_expand (string, sindex, quoted, expanded_something, int *sindex, quoted, *expanded_something, *contains_dollar_at; int *quoted_dollar_at_p, *had_quoted_null_p, pflags; { - char *temp, *temp1, uerror[3]; + char *temp, *temp1, uerror[3], *savecmd; int zindex, t_index, expok; unsigned char c; intmax_t number; @@ -8369,8 +8381,10 @@ param_expand (string, sindex, quoted, expanded_something, arithsub: /* No error messages. */ + savecmd = this_command_name; this_command_name = (char *)NULL; number = evalexp (temp1, &expok); + this_command_name = savecmd; free (temp); free (temp1); if (expok == 0) @@ -9330,6 +9344,17 @@ finished_with_string: free (tstring); goto set_word_flags; } + /* This is the attempt to make $* in an assignment context (a=$*) and + array variables subscripted with * in an assignment context (a=${foo[*]}) + behave similarly. It has side effects that, though they increase + compatibility with other shells, are not backwards compatible. */ +#if 0 + else if (has_dollar_at && quoted == 0 && ifs_chars && (word->flags & W_ASSIGNRHS)) + { + tword = make_bare_word (istring); + goto set_word_flags; + } +#endif else if (has_dollar_at && ifs_chars) list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1); else @@ -10135,6 +10160,7 @@ expand_word_list_internal (list, eflags) { WORD_LIST *new_list, *temp_list; int tint; + char *savecmd; tempenv_assign_error = 0; if (list == 0) @@ -10152,8 +10178,10 @@ expand_word_list_internal (list, eflags) into the shell's environment. */ for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next) { + savecmd = this_command_name; this_command_name = (char *)NULL; /* no arithmetic errors */ tint = do_word_assignment (temp_list->word, 0); + this_command_name = savecmd; /* Variable assignment errors in non-interactive shells running in Posix.2 mode cause the shell to exit. */ if (tint == 0) @@ -10217,10 +10245,12 @@ expand_word_list_internal (list, eflags) for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next) { + savecmd = this_command_name; this_command_name = (char *)NULL; assigning_in_environment = (assign_func == assign_in_env); tint = (*assign_func) (temp_list->word, is_builtin_or_func); assigning_in_environment = 0; + this_command_name = savecmd; /* Variable assignment errors in non-interactive shells running in Posix.2 mode cause the shell to exit. */ if (tint == 0) diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 3efcf32d6..72ec06a2c 100755 --- a/tests/RUN-ONE-TEST +++ b/tests/RUN-ONE-TEST @@ -1,4 +1,4 @@ -BUILD_DIR=/usr/local/build/chet/bash/bash-current +BUILD_DIR=/usr/local/build/bash/bash-current THIS_SH=$BUILD_DIR/bash PATH=$PATH:$BUILD_DIR diff --git a/tests/array.right b/tests/array.right index 40e38b102..39bdc316e 100644 --- a/tests/array.right +++ b/tests/array.right @@ -33,6 +33,9 @@ declare -ar a=([1]="" [2]="bdef" [5]="hello world" [6]="test expression" [15]="t declare -ar c readonly -a a=([1]="" [2]="bdef" [5]="hello world" [6]="test expression" [15]="test 2") readonly -a c +./array.tests: line 86: warning: d=([1]="" [2]="bdef" [5]="hello world" "test"): quoted compound array assignment deprecated +./array.tests: line 90: warning: e[10]=(test): quoted compound array assignment deprecated +./array.tests: line 93: warning: f=("${d[@]}"): quoted compound array assignment deprecated a test declare -a BASH_ARGC=() declare -a BASH_ARGV=() @@ -44,7 +47,7 @@ declare -ar a=([1]="" [2]="bdef" [5]="hello world" [6]="test expression" [15]="t declare -a b=([0]="this" [1]="is" [2]="a" [3]="test" [4]="" [5]="/etc/passwd") declare -ar c declare -a d=([1]="" [2]="bdef" [5]="hello world" [6]="test" [9]="ninth element") -declare -a e=([10]="(test)") +declare -a e=([0]="test") declare -a f=([0]="" [1]="bdef" [2]="hello world" [3]="test" [4]="ninth element") ./array.tests: line 100: a: readonly variable ./array.tests: line 102: b[]: bad array subscript @@ -367,7 +370,7 @@ function function declare -a x=([0]="0" [1]="1" [2]="2" [3]="3" [4]="4" [5]="5") declare -a x=([0]="0" [1]="1" [2]="2" [3]="3" [4]="4") declare -a x=([0]="0" [1]="1" [2]="2" [4]="4") -./array14.sub: line 11: [-10]: bad array subscript +./array14.sub: line 11: unset: [-10]: bad array subscript declare -a x=([0]="0" [1]="1" [2]="2" [3]="3" [4]="4") declare -a x=([0]="0" [1]="1" [2]="2" [3]="3" [4]="4" [5]="five") declare -a x=([0]="0" [1]="1" [2]="2" [3]="3" [4]="4" [5]="5") @@ -376,8 +379,10 @@ declare -a x=([0]="0" [1]="1" [2]="2" [3]="3" [4]="4" [5]="5") declare -a x=([0]="0" [1]="1" [2]="2" [3]="3" [4]="4four" [5]="5") strlen(4four) = 5 1 2 0 3 +./array15.sub: line 6: warning: foo=(1 2 xx 3): quoted compound array assignment deprecated 1 2 0 3 1 2 0 3 +./array15.sub: line 14: warning: foo=(1 2 xx 3): quoted compound array assignment deprecated 1 2 0 3 1 2 0 3 foo index 1: ok @@ -433,50 +438,88 @@ argv[1] = <-> argv[2] = <-> argv[1] = < > declare -a foo=([0]="( zeroind )") +./array19.sub: line 13: warning: foo=( zeroind ): quoted compound array assignment deprecated declare -a foo=([0]="zeroind") +./array19.sub: line 17: warning: foo=( zeroind ): quoted compound array assignment deprecated declare -a foo=([0]="zeroind") declare -a foo=([0]="[0]=bar") declare -a foo=([0]="[0]=bar") declare -a foo=([0]="[0]=bar") declare -- a="(1 2 3)" -declare -a a=([0]="(1 2 3)") -declare -A a=([0]="(1 2 3)" ) +./array19.sub: line 41: warning: a=(1 2 3): quoted compound array assignment deprecated +declare -a a=([0]="1" [1]="2" [2]="3") +./array19.sub: line 46: warning: a=(1 2 3): quoted compound array assignment deprecated +./array19.sub: line 46: a: 1: must use subscript when assigning associative array +./array19.sub: line 46: a: 2: must use subscript when assigning associative array +./array19.sub: line 46: a: 3: must use subscript when assigning associative array +declare -A a=() declare -- a="([0]=a [1]=b)" -declare -a a=([0]="([0]=a [1]=b)") -declare -A a=([0]="([0]=a [1]=b)" ) +./array19.sub: line 55: warning: a=([0]=a [1]=b): quoted compound array assignment deprecated +declare -a a=([0]="a" [1]="b") +./array19.sub: line 60: warning: a=([0]=a [1]=b): quoted compound array assignment deprecated +declare -A a=([0]="a" [1]="b" ) declare -a var=([0]="[\$(echo" [1]="total" [2]="0)]=1" [3]="[2]=2]") declare -a var=([0]="[\$(echo total 0)]=1 [2]=2]") declare -a var=([0]="[\$(echo" [1]="total" [2]="0)]=1" [3]="[2]=2]") +./array19.sub: line 81: warning: var=([$(echo total 0)]=1 [2]=2]): quoted compound array assignment deprecated ./array19.sub: line 81: total 0: syntax error in expression (error token is "0") declare -a var=() declare -al foo=([0]="abcde" [1]="two" [2]="three") -declare -al foo=([0]="(abcde)" [1]="two" [2]="three") +./array19.sub: line 99: warning: foo=(AbCdE): quoted compound array assignment deprecated +declare -al foo=([0]="abcde") declare -al ar=([0]="one" [1]="two" [2]="three") declare -a a=([2]="foo") declare -a a=([2]="foo") declare -a a=([1]="(var)" [2]="foo") +./array19.sub: line 120: warning: a[1]=(var): quoted compound array assignment deprecated declare -a a=([0]="var") declare -a a=([0]="1" [1]="2" [2]="(1 2 3)") declare -a a=([0]="1" [1]="2" [2]="(1 2 3)") -declare -a a=([0]="(1 2 3)" [1]="2" [2]="3") -declare -a a=([0]="(1 2 3)" [1]="2" [2]="3") +./array19.sub: line 137: warning: a=(1 2 3): quoted compound array assignment deprecated +declare -a a=([0]="1" [1]="2" [2]="3") +./array19.sub: line 143: warning: a=(1 2 3): quoted compound array assignment deprecated +declare -a a=([0]="1" [1]="2" [2]="3") +./array19.sub: line 148: warning: a=(1 2 3): quoted compound array assignment deprecated declare -a a=([0]="1" [1]="2" [2]="3") declare -- a="a b" declare -- b="/scratch/bash" declare -- c="(1 2)" declare -- d="(\$a)" declare -- e="(\$(echo Darwin))" +./array19.sub: line 162: warning: c=(1 2): quoted compound array assignment deprecated +./array19.sub: line 162: warning: d=($a): quoted compound array assignment deprecated +./array19.sub: line 162: warning: e=($(echo Darwin)): quoted compound array assignment deprecated declare -a a=([0]="a b") declare -a b=([0]="/scratch/bash") declare -a c=([0]="1" [1]="2") declare -a d=([0]="a" [1]="b") declare -a e=([0]="Darwin") +./array19.sub: line 166: warning: c=(1 2): quoted compound array assignment deprecated ./array19.sub: line 166: c: 1: must use subscript when assigning associative array ./array19.sub: line 166: c: 2: must use subscript when assigning associative array +./array19.sub: line 166: warning: d=($a): quoted compound array assignment deprecated ./array19.sub: line 166: d: $a: must use subscript when assigning associative array +./array19.sub: line 166: warning: e=($(echo Darwin)): quoted compound array assignment deprecated ./array19.sub: line 166: e: $(echo Darwin): must use subscript when assigning associative array declare -A a=([0]="a b" ) declare -A b=([0]="/scratch/bash" ) declare -A c=() declare -A d=() declare -A e=() +a+b+c +x+b+c +a+b+c +x+b+c +argv[1] = +argv[1] = +a b c +x b c +a b c +x b c +declare -a a=([1]="2" [2]="3" [3]="4") +abcd +unset +./array21.sub: line 17: typeset: a: not found +./array21.sub: line 20: typeset: A: not found +declare -a a=() +declare -A A=() diff --git a/tests/array.tests b/tests/array.tests index 82d9c34d9..b10539376 100644 --- a/tests/array.tests +++ b/tests/array.tests @@ -384,25 +384,16 @@ ${THIS_SH} ./array6.sub ${THIS_SH} ./array7.sub ${THIS_SH} ./array8.sub - ${THIS_SH} ./array9.sub - ${THIS_SH} ./array10.sub - ${THIS_SH} ./array11.sub - ${THIS_SH} ./array12.sub - ${THIS_SH} ./array13.sub - ${THIS_SH} ./array14.sub - ${THIS_SH} ./array15.sub - ${THIS_SH} ./array16.sub - ${THIS_SH} ./array17.sub - ${THIS_SH} ./array18.sub - ${THIS_SH} ./array19.sub +${THIS_SH} ./array20.sub +${THIS_SH} ./array21.sub diff --git a/tests/array20.sub b/tests/array20.sub new file mode 100644 index 000000000..035d936bf --- /dev/null +++ b/tests/array20.sub @@ -0,0 +1,34 @@ +# tests to make sure that $* and ${array[*]} expand consistently in `list' +# and `scalar' contexts + +arr=(a b c) +IFS=+ + +# these two should both expand to `+' separated strings +a=${arr[*]} ; echo "$a" +b=${arr[*]/a/x}; echo "$b" + +set -- a b c + +# these two should both expand to `+' separated strings +a=${*} ; echo "$a" +b=${*/a/x}; echo "$b" + +# these two should both expand to `+' separated strings and it should handle +# characters in IFS as chars in the string +unset a b + +set -- 'a+b' 'c+d' 'e+f' +a=${*} ; recho "$a" +b=${*/a/x}; recho "$b" + +# now let's make sure that @ always uses space separators even in contexts +# where we don't do word splitting +set -- a b c +a=${@} ; echo "$a" +b=${@/a/x}; echo "$b" + +unset a b + +a=${arr[@]} ; echo "$a" +b=${arr[@]/a/x}; echo "$b" diff --git a/tests/array21.sub b/tests/array21.sub new file mode 100644 index 000000000..5dfa16b8a --- /dev/null +++ b/tests/array21.sub @@ -0,0 +1,31 @@ +typeset -a a +a=(1 2 3 4) + +typeset -A A +A=([one]=1 [two]=2 [three]=3 [four]=4) + +unset 'a[0]' +typeset -p a + +scalar=abcd +echo ${scalar[0]} + +unset 'scalar[0]' +echo ${scalar-unset} + +unset 'a[@]' +typeset -p a + +unset 'A[@]' +typeset -p A + +typeset -a a +a=(1 2 3 4) +typeset -A A +A=([one]=1 [two]=2 [three]=3 [four]=4) + +# supported, recommended way to unset all array elements +a=() +typeset -p a +A=() +typeset -p A diff --git a/tests/builtins.right b/tests/builtins.right index 63e5605fb..8a5e3f925 100644 --- a/tests/builtins.right +++ b/tests/builtins.right @@ -168,4 +168,30 @@ declare -a c=([0]="1" [1]="2" [2]="3") declare -a c=([0]="1" [1]="2" [2]="3") unset unset -./builtins.tests: line 260: exit: status: numeric argument required +assoc 1 unset +array 1 unset +assoc 2 unset +array 2 unset +unset1 +unset2 +1 +1 +1 +1 +assoc A +array a +assoc B unset +array b unset +scalar 1 +scalar 2 +scalar 3 unset +argv[1] = +assoc: 3 +array: 3 +scalar: 13 +scalar: 1 +scalar: 0 +scalar: 1 +scalar: 0 +scalar: 0 +./builtins.tests: line 263: exit: status: numeric argument required diff --git a/tests/builtins.tests b/tests/builtins.tests index 9d775201a..ccf55a87e 100644 --- a/tests/builtins.tests +++ b/tests/builtins.tests @@ -256,6 +256,9 @@ ${THIS_SH} ./builtins3.sub # test behavior of using declare to create variables without assigning values ${THIS_SH} ./builtins4.sub +# test behavior of set and unset array variables +${THIS_SH} ./builtins5.sub + # this must be last -- it is a fatal error exit status diff --git a/tests/builtins5.sub b/tests/builtins5.sub new file mode 100644 index 000000000..9a5dd7b99 --- /dev/null +++ b/tests/builtins5.sub @@ -0,0 +1,61 @@ +# a start at a test suite for what it means for an array to be set or unset and +# how to test that state +typeset -A A +A[a]=1 +typeset -a a +a[1]=1 + +if [ -v A ]; then echo assoc 1; else echo assoc 1 unset; fi +if [ -v a ]; then echo array 1; else echo array 1 unset; fi + +if [ -v "${A[@]}" ]; then echo assoc 2; else echo assoc 2 unset; fi +if [ -v "${a[@]}" ]; then echo array 2; else echo array 2 unset; fi + +echo ${A-unset1} +echo ${a-unset2} + +echo ${A[@]-unset3} +echo ${a[@]-unset4} + +echo ${#A[@]} +echo ${#a[@]} + +typeset -A B +typeset -a b + +scalar1=foo +scalar2= + +if [ -v A[@] ]; then echo assoc A; else echo assoc A unset; fi +if [ -v a[@] ]; then echo array a; else echo array a unset; fi + +if [ -v B[@] ]; then echo assoc B; else echo assoc B unset; fi +if [ -v b[@] ]; then echo array b; else echo array b unset; fi + +if [ -v scalar1[@] ]; then echo scalar 1; else echo scalar 1 unset; fi +if [ -v scalar2[@] ]; then echo scalar 2; else echo scalar 2 unset; fi +if [ -v scalar3[@] ]; then echo scalar 3; else echo scalar 3 unset; fi + +unset a A +declare -A assoc=([one]=one [two]=two [three]=three) +declare -a array=(one two three) + +scalar="one two three" +scalar2= + +recho "${scalar[@]}" + +echo assoc: ${#assoc[@]} +echo array: ${#array[@]} + +echo scalar: ${#scalar} +echo scalar: ${#scalar[@]} + +echo scalar: ${#scalar2} +echo scalar: ${#scalar2[@]} + +echo scalar: ${#scalar3} +echo scalar: ${#scalar3[@]} + + + diff --git a/tests/errors.right b/tests/errors.right index 63d6b7e3a..1ac9735fc 100644 --- a/tests/errors.right +++ b/tests/errors.right @@ -35,7 +35,7 @@ hash: usage: hash [-lr] [-p pathname] [-dt] [name ...] ./errors.tests: line 106: hash: hashing disabled ./errors.tests: line 109: export: `AA[4]': not a valid identifier ./errors.tests: line 110: readonly: `AA[4]': not a valid identifier -./errors.tests: line 113: [-2]: bad array subscript +./errors.tests: line 113: unset: [-2]: bad array subscript ./errors.tests: line 117: AA: readonly variable ./errors.tests: line 121: AA: readonly variable ./errors.tests: line 129: shift: 5: shift count out of range diff --git a/tests/intl.right b/tests/intl.right index acf108a45..ff1ae17cc 100644 --- a/tests/intl.right +++ b/tests/intl.right @@ -17,6 +17,10 @@ aéb 1.0000 1.0000 1,0000 +1 +bytematch +0000000 254 012 +0000002 Passed all 1378 Unicode tests 0000000 303 277 012 0000003 diff --git a/tests/intl.tests b/tests/intl.tests index 3844fa878..3c42086b1 100644 --- a/tests/intl.tests +++ b/tests/intl.tests @@ -44,6 +44,9 @@ ${THIS_SH} ./intl1.sub # this tests both international handling in printf and temporary environments ${THIS_SH} ./intl2.sub +# test splitting on characters instead of bytes +${THIS_SH} ./intl3.sub + ${THIS_SH} ./unicode1.sub 2>/dev/null ${THIS_SH} ./unicode2.sub diff --git a/tests/intl3.sub b/tests/intl3.sub new file mode 100644 index 000000000..35a4afad7 --- /dev/null +++ b/tests/intl3.sub @@ -0,0 +1,21 @@ +# more tests to make sure that IFS splits on characters, not bytes +export LANG=en_US.UTF-8 + +euro=$'\342\202\254' +o342=$'\342' +o202=$'\202' +o254=$'\254' + +IFS=$o254 +t=+$euro+ +set -- $t + +echo "$#" + +# but matching still occurs on bytes if we don't have a valid multibyte char +case $euro in +*$o202*) echo bytematch ;; +*) echo mbchar match ;; +esac + +echo "${euro##*$o202}" | od -b diff --git a/tests/redir.right b/tests/redir.right index 12d740888..c158e2518 100644 --- a/tests/redir.right +++ b/tests/redir.right @@ -157,3 +157,4 @@ a+=3 foo foo ./redir11.sub: line 53: $(echo $a): Bad file descriptor +123 diff --git a/tests/redir.tests b/tests/redir.tests index 7b74ac53d..24e3cd1a5 100644 --- a/tests/redir.tests +++ b/tests/redir.tests @@ -191,3 +191,4 @@ ${THIS_SH} ./redir9.sub ${THIS_SH} ./redir10.sub ${THIS_SH} ./redir11.sub +${THIS_SH} ./redir12.sub diff --git a/tests/redir12.sub b/tests/redir12.sub new file mode 100644 index 000000000..61dbfed76 --- /dev/null +++ b/tests/redir12.sub @@ -0,0 +1,5 @@ +# make sure we can wait for the last process substitution, since it sets $! +echo <(exit 123) >/dev/null + +wait "$!" +echo $? diff --git a/tests/run-varenv b/tests/run-varenv index f0ce19529..951c44fe8 100644 --- a/tests/run-varenv +++ b/tests/run-varenv @@ -1,2 +1,2 @@ -${THIS_SH} ./varenv.sh | grep -v '^expect' > /tmp/xx +${THIS_SH} ./varenv.sh 2>&1 | grep -v '^expect' > /tmp/xx diff /tmp/xx varenv.right && rm -f /tmp/xx diff --git a/tests/varenv.right b/tests/varenv.right index a1a954009..7765e5c4d 100644 --- a/tests/varenv.right +++ b/tests/varenv.right @@ -54,6 +54,7 @@ after fff3: x=4 a:b:c:d a-b-c-d a:b:c:d +./varenv4.sub: line 13: warning: v=( asdf fdsa ): quoted compound array assignment deprecated g: , f: , FIN: asdf fdsa, asdf fdsa