Index: BOOK/introduction/common/changelog.xml
===================================================================
--- BOOK/introduction/common/changelog.xml (revision 9bf6f510e5e4f343c1673b355ec4210b599f610b)
+++ BOOK/introduction/common/changelog.xml (revision 140d857546bc2378d9f0c30e8691040b08a10fc0)
@@ -36,4 +36,13 @@
-->
+
+
+ May 24, 2009
+
+
+ [Jim] - Updated Bash Update Patch to 5.
+
+
+
Index: BOOK/patches.ent
===================================================================
--- BOOK/patches.ent (revision 9bf6f510e5e4f343c1673b355ec4210b599f610b)
+++ BOOK/patches.ent (revision 140d857546bc2378d9f0c30e8691040b08a10fc0)
@@ -5,7 +5,7 @@
-
-
-
+
+
+
Index: tches/bash-4.0-branch_update-4.patch
===================================================================
--- patches/bash-4.0-branch_update-4.patch (revision 9bf6f510e5e4f343c1673b355ec4210b599f610b)
+++ (revision )
@@ -1,794 +1,0 @@
-Submitted By: Jim Gifford (jim at cross-lfs dot org)
-Date: 04-09-2009
-Initial Package Version: 4.0
-Origin: Upstream
-Upstream Status: Applied
-Description: Contains all upstream patches up to 4.0-017
-
-diff -Naur bash-4.0.orig/arrayfunc.c bash-4.0/arrayfunc.c
---- bash-4.0.orig/arrayfunc.c 2009-01-04 11:32:21.000000000 -0800
-+++ bash-4.0/arrayfunc.c 2009-04-09 22:09:24.500045537 -0700
-@@ -604,64 +604,7 @@
- }
- }
-
--/* This function assumes s[i] == '['; returns with s[ret] == ']' if
-- an array subscript is correctly parsed. */
--int
--skipsubscript (s, i)
-- const char *s;
-- int i;
--{
-- int count, c;
--#if defined (HANDLE_MULTIBYTE)
-- mbstate_t state, state_bak;
-- size_t slength, mblength;
--#endif
--
--#if defined (HANDLE_MULTIBYTE)
-- memset (&state, '\0', sizeof (mbstate_t));
-- slength = strlen (s + i);
--#endif
--
-- count = 1;
-- while (count)
-- {
-- /* Advance one (possibly multibyte) character in S starting at I. */
--#if defined (HANDLE_MULTIBYTE)
-- if (MB_CUR_MAX > 1)
-- {
-- state_bak = state;
-- mblength = mbrlen (s + i, slength, &state);
--
-- if (MB_INVALIDCH (mblength))
-- {
-- state = state_bak;
-- i++;
-- slength--;
-- }
-- else if (MB_NULLWCH (mblength))
-- return i;
-- else
-- {
-- i += mblength;
-- slength -= mblength;
-- }
-- }
-- else
--#endif
-- ++i;
--
-- c = s[i];
--
-- if (c == 0)
-- break;
-- else if (c == '[')
-- count++;
-- else if (c == ']')
-- count--;
-- }
--
-- return i;
--}
-+/* skipsubscript moved to subst.c to use private functions. 2009/02/24. */
-
- /* This function is called with SUB pointing to just after the beginning
- `[' of an array subscript and removes the array element to which SUB
-diff -Naur bash-4.0.orig/builtins/declare.def bash-4.0/builtins/declare.def
---- bash-4.0.orig/builtins/declare.def 2009-01-04 11:32:22.000000000 -0800
-+++ bash-4.0/builtins/declare.def 2009-04-09 22:09:21.747868696 -0700
-@@ -295,6 +295,13 @@
- subscript_start = (char *)NULL;
- if (t = strchr (name, '[')) /* ] */
- {
-+ /* If offset != 0 we have already validated any array reference */
-+ if (offset == 0 && valid_array_reference (name) == 0)
-+ {
-+ sh_invalidid (name);
-+ assign_error++;
-+ NEXT_VARIABLE ();
-+ }
- subscript_start = t;
- *t = '\0';
- making_array_special = 1;
-@@ -484,7 +491,7 @@
- }
- /* declare -a name[[n]] or declare name[n] makes name an indexed
- array variable. */
-- else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0)
-+ else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0)
- var = convert_var_to_array (var);
- #endif /* ARRAY_VARS */
-
-diff -Naur bash-4.0.orig/builtins/exit.def bash-4.0/builtins/exit.def
---- bash-4.0.orig/builtins/exit.def 2009-01-04 11:32:22.000000000 -0800
-+++ bash-4.0/builtins/exit.def 2009-04-09 22:09:20.423784047 -0700
-@@ -113,7 +113,7 @@
- for (i = stopmsg = 0; i < js.j_jobslots; i++)
- if (jobs[i] && STOPPED (i))
- stopmsg = JSTOPPED;
-- else if (check_jobs_at_exit && stopmsg == 0 && RUNNING (i))
-+ else if (check_jobs_at_exit && stopmsg == 0 && jobs[i] && RUNNING (i))
- stopmsg = JRUNNING;
-
- if (stopmsg == JSTOPPED)
-diff -Naur bash-4.0.orig/builtins/fc.def bash-4.0/builtins/fc.def
---- bash-4.0.orig/builtins/fc.def 2009-01-04 11:32:22.000000000 -0800
-+++ bash-4.0/builtins/fc.def 2009-04-09 22:09:34.484684732 -0700
-@@ -88,6 +88,7 @@
- extern int current_command_line_count;
- extern int literal_history;
- extern int posixly_correct;
-+extern int subshell_environment, interactive_shell;
-
- extern int unlink __P((const char *));
-
-@@ -172,7 +173,7 @@
- register int i;
- register char *sep;
- int numbering, reverse, listing, execute;
-- int histbeg, histend, last_hist, retval, opt;
-+ int histbeg, histend, last_hist, retval, opt, rh;
- FILE *stream;
- REPL *rlist, *rl;
- char *ename, *command, *newcom, *fcedit;
-@@ -275,6 +276,8 @@
-
- fprintf (stderr, "%s\n", command);
- fc_replhist (command); /* replace `fc -s' with command */
-+ /* Posix says that the re-executed commands should be entered into the
-+ history. */
- return (parse_and_execute (command, "fc", SEVAL_NOHIST));
- }
-
-@@ -293,7 +296,12 @@
- line was actually added (HISTIGNORE may have caused it to not be),
- so we check hist_last_line_added. */
-
-- last_hist = i - remember_on_history - hist_last_line_added;
-+ /* Even though command substitution through parse_and_execute turns off
-+ remember_on_history, command substitution in a shell when set -o history
-+ has been enabled (interactive or not) should use it in the last_hist
-+ calculation as if it were on. */
-+ rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
-+ last_hist = i - rh - hist_last_line_added;
-
- if (list)
- {
-@@ -456,7 +464,7 @@
- char *command;
- HIST_ENTRY **hlist;
- {
-- int sign, n, clen;
-+ int sign, n, clen, rh;
- register int i, j;
- register char *s;
-
-@@ -472,7 +480,12 @@
- line was actually added (HISTIGNORE may have caused it to not be),
- so we check hist_last_line_added. This needs to agree with the
- calculation of last_hist in fc_builtin above. */
-- i -= remember_on_history + hist_last_line_added;
-+ /* Even though command substitution through parse_and_execute turns off
-+ remember_on_history, command substitution in a shell when set -o history
-+ has been enabled (interactive or not) should use it in the last_hist
-+ calculation as if it were on. */
-+ rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
-+ i -= rh + hist_last_line_added;
-
- /* No specification defaults to most recent command. */
- if (command == NULL)
-diff -Naur bash-4.0.orig/builtins/read.def bash-4.0/builtins/read.def
---- bash-4.0.orig/builtins/read.def 2009-01-15 20:11:21.000000000 -0800
-+++ bash-4.0/builtins/read.def 2009-04-09 22:09:27.380229641 -0700
-@@ -369,14 +369,14 @@
- code = setjmp (alrmbuf);
- if (code)
- {
--#if 0
-+ /* Tricky. The top of the unwind-protect stack is the free of
-+ input_string. We want to run all the rest and use input_string,
-+ so we have to remove it from the stack. */
-+ remove_unwind_protect ();
- run_unwind_frame ("read_builtin");
-- return (EXECUTION_FAILURE);
--#else
- input_string[i] = '\0'; /* make sure it's terminated */
-- retval = 128+SIGALRM;;
-+ retval = 128+SIGALRM;
- goto assign_vars;
--#endif
- }
- old_alrm = set_signal_handler (SIGALRM, sigalrm);
- add_unwind_protect (reset_alarm, (char *)NULL);
-diff -Naur bash-4.0.orig/execute_cmd.c bash-4.0/execute_cmd.c
---- bash-4.0.orig/execute_cmd.c 2009-02-13 13:41:41.000000000 -0800
-+++ bash-4.0/execute_cmd.c 2009-04-09 22:09:37.908905992 -0700
-@@ -568,6 +568,7 @@
-
- /* Fork a subshell, turn off the subshell bit, turn off job
- control and call execute_command () on the command again. */
-+ line_number_for_err_trap = line_number;
- paren_pid = make_child (savestring (make_command_string (command)),
- asynchronous);
- if (paren_pid == 0)
-@@ -610,7 +611,10 @@
- if (user_subshell && was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
- {
- last_command_exit_value = exec_result;
-+ save_line_number = line_number;
-+ line_number = line_number_for_err_trap;
- run_error_trap ();
-+ line_number = save_line_number;
- }
-
- if (user_subshell && ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
-@@ -766,7 +770,9 @@
- if (was_error_trap && ignore_return == 0 && invert == 0 && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS)
- {
- last_command_exit_value = exec_result;
-+ line_number = line_number_for_err_trap;
- run_error_trap ();
-+ line_number = save_line_number;
- }
-
- if (ignore_return == 0 && invert == 0 &&
-@@ -2105,6 +2111,7 @@
- REDIRECT *rp;
- COMMAND *tc, *second;
- int ignore_return, exec_result, was_error_trap, invert;
-+ volatile int save_line_number;
-
- ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
-
-@@ -2174,12 +2181,16 @@
- invert = (command->flags & CMD_INVERT_RETURN) != 0;
- ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
-
-+ line_number_for_err_trap = line_number;
- exec_result = execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close);
-
- if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
- {
- last_command_exit_value = exec_result;
-+ save_line_number = line_number;
-+ line_number = line_number_for_err_trap;
- run_error_trap ();
-+ line_number = save_line_number;
- }
-
- if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
-@@ -2930,7 +2941,7 @@
- retval = execute_command (clauses->action);
- }
- while ((clauses->flags & CASEPAT_FALLTHROUGH) && (clauses = clauses->next));
-- if ((clauses->flags & CASEPAT_TESTNEXT) == 0)
-+ if (clauses == 0 || (clauses->flags & CASEPAT_TESTNEXT) == 0)
- EXIT_CASE ();
- else
- break;
-diff -Naur bash-4.0.orig/parse.y bash-4.0/parse.y
---- bash-4.0.orig/parse.y 2009-01-08 05:29:12.000000000 -0800
-+++ bash-4.0/parse.y 2009-04-09 22:09:39.212989803 -0700
-@@ -1122,7 +1122,7 @@
- REDIRECTEE rd;
- REDIRECT *r;
-
-- tc = $1;
-+ tc = $1->type == cm_simple ? (COMMAND *)$1->value.Simple : $1;
- rd.dest = 1;
- r = make_redirection (2, r_duplicating_output, rd);
- if (tc->redirects)
-@@ -1615,10 +1615,11 @@
- {
- int *ret;
-
-- ret = (int *)xmalloc (3 * sizeof (int));
-+ ret = (int *)xmalloc (4 * sizeof (int));
- ret[0] = last_read_token;
- ret[1] = token_before_that;
- ret[2] = two_tokens_ago;
-+ ret[3] = current_token;
- return ret;
- }
-
-@@ -1631,6 +1632,7 @@
- last_read_token = ts[0];
- token_before_that = ts[1];
- two_tokens_ago = ts[2];
-+ current_token = ts[3];
- }
-
- /*
-@@ -1877,7 +1879,7 @@
- prompt_again ();
- ret = read_a_line (remove_quoted_newline);
- #if defined (HISTORY)
-- if (remember_on_history && (parser_state & PST_HEREDOC))
-+ if (ret && remember_on_history && (parser_state & PST_HEREDOC))
- {
- /* To make adding the the here-document body right, we need to rely
- on history_delimiting_chars() returning \n for the first line of
-@@ -2668,6 +2670,7 @@
- FREE (word_desc_to_read);
- word_desc_to_read = (WORD_DESC *)NULL;
-
-+ current_token = '\n'; /* XXX */
- last_read_token = '\n';
- token_to_read = '\n';
- }
-@@ -2915,6 +2918,7 @@
- #define P_DQUOTE 0x04
- #define P_COMMAND 0x08 /* parsing a command, so look for comments */
- #define P_BACKQUOTE 0x10 /* parsing a backquoted command substitution */
-+#define P_ARRAYSUB 0x20 /* parsing a [...] array subscript for assignment */
-
- /* Lexical state while parsing a grouping construct or $(...). */
- #define LEX_WASDOL 0x001
-@@ -2927,6 +2931,7 @@
- #define LEX_INHEREDOC 0x080
- #define LEX_HEREDELIM 0x100 /* reading here-doc delimiter */
- #define LEX_STRIPDOC 0x200 /* <<- strip tabs from here doc delim */
-+#define LEX_INWORD 0x400
-
- #define COMSUB_META(ch) ((ch) == ';' || (ch) == '&' || (ch) == '|')
-
-@@ -3129,6 +3134,8 @@
- APPEND_NESTRET ();
- FREE (nestret);
- }
-+ else if ((flags & P_ARRAYSUB) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
-+ goto parse_dollar_word;
- }
- /* Parse an old-style command substitution within double quotes as a
- single word. */
-@@ -3145,6 +3152,7 @@
- else if MBTEST(open != '`' && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
- /* check for $(), $[], or ${} inside quoted string. */
- {
-+parse_dollar_word:
- if (open == ch) /* undo previous increment */
- count--;
- if (ch == '(') /* ) */
-@@ -3179,7 +3187,7 @@
- int open, close;
- int *lenp, flags;
- {
-- int count, ch, peekc, tflags, lex_rwlen, lex_firstind;
-+ int count, ch, peekc, tflags, lex_rwlen, lex_wlen, lex_firstind;
- int nestlen, ttranslen, start_lineno;
- char *ret, *nestret, *ttrans, *heredelim;
- int retind, retsize, rflags, hdlen;
-@@ -3200,7 +3208,7 @@
- retind = 0;
-
- start_lineno = line_number;
-- lex_rwlen = 0;
-+ lex_rwlen = lex_wlen = 0;
-
- heredelim = 0;
- lex_firstind = -1;
-@@ -3267,6 +3275,46 @@
- continue;
- }
-
-+ if (tflags & LEX_PASSNEXT) /* last char was backslash */
-+ {
-+/*itrace("parse_comsub:%d: lex_passnext -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
-+ tflags &= ~LEX_PASSNEXT;
-+ if (qc != '\'' && ch == '\n') /* double-quoted \ disappears. */
-+ {
-+ if (retind > 0)
-+ retind--; /* swallow previously-added backslash */
-+ continue;
-+ }
-+
-+ RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
-+ if MBTEST(ch == CTLESC || ch == CTLNUL)
-+ ret[retind++] = CTLESC;
-+ ret[retind++] = ch;
-+ continue;
-+ }
-+
-+ /* If this is a shell break character, we are not in a word. If not,
-+ we either start or continue a word. */
-+ if MBTEST(shellbreak (ch))
-+ {
-+ tflags &= ~LEX_INWORD;
-+/*itrace("parse_comsub:%d: lex_inword -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
-+ }
-+ else
-+ {
-+ if (tflags & LEX_INWORD)
-+ {
-+ lex_wlen++;
-+/*itrace("parse_comsub:%d: lex_inword == 1 ch = `%c' lex_wlen = %d (%d)", line_number, ch, lex_wlen, __LINE__);*/
-+ }
-+ else
-+ {
-+/*itrace("parse_comsub:%d: lex_inword -> 1 ch = `%c' (%d)", line_number, ch, __LINE__);*/
-+ tflags |= LEX_INWORD;
-+ lex_wlen = 0;
-+ }
-+ }
-+
- /* Skip whitespace */
- if MBTEST(shellblank (ch) && lex_rwlen == 0)
- {
-@@ -3364,9 +3412,21 @@
- }
- tflags &= ~LEX_RESWDOK;
- }
-- else if (shellbreak (ch) == 0)
-+ else if MBTEST((tflags & LEX_CKCOMMENT) && ch == '#' && (lex_rwlen == 0 || ((tflags & LEX_INWORD) && lex_wlen == 0)))
-+ ; /* don't modify LEX_RESWDOK if we're starting a comment */
-+ else if MBTEST((tflags & LEX_INCASE) && ch != '\n')
-+ /* If we can read a reserved word and we're in case, we're at the
-+ point where we can read a new pattern list or an esac. We
-+ handle the esac case above. If we read a newline, we want to
-+ leave LEX_RESWDOK alone. If we read anything else, we want to
-+ turn off LEX_RESWDOK, since we're going to read a pattern list. */
- {
-- tflags &= ~LEX_RESWDOK;
-+ tflags &= ~LEX_RESWDOK;
-+/*itrace("parse_comsub:%d: lex_incase == 1 found `%c', lex_reswordok -> 0", line_number, ch);*/
-+}
-+ else if MBTEST(shellbreak (ch) == 0)
-+{
-+ tflags &= ~LEX_RESWDOK;
- /*itrace("parse_comsub:%d: found `%c', lex_reswordok -> 0", line_number, ch);*/
- }
- }
-@@ -3394,36 +3454,23 @@
- }
- else
- shell_ungetc (peekc);
-- tflags |= LEX_HEREDELIM;
-- lex_firstind = -1;
-+ if (peekc != '<')
-+ {
-+ tflags |= LEX_HEREDELIM;
-+ lex_firstind = -1;
-+ }
- continue;
- }
- else
-- ch = peekc; /* fall through and continue XXX - this skips comments if peekc == '#' */
-+ ch = peekc; /* fall through and continue XXX */
- }
-- /* Not exactly right yet, should handle shell metacharacters, too. If
-- any changes are made to this test, make analogous changes to subst.c:
-- extract_delimited_string(). */
-- else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || shellblank (ret[retind - 1])))
-+ else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (((tflags & LEX_RESWDOK) && lex_rwlen == 0) || ((tflags & LEX_INWORD) && lex_wlen == 0)))
-+{
-+/*itrace("parse_comsub:%d: lex_incomment -> 1 (%d)", line_number, __LINE__);*/
- tflags |= LEX_INCOMMENT;
-+}
-
-- if (tflags & LEX_PASSNEXT) /* last char was backslash */
-- {
-- tflags &= ~LEX_PASSNEXT;
-- if (qc != '\'' && ch == '\n') /* double-quoted \ disappears. */
-- {
-- if (retind > 0)
-- retind--; /* swallow previously-added backslash */
-- continue;
-- }
--
-- RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
-- if MBTEST(ch == CTLESC || ch == CTLNUL)
-- ret[retind++] = CTLESC;
-- ret[retind++] = ch;
-- continue;
-- }
-- else if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
-+ if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
- {
- RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
- ret[retind++] = CTLESC;
-@@ -4248,7 +4295,7 @@
- ((token_index > 0 && assignment_acceptable (last_read_token) && token_is_ident (token, token_index)) ||
- (token_index == 0 && (parser_state&PST_COMPASSIGN))))
- {
-- ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
-+ ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARRAYSUB);
- if (ttok == &matched_pair_error)
- return -1; /* Bail immediately. */
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
-@@ -4449,6 +4496,7 @@
- case '}': /* XXX */
- case AND_AND:
- case BANG:
-+ case BAR_AND:
- case DO:
- case DONE:
- case ELIF:
-diff -Naur bash-4.0.orig/patchlevel.h bash-4.0/patchlevel.h
---- bash-4.0.orig/patchlevel.h 2009-01-04 11:32:40.000000000 -0800
-+++ bash-4.0/patchlevel.h 2009-04-09 22:09:39.212989803 -0700
-@@ -25,6 +25,6 @@
- regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
- looks for to find the patch level (for the sccs version string). */
-
--#define PATCHLEVEL 0
-+#define PATCHLEVEL 17
-
- #endif /* _PATCHLEVEL_H_ */
-diff -Naur bash-4.0.orig/pcomplete.c bash-4.0/pcomplete.c
---- bash-4.0.orig/pcomplete.c 2009-02-01 14:12:31.000000000 -0800
-+++ bash-4.0/pcomplete.c 2009-04-09 22:09:17.783614750 -0700
-@@ -1032,6 +1032,7 @@
- cmdlist = build_arg_list (funcname, text, lwords, cw);
-
- pps = &ps;
-+ save_parser_state (pps);
- begin_unwind_frame ("gen-shell-function-matches");
- add_unwind_protect (restore_parser_state, (char *)pps);
- add_unwind_protect (dispose_words, (char *)cmdlist);
-diff -Naur bash-4.0.orig/sig.c bash-4.0/sig.c
---- bash-4.0.orig/sig.c 2009-01-04 11:32:41.000000000 -0800
-+++ bash-4.0/sig.c 2009-04-09 22:09:36.612821343 -0700
-@@ -448,6 +448,48 @@
- termsig_sighandler (sig)
- int sig;
- {
-+ /* If we get called twice with the same signal before handling it,
-+ terminate right away. */
-+ if (
-+#ifdef SIGHUP
-+ sig != SIGHUP &&
-+#endif
-+#ifdef SIGINT
-+ sig != SIGINT &&
-+#endif
-+#ifdef SIGDANGER
-+ sig != SIGDANGER &&
-+#endif
-+#ifdef SIGPIPE
-+ sig != SIGPIPE &&
-+#endif
-+#ifdef SIGALRM
-+ sig != SIGALRM &&
-+#endif
-+#ifdef SIGTERM
-+ sig != SIGTERM &&
-+#endif
-+#ifdef SIGXCPU
-+ sig != SIGXCPU &&
-+#endif
-+#ifdef SIGXFSZ
-+ sig != SIGXFSZ &&
-+#endif
-+#ifdef SIGVTALRM
-+ sig != SIGVTALRM &&
-+#endif
-+#ifdef SIGLOST
-+ sig != SIGLOST &&
-+#endif
-+#ifdef SIGUSR1
-+ sig != SIGUSR1 &&
-+#endif
-+#ifdef SIGUSR2
-+ sig != SIGUSR2 &&
-+#endif
-+ sig == terminating_signal)
-+ terminate_immediately = 1;
-+
- terminating_signal = sig;
-
- /* XXX - should this also trigger when interrupt_immediately is set? */
-diff -Naur bash-4.0.orig/subst.c bash-4.0/subst.c
---- bash-4.0.orig/subst.c 2009-01-28 11:34:12.000000000 -0800
-+++ bash-4.0/subst.c 2009-04-09 22:09:33.024593378 -0700
-@@ -85,6 +85,7 @@
-
- /* Flags for the `pflags' argument to param_expand() */
- #define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
-+#define PF_IGNUNBOUND 0x02 /* ignore unbound vars even if -u set */
-
- /* These defs make it easier to use the editor. */
- #define LBRACE '{'
-@@ -222,6 +223,7 @@
- static int skip_double_quoted __P((char *, size_t, int));
- static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
- static char *extract_dollar_brace_string __P((char *, int *, int, int));
-+static int skip_matched_pair __P((const char *, int, int, int, int));
-
- static char *pos_params __P((char *, int, int, int));
-
-@@ -262,7 +264,7 @@
- static int chk_atstar __P((char *, int, int *, int *));
- static int chk_arithsub __P((const char *, int));
-
--static WORD_DESC *parameter_brace_expand_word __P((char *, int, int));
-+static WORD_DESC *parameter_brace_expand_word __P((char *, int, int, int));
- static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
- static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
- static void parameter_brace_expand_error __P((char *, char *));
-@@ -1374,6 +1376,107 @@
-
- #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
-
-+/* This function assumes s[i] == open; returns with s[ret] == close; used to
-+ parse array subscripts. FLAGS currently unused. */
-+static int
-+skip_matched_pair (string, start, open, close, flags)
-+ const char *string;
-+ int start, open, close, flags;
-+{
-+ int i, pass_next, backq, si, c, count;
-+ size_t slen;
-+ char *temp, *ss;
-+ DECLARE_MBSTATE;
-+
-+ slen = strlen (string + start) + start;
-+ no_longjmp_on_fatal_error = 1;
-+
-+ i = start + 1; /* skip over leading bracket */
-+ count = 1;
-+ pass_next = backq = 0;
-+ ss = (char *)string;
-+ while (c = string[i])
-+ {
-+ if (pass_next)
-+ {
-+ pass_next = 0;
-+ if (c == 0)
-+ CQ_RETURN(i);
-+ ADVANCE_CHAR (string, slen, i);
-+ continue;
-+ }
-+ else if (c == '\\')
-+ {
-+ pass_next = 1;
-+ i++;
-+ continue;
-+ }
-+ else if (backq)
-+ {
-+ if (c == '`')
-+ backq = 0;
-+ ADVANCE_CHAR (string, slen, i);
-+ continue;
-+ }
-+ else if (c == '`')
-+ {
-+ backq = 1;
-+ i++;
-+ continue;
-+ }
-+ else if (c == open)
-+ {
-+ count++;
-+ i++;
-+ continue;
-+ }
-+ else if (c == close)
-+ {
-+ count--;
-+ if (count == 0)
-+ break;
-+ i++;
-+ continue;
-+ }
-+ else if (c == '\'' || c == '"')
-+ {
-+ i = (c == '\'') ? skip_single_quoted (ss, slen, ++i)
-+ : skip_double_quoted (ss, slen, ++i);
-+ /* no increment, the skip functions increment past the closing quote. */
-+ }
-+ else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
-+ {
-+ si = i + 2;
-+ if (string[si] == '\0')
-+ CQ_RETURN(si);
-+
-+ if (string[i+1] == LPAREN)
-+ temp = extract_delimited_string (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
-+ else
-+ temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC);
-+ i = si;
-+ if (string[i] == '\0') /* don't increment i past EOS in loop */
-+ break;
-+ i++;
-+ continue;
-+ }
-+ else
-+ ADVANCE_CHAR (string, slen, i);
-+ }
-+
-+ CQ_RETURN(i);
-+}
-+
-+#if defined (ARRAY_VARS)
-+int
-+skipsubscript (string, start)
-+ const char *string;
-+ int start;
-+{
-+ return (skip_matched_pair (string, start, '[', ']', 0));
-+}
-+#endif
-+
- /* Skip characters in STRING until we find a character in DELIMS, and return
- the index of that character. START is the index into string at which we
- begin. This is similar in spirit to strpbrk, but it returns an index into
-@@ -5093,9 +5196,9 @@
- the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
- NAME was found inside of a double-quoted expression. */
- static WORD_DESC *
--parameter_brace_expand_word (name, var_is_special, quoted)
-+parameter_brace_expand_word (name, var_is_special, quoted, pflags)
- char *name;
-- int var_is_special, quoted;
-+ int var_is_special, quoted, pflags;
- {
- WORD_DESC *ret;
- char *temp, *tt;
-@@ -5127,7 +5230,7 @@
- strcpy (tt + 1, name);
-
- ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
-- (int *)NULL, (int *)NULL, 0);
-+ (int *)NULL, (int *)NULL, pflags);
- free (tt);
- }
- #if defined (ARRAY_VARS)
-@@ -5188,7 +5291,7 @@
- char *temp, *t;
- WORD_DESC *w;
-
-- w = parameter_brace_expand_word (name, var_is_special, quoted);
-+ w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND);
- t = w->word;
- /* Have to dequote here if necessary */
- if (t)
-@@ -5205,7 +5308,7 @@
- if (t == 0)
- return (WORD_DESC *)NULL;
-
-- w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted);
-+ w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted, 0);
- free (t);
-
- return w;
-@@ -6556,7 +6659,7 @@
- if (want_indir)
- tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
- else
-- tdesc = parameter_brace_expand_word (name, var_is_special, quoted);
-+ tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND);
-
- if (tdesc)
- {
-@@ -6887,7 +6990,7 @@
- case '*': /* `$*' */
- list = list_rest_of_args ();
-
-- if (list == 0 && unbound_vars_is_error)
-+ if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
- {
- uerror[0] = '$';
- uerror[1] = '*';
-@@ -6949,7 +7052,7 @@
- case '@': /* `$@' */
- list = list_rest_of_args ();
-
-- if (list == 0 && unbound_vars_is_error)
-+ if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
- {
- uerror[0] = '$';
- uerror[1] = '@';
-diff -Naur bash-4.0.orig/trap.c bash-4.0/trap.c
---- bash-4.0.orig/trap.c 2009-01-16 14:07:53.000000000 -0800
-+++ bash-4.0/trap.c 2009-04-09 22:09:37.908905992 -0700
-@@ -755,7 +755,7 @@
- }
-
- flags = SEVAL_NONINT|SEVAL_NOHIST;
-- if (sig != DEBUG_TRAP && sig != RETURN_TRAP)
-+ if (sig != DEBUG_TRAP && sig != RETURN_TRAP && sig != ERROR_TRAP)
- flags |= SEVAL_RESETLINE;
- if (function_code == 0)
- parse_and_execute (trap_command, tag, flags);
Index: patches/bash-4.0-branch_update-5.patch
===================================================================
--- patches/bash-4.0-branch_update-5.patch (revision 140d857546bc2378d9f0c30e8691040b08a10fc0)
+++ patches/bash-4.0-branch_update-5.patch (revision 140d857546bc2378d9f0c30e8691040b08a10fc0)
@@ -0,0 +1,1067 @@
+Submitted By: Jim Gifford (jim at cross-lfs dot org)
+Date: 05-24-2009
+Initial Package Version: 4.0
+Origin: Upstream
+Upstream Status: Applied
+Description: Contains all upstream patches up to 4.0-024
+
+diff -Naur bash-4.0.orig/arrayfunc.c bash-4.0/arrayfunc.c
+--- bash-4.0.orig/arrayfunc.c 2009-01-04 11:32:21.000000000 -0800
++++ bash-4.0/arrayfunc.c 2009-05-24 09:14:10.000000000 -0700
+@@ -604,64 +604,7 @@
+ }
+ }
+
+-/* This function assumes s[i] == '['; returns with s[ret] == ']' if
+- an array subscript is correctly parsed. */
+-int
+-skipsubscript (s, i)
+- const char *s;
+- int i;
+-{
+- int count, c;
+-#if defined (HANDLE_MULTIBYTE)
+- mbstate_t state, state_bak;
+- size_t slength, mblength;
+-#endif
+-
+-#if defined (HANDLE_MULTIBYTE)
+- memset (&state, '\0', sizeof (mbstate_t));
+- slength = strlen (s + i);
+-#endif
+-
+- count = 1;
+- while (count)
+- {
+- /* Advance one (possibly multibyte) character in S starting at I. */
+-#if defined (HANDLE_MULTIBYTE)
+- if (MB_CUR_MAX > 1)
+- {
+- state_bak = state;
+- mblength = mbrlen (s + i, slength, &state);
+-
+- if (MB_INVALIDCH (mblength))
+- {
+- state = state_bak;
+- i++;
+- slength--;
+- }
+- else if (MB_NULLWCH (mblength))
+- return i;
+- else
+- {
+- i += mblength;
+- slength -= mblength;
+- }
+- }
+- else
+-#endif
+- ++i;
+-
+- c = s[i];
+-
+- if (c == 0)
+- break;
+- else if (c == '[')
+- count++;
+- else if (c == ']')
+- count--;
+- }
+-
+- return i;
+-}
++/* skipsubscript moved to subst.c to use private functions. 2009/02/24. */
+
+ /* This function is called with SUB pointing to just after the beginning
+ `[' of an array subscript and removes the array element to which SUB
+diff -Naur bash-4.0.orig/builtins/declare.def bash-4.0/builtins/declare.def
+--- bash-4.0.orig/builtins/declare.def 2009-01-04 11:32:22.000000000 -0800
++++ bash-4.0/builtins/declare.def 2009-05-24 09:14:07.000000000 -0700
+@@ -295,6 +295,13 @@
+ subscript_start = (char *)NULL;
+ if (t = strchr (name, '[')) /* ] */
+ {
++ /* If offset != 0 we have already validated any array reference */
++ if (offset == 0 && valid_array_reference (name) == 0)
++ {
++ sh_invalidid (name);
++ assign_error++;
++ NEXT_VARIABLE ();
++ }
+ subscript_start = t;
+ *t = '\0';
+ making_array_special = 1;
+@@ -484,7 +491,7 @@
+ }
+ /* declare -a name[[n]] or declare name[n] makes name an indexed
+ array variable. */
+- else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0)
++ else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0)
+ var = convert_var_to_array (var);
+ #endif /* ARRAY_VARS */
+
+diff -Naur bash-4.0.orig/builtins/exit.def bash-4.0/builtins/exit.def
+--- bash-4.0.orig/builtins/exit.def 2009-01-04 11:32:22.000000000 -0800
++++ bash-4.0/builtins/exit.def 2009-05-24 09:14:06.000000000 -0700
+@@ -113,7 +113,7 @@
+ for (i = stopmsg = 0; i < js.j_jobslots; i++)
+ if (jobs[i] && STOPPED (i))
+ stopmsg = JSTOPPED;
+- else if (check_jobs_at_exit && stopmsg == 0 && RUNNING (i))
++ else if (check_jobs_at_exit && stopmsg == 0 && jobs[i] && RUNNING (i))
+ stopmsg = JRUNNING;
+
+ if (stopmsg == JSTOPPED)
+diff -Naur bash-4.0.orig/builtins/fc.def bash-4.0/builtins/fc.def
+--- bash-4.0.orig/builtins/fc.def 2009-01-04 11:32:22.000000000 -0800
++++ bash-4.0/builtins/fc.def 2009-05-24 09:14:20.000000000 -0700
+@@ -88,6 +88,7 @@
+ extern int current_command_line_count;
+ extern int literal_history;
+ extern int posixly_correct;
++extern int subshell_environment, interactive_shell;
+
+ extern int unlink __P((const char *));
+
+@@ -172,7 +173,7 @@
+ register int i;
+ register char *sep;
+ int numbering, reverse, listing, execute;
+- int histbeg, histend, last_hist, retval, opt;
++ int histbeg, histend, last_hist, retval, opt, rh;
+ FILE *stream;
+ REPL *rlist, *rl;
+ char *ename, *command, *newcom, *fcedit;
+@@ -275,6 +276,8 @@
+
+ fprintf (stderr, "%s\n", command);
+ fc_replhist (command); /* replace `fc -s' with command */
++ /* Posix says that the re-executed commands should be entered into the
++ history. */
+ return (parse_and_execute (command, "fc", SEVAL_NOHIST));
+ }
+
+@@ -293,7 +296,12 @@
+ line was actually added (HISTIGNORE may have caused it to not be),
+ so we check hist_last_line_added. */
+
+- last_hist = i - remember_on_history - hist_last_line_added;
++ /* Even though command substitution through parse_and_execute turns off
++ remember_on_history, command substitution in a shell when set -o history
++ has been enabled (interactive or not) should use it in the last_hist
++ calculation as if it were on. */
++ rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
++ last_hist = i - rh - hist_last_line_added;
+
+ if (list)
+ {
+@@ -456,7 +464,7 @@
+ char *command;
+ HIST_ENTRY **hlist;
+ {
+- int sign, n, clen;
++ int sign, n, clen, rh;
+ register int i, j;
+ register char *s;
+
+@@ -472,7 +480,12 @@
+ line was actually added (HISTIGNORE may have caused it to not be),
+ so we check hist_last_line_added. This needs to agree with the
+ calculation of last_hist in fc_builtin above. */
+- i -= remember_on_history + hist_last_line_added;
++ /* Even though command substitution through parse_and_execute turns off
++ remember_on_history, command substitution in a shell when set -o history
++ has been enabled (interactive or not) should use it in the last_hist
++ calculation as if it were on. */
++ rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
++ i -= rh + hist_last_line_added;
+
+ /* No specification defaults to most recent command. */
+ if (command == NULL)
+diff -Naur bash-4.0.orig/builtins/read.def bash-4.0/builtins/read.def
+--- bash-4.0.orig/builtins/read.def 2009-01-15 20:11:21.000000000 -0800
++++ bash-4.0/builtins/read.def 2009-05-24 09:14:13.000000000 -0700
+@@ -369,14 +369,14 @@
+ code = setjmp (alrmbuf);
+ if (code)
+ {
+-#if 0
++ /* Tricky. The top of the unwind-protect stack is the free of
++ input_string. We want to run all the rest and use input_string,
++ so we have to remove it from the stack. */
++ remove_unwind_protect ();
+ run_unwind_frame ("read_builtin");
+- return (EXECUTION_FAILURE);
+-#else
+ input_string[i] = '\0'; /* make sure it's terminated */
+- retval = 128+SIGALRM;;
++ retval = 128+SIGALRM;
+ goto assign_vars;
+-#endif
+ }
+ old_alrm = set_signal_handler (SIGALRM, sigalrm);
+ add_unwind_protect (reset_alarm, (char *)NULL);
+diff -Naur bash-4.0.orig/execute_cmd.c bash-4.0/execute_cmd.c
+--- bash-4.0.orig/execute_cmd.c 2009-02-13 13:41:41.000000000 -0800
++++ bash-4.0/execute_cmd.c 2009-05-24 09:14:23.000000000 -0700
+@@ -568,6 +568,7 @@
+
+ /* Fork a subshell, turn off the subshell bit, turn off job
+ control and call execute_command () on the command again. */
++ line_number_for_err_trap = line_number;
+ paren_pid = make_child (savestring (make_command_string (command)),
+ asynchronous);
+ if (paren_pid == 0)
+@@ -610,7 +611,10 @@
+ if (user_subshell && was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
+ {
+ last_command_exit_value = exec_result;
++ save_line_number = line_number;
++ line_number = line_number_for_err_trap;
+ run_error_trap ();
++ line_number = save_line_number;
+ }
+
+ if (user_subshell && ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
+@@ -766,7 +770,9 @@
+ if (was_error_trap && ignore_return == 0 && invert == 0 && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS)
+ {
+ last_command_exit_value = exec_result;
++ line_number = line_number_for_err_trap;
+ run_error_trap ();
++ line_number = save_line_number;
+ }
+
+ if (ignore_return == 0 && invert == 0 &&
+@@ -2105,6 +2111,7 @@
+ REDIRECT *rp;
+ COMMAND *tc, *second;
+ int ignore_return, exec_result, was_error_trap, invert;
++ volatile int save_line_number;
+
+ ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
+
+@@ -2174,12 +2181,16 @@
+ invert = (command->flags & CMD_INVERT_RETURN) != 0;
+ ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
+
++ line_number_for_err_trap = line_number;
+ exec_result = execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close);
+
+ if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
+ {
+ last_command_exit_value = exec_result;
++ save_line_number = line_number;
++ line_number = line_number_for_err_trap;
+ run_error_trap ();
++ line_number = save_line_number;
+ }
+
+ if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
+@@ -2930,7 +2941,7 @@
+ retval = execute_command (clauses->action);
+ }
+ while ((clauses->flags & CASEPAT_FALLTHROUGH) && (clauses = clauses->next));
+- if ((clauses->flags & CASEPAT_TESTNEXT) == 0)
++ if (clauses == 0 || (clauses->flags & CASEPAT_TESTNEXT) == 0)
+ EXIT_CASE ();
+ else
+ break;
+diff -Naur bash-4.0.orig/jobs.c bash-4.0/jobs.c
+--- bash-4.0.orig/jobs.c 2009-01-29 14:09:49.000000000 -0800
++++ bash-4.0/jobs.c 2009-05-24 09:14:28.000000000 -0700
+@@ -442,7 +442,7 @@
+ old_pipeline = the_pipeline;
+ the_pipeline = saved_pipeline;
+ already_making_children = saved_already_making_children;
+- if (discard)
++ if (discard && old_pipeline)
+ discard_pipeline (old_pipeline);
+ }
+
+@@ -4202,4 +4202,23 @@
+ sh_closepipe (pgrp_pipe);
+ }
+
++void
++save_pgrp_pipe (p, clear)
++ int *p;
++ int clear;
++{
++ p[0] = pgrp_pipe[0];
++ p[1] = pgrp_pipe[1];
++ if (clear)
++ pgrp_pipe[0] = pgrp_pipe[1] = -1;
++}
++
++void
++restore_pgrp_pipe (p)
++ int *p;
++{
++ pgrp_pipe[0] = p[0];
++ pgrp_pipe[1] = p[1];
++}
++
+ #endif /* PGRP_PIPE */
+diff -Naur bash-4.0.orig/jobs.h bash-4.0/jobs.h
+--- bash-4.0.orig/jobs.h 2009-01-04 11:32:29.000000000 -0800
++++ bash-4.0/jobs.h 2009-05-24 09:14:28.000000000 -0700
+@@ -235,6 +235,8 @@
+ extern void init_job_stats __P((void));
+
+ extern void close_pgrp_pipe __P((void));
++extern void save_pgrp_pipe __P((int *, int));
++extern void restore_pgrp_pipe __P((int *));
+
+ #if defined (JOB_CONTROL)
+ extern int job_control;
+diff -Naur bash-4.0.orig/lib/glob/glob.c bash-4.0/lib/glob/glob.c
+--- bash-4.0.orig/lib/glob/glob.c 2009-01-04 11:32:30.000000000 -0800
++++ bash-4.0/lib/glob/glob.c 2009-05-24 09:14:36.000000000 -0700
+@@ -356,7 +356,7 @@
+ *np = 0;
+ if (ep)
+ *ep = 0;
+- if (r)
++ if (r && r != &glob_error_return)
+ free (r);
+ return (struct globval *)0;
+ }
+@@ -665,8 +665,9 @@
+ (void) closedir (d);
+ }
+
+- /* compat: if GX_ALLDIRS, add the passed directory also */
+- if (add_current)
++ /* compat: if GX_ALLDIRS, add the passed directory also, but don't add an
++ empty directory name. */
++ if (add_current && (flags & GX_NULLDIR) == 0)
+ {
+ sdlen = strlen (dir);
+ nextname = (char *)malloc (sdlen + 1);
+@@ -678,10 +679,7 @@
+ nextlink->name = nextname;
+ nextlink->next = lastlink;
+ lastlink = nextlink;
+- if (flags & GX_NULLDIR)
+- nextname[0] = '\0';
+- else
+- bcopy (dir, nextname, sdlen + 1);
++ bcopy (dir, nextname, sdlen + 1);
+ ++count;
+ }
+ }
+@@ -942,7 +940,12 @@
+ char **array;
+ register unsigned int l;
+
+- array = glob_dir_to_array (directories[i], temp_results, flags);
++ /* If we're expanding **, we don't need to glue the directory
++ name to the results; we've already done it in glob_vector */
++ if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
++ array = temp_results;
++ else
++ array = glob_dir_to_array (directories[i], temp_results, flags);
+ l = 0;
+ while (array[l] != NULL)
+ ++l;
+@@ -959,7 +962,8 @@
+ result[result_size - 1] = NULL;
+
+ /* Note that the elements of ARRAY are not freed. */
+- free ((char *) array);
++ if (array != temp_results)
++ free ((char *) array);
+ }
+ }
+ /* Free the directories. */
+diff -Naur bash-4.0.orig/lib/readline/display.c bash-4.0/lib/readline/display.c
+--- bash-4.0.orig/lib/readline/display.c 2009-01-04 11:32:32.000000000 -0800
++++ bash-4.0/lib/readline/display.c 2009-05-24 09:14:34.000000000 -0700
+@@ -512,6 +512,7 @@
+ /* Block keyboard interrupts because this function manipulates global
+ data structures. */
+ _rl_block_sigint ();
++ RL_SETSTATE (RL_STATE_REDISPLAYING);
+
+ if (!rl_display_prompt)
+ rl_display_prompt = "";
+@@ -1236,6 +1237,7 @@
+ visible_wrap_offset = wrap_offset;
+ }
+
++ RL_UNSETSTATE (RL_STATE_REDISPLAYING);
+ _rl_release_sigint ();
+ }
+
+@@ -1772,7 +1774,7 @@
+ space_to_eol will insert too many spaces. XXX - maybe we should
+ adjust col_lendiff based on the difference between _rl_last_c_pos
+ and _rl_screenwidth */
+- if (col_lendiff && (_rl_last_c_pos < _rl_screenwidth))
++ if (col_lendiff && ((MB_CUR_MAX == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
+ #endif
+ {
+ if (_rl_term_autowrap && current_line < inv_botlin)
+@@ -1892,6 +1894,10 @@
+
+ woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
+ cpos = _rl_last_c_pos;
++
++ if (cpos == 0 && cpos == new)
++ return;
++
+ #if defined (HANDLE_MULTIBYTE)
+ /* If we have multibyte characters, NEW is indexed by the buffer point in
+ a multibyte string, but _rl_last_c_pos is the display position. In
+@@ -1905,9 +1911,9 @@
+ prompt string, since they're both buffer indices and DPOS is a
+ desired display position. */
+ if ((new > prompt_last_invisible) || /* XXX - don't use woff here */
+- (prompt_physical_chars > _rl_screenwidth &&
++ (prompt_physical_chars >= _rl_screenwidth &&
+ _rl_last_v_pos == prompt_last_screen_line &&
+- wrap_offset >= woff &&
++ wrap_offset >= woff && dpos >= woff &&
+ new > (prompt_last_invisible-(_rl_screenwidth*_rl_last_v_pos)-wrap_offset)))
+ /* XXX last comparison might need to be >= */
+ {
+diff -Naur bash-4.0.orig/lib/readline/readline.h bash-4.0/lib/readline/readline.h
+--- bash-4.0.orig/lib/readline/readline.h 2009-01-04 11:32:33.000000000 -0800
++++ bash-4.0/lib/readline/readline.h 2009-05-24 09:14:30.000000000 -0700
+@@ -814,8 +814,9 @@
+ #define RL_STATE_VIMOTION 0x100000 /* reading vi motion arg */
+ #define RL_STATE_MULTIKEY 0x200000 /* reading multiple-key command */
+ #define RL_STATE_VICMDONCE 0x400000 /* entered vi command mode at least once */
++#define RL_STATE_REDISPLAYING 0x800000 /* updating terminal display */
+
+-#define RL_STATE_DONE 0x800000 /* done; accepted line */
++#define RL_STATE_DONE 0x1000000 /* done; accepted line */
+
+ #define RL_SETSTATE(x) (rl_readline_state |= (x))
+ #define RL_UNSETSTATE(x) (rl_readline_state &= ~(x))
+diff -Naur bash-4.0.orig/lib/readline/terminal.c bash-4.0/lib/readline/terminal.c
+--- bash-4.0.orig/lib/readline/terminal.c 2009-01-04 11:32:34.000000000 -0800
++++ bash-4.0/lib/readline/terminal.c 2009-05-24 09:14:30.000000000 -0700
+@@ -355,7 +355,7 @@
+ _rl_get_screen_size (fileno (rl_instream), 1);
+ if (CUSTOM_REDISPLAY_FUNC ())
+ rl_forced_update_display ();
+- else
++ else if (RL_ISSTATE(RL_STATE_REDISPLAYING) == 0)
+ _rl_redisplay_after_sigwinch ();
+ }
+ }
+diff -Naur bash-4.0.orig/lib/sh/winsize.c bash-4.0/lib/sh/winsize.c
+--- bash-4.0.orig/lib/sh/winsize.c 2008-08-12 10:53:51.000000000 -0700
++++ bash-4.0/lib/sh/winsize.c 2009-05-24 09:14:27.000000000 -0700
+@@ -30,16 +30,29 @@
+
+ #include
+
+-#if !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
+-/* For struct winsize on SCO */
+-/* sys/ptem.h has winsize but needs mblk_t from sys/stream.h */
+-# if defined (HAVE_SYS_PTEM_H) && defined (TIOCGWINSZ) && defined (SIGWINCH)
+-# if defined (HAVE_SYS_STREAM_H)
+-# include
+-# endif
++/* Try to find the definitions of `struct winsize' and TIOGCWINSZ */
++
++#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
++# include
++#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
++
++#if defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
++# include
++#endif /* STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */
++
++/* Not in either of the standard places, look around. */
++#if !defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
++# if defined (HAVE_SYS_STREAM_H)
++# include
++# endif /* HAVE_SYS_STREAM_H */
++# if defined (HAVE_SYS_PTEM_H) /* SVR4.2, at least, has it here */
+ # include
+-# endif /* HAVE_SYS_PTEM_H && TIOCGWINSZ && SIGWINCH */
+-#endif /* !STRUCT_WINSIZE_IN_SYS_IOCTL */
++# define _IO_PTEM_H /* work around SVR4.2 1.1.4 bug */
++# endif /* HAVE_SYS_PTEM_H */
++# if defined (HAVE_SYS_PTE_H) /* ??? */
++# include
++# endif /* HAVE_SYS_PTE_H */
++#endif /* !STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */
+
+ #include
+
+diff -Naur bash-4.0.orig/parse.y bash-4.0/parse.y
+--- bash-4.0.orig/parse.y 2009-01-08 05:29:12.000000000 -0800
++++ bash-4.0/parse.y 2009-05-24 09:14:32.000000000 -0700
+@@ -1122,7 +1122,7 @@
+ REDIRECTEE rd;
+ REDIRECT *r;
+
+- tc = $1;
++ tc = $1->type == cm_simple ? (COMMAND *)$1->value.Simple : $1;
+ rd.dest = 1;
+ r = make_redirection (2, r_duplicating_output, rd);
+ if (tc->redirects)
+@@ -1615,10 +1615,11 @@
+ {
+ int *ret;
+
+- ret = (int *)xmalloc (3 * sizeof (int));
++ ret = (int *)xmalloc (4 * sizeof (int));
+ ret[0] = last_read_token;
+ ret[1] = token_before_that;
+ ret[2] = two_tokens_ago;
++ ret[3] = current_token;
+ return ret;
+ }
+
+@@ -1631,6 +1632,7 @@
+ last_read_token = ts[0];
+ token_before_that = ts[1];
+ two_tokens_ago = ts[2];
++ current_token = ts[3];
+ }
+
+ /*
+@@ -1877,7 +1879,7 @@
+ prompt_again ();
+ ret = read_a_line (remove_quoted_newline);
+ #if defined (HISTORY)
+- if (remember_on_history && (parser_state & PST_HEREDOC))
++ if (ret && remember_on_history && (parser_state & PST_HEREDOC))
+ {
+ /* To make adding the the here-document body right, we need to rely
+ on history_delimiting_chars() returning \n for the first line of
+@@ -2668,6 +2670,7 @@
+ FREE (word_desc_to_read);
+ word_desc_to_read = (WORD_DESC *)NULL;
+
++ current_token = '\n'; /* XXX */
+ last_read_token = '\n';
+ token_to_read = '\n';
+ }
+@@ -2915,6 +2918,7 @@
+ #define P_DQUOTE 0x04
+ #define P_COMMAND 0x08 /* parsing a command, so look for comments */
+ #define P_BACKQUOTE 0x10 /* parsing a backquoted command substitution */
++#define P_ARRAYSUB 0x20 /* parsing a [...] array subscript for assignment */
+
+ /* Lexical state while parsing a grouping construct or $(...). */
+ #define LEX_WASDOL 0x001
+@@ -2927,6 +2931,7 @@
+ #define LEX_INHEREDOC 0x080
+ #define LEX_HEREDELIM 0x100 /* reading here-doc delimiter */
+ #define LEX_STRIPDOC 0x200 /* <<- strip tabs from here doc delim */
++#define LEX_INWORD 0x400
+
+ #define COMSUB_META(ch) ((ch) == ';' || (ch) == '&' || (ch) == '|')
+
+@@ -3129,6 +3134,8 @@
+ APPEND_NESTRET ();
+ FREE (nestret);
+ }
++ else if ((flags & P_ARRAYSUB) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
++ goto parse_dollar_word;
+ }
+ /* Parse an old-style command substitution within double quotes as a
+ single word. */
+@@ -3145,6 +3152,7 @@
+ else if MBTEST(open != '`' && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
+ /* check for $(), $[], or ${} inside quoted string. */
+ {
++parse_dollar_word:
+ if (open == ch) /* undo previous increment */
+ count--;
+ if (ch == '(') /* ) */
+@@ -3179,7 +3187,7 @@
+ int open, close;
+ int *lenp, flags;
+ {
+- int count, ch, peekc, tflags, lex_rwlen, lex_firstind;
++ int count, ch, peekc, tflags, lex_rwlen, lex_wlen, lex_firstind;
+ int nestlen, ttranslen, start_lineno;
+ char *ret, *nestret, *ttrans, *heredelim;
+ int retind, retsize, rflags, hdlen;
+@@ -3200,7 +3208,7 @@
+ retind = 0;
+
+ start_lineno = line_number;
+- lex_rwlen = 0;
++ lex_rwlen = lex_wlen = 0;
+
+ heredelim = 0;
+ lex_firstind = -1;
+@@ -3267,6 +3275,46 @@
+ continue;
+ }
+
++ if (tflags & LEX_PASSNEXT) /* last char was backslash */
++ {
++/*itrace("parse_comsub:%d: lex_passnext -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
++ tflags &= ~LEX_PASSNEXT;
++ if (qc != '\'' && ch == '\n') /* double-quoted \ disappears. */
++ {
++ if (retind > 0)
++ retind--; /* swallow previously-added backslash */
++ continue;
++ }
++
++ RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
++ if MBTEST(ch == CTLESC || ch == CTLNUL)
++ ret[retind++] = CTLESC;
++ ret[retind++] = ch;
++ continue;
++ }
++
++ /* If this is a shell break character, we are not in a word. If not,
++ we either start or continue a word. */
++ if MBTEST(shellbreak (ch))
++ {
++ tflags &= ~LEX_INWORD;
++/*itrace("parse_comsub:%d: lex_inword -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
++ }
++ else
++ {
++ if (tflags & LEX_INWORD)
++ {
++ lex_wlen++;
++/*itrace("parse_comsub:%d: lex_inword == 1 ch = `%c' lex_wlen = %d (%d)", line_number, ch, lex_wlen, __LINE__);*/
++ }
++ else
++ {
++/*itrace("parse_comsub:%d: lex_inword -> 1 ch = `%c' (%d)", line_number, ch, __LINE__);*/
++ tflags |= LEX_INWORD;
++ lex_wlen = 0;
++ }
++ }
++
+ /* Skip whitespace */
+ if MBTEST(shellblank (ch) && lex_rwlen == 0)
+ {
+@@ -3306,7 +3354,7 @@
+ }
+
+ /* Meta-characters that can introduce a reserved word. Not perfect yet. */
+- if MBTEST((tflags & LEX_RESWDOK) == 0 && (tflags & LEX_CKCASE) && (tflags & LEX_INCOMMENT) == 0 && shellmeta(ch))
++ if MBTEST((tflags & LEX_RESWDOK) == 0 && (tflags & LEX_CKCASE) && (tflags & LEX_INCOMMENT) == 0 && (shellmeta(ch) || ch == '\n'))
+ {
+ /* Add this character. */
+ RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
+@@ -3364,9 +3412,21 @@
+ }
+ tflags &= ~LEX_RESWDOK;
+ }
+- else if (shellbreak (ch) == 0)
++ else if MBTEST((tflags & LEX_CKCOMMENT) && ch == '#' && (lex_rwlen == 0 || ((tflags & LEX_INWORD) && lex_wlen == 0)))
++ ; /* don't modify LEX_RESWDOK if we're starting a comment */
++ else if MBTEST((tflags & LEX_INCASE) && ch != '\n')
++ /* If we can read a reserved word and we're in case, we're at the
++ point where we can read a new pattern list or an esac. We
++ handle the esac case above. If we read a newline, we want to
++ leave LEX_RESWDOK alone. If we read anything else, we want to
++ turn off LEX_RESWDOK, since we're going to read a pattern list. */
+ {
+- tflags &= ~LEX_RESWDOK;
++ tflags &= ~LEX_RESWDOK;
++/*itrace("parse_comsub:%d: lex_incase == 1 found `%c', lex_reswordok -> 0", line_number, ch);*/
++}
++ else if MBTEST(shellbreak (ch) == 0)
++{
++ tflags &= ~LEX_RESWDOK;
+ /*itrace("parse_comsub:%d: found `%c', lex_reswordok -> 0", line_number, ch);*/
+ }
+ }
+@@ -3394,36 +3454,23 @@
+ }
+ else
+ shell_ungetc (peekc);
+- tflags |= LEX_HEREDELIM;
+- lex_firstind = -1;
++ if (peekc != '<')
++ {
++ tflags |= LEX_HEREDELIM;
++ lex_firstind = -1;
++ }
+ continue;
+ }
+ else
+- ch = peekc; /* fall through and continue XXX - this skips comments if peekc == '#' */
++ ch = peekc; /* fall through and continue XXX */
+ }
+- /* Not exactly right yet, should handle shell metacharacters, too. If
+- any changes are made to this test, make analogous changes to subst.c:
+- extract_delimited_string(). */
+- else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || shellblank (ret[retind - 1])))
++ else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (((tflags & LEX_RESWDOK) && lex_rwlen == 0) || ((tflags & LEX_INWORD) && lex_wlen == 0)))
++{
++/*itrace("parse_comsub:%d: lex_incomment -> 1 (%d)", line_number, __LINE__);*/
+ tflags |= LEX_INCOMMENT;
++}
+
+- if (tflags & LEX_PASSNEXT) /* last char was backslash */
+- {
+- tflags &= ~LEX_PASSNEXT;
+- if (qc != '\'' && ch == '\n') /* double-quoted \ disappears. */
+- {
+- if (retind > 0)
+- retind--; /* swallow previously-added backslash */
+- continue;
+- }
+-
+- RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
+- if MBTEST(ch == CTLESC || ch == CTLNUL)
+- ret[retind++] = CTLESC;
+- ret[retind++] = ch;
+- continue;
+- }
+- else if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
++ if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
+ {
+ RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
+ ret[retind++] = CTLESC;
+@@ -4248,7 +4295,7 @@
+ ((token_index > 0 && assignment_acceptable (last_read_token) && token_is_ident (token, token_index)) ||
+ (token_index == 0 && (parser_state&PST_COMPASSIGN))))
+ {
+- ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
++ ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARRAYSUB);
+ if (ttok == &matched_pair_error)
+ return -1; /* Bail immediately. */
+ RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
+@@ -4449,6 +4496,7 @@
+ case '}': /* XXX */
+ case AND_AND:
+ case BANG:
++ case BAR_AND:
+ case DO:
+ case DONE:
+ case ELIF:
+diff -Naur bash-4.0.orig/patchlevel.h bash-4.0/patchlevel.h
+--- bash-4.0.orig/patchlevel.h 2009-01-04 11:32:40.000000000 -0800
++++ bash-4.0/patchlevel.h 2009-05-24 09:14:36.000000000 -0700
+@@ -25,6 +25,6 @@
+ regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
+ looks for to find the patch level (for the sccs version string). */
+
+-#define PATCHLEVEL 0
++#define PATCHLEVEL 24
+
+ #endif /* _PATCHLEVEL_H_ */
+diff -Naur bash-4.0.orig/pcomplete.c bash-4.0/pcomplete.c
+--- bash-4.0.orig/pcomplete.c 2009-02-01 14:12:31.000000000 -0800
++++ bash-4.0/pcomplete.c 2009-05-24 09:14:02.000000000 -0700
+@@ -1032,6 +1032,7 @@
+ cmdlist = build_arg_list (funcname, text, lwords, cw);
+
+ pps = &ps;
++ save_parser_state (pps);
+ begin_unwind_frame ("gen-shell-function-matches");
+ add_unwind_protect (restore_parser_state, (char *)pps);
+ add_unwind_protect (dispose_words, (char *)cmdlist);
+diff -Naur bash-4.0.orig/sig.c bash-4.0/sig.c
+--- bash-4.0.orig/sig.c 2009-01-04 11:32:41.000000000 -0800
++++ bash-4.0/sig.c 2009-05-24 09:14:22.000000000 -0700
+@@ -448,6 +448,48 @@
+ termsig_sighandler (sig)
+ int sig;
+ {
++ /* If we get called twice with the same signal before handling it,
++ terminate right away. */
++ if (
++#ifdef SIGHUP
++ sig != SIGHUP &&
++#endif
++#ifdef SIGINT
++ sig != SIGINT &&
++#endif
++#ifdef SIGDANGER
++ sig != SIGDANGER &&
++#endif
++#ifdef SIGPIPE
++ sig != SIGPIPE &&
++#endif
++#ifdef SIGALRM
++ sig != SIGALRM &&
++#endif
++#ifdef SIGTERM
++ sig != SIGTERM &&
++#endif
++#ifdef SIGXCPU
++ sig != SIGXCPU &&
++#endif
++#ifdef SIGXFSZ
++ sig != SIGXFSZ &&
++#endif
++#ifdef SIGVTALRM
++ sig != SIGVTALRM &&
++#endif
++#ifdef SIGLOST
++ sig != SIGLOST &&
++#endif
++#ifdef SIGUSR1
++ sig != SIGUSR1 &&
++#endif
++#ifdef SIGUSR2
++ sig != SIGUSR2 &&
++#endif
++ sig == terminating_signal)
++ terminate_immediately = 1;
++
+ terminating_signal = sig;
+
+ /* XXX - should this also trigger when interrupt_immediately is set? */
+diff -Naur bash-4.0.orig/subst.c bash-4.0/subst.c
+--- bash-4.0.orig/subst.c 2009-01-28 11:34:12.000000000 -0800
++++ bash-4.0/subst.c 2009-05-24 09:14:19.000000000 -0700
+@@ -85,6 +85,7 @@
+
+ /* Flags for the `pflags' argument to param_expand() */
+ #define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
++#define PF_IGNUNBOUND 0x02 /* ignore unbound vars even if -u set */
+
+ /* These defs make it easier to use the editor. */
+ #define LBRACE '{'
+@@ -222,6 +223,7 @@
+ static int skip_double_quoted __P((char *, size_t, int));
+ static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
+ static char *extract_dollar_brace_string __P((char *, int *, int, int));
++static int skip_matched_pair __P((const char *, int, int, int, int));
+
+ static char *pos_params __P((char *, int, int, int));
+
+@@ -262,7 +264,7 @@
+ static int chk_atstar __P((char *, int, int *, int *));
+ static int chk_arithsub __P((const char *, int));
+
+-static WORD_DESC *parameter_brace_expand_word __P((char *, int, int));
++static WORD_DESC *parameter_brace_expand_word __P((char *, int, int, int));
+ static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
+ static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
+ static void parameter_brace_expand_error __P((char *, char *));
+@@ -1374,6 +1376,107 @@
+
+ #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
+
++/* This function assumes s[i] == open; returns with s[ret] == close; used to
++ parse array subscripts. FLAGS currently unused. */
++static int
++skip_matched_pair (string, start, open, close, flags)
++ const char *string;
++ int start, open, close, flags;
++{
++ int i, pass_next, backq, si, c, count;
++ size_t slen;
++ char *temp, *ss;
++ DECLARE_MBSTATE;
++
++ slen = strlen (string + start) + start;
++ no_longjmp_on_fatal_error = 1;
++
++ i = start + 1; /* skip over leading bracket */
++ count = 1;
++ pass_next = backq = 0;
++ ss = (char *)string;
++ while (c = string[i])
++ {
++ if (pass_next)
++ {
++ pass_next = 0;
++ if (c == 0)
++ CQ_RETURN(i);
++ ADVANCE_CHAR (string, slen, i);
++ continue;
++ }
++ else if (c == '\\')
++ {
++ pass_next = 1;
++ i++;
++ continue;
++ }
++ else if (backq)
++ {
++ if (c == '`')
++ backq = 0;
++ ADVANCE_CHAR (string, slen, i);
++ continue;
++ }
++ else if (c == '`')
++ {
++ backq = 1;
++ i++;
++ continue;
++ }
++ else if (c == open)
++ {
++ count++;
++ i++;
++ continue;
++ }
++ else if (c == close)
++ {
++ count--;
++ if (count == 0)
++ break;
++ i++;
++ continue;
++ }
++ else if (c == '\'' || c == '"')
++ {
++ i = (c == '\'') ? skip_single_quoted (ss, slen, ++i)
++ : skip_double_quoted (ss, slen, ++i);
++ /* no increment, the skip functions increment past the closing quote. */
++ }
++ else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
++ {
++ si = i + 2;
++ if (string[si] == '\0')
++ CQ_RETURN(si);
++
++ if (string[i+1] == LPAREN)
++ temp = extract_delimited_string (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
++ else
++ temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC);
++ i = si;
++ if (string[i] == '\0') /* don't increment i past EOS in loop */
++ break;
++ i++;
++ continue;
++ }
++ else
++ ADVANCE_CHAR (string, slen, i);
++ }
++
++ CQ_RETURN(i);
++}
++
++#if defined (ARRAY_VARS)
++int
++skipsubscript (string, start)
++ const char *string;
++ int start;
++{
++ return (skip_matched_pair (string, start, '[', ']', 0));
++}
++#endif
++
+ /* Skip characters in STRING until we find a character in DELIMS, and return
+ the index of that character. START is the index into string at which we
+ begin. This is similar in spirit to strpbrk, but it returns an index into
+@@ -5093,9 +5196,9 @@
+ the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
+ NAME was found inside of a double-quoted expression. */
+ static WORD_DESC *
+-parameter_brace_expand_word (name, var_is_special, quoted)
++parameter_brace_expand_word (name, var_is_special, quoted, pflags)
+ char *name;
+- int var_is_special, quoted;
++ int var_is_special, quoted, pflags;
+ {
+ WORD_DESC *ret;
+ char *temp, *tt;
+@@ -5127,7 +5230,7 @@
+ strcpy (tt + 1, name);
+
+ ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
+- (int *)NULL, (int *)NULL, 0);
++ (int *)NULL, (int *)NULL, pflags);
+ free (tt);
+ }
+ #if defined (ARRAY_VARS)
+@@ -5188,7 +5291,7 @@
+ char *temp, *t;
+ WORD_DESC *w;
+
+- w = parameter_brace_expand_word (name, var_is_special, quoted);
++ w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND);
+ t = w->word;
+ /* Have to dequote here if necessary */
+ if (t)
+@@ -5205,7 +5308,7 @@
+ if (t == 0)
+ return (WORD_DESC *)NULL;
+
+- w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted);
++ w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted, 0);
+ free (t);
+
+ return w;
+@@ -6556,7 +6659,7 @@
+ if (want_indir)
+ tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
+ else
+- tdesc = parameter_brace_expand_word (name, var_is_special, quoted);
++ tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND);
+
+ if (tdesc)
+ {
+@@ -6887,7 +6990,7 @@
+ case '*': /* `$*' */
+ list = list_rest_of_args ();
+
+- if (list == 0 && unbound_vars_is_error)
++ if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
+ {
+ uerror[0] = '$';
+ uerror[1] = '*';
+@@ -6949,7 +7052,7 @@
+ case '@': /* `$@' */
+ list = list_rest_of_args ();
+
+- if (list == 0 && unbound_vars_is_error)
++ if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
+ {
+ uerror[0] = '$';
+ uerror[1] = '@';
+diff -Naur bash-4.0.orig/trap.c bash-4.0/trap.c
+--- bash-4.0.orig/trap.c 2009-01-16 14:07:53.000000000 -0800
++++ bash-4.0/trap.c 2009-05-24 09:14:28.000000000 -0700
+@@ -755,7 +755,7 @@
+ }
+
+ flags = SEVAL_NONINT|SEVAL_NOHIST;
+- if (sig != DEBUG_TRAP && sig != RETURN_TRAP)
++ if (sig != DEBUG_TRAP && sig != RETURN_TRAP && sig != ERROR_TRAP)
+ flags |= SEVAL_RESETLINE;
+ if (function_code == 0)
+ parse_and_execute (trap_command, tag, flags);
+@@ -798,12 +798,36 @@
+ run_debug_trap ()
+ {
+ int trap_exit_value;
++ pid_t save_pgrp;
++ int save_pipe[2];
+
+ /* XXX - question: should the DEBUG trap inherit the RETURN trap? */
+ trap_exit_value = 0;
+ if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_IGNORED) == 0) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0))
+ {
++#if defined (JOB_CONTROL)
++ save_pgrp = pipeline_pgrp;
++ pipeline_pgrp = 0;
++ save_pipeline (1);
++# if defined (PGRP_PIPE)
++ save_pgrp_pipe (save_pipe, 1);
++# endif
++ stop_making_children ();
++#endif
++
+ trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
++
++#if defined (JOB_CONTROL)
++ pipeline_pgrp = save_pgrp;
++ restore_pipeline (1);
++# if defined (PGRP_PIPE)
++ close_pgrp_pipe ();
++ restore_pgrp_pipe (save_pipe);
++# endif
++ if (pipeline_pgrp > 0)
++ give_terminal_to (pipeline_pgrp, 1);
++ notify_and_cleanup ();
++#endif
+
+ #if defined (DEBUGGER)
+ /* If we're in the debugger and the DEBUG trap returns 2 while we're in