diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 155f237a..444c0331 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -12819,3 +12819,37 @@ doc/bash.1,lib/readline/doc/hsuser.texi lib/readline/history.c - remove_history: use memmove to move the history list around instead of a loop that copies pointers one at a time, similar to add_history + + 12/19 + ----- +configure.ac + - linux: make sure PGRP_PIPE is defined unconditionally for all kernel + versions greater than 2.3.* + +lib/readline/history.c + - clear_history: when clearing the history, reset history_base to 1 + (its default) + - remove_history_range: new function, removes a set of history entries + and returns them all for deallocation + +lib/readline/history.h + - remove_history_range: extern declaration + + 12/20 + ----- +execute_cmd.c + - eval_arith_for_expr: pass EXP_EXPANDED to evalexp, since we run the + expression through expand_words_no_vars + + 12/21 + ----- +input.c + - b_fill_buffer: when read returns EOF or error, and we reset the + buffer and pointers, reset the input pointer to 0. Fixes issue + reported by Stephane Chazelas + + 12/22 + ----- +arrayfunc.[ch],subst.c + - array_expand_index: added new FLAGS argument, reserved for future use, + changed callers diff --git a/arrayfunc.c b/arrayfunc.c index 9a1a1401..cea8fba1 100644 --- a/arrayfunc.c +++ b/arrayfunc.c @@ -47,6 +47,9 @@ extern int array_needs_making; once, when performing variable expansion. */ int assoc_expand_once = 0; +/* Ditto for indexed array subscripts */ +int array_expand_once = 1; + static SHELL_VAR *bind_array_var_internal __P((SHELL_VAR *, arrayind_t, char *, char *, int)); static SHELL_VAR *assign_array_element_internal __P((SHELL_VAR *, char *, char *, char *, int, char *, int)); @@ -337,7 +340,7 @@ assign_array_element_internal (entry, name, vname, sub, sublen, value, flags) } else { - ind = array_expand_index (entry, sub, sublen); + ind = array_expand_index (entry, sub, sublen, 0); /* negative subscripts to indexed arrays count back from end */ if (entry && ind < 0) ind = (array_p (entry) ? array_max_index (array_cell (entry)) : 0) + 1 + ind; @@ -591,7 +594,7 @@ assign_compound_array_list (var, nlist, flags) if (array_p (var)) { - ind = array_expand_index (var, w + 1, len); + ind = array_expand_index (var, w + 1, len, 0); /* negative subscripts to indexed arrays count back from end */ if (ind < 0) ind = array_max_index (array_cell (var)) + 1 + ind; @@ -813,7 +816,7 @@ unbind_array_element (var, sub, flags) } else if (array_p (var)) { - ind = array_expand_index (var, sub, len+1); + ind = array_expand_index (var, sub, len+1, 0); /* negative subscripts to indexed arrays count back from end */ if (ind < 0) ind = array_max_index (array_cell (var)) + 1 + ind; @@ -829,7 +832,7 @@ unbind_array_element (var, sub, flags) else /* array_p (var) == 0 && assoc_p (var) == 0 */ { akey = this_command_name; - ind = array_expand_index (var, sub, len+1); + ind = array_expand_index (var, sub, len+1, 0); this_command_name = akey; if (ind == 0) { @@ -922,10 +925,11 @@ valid_array_reference (name, flags) /* Expand the array index beginning at S and extending LEN characters. */ arrayind_t -array_expand_index (var, s, len) +array_expand_index (var, s, len, flags) SHELL_VAR *var; char *s; int len; + int flags; { char *exp, *t, *savecmd; int expok; @@ -1117,7 +1121,7 @@ array_value_internal (s, quoted, flags, rtype, indp) { if ((flags & AV_USEIND) == 0 || indp == 0) { - ind = array_expand_index (var, t, len); + ind = array_expand_index (var, t, len, 0); if (ind < 0) { /* negative subscripts to indexed arrays count back from end */ diff --git a/arrayfunc.h b/arrayfunc.h index 07f0302c..1d3eec4f 100644 --- a/arrayfunc.h +++ b/arrayfunc.h @@ -63,7 +63,7 @@ extern int skipsubscript __P((const char *, int, int)); extern void print_array_assignment __P((SHELL_VAR *, int)); extern void print_assoc_assignment __P((SHELL_VAR *, int)); -extern arrayind_t array_expand_index __P((SHELL_VAR *, char *, int)); +extern arrayind_t array_expand_index __P((SHELL_VAR *, char *, int, int)); extern int valid_array_reference __P((const char *, int)); extern char *array_value __P((const char *, int, int, int *, arrayind_t *)); extern char *get_array_value __P((const char *, int, int *, arrayind_t *)); diff --git a/bashhist.c b/bashhist.c index c0d6f64c..3de75134 100644 --- a/bashhist.c +++ b/bashhist.c @@ -355,6 +355,21 @@ bash_delete_histent (i) return 1; } +int +bash_delete_history_range (first, last) + int first, last; +{ + register int i; + HIST_ENTRY **discard_list; + + discard_list = remove_history_range (first, last); + for (i = 0; discard_list && discard_list[i]; i++) + free_history_entry (discard_list[i]); + history_lines_this_session -= i; + + return 1; +} + int bash_delete_last_history () { diff --git a/bashhist.h b/bashhist.h index 34bc2347..48156b6f 100644 --- a/bashhist.h +++ b/bashhist.h @@ -59,6 +59,7 @@ extern void bash_history_disable __P((void)); extern void bash_history_enable __P((void)); extern void bash_clear_history __P((void)); extern int bash_delete_histent __P((int)); +extern int bash_delete_history_range __P((int, int)); extern int bash_delete_last_history __P((void)); extern void load_history __P((void)); extern void save_history __P((void)); diff --git a/builtins/history.def b/builtins/history.def index 8428bc36..4573b437 100644 --- a/builtins/history.def +++ b/builtins/history.def @@ -106,7 +106,7 @@ history_builtin (list) WORD_LIST *list; { int flags, opt, result, old_history_lines, obase, ind; - char *filename, *delete_arg; + char *filename, *delete_arg, *range; intmax_t delete_offset; flags = 0; @@ -179,6 +179,46 @@ history_builtin (list) return (sh_chkwrite (EXECUTION_SUCCESS)); } #endif +#if defined (BASH_50) /* bash 5.0 */ + else if ((flags & DFLAG) && (range = strchr (delete_arg[0] == '-' ? delete_arg + 1 : delete_arg, '-'))) + { + intmax_t delete_start, delete_end; + *range++ = '\0'; + if (legal_number (delete_arg, &delete_start) == 0 || legal_number (range, &delete_end) == 0) + { + sh_erange (delete_arg, _("history position")); + return (EXECUTION_FAILURE); + } + if (delete_arg[0] == '-' && delete_start < 0) + { + /* the_history[history_length == 0x0, so this is correct */ + delete_start += history_length; + if (delete_start < history_base) + { + sh_erange (delete_arg, _("history position")); + return (EXECUTION_FAILURE); + } + } + /* numbers as displayed by display_history are offset by history_base */ + else if (delete_start > 0) + delete_start -= history_base; + if (range[0] == '-' && delete_end < 0) + { + delete_end += history_length; + if (delete_end < history_base) + { + sh_erange (delete_arg, _("history position")); + return (EXECUTION_FAILURE); + } + } + else if (delete_end > 0) + delete_end -= history_base; + result = bash_delete_history_range (delete_start, delete_end); + if (where_history () > history_length) + history_set_pos (history_length); + return (result ? EXECUTION_SUCCESS : EXECUTION_FAILURE); + } +#endif /* BASH_50 */ else if (flags & DFLAG) { if (legal_number (delete_arg, &delete_offset) == 0) @@ -189,13 +229,16 @@ history_builtin (list) /* check for negative offsets, count back from end of list */ if (delete_arg[0] == '-' && delete_offset < 0) { + /* since the_history[history_length] == 0x0, this calculation means + that history -d -1 will delete the last history entry, which at + this point is the history -d -1 we just added. */ ind = history_length + delete_offset; if (ind < history_base) { sh_erange (delete_arg, _("history position")); return (EXECUTION_FAILURE); } - opt = ind + 1; /* so history -d -1 deletes last history entry */ + opt = ind + history_base; /* compensate for opt - history_base below */ } else if ((delete_offset < history_base) || (delete_offset > (history_base + history_length))) { @@ -205,6 +248,8 @@ history_builtin (list) else opt = delete_offset; + /* Positive arguments from numbers as displayed by display_history need + to be offset by history_base */ result = bash_delete_histent (opt - history_base); /* Since remove_history changes history_length, this can happen if we delete the last history entry. */ diff --git a/configure b/configure index cd659978..f8a8c2f6 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac for Bash 4.4, version 4.087. +# From configure.ac for Bash 4.4, version 4.088. # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for bash 4.4-maint. # @@ -16170,7 +16170,8 @@ solaris2*) LOCAL_CFLAGS=-DSOLARIS ;; lynxos*) LOCAL_CFLAGS=-DRECYCLES_PIDS ;; linux*) LOCAL_LDFLAGS=-rdynamic # allow dynamic loading case "`uname -r`" in - 2.[456789]*|[34]*) $as_echo "#define PGRP_PIPE 1" >>confdefs.h + 1.*|2.[0123]*) : ;; + *) $as_echo "#define PGRP_PIPE 1" >>confdefs.h ;; esac ;; *qnx6*) LOCAL_CFLAGS="-Dqnx -Dqnx6" LOCAL_LIBS="-lncurses" ;; diff --git a/configure.ac b/configure.ac index 5142da25..40394192 100644 --- a/configure.ac +++ b/configure.ac @@ -21,7 +21,7 @@ dnl Process this file with autoconf to produce a configure script. # You should have received a copy of the GNU General Public License # along with this program. If not, see . -AC_REVISION([for Bash 4.4, version 4.087])dnl +AC_REVISION([for Bash 4.4, version 4.088])dnl define(bashvers, 4.4) define(relstatus, maint) @@ -1105,7 +1105,8 @@ solaris2*) LOCAL_CFLAGS=-DSOLARIS ;; lynxos*) LOCAL_CFLAGS=-DRECYCLES_PIDS ;; linux*) LOCAL_LDFLAGS=-rdynamic # allow dynamic loading case "`uname -r`" in - 2.[[456789]]*|[[34]]*) AC_DEFINE(PGRP_PIPE) ;; + 1.*|2.[[0123]]*) : ;; + *) AC_DEFINE(PGRP_PIPE) ;; esac ;; *qnx6*) LOCAL_CFLAGS="-Dqnx -Dqnx6" LOCAL_LIBS="-lncurses" ;; *qnx*) LOCAL_CFLAGS="-Dqnx -F -3s" LOCAL_LDFLAGS="-3s" LOCAL_LIBS="-lunix -lncurses" ;; diff --git a/execute_cmd.c b/execute_cmd.c index 41ac4209..2fff0939 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -2911,7 +2911,7 @@ eval_arith_for_expr (l, okp) skip the command. */ #if defined (DEBUGGER) if (debugging_mode == 0 || r == EXECUTION_SUCCESS) - expresult = evalexp (new->word->word, 0, okp); + expresult = evalexp (new->word->word, EXP_EXPANDED, okp); else { expresult = 0; @@ -2919,7 +2919,7 @@ eval_arith_for_expr (l, okp) *okp = 1; } #else - expresult = evalexp (new->word->word, 0, okp); + expresult = evalexp (new->word->word, EXP_EXPANDED, okp); #endif dispose_words (new); } diff --git a/input.c b/input.c index 308b87e4..a03911d3 100644 --- a/input.c +++ b/input.c @@ -504,7 +504,7 @@ b_fill_buffer (bp) nr = zread (bp->b_fd, bp->b_buffer, bp->b_size); if (nr <= 0) { - bp->b_used = 0; + bp->b_used = bp->b_inputp = 0; bp->b_buffer[0] = 0; if (nr == 0) bp->b_flag |= B_EOF; diff --git a/lib/readline/history.c b/lib/readline/history.c index 915e7ae4..ef293c76 100644 --- a/lib/readline/history.c +++ b/lib/readline/history.c @@ -525,6 +525,43 @@ remove_history (which) return (return_value); } +HIST_ENTRY ** +remove_history_range (first, last) + int first, last; +{ + HIST_ENTRY **return_value; + register int i; + int nentries; + HIST_ENTRY **start, **end; + + if (the_history == 0 || history_length == 0) + return ((HIST_ENTRY **)NULL); + if (first < 0 || first >= history_length || last < 0 || last >= history_length) + return ((HIST_ENTRY **)NULL); + if (first > last) + return (HIST_ENTRY **)NULL; + + nentries = last - first + 1; + return_value = (HIST_ENTRY **)malloc ((nentries + 1) * sizeof (HIST_ENTRY *)); + if (return_value == 0) + return return_value; + + /* Return all the deleted entries in a list */ + for (i = first ; i <= last; i++) + return_value[i - first] = the_history[i]; + return_value[i - first] = (HIST_ENTRY *)NULL; + + /* Copy the rest of the entries, moving down NENTRIES slots. Copy includes + trailing NULL. */ + start = the_history + first; + end = the_history + last + 1; + memmove (start, end, (history_length - last) * sizeof (HIST_ENTRY *)); + + history_length -= nentries; + + return (return_value); +} + /* Stifle the history list, remembering only MAX number of lines. */ void stifle_history (max) @@ -586,4 +623,5 @@ clear_history () } history_offset = history_length = 0; + history_base = 1; /* reset history base to default */ } diff --git a/lib/readline/history.h b/lib/readline/history.h index 8ce7c805..fceb99ca 100644 --- a/lib/readline/history.h +++ b/lib/readline/history.h @@ -86,11 +86,13 @@ extern void add_history PARAMS((const char *)); STRING. */ extern void add_history_time PARAMS((const char *)); -/* A reasonably useless function, only here for completeness. WHICH - is the magic number that tells us which element to delete. The - elements are numbered from 0. */ +/* Remove an entry from the history list. WHICH is the magic number that + tells us which element to delete. The elements are numbered from 0. */ extern HIST_ENTRY *remove_history PARAMS((int)); +/* Remove a set of entries from the history list: FIRST to LAST, inclusive */ +extern HIST_ENTRY **remove_history_range PARAMS((int, int)); + /* Allocate a history entry consisting of STRING and TIMESTAMP and return a pointer to it. */ extern HIST_ENTRY *alloc_history_entry PARAMS((char *, char *)); diff --git a/subst.c b/subst.c index 16f19e34..fafb39aa 100644 --- a/subst.c +++ b/subst.c @@ -6464,7 +6464,7 @@ array_length_reference (s) } else { - ind = array_expand_index (var, t, len); + ind = array_expand_index (var, t, len, 0); /* negative subscripts to indexed arrays count back from end */ if (var && array_p (var) && ind < 0) ind = array_max_index (array_cell (var)) + 1 + ind; diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 554f3d6e..58c375b7 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 fe42d62d..7244a465 100644 --- a/variables.c +++ b/variables.c @@ -2760,6 +2760,52 @@ make_variable_value (var, value, flags) return retval; } +/* If we can optimize appending to string variables, say so */ +static int +can_optimize_assignment (entry, value, aflags) + SHELL_VAR *entry; + char *value; + int aflags; +{ + if ((aflags & ASS_APPEND) == 0) + return 0; +#if defined (ARRAY_VARS) + if (array_p (entry) || assoc_p (entry)) + return 0; +#endif + if (integer_p (entry) || uppercase_p (entry) || lowercase_p (entry) || capcase_p (entry)) + return 0; + if (readonly_p (entry) || noassign_p (entry)) + return 0; + return 1; +} + +/* right now we optimize appends to string variables */ +static SHELL_VAR * +optimized_assignment (entry, value, aflags) + SHELL_VAR *entry; + char *value; + int aflags; +{ + size_t len, vlen; + char *v, *new; + + v = value_cell (entry); + len = STRLEN (v); + vlen = STRLEN (value); + + new = (char *)xrealloc (v, len + vlen + 8); /* for now */ + if (vlen == 1) + { + new[len] = *value; + new[len+1] = '\0'; + } + else + strcpy (new + len, value); + var_setvalue (entry, new); + return entry; +} + /* Bind a variable NAME to VALUE in the HASH_TABLE TABLE, which may be the temporary environment (but usually is not). */ static SHELL_VAR * @@ -2863,6 +2909,22 @@ assign_value: else #endif + /* If we can optimize the assignment, do so and return. Right now, we + optimize appends to string variables. */ + if (can_optimize_assignment (entry, value, aflags)) + { + INVALIDATE_EXPORTSTR (entry); + optimized_assignment (entry, value, aflags); + + if (mark_modified_vars) + VSETATTR (entry, att_exported); + + if (exported_p (entry)) + array_needs_making = 1; + + return (entry); + } + newval = make_variable_value (entry, value, aflags); /* XXX */ /* Invalidate any cached export string */