]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20140327 snapshot
authorChet Ramey <chet.ramey@case.edu>
Mon, 7 Apr 2014 14:47:09 +0000 (10:47 -0400)
committerChet Ramey <chet.ramey@case.edu>
Mon, 7 Apr 2014 14:47:09 +0000 (10:47 -0400)
31 files changed:
CWRU/CWRU.chlog
CWRU/CWRU.chlog~ [new file with mode: 0644]
MANIFEST
Makefile.in
Makefile.in~ [new file with mode: 0644]
bashline.c
bashline.c~ [new file with mode: 0644]
builtins/Makefile.in
builtins/Makefile.in~ [new file with mode: 0644]
builtins/declare.def
builtins/declare.def~ [new file with mode: 0644]
builtins/setattr.def
builtins/setattr.def~ [new file with mode: 0644]
doc/bash.0
execute_cmd.c
execute_cmd.c~ [new file with mode: 0644]
lib/readline/display.c
lib/readline/kill.c
lib/readline/kill.c~ [new file with mode: 0644]
lib/readline/macro.c
lib/readline/macro.c~ [new file with mode: 0644]
lib/readline/text.c
lib/readline/text.c~ [new file with mode: 0644]
lib/readline/vi_mode.c
lib/readline/vi_mode.c~ [new file with mode: 0644]
parse.y
pcomplete.c
tests/extglob.right
tests/extglob.tests
tests/extglob3.sub [new file with mode: 0644]
variables.c~ [new file with mode: 0644]

index 586f8e14fbd90b67a4dc86fb6dae33ec07170026..12ec2bb9f29ae9265c08445a2f6eba39139dfb5e 100644 (file)
@@ -6043,3 +6043,63 @@ parse.y
          will not be reallocated.  Use len+3 > size instead of len > size-3.
          Fixes bug reported in
          https://bugs.launchpad.net/ubuntu/+source/bash/+bug/1295467
+
+                                  3/27
+                                  ----
+lib/readline/display.c
+       - _rl_clean_up_for_exit: don't bother to call _rl_move_vert to whatever
+         readline thinks the last displayed line is if it's 0.  Two reasons: a
+         minor optimization, and it protects against unwanted moving if this
+         function is called twice, as it is when ^C is pressed.  Fixes bug
+         reported by Egmont Koblinger <egmont@gmail.com>
+
+                                  3/28
+                                  ----
+bashline.c
+       - invalid_completion: new function, used to identify attempts to
+         complete words that are syntax errors
+       - attempt_shell_completion: if invalid_completion returns true for a
+         word in a command position, punt on all completions.  Fixes cosmetic
+         issue reported by Uwe Storbeck <uwe@ibr.ch>
+       - attempt_shell_completion: add clause so that in_command_position
+         remains set to 1 for an empty word following a command separator like
+         (, &, or |
+
+lib/readline/kill.c
+       - rl_yank, rl_yank_nth_arg_internal: don't return -1 from bindable
+         functions, return 1 instead
+
+lib/readline/text.c
+       - rl_rubout, _rl_rubout_char, rl_delete, rl_change_case,
+         rl_transpose_chars, rl_transpose_words, _rl_set_mark_at_pos,
+         rl_exchange_point_and_mark, _rl_insert_next, _rl_char_search,
+         _rl_char_search_internal:
+         don't return -1 from bindable functions, return 1 instead
+
+lib/readline/vi_mode.c
+       - rl_vi_end_word, rl_vi_rubout, rl_vi_delete, rl_vi_char_search,
+         rl_vi_match, _rl_vi_set_mark, _rl_vi_goto_mark:
+         don't return -1 from bindable functions, return 1 instead
+
+lib/readline/macro.c
+       - rl_start_kbd_macro, rl_end_kbd_macro:
+         don't return -1 from bindable functions, return 1 instead
+
+builtins/setattr.def
+       - set_var_attribute: honor setting of no_invisible_vars when setting
+         att_invisible on a variable
+       - include "../flags.h" for no_invisible_vars
+
+builtins/declare.def
+       - declare_internal: honor setting of no_invisible_vars when setting
+         att_invisible on a variable
+       - include "../flags.h" for no_invisible_vars
+
+Makefile.in,builtins/Makefile.in
+       - make sure declare.o and setattr.o depend on flags.h
+
+execute_cmd.c
+       - decpoint: new function, returns locale's decimal point or `.' default
+       - mkfmt: use decpoint() to get decimal point instead of unconditionally
+         using `.'.  Fixes bug reported by Andrey Tataranovich
+         <tataranovich@gmail.com> in debian bug 741669
diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~
new file mode 100644 (file)
index 0000000..0cd0ecc
--- /dev/null
@@ -0,0 +1,6099 @@
+                                2/14/2011
+                                ---------
+[bash-4.2 released]
+
+                                  2/15
+                                  ----
+lib/glob/gmisc.c
+       - fix wmatchlen and umatchlen to avoid going past the end of the
+         string on an incomplete bracket expression that ends with a
+         NUL.  Partial fix for bug reported by Clark Wang <dearvoid@gmail.com>
+
+                                  2/16
+                                  ----
+subst.h
+       - new string extract flag value: SX_WORD.  Used when calling
+         extract_dollar_brace_string to skip over the word in
+         ${param op word} from parameter_brace_expand
+
+subst.c
+       - change parameter_brace_expand to add SX_WORD to flags passed to
+         extract_dollar_brace_string
+       - change parameter_brace_expand to use SX_POSIXEXP for all non-posix
+         word expansion operators that treat single quotes as special, not
+         just % and #
+       - change extract_dollar_brace_string to initialize dolbrace_state to
+         DOLBRACE_WORD if SX_WORD flag supplied and we shouldn't use
+         DOLBRACE_QUOTE.  Fixes bug reported by Juergen Daubert <jue@jue.li>
+
+doc/{bash.1,bashref.texi}
+       - document the exact expansions here strings undergo
+
+                                  2/17
+                                  ----
+lib/readline/vi_mode.c
+       - make sure that `dd', `cc', and `yy' call vidomove_dispatch from
+         rl_domove_read_callback.  Fixes bug reported by Clark Wang
+         <dearvoid@gmail.com>
+
+lib/readline/callback.c
+       - make sure _rl_internal_char_cleanup is called after the
+         vi-motion callbacks (rl_vi_domove_callback) in rl_callback_read_char.
+         Companion to above fix
+
+doc/{bash.1,bashref.texi}
+       - make sure that the text describing the rhs of the == and =~
+         operators to [[ states that only the quoted portion of the pattern
+         is matched as a string
+
+                                  2/18
+                                  ----
+lib/glob/gmisc.c
+       - better fix for umatchlen/wmatchlen: keep track of the number of
+         characters in a bracket expression as the value to increase
+         matchlen by if the bracket expression is not well-formed.  Fixes
+         bug reported by Clark Wang <dearvoid@gmail.com>
+
+subst.c
+       - change expand_string_for_rhs so that it sets the W_NOSPLIT2 flag
+         in the word flags.  We will not perform word splitting or quote
+         removal on the result, so we do not want to add quoted nulls if
+         we see "" or ''.  Fixes bug reported by Mike Frysinger
+         <vapier@gentoo.org>
+
+                                  2/19
+                                  ----
+variables.c
+       - new function, int chkexport(name), checks whether variable NAME is
+         exported and remakes the export environment if necessary.  Returns
+         1 if NAME is exported and 0 if not
+       - call chkexport(name) to get tzset to look at the right variable in
+         the environment when modifying TZ in sv_tz.  Don't call tzset if
+         chkexport doesn't indicate that the variable is exported
+
+variables.h
+       - new extern declaration for chkexport
+
+
+{parse.y,builtins/printf.def}
+       - call sv_tz before calling localtime() when formatting time strings
+         in prompt strings or using printf.  Fixes bug reported by
+         Dennis Williamson <dennistwilliamson@gmail.com>
+
+execute_cmd.c
+       - modify fix of 2/9 to add casts when those variables are passed to
+         functions; some compilers throw errors instead of warnings.  Report
+         and fix from Joachim Schmitz <jojo@schmitz-digital.de>
+
+support/shobj-conf
+       - add a stanza for nsk on the Tandem from Joachim Schmitz
+         <jojo@schmitz-digital.de>
+
+{shell,lib/readline/shell}.c
+       - Tandem systems should use getpwnam (getlogin()); for some reason
+         they don't do well with using getuid().  Fix from Joachim Schmitz
+         <jojo@schmitz-digital.de>
+
+                                   3/1
+                                   ---
+variables.c
+       - make sure that the return value from find_variable is non-null
+         before trying to use it in chkexport.  Fixes bug reported by
+         Evangelos Foutras <foutrelis@gmail.com>
+
+                                   3/3
+                                   ---
+parse.y
+       - when adding $$ to the current token buffer in read_token_word(),
+         don't xmalloc a buffer for two characters and then strcpy it, just
+         copy the characters directly into the token buffer.  Fix from
+         Michael Whitten <mfwitten@gmail.com>
+
+execute_cmd.c
+       - fix expand_word_unsplit to add the W_NOSPLIT2 flag to the word to
+         be expanded, so "" doesn't add CTLNUL.  Similar to fix of 2/18 to
+         expand_string_for_rhs.  Fixes bug reported by Nathanael D. Noblet
+         <nathanael@gnat.ca> and Matthias Klose <doko@debian.org>
+
+parse.y
+       - fix extended_glob case of read_token_word to allocate an extra
+         space in the buffer for the next character read after the extended
+         glob specification if it's a CTLESC or CTLNUL.  Report and fix from
+         Michael Witten <mfwitten@gmail.com>
+       - fix shell expansions case of read_token_word to allocate an extra
+         space in the buffer for the next character read after the shell
+         expansion if it's a CTLESC or CTLNUL.  Report and fix from
+         Michael Witten <mfwitten@gmail.com>
+       - TENTATIVE: fix read_token_word to reduce the amount of buffer space
+         required to hold the translated and double-quoted value of $"..."
+         strings.  Report and fix from Michael Witten <mfwitten@gmail.com>
+       - change code around got_character and got_escaped_character labels to
+         make sure that we call RESIZE_MALLOCED_BUFFER before adding the
+         CTLESC before a CTLESC or CTLNUL, and before adding the character if
+         we're not adding a CTLESC.  Report and fix from
+         Michael Witten <mfwitten@gmail.com>
+
+subst.c
+       - new param flags value, PF_ASSIGNRHS, mirrors W_ASSIGNRHS, noting that
+         parameter expansion is on rhs of assignment statement.  That inhibits
+         word splitting
+       - change param_expand to call string_list_dollar_at with quoted == 1
+         if PF_ASSIGNRHS is set, so it will quote IFS characters in the
+         positional parameter before separating them with the first char of
+         $IFS.  This keeps the rhs from being split inappropriately.  Fixes
+         bug reported by Andres Perera <andres.p@zoho.com>
+
+                                   3/4
+                                   ---
+lib/readline/bind.c
+       - add a missing free of `names' in rl_function_dumper.  Bug report
+         and fix from Michael Snyder <msnyder@vmware.com>
+
+                                   3/5
+                                   ---
+lib/readline/rltty.c
+       - change rl_deprep_terminal so it uses fileno (stdin) for the tty fd
+         if rl_instream is not set, like rl_prep_terminal
+
+                                   3/6
+                                   ---
+lib/readline/display.c
+       - fix rl_message to use a dynamically-allocated buffer instead of a
+         fixed-size buffer of 128 chars for the `local message prompt'.  Bug
+         report and fix from Micah Cowan <micah@cowan.name>
+
+                                   3/7
+                                   ---
+jobs.c
+       - add sentinel to wait_sigint_handler so it only sets wait_sigint_received
+         if waiting_for_child is non-zero; otherwise, it restores the old
+         SIGINT handler and sends itself the SIGINT
+       - set waiting_for_child around the calls to waitchld that use it to
+         synchronously wait for a process
+       - change logic that decides whether or not the child process blocked
+         or handled SIGINT based on whether or not waitpid returns -1/EINTR
+         and the shell receives a SIGINT and the child does not exit.  If
+         the child later exits due to SIGINT, cancel the assumoption that it
+         was handled
+       - instead of testing whether or not the child exited due to SIGINT
+         when deciding whether the shell should act on a SIGINT it received
+         while waiting, test whether or not we think the child caught
+         SIGINT.  If it did, we let it go (unless the shell has it trapped);
+         if it did not catch it, the shell acts on the SIGINT.  Fix from
+         Linus Torvalds <torvalds@linux-foundation.org>, bug report originally
+         from Oleg Nesterov <oleg@redhat.com>
+
+                                   3/8
+                                   ---
+shell.c
+       - initialize no_line_editing to 1 if READLINE is not defined -- we
+         can't have line editing without readline
+
+                                  3/12
+                                  ----
+lib/readline/signals.c
+       - add SIGHUP to the set of signals readline handles
+
+lib/readline/doc/rltech.texi
+       - document that SIGHUP is now part of the set of signals readline
+         handles
+
+lib/readline/input.c
+       - if _rl_caught_signal indicates that read() was interrupted by a
+         SIGHUP or SIGTERM, return READERR or EOF as appropriate
+       - call rl_event_hook, if it's set, if call to read in rl_getc
+         returns -1/EINTR.  If rl_event_hook doesn't do anything, this
+         continues the loop as before.  This handles the other fatal
+         signals
+
+execute_cmd.c
+       - add a couple of QUIT; calls to execute_disk_command and
+         execute_simple_command to improve responsiveness to interrupts
+         and fatal signals
+
+input.c
+       - rearrange getc_with_restart so that the return values from read()
+         are handled right
+
+parse.y
+       - don't need to set terminate_immediately in yy_stream_get, since
+         getc_with_restart checks for terminating signals itself
+       - since readline returns READERR on SIGHUP or SIGTERM, don't need
+         to set terminate_immediately.  Still doesn't handle other
+         signals well -- will have to check that some more
+
+bashline.c
+       - new function, bash_event_hook, for rl_event_hook.  Just checks for
+         terminating signals and acts on them using CHECK_TERMSIG.
+       - set rl_event_hook to bash_event_hook
+
+builtins/read.def
+       - take out setting terminate_immediately; add calls to CHECK_TERMSIG
+         after read calls
+
+doc/{bash.1,bashref.texi}
+       - move the text describing the effect of negative subscripts used to
+         reference indexed array elements to the paragraphs describing
+         ${parameter[subscript]}, since that's where they are implemented.
+         Pointed out by Christopher F. A. Johnson <cfajohnson@gmail.com>
+
+arrayfunc.[ch],subst.c
+       - array_expand_index now takes a new first argument: a SHELL_VAR *
+         of the array variable being subscripted.  Can be used later to fully
+         implement negative subscripts
+
+                                  3/14
+                                  ----
+lib/glob/glob.c
+       - fix mbskipname to not turn the directory entry name into a wide char
+         string if the conversion of the pattern to a wide char string fails
+       - fix mbskipname to call skipname if either the pattern or the filename
+         can't be converted into a wide-char string
+
+lib/glob/xmbsrtowcs.c
+       - fix xdupmbstowcs2 to handle return value of 0 from mbsnrtowcs and
+         short-circuit with failure in that case.  Fixes bug reported by
+         Roman Rakus <rrakus@redhat.com>
+
+                                  3/15
+                                  ----
+bashline.c
+       - new variable, bash_filename_quote_characters to store the value
+         assigned to rl_filename_quote_characters so it can be restored
+         if changed.
+       - change bashline_reset and attempt_shell_completion to restore
+         rl_filename_quote_characters if not set to default
+
+                                  3/22
+                                  ----
+lib/glob/glob.c
+       - wdequote_pathname falls back to udequote_pathname if xdupmbstowcs
+         fails to convert the pathname to a wide-character string
+
+lib/glob/xmbsrtowcs.c
+       - xdupmbstowcs2: change to fix problem with leading '\\' (results in
+         nms == 0, which causes it to short-circuit with failure right
+         away).  Fixes bug pointed out by Werner Fink <werner@suse.de>
+       - xdupmbstowcs2: compensate for mbsnrtowcs returning 0 by taking the
+         next single-byte character and going on
+       - xdupmbstowcs2: change memory allocation to increase by WSBUF_INC
+         bytes; try to avoid calls to realloc (even if they don't actually
+         result in more memory being allocated)
+
+                                  3/24
+                                  ----
+doc/{bash.1,bashref.texi}
+       - slightly modify BASH_SUBSHELL description based on complaint from
+         Sam Liddicott <sam@liddicott.com>
+
+                                  3/25
+                                  ----
+trap.c
+       - change free_trap_strings to not call free_trap_string for signals
+         that are being ignored, like reset_or_restore_signal_handlers.
+         Fixes bug reported by Satoshi Takahashi <blue3waters@gmail.com>
+
+                                  3/26
+                                  ----
+lib/readline/rltypedefs.h
+       - remove old Function/VFunction/CPFunction/CPPFunction typedefs as
+         suggested by Tom Tromey <tromey@redhat.com>
+
+lib/readline/rlstdc.h
+       - move defines for USE_VARARGS/PREFER_STDARG/PREFER_VARARGS from
+         config.h.in to here because declaration of rl_message in
+         readline.h uses the defines.  This makes it hard for another packages
+         to use after the header files are installed, since config.h is not
+         one of the installed files.  Suggested by Tom Tromey
+         <tromey@redhat.com>
+
+                                  3/27
+                                  ----
+print_cmd.c
+       - change indirection_string from a static buffer to a dynamic one
+         managed by indirection_level_string(), so we don't end up truncating
+         PS4.  Suggested by Dennis Williamson <dennistwilliamson@gmail.com>
+
+lib/readline/shell.c
+       - change sh_set_lines_and_columns to use static buffers instead of
+         allocating the buffers to pass to setenv/putenv
+
+lib/readline/terminal.c
+       - change _rl_get_screen_size to not call sh_set_lines_and_columns if
+         ignore_env == 0
+       - _rl_sigwinch_resize_terminal: new function to just retrieve terminal
+         size, ignoring environment
+
+lib/readline/rlprivate.h
+       - new external declaration for _rl_sigwinch_resize_terminal() (currently
+         unused)
+
+lib/readline/signals.c
+       - rl_sigwinch_handler: set _rl_caught_signal to SIGWINCH
+       - rl_sigwinch_handler: don't immediately call rl_resize_terminal; just
+         leave _rl_caught_signal set for RL_CHECK_SIGNALS to handle
+       - _rl_signal_handler: call rl_resize_terminal if sig == SIGWINCH.
+         Should fix hang when sending multiple repeated SIGWINCH reported by
+         Henning Bekel <h.bekel@googlemail.com>
+
+                                  3/29
+                                  ----
+lib/sh/snprintf.c
+       - include math.h for any defines for isinf/isnan
+       - use code from gnulib documentation to implement isinf/isnan if they
+         are not defined
+
+configure.in
+       - don't check for isinf or isnan; c99 says they're macros anyway
+
+config.h.in
+       - remove defines for ISINF_IN_LIBC and ISNAN_IN_LIBC, no longer used
+         by snprintf.c
+
+                                   4/2
+                                   ---
+braces.c
+       - brace_gobbler: fix to understand double-quoted command substitution,
+         since the shell understands unquoted comsubs.  Fixes bug reported
+         by Michael Whitten <mfwitten@gmail.com>
+
+lib/readline/display.c
+       - include <pc.h> on MDOS
+       - get and set screen size using DJGPP-specific calls on MSDOS
+       - move cursor up clear screen using DJGPP-specific calls
+       - don't call tputs on DJGPP; there is no good terminfo support
+
+lib/readline/terminal.c
+       - include <pc.h> on MDOS
+       - get and set screen size using DJGPP-specific calls on MSDOS
+       - use DJGPP-specific initialization on MSDOS, zeroing all the
+         _rl_term_* variables
+       - don't call tputs on DJGPP; there is no good terminfo support
+         DJGPP support from Eli Zaretskii  <eliz@gnu.org>
+
+                                   4/6
+                                   ---
+
+config-top.h
+       - change DEFAULT_PATH_VALUE to something more useful and modern
+
+                                   4/8
+                                   ---
+tests/printf2.sub
+       - make sure LC_ALL and LC_CTYPE are set so LANG assignment takes effect.
+         Reported by Cedric Arbogast <arbogast.cedric@gmail.com>
+
+                                  4/11
+                                  ----
+include/chartypes.h
+       - fix a couple of dicey defines (though ones that don't cause any
+         compiler warnings) in IN_CTYPE_DOMAIN
+
+doc/{bashref.texi,bash.1}
+       - add note referring to duplicating file descriptors in sections
+         describing redirecting stdout and stderr and appending to stdout
+         and stderr.  Suggested by Matthew Dinger <mdinger.bugzilla@gmail.com>
+
+pcomplete.c
+       - it_init_helptopics: new function to support completing on help topics,
+         not just builtins
+       - it_helptopics: new programmable completion list of help topics
+       - build list of helptopic completions in gen_action_completions on
+         demand
+
+pcomplete.h
+       - new extern declaration for it_helptopics
+
+builtins/complete.def
+       - the `helptopic' action now maps to CA_HELPTOPIC intead of CA_BUILTIN,
+         since there are more help topics than just builtins.  Suggested by
+         Clark Wang <dearvoid@gmail.com>
+
+                                  4/12
+                                  ----
+print_cmd.c
+       - fix print_arith_for_command to add a call to PRINT_DEFERRED_HEREDOCS
+         before ending the body of the command, so heredocs get attached to
+         the right command instead of to the loop.  From gentoo bug 363371
+         http://bugs.gentoo.org/show_bug.cgi?id=363371
+
+execute_cmd.c
+       - change coproc_pidchk to unset the appropriate shell variables when
+         the (currently single) known coproc pid terminates
+       - cleanup and new functions to fully support multiple coprocesses when
+         and if I decide to go there
+
+                                  4/13
+                                  ----
+print_cmd.c
+       - fix print_group_command to add a call to PRINT_DEFERRED_HEREDOCS
+         after call to make_command_string_internal before printing closing
+         `}'
+       - fix make_command_string_internal to add a call to
+         PRINT_DEFERRED_HEREDOCS after recursive call to
+         make_command_string_internal in case cm_subshell before printing
+         closing `)'
+
+                                  4/14
+                                  ----
+print_cmd.c
+       - change overlapping strcpy in named_function_string to memmove
+
+sig.h
+       - UNBLOCK_SIGNAL: convenience define, same as UNBLOCK_CHILD, just
+         restores an old signal mask
+
+trap.c
+       - set_signal: instead of setting the signal handler to SIG_IGN while
+         installing the new trap handler, block the signal and unblock it
+         after the new handler is installed.  Fixes bug reported by Roman
+         Rakus <rrakus@redhat.com>
+
+                                  4/15
+                                  ----
+doc/{bash.1,bashref.texi}
+       - make it clear that enabling monitor mode means that all jobs run in
+         separate process groups
+
+                                  4/18
+                                  ----
+builtins/fc.def
+       - update fix of 4/15/2010 to not take saved_command_line_count into
+         account when stepping down the history list to make sure that
+         last_hist indexes something that is valid.  Fixes bug reported by
+         <piuma@piumalab.org>
+
+                                  4/19
+                                  ----
+builtins/fc.def
+       - fc_gethnum: make sure the calculation to decide the last history
+         entry is exactly the same as fc_builtin.  Fixes bug uncovered by
+         fix of 4/18 to stop seg fault
+
+                                  4/22
+                                  ----
+lib/readline/terminal.c
+       - change _rl_enable_meta_key to set a flag indicating that it sent the
+         enable-meta sequence
+       - _rl_disable_meta_key: new function to turn off meta mode after we
+         turned it on with _rl_enable_meta_key
+
+lib/readline/rlprivate.h
+       - extern declaration for _rl_disable_meta_key
+
+configure.in
+       - if not cross-compiling, set CFLAGS_FOR_BUILD from any CFLAGS inherited
+         from the environment.  Fixes HP/UX build problem reported by
+         "Daniel Richard G." <skunk@iSKUNK.ORG>
+
+                                  4/26
+                                  ----
+config-top.h
+       - define MULTIPLE_COPROCS to 0 so the code is still disabled but easy
+         to enable via configure option or editing this file
+
+                                  4/29
+                                  ----
+lib/sh/eaccess.c
+       - freebsd provides faccessat, with the same misfeature as their eaccess
+         and access implementations (X_OK returns true for uid==0 regardless
+         of the actual file permissions), so reorganize code to check the
+         file permissions as with eaccess.  Report and fix from Johan Hattne
+         <johan.hattne@utsouthwestern.edu>
+
+                                   5/2
+                                   ---
+doc/{bash.1,bashref.texi}
+       - add forward reference to `Pattern Matching' from `Pathname
+         Expansion', suggested by Greg Wooledge <wooledg@eeg.ccf.org>
+
+                                   5/5
+                                   ---
+pcomplib.c
+       - the bash_completion project now distributes over 200 completions
+         for various programs, with no end in sight, so increase the value
+         of COMPLETE_HASH_BUCKETS from 32 to 128
+
+pathexp.c
+       - quote_string_for_globbing: make sure CTLESC quoting CTLESC is
+         translated into \<CTLESC> even if the flags include QGLOB_REGEXP.
+         We don't want to process the second CTLESC as a quote character.
+         Fixes bug reported by Shawn Bohrer <sbohrer@rgmadvisors.com>
+
+                                   5/6
+                                   ---
+builtins/printf.def
+       - change PRETURN to not call fflush if ferror(stdout) is true
+       - if a call to one of the stdio functions or printstr leaves
+         ferror(stdout) true, and PRETURN is going to be called, let PRETURN
+         print the error message rather than doubling up the messages.  Fixes
+         problem reported by Roman Rakus <rrakus@redhat.com>
+
+                                   5/9
+                                   ---
+doc/{bash.1,bashref.texi}
+       - add note to the effect that lists inside compound command can be
+         terminated by newlines as well as semicolons.  Suggested by
+         Roman Byshko <rbyshko@gmail.com>
+
+                                  5/10
+                                  ----
+subst.c
+       - remove_quoted_nulls: fix problem that caused it to skip over the
+         character after a CTLNUL, which had the effect of skipping every
+         other of a series of CTLNULs.  Fixes bug reported by
+         Marten Wikstrom <marten.wikstrom@keystream.se>
+
+                                  5/11
+                                  ----
+subst.c
+       - extract_process_subst: add SX_COMMAND flag to call to
+         extract_delimited_string, since we're expanding the same sort of
+         command as command substitution.  Fixes bug reported in Ubuntu
+         bug 779848
+
+                                  5/12
+                                  ----
+configure.in
+       - set the prefer_shared and prefer_static variables appropriately
+         depending on the value of $opt_static_link
+
+aclocal.m4
+       - AC_LIB_LINKFLAGS_BODY: change to not prefer shared versions of the
+         libraries it's searching for if the prefer_shared variable is "no".
+         Fixes problem reported by Cedric Arbogast <arbogast.cedric@gmail.com>
+
+                                  5/13
+                                  ----
+lib/readline/readline.c
+       - _rl_internal_teardown: add call to _rl_disable_meta_key to make the
+         meta key active only for the duration of the call to readline()
+       - _rl_internal_setup: move call to _rl_enable_meta_key here from
+         readline_initialize_everything so the meta key is active only for
+         the duration of the call to readline().  Suggestion from Miroslav
+         Lichvar <mlichvar@redhat.com>
+
+builtins/help.def
+       - help_builtin: change strncmp to strcmp so that `help read' no longer
+         matches `readonly'.  Suggested by Clark Wang <dearvoid@gmail.com>
+
+config.h.in
+       - add define for GLIBC21, checked using jm_GLIBC21 as part of the tests
+         for libintl
+
+lib/malloc/malloc.c
+       - internal_free: don't use the cached value of memtop when deciding
+         whether or not to adjust the break and give memory back to the kernel
+         when using the GNU C library, since glibc uses sbrk for its own
+         internal purposes.  From Debian bug 614815, reported by Samuel
+         Thibault <samuel.thibault@gnu.org>
+
+aclocal.m4
+       - BASH_STRUCT_WEXITSTATUS_OFFSET: change AC_RUN_IFELSE to AC_TRY_RUN
+         to avoid warning about not using AC_LANG_SOURCE
+
+                                  5/14
+                                  ----
+bashline.[ch]
+       - two new functions, bashline_set_event_hook and bashline_reset_event_hook,
+         to set rl_event_hook to bash_event_hook and back to NULL, respectively
+       - don't set rl_event_hook unconditionally
+
+sig.c
+       - termsig_sighandler: if the shell is currently interactive and
+         readline is active, call bashline_set_event_hook to cause
+         termsig_handler to be called via bash_event_hook when the shell
+         returns from the signal handler
+
+                                  5/15
+                                  ----
+lib/readline/display.c
+       - _rl_col_width: Mac OS X has a bug in wcwidth: it does not return 0
+         for UTF-8 combining characters.  Added workaround dependent on
+         MACOSX.  Fixes problem pointed out by Thomas De Contes
+         <d.l.tDecontes@free.fr>
+
+                                  5/16
+                                  ----
+lib/readline/rlmbutil.h
+       - WCWIDTH: wrapper for wcwidth that returns 0 for Unicode combining
+         characters on systems where wcwidth is broken (e.g., Mac OS X).
+
+lib/readline/{complete,display,mbutil}.c
+       - use WCWIDTH instead of wcwidth
+
+                                  5/17
+                                  ----
+lib/readline/display.c
+       - update_line: after computing ofd and nfd, see whether the next
+         character in ofd is a zero-width combining character.  If it is,
+         back ofd and nfd up one, so the base characters no longer compare
+         as equivalent.  Fixes problem reported by Keith Winstein
+         <keithw@mit.edu>
+
+lib/readline/nls.c
+       - _rl_utf8locale: new flag variable, set to non-zero if the current
+         locale is UTF-8
+       - utf8locale(): new function, returns 1 if the passed lspec (or the
+         current locale) indicates that the locale is UTF-8.  Called from
+         _rl_init_eightbit
+
+lib/readline/rlprivate.h
+       - extern declaration for _rl_utf8locale
+
+locale.c
+       - locale_utf8locale: new flag variable, set to non-zero if the current
+         locale is UTF-8 (currently unused)
+       - locale_isutf8(): new function, returns 1 if the passed lspec (or the
+         current locale) indicates that the locale is UTF-8.  Should be called
+         whenever the locale or LC_CTYPE value is modified
+
+aclocal.m4
+       - BASH_WCWIDTH_BROKEN: new test for whether or not wcwidth returns
+         zero-width characters like unicode combining characters as having
+         display length 1; define WCWIDTH_BROKEN in this case
+
+config.h.in
+       - WCWIDTH_BROKEN: new define
+
+lib/readline/rlmbutil.h
+       - change WCWIDTH macro to use _rl_utf8locale and the full range of
+         Unicode combining characters (U+0300-U+036F)
+
+                                  5/19
+                                  ----
+lib/readline/rlprivate.h
+       - _rl_search_context: new member, prevc, will hold character read
+         prior to lastc
+
+lib/readline/isearch.c
+       - _rl_isearch_dispatch: if the character causes us to index into
+         another keymap, save that character in cxt->prevc
+       - _rl_isearch_dispatch: if we index into another keymap, but don't
+         find a function that's special to i-search, and the character that
+         caused us to index into that keymap would have terminated the
+         search, push back cxt->prevc and cxt->lastc to make it appear as
+         if `prevc' terminated the search, and execute lastc as a command.
+         We have to push prevc back so we index into the same keymap before
+         we read lastc.  Fixes bug report from Davor Cubranic
+         <cubranic@stat.ubc.ca>
+
+                                  5/20
+                                  ----
+expr.c
+       - expr_bind_variable: pay attention to the return value from
+         bind_variable and check whether or not we should error out due to
+         a readonly or noassign variable.  Fixes bug reported by Eric
+         Blake <eblake@redhat.com>
+
+                                  5/26
+                                  ----
+
+lib/readline/search.c
+       - include histlib.h for ANCHORED_SEARCH defines
+       - rl_history_search_flags: new variable, holds ANCHORED_SEARCH flag for
+         the duration of a history search
+       - rl_history_search_reinit: takes a new flags variable, defines whether
+         or not the search is anchored; assigned to rl_history_search_flags
+       - rl_history_serarch_reinit: if ANCHORED_SEARCH flag passed, add ^ to
+         beginning of search string; otherwise search string is unmodified
+       - rl_history_search_internal: set rl_point appropriately based on
+         whether or not rl_history_search_flags includes ANCHORED_SEARCH
+       - rl_history_substr_search_forward: new function, for non-anchored
+         substring search forward through history for string of characters
+         preceding rl_point
+       - rl_history_substr_search_backward: new function, for non-anchored
+         substring search backward through history for string of characters
+         preceding rl_point.  Original code from Niraj Kulkarni
+         <kulkarniniraj14@gmail.com>
+
+lib/readline/readline.h
+       - extern declarations for rl_history_substr_search_{for,back}ward
+
+lib/readline/funmap.c
+       - history-substring-search-forward: new bindable command, invokes
+         rl_history_substr_search_forward
+       - history-substring-search-backward: new bindable command, invokes
+         rl_history_substr_search_backward
+
+lib/readline/doc/{rluser.texi,readline.3}
+       - document history-substring-search-forward and
+         history-substring-search-backward
+
+                                  5/27
+                                  ----
+{nojobs,jobs}.c
+       - add support for DONT_REPORT_SIGTERM so that the shell doesn't print
+         a message when a job exits due to SIGTERM since that's the default
+         signal sent by the kill builtin.  Suggested by Marc Herbert
+         <mark.herbert@gmail.com>
+
+config-top.h
+       - DONT_REPORT_SIGTERM: new user-modifiable setting.  Commented out
+         by default
+
+                                  5/28
+                                  ----
+lib/readline/bind.c
+       - _rl_skip_to_delim: skip to a closing double quote or other delimiter,
+         allowing backslash to quote any character, including the delimiter
+       - rl_parse_and_bind: call _rl_skip_to_delim instead of using inline
+         code
+       - rl_parse_and_bind: allow quoted strings as the values of string
+         variables.  Variable values without double quotes have trailing
+         whitespace removed (which still allows embedded whitespace, for
+         better or worse).  Fixes problem with string variables not matching
+         in `set' command if values happen to have trailing spaces or tabs
+         (debian bash bug #602762), but introduces slight incompatibility.
+
+                                  5/29
+                                  ----
+doc/{bash.1,bashref.texi}
+       - clarify unset description to specify that without options, a
+         variable, then a shell function if there is no variable by that
+         name, is unset.  Fixes discrepancy reported by Mu Qiao
+         <qiaomuf@gentoo.org>
+
+                                  6/4
+                                  ----
+doc/{bash.1,bashref.texi}
+       - clarify description of LINES and COLUMNS (and checkwinsize shopt
+         option) to make it clear that only interactive shells set a
+         handler for SIGWINCH and update LINES and COLUMNS.  Original
+         report submitted by Jonathan Nieder <jrnieder@gmail.com>
+
+arrayfunc.c
+       - expand_compound_array_assignment: defer expansion of words between
+         parens when performing compound assignmnt to an associative array
+         variable
+       - assign_compound_array_list: perform the same expansions when doing
+         a compound array assignment to an associative array variable as
+         when doing a straight array index assignment.  The idea is that
+               foo=( [ind1]=bar [ind2]=quux)
+         is the same as
+               foo[ind1]=bar ; foo[ind2]=quux
+
+         This fixes problems with double-expansion and quote removal being
+         performed on the array indices
+
+                                  6/13
+                                  ----
+doc/{bash.1,bashref.texi}
+       - Add a little text to make it clear that the locale determines how
+         range expressions in glob patterns are handled.
+
+
+                                  6/21
+                                  ----
+builtins/read.def
+       - display a message and return error status if -a is used with an
+         existing associative array.  Fixes bug reported by Curtis Doty
+         <curtis@greenkey.net>
+
+                                  6/24
+                                  ----
+{jobs,nojobs}.c
+       - non-interactive shells now react to the setting of checkwinsize
+         and set LINES and COLUMNS after a foreground job exits.  From a
+         suggestion by Leslie Rhorer <lrhorer@satx.rr.com>
+
+doc/{bash.1,bashref.texi}
+       - checkwinsize: remove language saying that only interactive shells
+         check the window size after each command
+
+lib/readline/histfile.c
+       - history_backupfile: new file, creates a backup history file name
+         given a filename (appending `-')
+       - history_do_write: when overwriting the history file, back it up
+         before writing.  Restore backup file on a write error.  Suggested
+         by chkno@chkno.net
+
+bashline.c
+       - find_cmd_name: two new arguments, return the start and end of the
+         actual text string used to find the command name, without taking
+         whitespace into account
+       - attempt_shell_completion: small changes to make sure that completion
+         attempted at the beginning of a non-empty line does not find a
+         programmable completion, even if the command name starts at point
+       - attempt_shell_completion: small change to make sure that completion
+         does not find a progcomp when in whitespace before the command
+         name
+       - attempt_shell_completion: small change to make sure that completion
+         does not find a progcomp when point is at the first character of a
+         command name, even when there is leading whitespace (similar to
+         above).  Fixes problems noted by Ville Skytta <ville.skytta@iki.fi>
+
+subst.c
+       - brace_expand_word_list: since the individual strings in the strvec
+         returned by brace_expand are already allocated, don't copy them to
+         newly-allocated memory when building the WORD_LIST, just use them
+         intact
+
+locale.c
+       - locale_mb_cur_max: cache value of MB_CUR_MAX when we set or change
+         the locale to avoid a function call every time we need to read it
+
+shell.h
+       - new struct to save shell_input_line and associated variables:
+         shell_input_line_state_t
+       - add members of sh_parser_state_t to save and restore token and the
+         size of the token buffer
+
+parse.y
+       - {save,restore}_input_line_state: new functions to save and restore
+         shell_input_line and associated variables
+       - {save,restore}_parser_state: add code to save and restore the token
+         and token buffer size
+       - xparse_dolparen: call save_ and restore_input_line_state to avoid
+         problems with overwriting shell_input_line when we recursively
+         call the parser to parse a command substitution.  Fixes bug
+         reported by Rui Santos <rsantos@grupopie.com>
+
+include/shmbutil.h
+       - use locale_mb_cur_max instead of MB_CUR_MAX in ADVANCE_CHAR and
+         similar macros
+
+lib/glob/smatch.c
+       - rangecmp,rangecmp_wc: change to take an additional argument, which
+         forces the use of strcoll/wscoll when non-zero.  If it's 0, a new
+         variable `glob_asciirange' controls whether or not we use strcoll/
+         wscoll.  If glob_asciirange is non-zero, we use straight
+         C-locale-like ordering. Suggested by  Aharon Robbins
+         <arnold@skeeve.com>
+
+                                  6/30
+                                  ----
+execute_cmd.c
+       - execute_pipeline: make sure the lastpipe code is protected by
+         #ifdef JOB_CONTROL.  Fixes problem reported by Thomas Cort
+         <tcort@minix3.org>
+
+                                   7/2
+                                   ---
+lib/readline/complete.c
+       - EXPERIMENTAL: remove setting of _rl_interrupt_immediately around
+         completion functions that touch the file system.  Idea from Jan
+         Kratochvil <jan.ktratochvil@redhat.com> and the GDB development
+         team
+
+lib/readline/signals.c
+       - rl_signal_handler: if we're in callback mode, don't interrupt
+         immediately on a SIGWINCH
+
+                                   7/3
+                                   ---
+bashline.c
+       - set_directory_hook: and its siblings are a new set of functions to
+         set, save, and restore the appropriate directory completion hook
+       - change callers to use {set,save,restore}_directory_hook instead of
+         manipulating rl_directory_rewrite_hook directly
+       - dircomplete_expand: new variable, defaults to 0, if non-zero causes
+         directory names to be word-expanded during word and filename
+         completion
+       - change {set,save,restore}_directory_hook to look at dircomplete_expand
+         and change rl_directory_completion_hook or rl_directory_rewrite_hook
+         appropriately
+
+bashline.h
+       - extern declaration for set_directory_hook so shopt code can use it
+
+                                   7/6
+                                   ---
+builtins/shopt.def
+       - globasciiranges: new settable shopt option, makes glob ranges act
+         as if in the C locale (so b no longer comes between A and B).
+         Suggested by Aharon Robbins <arnold@skeeve.com>
+
+                                   7/7
+                                   ---
+doc/{bash.1,bashref.texi}
+       - document new `globasciiranges' shopt option
+
+                                   7/8
+                                   ---
+builtins/shopt.def
+       - direxpand: new settable option, makes filename completion expand
+         variables in directory names like bash-4.1 did.
+       - shopt_set_complete_direxpand: new function, does the work for the
+         above by calling set_directory_hook
+
+doc/{bash.1,bashref.texi}
+       - document new `direxpand' shopt option
+
+                                  7/15
+                                  ----
+lib/readline/isearch.c
+       - _rl_isearch_dispatch: when adding character to search string, use
+         cxt->lastc (which we use in the switch statement) instead of c,
+         since lastc can be modified earlier in the function
+
+                                  7/18
+                                  ----
+lib/readline/rlprivate.h
+       - _rl_search_context: add another member to save previous value of
+         (multibyte) lastc: pmb is to mb as prevc is to lastc
+
+lib/readline/isearch.c:
+       - _rl_isearch_dispatch: if a key sequence indexes into a new keymap,
+         but doesn't find any bound function (k[ind].function == 0) or is
+         bound to self-insert (k[ind].function == rl_insert), back up and
+         insert the previous character (the one that caused the index into a
+         new keymap) and arrange things so the current character is the next
+         one read, so both of them end up in the search string.  Fixes bug
+         reported by Clark Wang <dearvoid@gmail.com>
+       - _rl_isearch_dispatch: a couple of efficiency improvements when adding
+         characters to the isearch string
+
+                                  7/24
+                                  ----
+lib/readline/isearch.c
+       - _rl_isearch_dispatch: save and restore cxt->mb and cxt->pmb
+         appropriately when in a multibyte locale
+
+doc/{bash.1,bashref.texi}
+       - correct description of {x}>file (and other redirection operators
+         that allocate a file descriptor) to note the the fd range is
+         greater than or equal to 10.  Fixes problem reported by
+         Christian Ullrich 
+
+lib/readline/signals.c
+       - rl_signal_handler: don't interrupt immediately if in callback mode
+
+lib/readline/callback.c
+       - rl_callback_read_char: install signal handlers only when readline
+         has control in callback mode, so readline's signal handlers aren't
+         called when the application is active (e.g., between the calls to
+         rl_callback_handler_install and rl_callback_read_char).  If the
+         readline signal handlers only set a flag, which the application
+         doesn't know about, the signals will effectively be ignored until
+         the next time the application calls into the readline callback
+         interface.  Fixes problem of calling unsafe functions from signal
+         handlers when in callback mode reported by Jan Kratochvil
+         <jan.kratochvil@redhat.com>
+
+execute_cmd.c
+       - fix_assignment_words: when in Posix mode, the `command' builtin
+         doesn't change whether or not the command name it protects is an
+         assignment builtin.  One or more instances of `command'
+         preceding `export', for instance, doesn't make `export' treat its
+         assignment statement arguments differently.  Posix interpretation
+         #351
+
+doc/{bash.1,bashref.texi}
+       - document new Posix-mode behavior of `command' when preceding builtins
+         that take assignment statements as arguments
+
+builtins/printf.def
+       - printstr: if fieldwidth or precision are < 0 or > INT_MAX when
+         supplied explicitly (since we take care of the `-' separately),
+         clamp at INT_MAX like when using getint().  Fixes issue reported
+         by Ralph Coredroy <ralph@inputplus.co.uk>
+
+                                  7/25
+                                  ----
+lib/readline/chardefs.h
+       - isxdigit: don't define if compiling with c++; declared as a c++
+         template function.  Fixes bug reported by Miroslav Lichvar
+         <mlichvar@redhat.com>
+
+builtins/printf.def
+       - getint: if garglist == 0, return whatever getintmax returns (0).
+         Fixes bug reported  by Ralph Coredroy <ralph@inputplus.co.uk>
+
+                                  7/28
+                                  ----
+doc/{bash.1,bashref.texi}
+       - minor changes to the descriptions of the cd and pushd builtins
+
+lib/sh/zread.c
+       - zsyncfd: change variable holding return value from lseek to
+         off_t.  Bug report and fix from Gregory Margo <gmargo@pacbell.net>
+
+                                   8/1
+                                   ---
+expr.c
+       - don't check for division by 0 when in a context where no evaluation
+         is taking place.  Fixes bug reported by dnade.ext@orange-ftgroup.com
+
+                                   8/6
+                                   ---
+execute_cmd.c
+       - execute_command_internal: the parent branch of the subshell code
+         (where the child calls execute_in_subshell) should not close all
+         open FIFOs with unlink_fifo_list if it's part of a shell function
+         that's still executing.  Fixes bug reported by Maarten Billemont
+         <lhunath@lyndir.com>
+
+                                   8/9
+                                   ---
+builtins/common.c
+       - get_exitstat: return EX_BADUSAGE (2) on a non-numeric argument
+
+builtins/return.def
+       - return_builtin: just call get_exitstat to get the return status,
+         let it handle proper parsing and handling of arguments.  Fixes
+         issue most recently raised by Linda Walsh <bash@tlinx.org>.
+         Reverses change from 9/11/2008 (see above)
+
+                                  8/16
+                                  ----
+doc/{bash.1,bashref.texi}
+       - clean up `set -e' language to make it clearer that any failure of
+         a compound command will cause the shell to exit, not just subshells
+         and brace commands
+
+                                  8/17
+                                  ----
+configure.in
+       - make the various XXX_FOR_BUILD variables `precious' to autoconf to
+         avoid stale data
+       - change how CC_FOR_BUILD is initialized when cross-compiling and not,
+         but do not change behavior
+       - initialize CFLAGS_FOR_BUILD to -g when cross-compiling
+       - initialize LIBS_FOR_BUILD to $(LIBS) when not cross-compiling, empty
+         when cross-compiling
+       - create AUTO_CFLAGS variable to hold basic CFLAGS defaults; used when
+         CFLAGS not inherited from environment (like effect of old
+         auto_cflags variable)
+       - substitute LIBS_FOR_BUILD into output Makefiles
+         [changes inspired by bug report from Nathan Phillip Brink
+         <ohnobinki@ohnopublishing.net> -- gentoo bug 378941]
+
+builtins/Makefile.in   
+       - substitute LIBS_FOR_BUILD from configure, not strictly initialized
+         to $(LIBS)
+
+                                  8/27
+                                  ----
+doc/{bash.1,bashref.texi}
+       - minor changes to the here string description to clarify the
+         expansions performed on the word
+
+support/shobj-conf
+       - handle compilation on Lion (Mac OS X 10.7/darwin11) with changes
+         to darwin stanzas.  Fixes readline bug reported by Vincent
+         Sheffer <vince.sheffer@apisphere.com>
+
+lib/sh/strtrans.c
+       - ansic_wshouldquote: check a string with multi-byte characters for
+         characters that needs to be backslash-octal escaped for $'...'
+       - ansic_shouldquote: if is_basic fails for one character, let
+         ansic_wshouldquote examine the rest of the string and return what
+         it returns.  From a patch sent by Roman Rakus <rrakus@redhat.com>
+
+                                  8/30
+                                  ----
+lib/sh/strtrans.c
+       - ansic_quote: changes to quote (or not) multibyte characters.  New
+         code converts them to wide characters and uses iswprint to check
+         valid wide chars.  From a patch sent by Roman Rakus
+         <rrakus@redhat.com>
+
+                                   9/7
+                                   ---
+lib/sh/shquote.c
+       - sh_backslash_quote: change to be table-driven so we can use a
+         different table if we want to
+       - sh_backslash_quote: takes a second char table[256] argument;
+
+externs.h
+       - sh_backslash_quote: add second argument to function prototype
+
+bashline.c,braces.c,parse.y,builtins/printf.def
+       - change callers of sh_backslash_quote to add second argument
+
+bashline.c
+       - filename_bstab: table of characters to pass to sh_backslash_quote;
+         characters with value 1 will be backslash-quoted
+       - set_filename_bstab: turn on characters in filename backslash-quote
+         table according to passed string argument
+       - call set_filename_bstab every time rl_filename_quote_characters is
+         assigned a value
+       - bash_quote_filename: call sh_backslash_quote with filename_bstab
+         as second argument.  This allows other characters in filenames to
+         be quoted without quoting, for instance, a dollar sign in a shell
+         variable reference
+
+                                   9/8
+                                   ---
+bashline.c
+       - complete_fullquote: new variable, controls table passed to
+         sh_backslash_quote.  If non-zero (the default), the standard set
+         of shell metacharacters -- as in bash versions up to and including
+         bash-4.2 -- gets backslash-quoted by the completion code.  If zero,
+         sh_backslash_quote gets the table with the characters in the
+         variable reference removed, which means they are removed from the
+         set of characters to be quoted in filenames
+
+                                  9/10
+                                  ----
+bashline.c
+       - bash_filename_stat_hook: new function, designed to expand variable
+         references in filenames before readline passes them to stat(2)
+         to determine whether or not they are a directory
+
+                                  9/15
+                                  ----
+builtins/declare.def
+       - if assign_array_element fails due to a bad (or empty) subscript, mark
+         it as an assignment error and don't attempt any further processing
+         of that declaration.  Fixes segfault bug reported by Diego Augusto
+         Molina <diegoaugustomolina@gmail.com>
+
+                                  9/19
+                                  ----
+expr.c
+       - exppower: replace the simple exponentiation algorithm with an
+         implementation of exponentiation by squaring.  Inspired by report
+         from Nicolas ARGYROU <nargy@yahoo.com>
+
+bashline.c
+       - bash_quote_filename: check for rtext being non-null before
+         dereferencing it
+       - set_saved_history: operate_and_get_next assumes that the previous
+         line was added to the history, even when the history is stifled and
+         at the max number of entries.  If it wasn't, make sure the history
+         number is incremented properly.  Partial fix for bug reported by
+         gregrwm <backuppc-users@whitleymott.net>
+
+doc/{bash.1,bashref.texi},lib/readline/doc/{hsuser,rluser}.texi
+       - minor editorial changes inspired by suggestions from
+         Roger Zauner <rogerx.oss@gmail.com>
+
+                                  9/20
+                                  ----
+lib/intl/localealias.c
+       - read_alias_file: close resource leak (fp) when returning on error
+
+                                  9/22
+                                  ----
+execute_command.c
+       - execute_intern_function: implement Posix interpretation 383 by making
+         it an error to define a function with the same name as a special
+         builtin when in Posix mode.
+         http://austingroupbugs.net/view.php?id=383#c692
+
+                                  9/25
+                                  ----
+doc/{bash.1,bashref.texi}
+       - formatting and some content changes from Benno Schulenberg
+         <bensberg@justemail.net>
+       - document new posix-mode behavior from interp 383 change of 9/22
+
+                                  9/30
+                                  ----
+execute_cmd.c
+       - shell_execve: add strerror to error message about executable file
+         that shell can't execute as a shell script.  From suggestion by
+         daysleeper <daysleeper@centrum.cz>
+
+                                  10/1
+                                  ----
+bashhist.c
+       - maybe_add_history: act as if literal_history is set when parser_state
+         includes PST_HEREDOC, so we save the bodies of here-documents just
+         as they were entered.  Fixes bug reported by Jonathan Wakely
+         <bugs@kayari.org>
+       - bash_add_history: make sure that the second and subsequent lines of
+         a here document don't have extra newlines or other delimiting
+         chars added, since they have the trailing newline preserved, when
+         `lithist' is set and history_delimiting_chars isn't called
+
+execute_cmd.c
+       - execute_command_internal: avoid fd exhaustion caused by using
+         process substitution in loops inside shell functions by using
+         copy_fifo_list and close_new_fifos ().  Fixes debian bash bug
+         642504
+
+lib/readline/complete.c
+       - new variable, rl_filename_stat_hook, used by append_to_match.  If
+         filename completion is desired, and rl_filename_stat_hook points
+         to a function, call that function to expand the filename in an
+         application-specific way before calling stat.
+
+bashline.c
+       - bash_default_completion: if variable completion returns a single
+         match, use bash_filename_stat_hook and file_isdir to determine
+         whether or not the variable name expands to a directory.  If it
+         does, set the filename_append_character to `/'.  This is not
+         perfect, so we will see how it works out.  Adds functionality
+         requested by Peter Toft <pto@linuxbog.dk> and Patrick Pfeifer
+         <patrick@pfeifer.de>
+       - rl_filename_stat_hook: assigned bash_filename_stat_hook, so things
+         like $HOME/Downloads (after completion) have a slash appended.
+         In general, this causes the stat hook to be called whenever
+         filename completion is appended.  Adds functionality requested by
+         Patrick Pfeifer <patrick@pfeifer.de>
+
+lib/readline/readline.h
+       - new extern declaration for rl_filename_stat_hook
+
+lib/readline/doc/rltech.texi
+       - rl_directory_rewrite_hook: now documented
+       - rl_filename_stat_hook: document
+
+pcomplete.c
+       - gen_action_completions: in the CA_DIRECTORY case, turn off
+         rl_filename_completion_desired if it was off before we called
+         rl_filename_completion_function and we didn't get any matches.
+         Having it on causes readline to quote the matches as if they
+         were filenames.  Adds functionality requested by many,
+         including Clark Wang <dearvoid@gmail.com>
+
+assoc.[ch]
+       - assoc_replace: new function, takes the same arguments as
+         assoc_insert, but returns the old data instead of freeing it
+       - assoc_insert: if the object returned by hash_insert doesn't have
+         the same value for its key as the key passed as an argument, we
+         are overwriting an existing value.  In this case, we can free the
+         key.  Fixes bug reported by David Parks <davidparks21@yahoo.com>
+
+                                  10/5
+                                  ----
+print_cmd.c
+       - indirection_level_string: small change to only re-enable `x'
+         option after calling decode_prompt_string if it was on before.  In
+         normal mode, it will be, but John Reiser <jreiser@bitwagon.com>
+         has a novel use for that code in conjunction with a pre-loaded
+         shared library that traces system call usage in shell scripts
+
+                                  10/10
+                                  -----
+Makefile.in
+       - Fix from Mike Frysinger <vapier@gentoo.org> to avoid trying to
+         build y.tab.c and y.tab.h with two separate runs of yacc if
+         parse.y changes.  Problem with parallel makes
+       - Fix from Mike Frysinger <vapier@gentoo.org> to avoid subdirectory
+         builds each trying to make version.h (and all its dependencies)
+
+lib/sh/Makefile.in
+       - remove some dependencies on version.h where it doesn't make sense
+
+variables.c
+       - initialize_shell_variables: while reading the environment, a shell
+         running in posix mode now checks for SHELLOPTS being readonly (it
+         gets set early on in main()) before trying to assign to it.  It
+         saves an error message and the variable gets parsed as it should.
+         Fixes bug reported by Len Giambrone <Len.Giambrone@intersystems.com>
+
+                                  10/14
+                                  -----
+doc/{bash.1,bashref.texi}
+       - add to the "duplicating file descriptors" description that >&word
+         doesn't redirect stdout and stderr if word expands to `-'
+       - add to the "appending standard output and standard error"
+         description a note that >&word, where word is a number or `-',
+         causes other redirection operators to apply for sh and Posix
+         compatibility reasons.  Suggested by Greg Wooledge
+         <wooledg@eeg.ccf.org>
+
+                                  10/15
+                                  -----
+pcomplete.c
+       - change pcomp_filename_completion_function to only run the filename
+         dequoting function in the cases (as best as it can figure) where
+         readline won't do it via rl_filename_completion_function.  Based
+         on reports from <lolilolicon@gmail.com>
+
+                                  10/19
+                                  -----
+bashline.c
+       - attempt_shell_completion: add call to set_directory_hook() to make
+         sure the rewrite functions are correct.  It's cheap and doesn't
+         hurt
+       - command_word_completion_function: if completing a command name that
+         starts with `.' or `..', temporarily suppress the effects of the
+         `direxpand' option and restore the correct value after calling
+         rl_filename_completion_function.  If it's enabled, the directory
+         name will be rewritten and no longer match `./' or `../'.  Fixes
+         problem reported by Michael Kalisz <michael@kalisz.homelinux.net>
+
+                                  10/22
+                                  -----
+builtins/history.def
+       - push_history: make sure remember_on_history is enabled before we
+         try to delete the last history entry -- the `history -s' command
+         might not have been saved.  Fixes bug reported by
+         lester@vmw-les.eng.vmware.com
+
+lib/readline/complete.c
+       - rl_callback_read_char: add calls to a macro CALLBACK_READ_RETURN
+         instead of straight return; add same call at end of function.
+         Placeholder for future work in deinstalling signal handlers when
+         readline is not active
+
+                                  10/25
+                                  -----
+expr.c
+       - exp2: catch arithmetic overflow when val1 == INTMAX_MIN and val2 == -1
+         for DIV and MOD and avoid SIGFPE.  Bug report and pointer to fix
+         from Jaak Ristioja <jaak.ristioja@cyber.ee>
+       - expassign: same changes for arithmetic overflow for DIV and MOD
+
+                                  10/28
+                                  -----
+subst.c
+       - parameter_brace_expand: allow pattern substitution when there is an
+         expansion of the form ${var/} as a no-op: replacing nothing with
+         nothing
+       - parameter_brace_patsub: don't need to check for PATSUB being NULL;
+         it never is
+
+flags.c
+       - if STRICT_POSIX is defined, initialize history_expansion to 0, since
+         history expansion (and its treatment of ! within double quotes) is
+         not a conforming posix environment.  From austin-group issue 500
+
+lib/readline/histexpand.c
+       - history_expand: when processing a string within double quotes
+         (DQUOTE == 1), make the closing double quote inhibit history
+         expansion, as if the word were outside double quotes.  In effect,
+         we assume that the double quote is followed by a character in
+         history_no_expand_chars.  tcsh and csh seem to do this.  This
+         answers a persistent complaint about history expansion
+
+                                  10/29
+                                  -----
+make_cmd.c
+       - make_arith_for_command: use skip_to_delim to find the next `;'
+         when breaking the string between the double parens into three
+         separate components instead of a simple character loop.  Fixes
+         bug reported by Dan Douglas <ormaaj@gmail.com>
+
+                                  11/2
+                                  ----
+Makefile.in
+       - make libbuiltins.a depend on builtext.h to serialize its creation
+         and avoid conflict between multiple invocations of mkbuiltins.
+         Fix from Mike Frysinger <vapier@gentoo.org>
+
+                                  11/5
+                                  ----
+findcmd.c
+       - user_command_matches: if stat(".", ...) returns -1, set st_dev
+         and st_ino fields in dotinfo to 0 to avoid same_file matches
+       - find_user_command_in_path: check stat(2) return the same way
+
+lib/glob/glob.c
+       - glob_vector: don't call strlen(pat) without checking pat == 0
+       - glob_dir_to_array: make sure to free `result' and all allocated
+         members before returning error due to malloc failure
+       - glob_vector: make sure to free `nextname' and `npat' on errors
+         (mostly when setting lose = 1)
+       - glob_vector: if flags & GX_MATCHDIRS but not GX_ALLDIRS, make
+         sure we free `subdir'
+       - glob_filename: when expanding ** (GX_ALLDIRS), make sure we
+         free temp_results (return value from glob_vector)
+
+lib/glob/xmbsrtowcs.c
+       - xdupmbstowcs: fix call to realloc to use sizeof (char *) instead
+         of sizeof (char **) when assigning idxtmp
+
+execute_cmd.c
+       - print_index_and_element: return 0 right away if L == 0
+       - is_dirname: fix memory leak by freeing `temp'
+       - time_command: don't try to deref NULL `command' when assigning
+         to `posix_time'
+       - shell_execve: null-terminate `sample' after READ_SAMPLE_BUF so it's
+         terminated for functions that expect that
+
+builtins/read.def
+       - read_builtin: don't call bind_read_variable with a potentially-null
+         string
+
+pcomplete.c
+       - gen_command_matches: don't call dispose_word_desc with a NULL arg
+       - gen_compspec_completions: fix memory leak by freeing `ret' before
+         calling gen_action_completions (tcs, ...).  happens when
+         performing directory completion as default and no completions
+         have been generated
+       - gen_progcomp_completions: make sure to set foundp to 0 whenever
+         returning NULL
+       - it_init_aliases: fix memory leak by freeing alias_list before
+         returning
+
+bashline.c
+       - command_word_completion_function: don't call restore_tilde with a
+         NULL directory_part argument
+       - bash_directory_expansion: bugfix: don't throw away results of
+         rl_directory_rewrite_hook if it's set and returns non-zero
+       - bind_keyseq_to_unix_command: free `kseq' before returning error
+
+arrayfunc.c
+       - assign_array_element_internal: make sure `akey' is freed if non-null
+         before returning error
+       - assign_compound_array_list: free `akey' before returning error
+       - array_value_internal: free `akey' before returning error
+       - unbind_array_element: free `akey' before returning error
+
+subst.c
+       - array_length_reference: free `akey' before returning error in case
+         of expand_assignment_string_to_string error
+       - array_length_reference: free `akey' after call to assoc_reference
+       - skip_to_delim: if skipping process and command substitution, free
+         return value from extract_process_subst
+       - parameter_brace_substring: free `val' (vtype == VT_VARIABLE) before
+         returning if verify_substring_values fails
+       - parameter_brace_expand: remove two duplicate lines that allocate
+         ret in parameter_brace_substring case
+       - parameter_brace_expand: convert `free (name); name = xmalloc (...)'
+         to use `xrealloc (name, ...)'
+       - parameter_brace_expand: free `name' before returning when handling
+         ${!PREFIX*} expansion
+       - split_at_delims: fix memory leak by freeing `d2' before returning
+
+redir.c
+       - redirection_error: free `filename' if the redirection operator is
+         REDIR_VARASSIGN by assigning allocname
+
+eval.c
+       - send_pwd_to_eterm: fix memory leak by freeing value returned by
+         get_working_directory()
+
+builtins/cd.def
+       - change_to_directory: fix memory leak by freeing return value from
+         resetpwd()
+       - cd_builtin: fix memory leak by freeing value returned by dirspell()
+       - cd_builtin: fix memory leak by freeing `directory' if appropriate
+         before overwriting with return value from resetpwd()
+
+builtins/type.def
+       - describe_command: free `full_path' before overwriting it with return
+         value from sh_makepath
+
+builtins/complete.def
+       - compgen_builtin: fix memory leak by calling strlist_dispose (sl)
+         before overwriting sl with return value from completions_to_stringlist
+
+builtins/hash.def
+       - list_hashed_filename_targets: fix memory leak by freeing `target'
+
+make_cmd.c
+       - make_arith_for_command: free `init', `test', and `step' before
+         returning error on parse error
+
+jobs.c
+       - initialize_job_control: don't call move_to_high_fd if shell_tty == -1
+
+general.c
+       - check_dev_tty: don't call close with an fd < 0
+       - legal_number: deal with NULL `string' argument, return invalid
+
+lib/sh/fmtulong.c
+       - fmtulong: if the `base' argument is invalid, make sure we index
+         buf by `len-1' at maximum
+
+print_cmd.c
+       - print_deferred_heredocs: don't try to dereference a NULL `cstring'
+       - cprintf: make sure to call va_end (args)
+
+variables.c
+       - push_dollar_vars: fix call to xrealloc to use sizeof (WORD_LIST *)
+         instead of sizeof (WORD_LIST **)
+
+lib/sh/zmapfd.c
+       - zmapfd: if read returns error, free result and return -1 immediately
+         instead of trying to reallocate it
+
+                                  11/6
+                                  ----
+execute_cmd.c
+       - cpl_reap: rewrote to avoid using pointer after freeing it; now builds
+         new coproc list on the fly while traversing the old one and sets the
+         right values for coproc_list when done
+
+                                  11/12
+                                  -----
+builtins/set.def
+       - if neither -f nor -v supplied, don't allow a readonly function to
+         be implicitly unset.  Fixes bug reported by Jens Schmidt
+         <jens.schmidt35@arcor.de>
+
+lib/readline/callback.c
+       - change CALLBACK_READ_RETURN to clear signal handlers before returning
+         from rl_callback_read_char so readline's signal handlers aren't
+         installed when readline doesn't have control.  Idea from Jan
+         Kratochvil <jan.ktratochvil@redhat.com> and the GDB development
+         team
+
+pcomplete.h
+       - COPT_NOQUOTE: new complete/compgen option value
+
+builtins/complete.def
+       - noquote: new complete/compgen option; will be used to disable
+         filename completion quoting
+
+pcomplete.c
+       - pcomp_set_readline_variables: pay attention to COPT_NOQUOTE; turns
+         of rl_filename_quoting_desired if set; turns it on if unset (value
+         is inverted, since default is on)
+
+doc/bash.1,lib/readline/doc/rluser.texi
+       - document new -o noquote option to complete/compgen/compopt
+
+pathexp.c
+       - quote_string_for_globbing: if QGLOB_REGEXP, make sure characters
+         between brackets in an ERE bracket expression are not inappropriately
+         quoted with backslashes.  This is a pretty substantial change,
+         should be stressed when opening bash up for alpha and beta tests.
+         Fixes bug pointed out by Stephane Chazleas
+         <stephane_chazelas@yahoo.fr>
+
+doc/{bash.1,bashref.texi}
+       - document that regexp matches can be inconsistent when quoting
+         characters in bracket expressions, since usual quoting characters
+         lose their meaning within brackets
+       - note that regular expression matching when the pattern is stored
+         in a shell variable which is quoted for expansion causes string
+         matching
+
+redir.h
+       - RX_SAVEFD: new flag value; notes that a redirection denotes an
+         fd used to save another even if it's not >= SHELL_FD_BASE
+
+redir.c
+       - do_redirection_internal: when deciding whether or not to reset the
+         close-on-exec flag on a restored file descriptor, trust the value
+         of redirect->flags & RX_SAVCLEXEC even if the fd is < SHELL_FD_BASE
+         if the RX_SAVEFD flag is set
+       - add_undo_redirect: set the RX_SAVEFD flag if the file descriptor
+         limit is such that the shell can't duplicate to a file descriptor
+         >= 10.  Fixes a limitation that tripped a coreutils test reported
+         by Paul Eggert <eggert@cs.ucla.edu>
+
+                                  11/19
+                                  -----
+doc/{bash.1,bashref.texi},lib/readline/doc/hsuser.texi
+       - make it clear that bash runs HISTFILESIZE=$HISTSIZE after reading
+         the startup files
+       - make it clear that bash runs HISTSIZE=500 after reading the
+         startup files
+       - make it clear that setting HISTSIZE=0 causes commands to not be
+         saved in the history list
+       - make it clear that setting HISTFILESIZE=0 causes the history file
+         to be truncated to zero size
+
+variables.c
+       - sv_histsize: change so setting HISTSIZE to a value less than 0
+         causes the history to be `unstifled'
+       - sv_histsize: change so setting HISTFILESIZE to a value less than 0
+         results in no file truncation
+       - make it clear that numeric values less than 0 for HISTFILESIZE or
+         HISTSIZE inhibit the usual functions
+
+                                  11/23
+                                  -----
+parse.y
+       - save_input_line_state: add missing `return ls' at the end, since the
+         function is supposed to return its argument.  Pointed out by
+         Andreas Schwab <schwab@linux-m68k.org>
+
+builtins/read.def
+       - skip over NUL bytes in input, as most modern shells seem to.  Bug
+         report by Matthew Story <matt@tablethotels.com>
+
+lib/readline/vi_mode.c
+       - rl_vi_replace: set _rl_vi_last_key_before_insert to invoking key
+
+                                  11/25
+                                  -----
+builtins/read.def
+       - read_builtin: if xrealloc returns same pointer as first argument,
+         don't bother with the remove_unwind_protect/add_unwind_protect pair
+       - read_builtin: set a flag (`reading') around calls to zread/zreadc
+         and readline()
+       - sigalrm: change to set flag (`sigalrm_seen') and only longjmp if
+         currently in read(2) (reading != 0)
+       - CHECK_ALRM: new macro, checks sigalrm_seen and longjmps if non-zero,
+         behavior of old SIGALRM catching function
+       - read_builtin: call CHECK_ALRM in appropriate places while reading
+         line of input.  Fixes bug reported by Pierre Gaston
+         <pierre.gaston@gmail.com>
+
+lib/readline/vi_mode.c
+       - rl_vi_replace: initialize characters before printing characters in
+         vi_replace_keymap to their default values in vi_insertion_keymap,
+         since we're supposed to be in insert mode replacing characters
+       - rl_vi_replace: call rl_vi_start_inserting to set last command to
+         `R' for undo
+       - rl_vi_replace: set _rl_vi_last_key_before_insert to `R' for future
+         use by _rl_vi_done_inserting
+       - vi_save_insert_buffer: new function, broke out code that copies text
+         into vi_insert_buffer from _rl_vi_save_insert
+       - _rl_vi_save_replace: new function, saves text modified by
+         rl_vi_replace (using current point and vi_replace_count to figure
+         it out) to vi_replace_buffer
+       - _rl_vi_save_insert: call vi_save_insert_buffer
+       - _rl_vi_done_inserting: if _rl_vi_last_key_before_insert == 'R', call
+         _rl_vi_save_replace to save text modified in replace mode (uses
+         vi_save_insert_buffer)
+       - _rl_vi_replace_insert: new function, replaces the number of chars
+         in vi_insert_buffer after rl_point with contents ov vi_insert_buffer
+       - rl_vi_redo: call _rl_vi_replace_insert if last command == 'R' and
+         there's something in vi_insert_buffer.  Fixes bug with `.' not
+         redoing the most recent `R' command, reported by Geoff Clare
+         <g.clare@opengroup.org> in readline area on savannah
+
+                                  11/26
+                                  -----
+lib/readline/rlprivate.h
+       - RL_SIG_RECEIVED(): evaluate to non-zero if there is a pending signal
+         to be handled
+       - RL_SIGINT_RECEIVED(): evaluate to non-zero if there is a pending
+         SIGINT to be handled
+
+lib/readline/complete.c
+       - remove all mention of _rl_interrupt_immediately
+       - rl_completion_matches: check RL_SIG_RECEIVED after each call to
+         the entry function, call RL_CHECK_SIGNALS if true to handle the
+         signal
+       - rl_completion_matches: if RL_SIG_RECEIVED evaluates to true, free
+         and zero out the match_list this function allocated
+       - rl_completion_matches: if the completion entry function is
+         rl_filename_completion_function, free the contents of match_list,
+         because that function does not keep state and will not free the
+         entries; avoids possible memory leak pointed out by
+         Garrett Cooper <yanegomi@gmail.com>
+       - gen_completion_matches: if RL_SIG_RECEIVED evalutes to true after
+         calling rl_attempted_completion_function, free the returned match
+         list and handle the signal with RL_CHECK_SIGNALS; avoids
+         possible memory leak pointed out by Garrett Cooper
+         <yanegomi@gmail.com>
+       - gen_completion_matches: if RL_SIG_RECEIVED evaluates to true after
+         calling rl_completion_matches, free the returned match list and
+         handle the signal with RL_CHECK_SIGNALS
+
+lib/readline/util.c
+       - rl_settracefp: new utility function to set the tracing FILE *
+
+lib/readline/signals.c
+       - _rl_sigcleanup: pointer to a function that will be called with the
+         signal and a void * argument from _rl_handle_signal
+       - _rl_sigcleanarg: void * that the rest of the code can set to have
+         passed to the signal cleanup function
+       - _rl_handle_signal: if _rl_sigcleanup set, call as
+               (*_rl_sigcleanup) (sig, _rl_sigcleanarg)
+
+lib/readline/rlprivate.h
+       - extern declarations for _rl_sigcleanup and _rl_sigcleanarg
+
+lib/readline/complete.c
+       - _rl_complete_sigcleanup: signal cleanup function for completion code;
+         calls _rl_free_match_list on _rl_sigcleanarg if signal == SIGINT
+       - rl_complete_internal: before calling display_matches if what_to_do
+         == `?', set _rl_sigcleanup to _rl_complete_sigcleanup so the match
+         list gets freed on SIGINT; avoids possible memory leak pointed out
+         by Garrett Cooper <yanegomi@gmail.com>
+       - rl_complete_internal: in default switch case, call _rl_free_match_list
+         before returning to avoid memory leak
+
+doc/bashref.texi
+       - start at a set of examples for the =~ regular expression matching
+         operator, touching on keeping the pattern in a shell variable and
+         quoting portions of the pattern to remove their special meaning
+
+                                  12/1
+                                  ----
+lib/glob/gmisc.c
+       - extglob_pattern: new function, returns 1 if pattern passed as an
+         argument looks like an extended globbing pattern
+
+lib/glob/glob.c
+       - skipname: return 0 immediately if extglob_pattern returns non-zero,
+         let the extended globbing code do the right thing with skipping
+         names beginning with a `.'
+       - mbskipname: return 0 immediately if extglob_pattern returns non-zero,
+         let the extended globbing code do the right thing with skipping
+         names beginning with a `.'.  Fixes bug reported by Yongzhi Pan
+         <panyongzhi@gmail.com>
+
+                                  12/2
+                                  ----
+lib/glob/smatch.c
+       - patscan, patscan_wc: no longer static so other parts of the glob
+         library can use them, renamed to glob_patscan, glob_patscan_wc
+
+lib/glob/glob.c
+       - extern declarations for glob_patscan, glob_patscan_wc
+       - wchkname: new function, does skipname on wchar_t pattern and dname,
+         old body of mbskipname after converting to wide chars
+       - extglob_skipname: new function, checks all subpatterns in an extglob
+         pattern to determine whether or not a filename should be skipped.
+         Calls skipname for each subpattern.  Dname is only skipped if all
+         subpatterns indicate it should be.  Better fix for bug reported by
+         Yongzhi Pan <panyongzhi@gmail.com>
+       - wextglob_skipname: wide-char version of extglob_skipname, calls
+         wchkname instead of calling back into mbskipname for each
+         subpattern to avoid problems with char/wchar_t mismatch
+       - skipname: call extglob_skipname if extglob_pattern returns non-zero
+       - mbskipname: call wextglob_skipname if extglob_pattern returns non-zero
+       - mbskipname: short-circuit immediately if no multibyte chars in
+         pattern or filename
+
+execute_cmd.c
+       - execute_cond_node: added parens to patmatch assignment statement to
+         make intent clearer
+
+                                  12/3
+                                  ----
+configure.in,config.h.in
+       - check for imaxdiv, define HAVE_IMAXDIV if present
+
+expr.c
+       - expassign, exp2: use imaxdiv if available.  Doesn't help with checks
+         for overflow from 10/25
+
+                                  12/6
+                                  ----
+lib/readline/complete.c
+       - compute_lcd_of_matches: if we're ignoring case in the matches, only
+         use what the user typed as the lcd if it matches the first match
+         (after sorting) up to the length of what was typed (if what the
+         user typed is longer than the shortest of the possible matches, use
+         the shortest common length of the matches instead).  If it doesn't
+         match, use the first of the list of matches, as if case were not
+         being ignored.  Fixes bug reported by Clark Wang
+         <dearvoid@gmail.com>
+
+                                  12/7
+                                  ----
+builtins/cd.def
+       - cd_builtin: add code to return error in case cd has more than one
+         non-option argument, conditional on CD_COMPLAINS define (which is
+         not defined anywhere)
+
+doc/{bash.1,bashref.texi}
+       - note that additional arguments to cd following the directory name
+         are ignored.  Suggested by Vaclav Hanzl <hanzl@noel.feld.cvut.cz>
+
+                                  12/10
+                                  -----
+lib/readline/input.c
+       - rl_read_key: don't need to increment key sequence length here; doing
+         it leads to an off-by-one error
+
+lib/readline/macro.c
+       - rl_end_kbd_macro: after off-by-one error with rl_key_sequence_length
+         fixed, can decrement current_macro_index by rl_key_sequence_length
+         (length of key sequence that closes keyboard macro)
+
+lib/readline/readline.c
+       - _rl_dispatch_subseq: fix extra increment of rl_key_sequence_length
+         when ESC maps to a new keymap and we're converting meta characters
+         to ESC+key
+       - _rl_dispatch_subseq: better increment of rl_key_sequence_length
+         before we dispatch to a function in the ISFUNC case (where the
+         second increment above should have happened)
+       - rl_executing_keyseq: the full key sequence that ended up executing
+         a readline command.  Available to the calling application, maintained
+         by _rl_dispatch_subseq, indexed by rl_key_sequence_length
+       - rl_executing_key: the key that was bound to the currently-executing
+         readline command.  Same as the `key' argument to the function
+
+lib/readline/readline.h
+       - rl_executing_keyseq: extern declaration
+       - rl_executing_key: extern declaration
+       - rl_key_sequence_length: declaration moved here from rlprivate.h,
+         now part of public interface
+
+lib/readline/rlprivate.h
+       - new extern declaration for _rl_executing_keyseq_size, buffer size
+         for rl_executing_keyseq
+
+lib/readline/doc/rltech.texi
+       - documented new variables: rl_executing_key, rl_executing_keyseq,
+         rl_key_sequence_length
+
+                                  12/13
+                                  -----
+bashline.c
+       - bash_execute_unix_command: replace ad-hoc code that searches
+         cmd_xmap for correct command with call to rl_function_of_keyseq
+         using rl_executing_keyseq; now supports key sequences longer
+         than two characters.  Fixes bug reported by Michael Kazior
+         <kazikcz@gmail.com>
+
+                                  12/15
+                                  -----
+make_cmd.c
+       - make_function_def: don't null out source_file before calling
+         make_command so it can be used later on when the function definition
+         is executed
+
+execute_cmd.c
+       - execute_intern_function: second argument is now FUNCTION_DEF *
+         instead of COMMAND *
+       - execute_command_internal: call execute_intern_function with the
+         new second argument (the entire FUNCTION_DEF instead of just the
+         command member)
+       - execute_intern_function: if DEBUGGER is defined, call
+         bind_function_def before calling bind_function, just like
+         make_function_def does (might be able to take out the call in
+         make_function_def depending on what the debugger does with it).
+         Fixes bug reported by <dethrophes@motd005>
+
+expr.c
+       - more minor changes to cases of INTMAX_MIN % -1 and INTMAX_MIN / 1;
+         fix typos and logic errors
+
+                                  12/16
+                                  -----
+bashline.c
+       - find_cmd_start: change flags to remove SD_NOSKIPCMD so it skips over
+         command substitutions and doesn't treat them as command separators
+       - attempt_shell_completion: instead of taking first return from
+         find_cmd_name as command name to use for programmable completion,
+         use loop to skip over assignment statements.  Fixes problem reported
+         by Raphael Droz <raphael.droz+floss@gmail.com>
+       - attempt_shell_completion: if we don't find a command name but the
+         command line is non-empty, assume the other words are all assignment
+         statements and flag that point is in a command position so we can
+         do command name completion
+       - attempt_shell_completion: if the word being completed is the first
+         word following a series of assignment statements, and the
+         command line is non-empty, flag that point is in a command position
+         so we can do command name completion
+
+lib/readline/history.c
+       - history_get_time: atol -> strtol
+
+                                  12/18
+                                  -----
+parse.y
+       - parser_in_command_position: external interface to the
+         command_token_position macro for use by other parts of the shell,
+         like the completion mechanism
+
+externs.h
+       - extern declaration for parser_in_command_position
+
+                                  12/19
+                                  -----
+
+builtins/read.def
+       - read_builtin: make sure all calls to bind_read_variable are passed
+         a non-null string.  Fixes bug reported by Dan Douglas
+         <ormaaj@gmail.com>
+
+bashline.c
+       - attempt_shell_completion: mark that we're in a command position if
+         we're at the start of the line and the parser is ready to accept
+         a reserved word or command name.  Feature most recently suggested
+         by Peng Yu <pengyu.ut@gmail.com>
+
+                                  12/21
+                                  -----
+lib/readline/bind.c
+       - _rl_escchar: return the character that would be backslash-escaped
+         to denote the control character passed as an argument ('\n' -> 'n')
+       - _rl_isescape: return 1 if character passed is one that has a
+         backslash escape
+       - _rl_untranslate_macro_value: new second argument: use_escapes, if
+         non-zero translate to backslash escapes where possible instead of
+         using straight \C-x for control character `x'.  Change callers
+       - _rl_untranslate_macro_value: now global
+
+lib/readline/rlprivate.h
+       - _rl_untranslate_macro_value: extern declaration
+
+lib/readline/{macro.c,readline.h}
+       - rl_print_last_kbd_macro: new bindable function, inspired by patch
+         from Mitchel Humpherys
+
+lib/readline/funmap.c
+       - print-last-kbd-macro: new bindable command, bound to
+         rl_print_last_kbd_macro
+
+lib/readline/doc/{rluser.texi,readline.3},doc/bash.1
+       - print-last-kbd-macro: document.
+
+lib/readline/text.c
+       - _rl_insert_next: if we're defining a macro, make sure the key gets
+         added to the macro text (should really audit calls to rl_read_key()
+         and make sure the right thing is happening for all of them)
+
+bashline.[ch]
+       - print_unix_command_map: new function, prints all bound commands in
+         cmd_xmap using rl_macro_dumper in a reusable format
+
+builtins/bind.def
+       - new -X option: print all keysequences bound to Unix commands using
+         print_unix_command_map.  Feature suggested by Dennis Williamson
+         (2/2011)
+
+doc/{bash.1,bashref.texi}
+       - document new `bind -X' option
+
+                                  12/24
+                                  -----
+
+doc/{bash.1,bashref.texi}
+       - add a couple of sentences to the description of the case modification
+         operators making it clearer that each character of parameter is
+         tested against the pattern, and that the pattern should only attempt
+         to match a single character.  Suggested by Bill Gradwohl
+         <bill@ycc.com>
+
+                                  12/28
+                                  -----
+shell.c
+       - init_noninteractive: instead of calling set_job_control(0) to
+         unconditionally turn off job control, turn on job control if
+         forced_interactive or jobs_m_flag is set
+       - shell_initialize: call initialize_job_control with jobs_m_flag as
+         argument so `bash -m script' enables job control while running the
+         script
+
+jobs.c
+       - initialize_job_control: if the `force' argument is non-zero, turn on
+         job control even if the shell is not currently interactive
+         (interactive == 0)
+
+                                  12/29
+                                  -----
+
+flags.h
+       - new extern declaration for jobs_m_flag
+
+builtins/{cd,set}.def,doc/{bash.1,bashref.texi}
+       - added text clarifying the descriptions of cd -L and -P, suggested by
+         Padraig Brady <p@draigbrady.com>
+       - slight change to the description of `set -P' about resolving symbolic
+         links
+
+lib/readline/doc/rluser.texi
+       - Added an example to the programmable completion section: _comp_cd,
+         a completion function for cd, with additional verbiage.  Text
+         includes a reference to the bash_completion project
+
+                                1/1/2012
+                                --------
+jobs.c
+       - set_job_status_and_cleanup: note that a job is stopped due to
+         SIGTSTP (any_tstped) if job_control is set; there's no need to
+         test interactive
+
+                                   1/5
+                                   ---
+quit.h
+       - LASTSIG(): new macro, expands to signal number of last terminating
+         signal received (terminating_signal or SIGINT)
+
+trap.c
+       - first_pending_trap: returns lowest signal number with a trap pending
+       - trapped_signal_received: set to the last trapped signal the shell
+         received in trap_handler(); reset to 0 in run_pending_traps
+
+builtins/read.def
+       - read_builtin: changes to posix-mode (posixly_correct != 0) to make
+         `read' interruptible by a trapped signal.  After the trap runs,
+         read returns 128+sig and does not assign the partially-read line
+         to the named variable(s).  From an austin-group discussion started
+         by David Korn
+
+                                  1/11
+                                  ----
+doc/{bash.1,bashref.texi}
+       - slight changes to the descriptions of the compat32 and compat40 shell
+         options to clarify their meaning
+
+                                  1/12
+                                  ----
+lib/readline/{colors.[ch],parse-colors.[ch]}
+       - new files, part of color infrastructure support
+
+Makefile.in,lib/readline/Makefile.in
+       - arrange to have colors.o and parse-colors.o added to readline
+         library
+
+{configure,config.h}.in
+       - check for stdbool.h, define HAVE_STDBOOL_H if found
+
+                                  1/14
+                                  ----
+lib/readline/bind.c
+       - colored_stats: new bindable variable, enables using colors to
+         indicate file type when listing completions
+
+lib/readline/complete.c
+       - _rl_colored_stats: new variable, controlled by colored-stats bindable
+         variable
+       - colored_stat_start, colored_stat_end: new functions to set and reset
+         the terminal color appropriately depending on the type of the
+         filename to be printed
+       - print_filename: changes to print colors if `colored-stats' variable
+         set.  Changes contributed by Raphael Droz
+         <raphael.droz+floss@gmail.com>
+
+lib/readline/readline.c
+       - rl_initialize_everything: add call to _rl_parse_colors to parse
+         color values out of $LS_COLORS.  May have to add to rl_initialize
+         to make more dynamic if LS_COLORS changes (which doesn't happen
+         very often, if at all)
+
+lib/readline/rlprivate.h
+       - _rl_colored_stats: new extern declaration
+
+lib/readline/doc/{readline.3,rluser.texi},doc/bash.1
+       - colored-stats: document new bindable readline variable
+
+lib/readline/colors.c
+       - _rl_print_color_indicator: call rl_filename_stat_hook before calling
+         lstat/stat so we can get color indicators for stuff like
+         $HOME/Applications
+
+lib/readline/complete.c
+       - stat_char: call rl_filename_stat_hook before calling lstat/stat
+
+findcmd.[ch],execute_cmd.c
+       - search_for_command: now takes a second `flags' argument; changed
+         header function prototype and callers
+       - search_for_command: if (flags & 1), put the command found in $PATH
+         into the command hash table (previous default behavior)
+
+execute_cmd.c
+       - is_dirname: call search_for_command with flags argument of 0 so it
+         doesn't try to put something in the command hash table
+
+bashline.c
+       - bash_command_name_stat_hook: a hook function for readline's
+         filename_stat_hook that does $PATH searching the same way that
+         execute_cmd.c:execute_disk_command() does it, and rewrites the
+         passed filename if found.  Does not put names into command hash
+         table.  This allows command name completion to take advantage
+         of `visible-stats' and `colored-stats' settings.
+       - executable_completion: new function, calls the directory completion
+         hook to expand the filename before calling executable_file or
+         executable_or_directory; change command_word_completion_function to
+         call executable_completion.  This allows $HOME/bin/[TAB] to do
+         command completion and display alternatives
+
+                                  1/17
+                                  ----
+pcomplete.c
+       - gen_command_matches: now takes a new second argument: the command
+         name as deciphered by the programmable completion code and used
+         to look up the compspec; changed callers (gen_compspec_completions)
+       - gen_shell_function_matches: now takes a new second argument: the
+         command that originally caused the completion function to be
+         invoked; changed callers (gen_compspec_completions))
+       - build_arg_list: now takes a new second argument: the command name
+         corresponding to the current compspec; changed callers
+         (gen_command_matches, gen_shell_function_matches)
+       - build_arg_list: now uses `cmd' argument to create $1 passed to
+         invoked command or shell function
+       - gen_compspec_completions: if we skipped a null command at the
+         beginning of the line (e.g., for completing `>'), add a new word for
+         it at the beginning of the word list and increment nw and cw
+         appropriately.  This is all a partial fix for the shortcoming
+         pointed out by Sung Pae <sungpae@gmail.com>
+
+                                  1/18
+                                  ----
+
+{configure,config.h}.in
+       - new check: check for AUDIT_USER_TTY defined in <linux/audit.h>,
+         define HAVE_DECL_AUDIT_USER_TTY if both are found
+
+lib/readline/rlconf.h
+       - ENABLE_TTY_AUDIT_SUPPORT: new define, allows use of the Linux kernel
+         tty auditing system if it's available and enabled
+
+lib/readline/util.c
+       - _rl_audit_tty: new function, send a string to the kernel tty audit
+         system
+
+lib/readline/rlprivate.h
+       - _rl_audit_tty: new extern declaration
+
+lib/readline/readline.c
+       - readline: call _rl_audit_tty with line to be returned before returning
+         it if the Linux tty audit system is available and it's been enabled
+         in rlconf.h  Original patch from Miroslav Trmac; recent request
+         from Miroslav Lichvar <mlichvar@redhat.com>
+
+                                  1/21
+                                  ----
+
+lib/readline/readline.c:
+       - _rl_dispatch_subseq: add an inter-character timeout for multi-char
+         key sequences.  Suggested by <rogerx.oss@gmail.com>.  Still needs
+         work to make a user-settable variable
+
+parse.y
+       - shell_getc: make code that uses the pop_alias dependent on ALIAS
+         define
+
+variables.h
+       - sv_tz: extern define should only depend on HAVE_TZSET
+
+expr.c
+       - expr_streval: if ARRAY_VARS is not defined, set lvalue->ind to -1;
+         move assignment to `ind' inside define
+       - expr_bind_array_element: declaration and uses need to be #ifdef
+         ARRAY_VARS
+
+arrayfunc.h
+       - AV_ALLOWALL, AV_QUOTED, AV_USEIND: define to 0 if ARRAY_VARS not
+         defined; used in subst.c unconditionally
+
+sig.h
+       - make the signal blocking functions not dependent on JOB_CONTROL
+
+sig.c
+       - sigprocmask: make the replacement definition not dependent on
+         JOB_CONTROL
+
+trap.c
+       - use BLOCK_SIGNAL/UNBLOCK_SIGNAL instead of code dependent on
+         HAVE_POSIX_SIGNALS and BSD signals
+
+                                  1/24
+                                  ----
+
+print_cmd.c
+       - print_redirection_list: change the conditions under which
+         r_duplicating_output_word is mapped to r_err_and_out to more or
+         less match those used in redir.c.  Fixes bug pointed out by
+         Dan Douglas <ormaaj@gmail.com>
+
+
+                                  1/29
+                                  ----
+lib/readline/signals.c
+       - _rl_block_sigwinch,_rl_release_sigwinch: don't compile in bodies
+         unless SIGWINCH is defined.  Fixes bug reported by Pierre Muller
+         <pierre.muller@ics-cnrs.unistra.fr>
+
+doc/{bash.1,bashref.texi}
+       - small modifications to the introduction to the REDIRECTION section
+         to describe how redirections can modify file handles
+       - small modification to the section describing base#n to make it
+         clearer that n can be denoted using non-numerics.  From a posting
+         by Linda Walsh <bash@tlinx.org>
+
+                                   2/2
+                                   ---
+builtins/printf.def
+       - printf_builtin: make sure vbuf is intialized and non-null when -v
+         is supplied, since other parts of the code assume that it's not
+         null (e.g., bind_printf_variable()).  Fixes bug reported by Jim
+         Avera <james_avera@yahoo.com>
+
+                                   2/4
+                                   ---
+lib/readline/undo.c
+       - _rl_free_undo_list: new function, old body of rl_free_undo_list,
+         frees undo entries in UNDO_LIST * passed as argument
+       - rl_free_undo_list: call _rl_free_undo_list
+
+lib/readline/rlprivate.h
+       - _rl_free_undo_list: new extern declaration
+       - _rl_keyseq_timeout: new extern declaration (see below)
+
+lib/readline/misc.c
+       - rl_clear_history: new function.  Clears the history list and frees
+         all associated data similar to history.c:clear_history(), but
+         takes rl_undo_list into account and frees and UNDO_LISTs saved as
+         `data' members of a history list entry
+
+lib/readline/doc/rltech.texi
+       - rl_clear_history: documented
+
+lib/readline/readline.c
+       - _rl_keyseq_timeout: new variable to hold intra-key timeout value
+         from 1/21 fix; specified in milliseconds.  Default value is 500
+       - _rl_dispatch_subseq: change to use _rl_keyseq_timeout as intra-key
+         timeout if it's greater than 0; no timeout if <= 0
+       - _rl_dispatch_subseq: don't check for queued keyboard input if we have
+         pushed or pending input, or if we're reading input from a macro
+
+lib/readline/bind.c
+       - keyseq-timeout: new bindable variable, shadows _rl_keyseq_timeout
+       - string_varlist: add keyseq-timeout
+       - sv_seqtimeout: new function to modify value of _rl_keyseq_timeout;
+         clamps negative values at 0 for now
+       - _rl_get_string_variable_value: return value for keyseq-timeout
+
+doc/bash.1,lib/readline/doc/{rluser.texi,readline.3}
+       - keyseq-timeout: documented
+
+lib/readline/isearch.c
+       - _rl_isearch_dispatch: modification to fix from 7/18 to not use
+         cxt->keymap and cxt->okeymap, since by the time this code is
+         executed, they are equal.  Use `f' to check for rl_insert or
+         unbound func
+       - _rl_isearch_dispatch: if we're switching keymaps, not in
+         callback mode, and don't have pending or pushed input, use
+         _rl_input_queued to resolve a potentially ambiguous key sequence.
+         Suggested by Roger Zauner <rogerx.oss@gmail.com>
+       - _rl_isearch_dispatch: if we have changed keymaps and resolved to
+         an editing function (not self-insert), make sure we stuff the
+         right characters back onto the input after changing the keymap
+         back so the right editing function is executed after the search
+         is terminated.  Rest of fix for bug reported by Roger Zauner
+         <rogerx.oss@gmail.com>
+
+                                   2/5
+                                   ---
+builtins/gen-helpfiles.c
+       - new file: reads struct builtin and writes the long docs to files
+         in the `helpdirs' subdirectory.  The filename is given in the
+         previously-unused `handle' member of the struct builtin.  Links
+         with `tmpbuiltins.o', which is created by Makefile to have the
+         right long documentation.  When not cross-compiling, gets the
+         right #defines based on configuration options from config.h instead
+         of trying to parse conditional parts of def files.  Fixes
+         shortcoming pointed out by Andreas Schwab <schwab@linux-m68k.org>
+
+builtins/Makefile.in
+       - tmpbuiltins.c: new generated file, created to enable creation of
+         separate helpfiles based on correct #defines instead of trying to
+         parse conditional parts of def files
+       - gen-helpfiles: new program to generate helpfiles, links with
+         tmpbuiltins.o
+       - HELPFILES_TARGET: new target, substituted by configure to `helpdoc'
+         if separate helpfiles requested
+       - targets: new target, libbuiltins.a and $(HELPFILES_TARGET)
+       - CREATED_OBJECTS: new variable, holds created object files for
+         make clean; changed make clean to remove created objects
+       - helpdoc: changed to call gen-helpfiles instead of mkbuiltins
+
+Makefile.in
+       - when building libbuiltins.a, recursively call make with `targets'
+         argument to make sure separate helpfiles get built
+
+configure.in
+       - substitute `helpdoc' as value of HELPFILES_TARGET if
+         --enable-separate-helpfiles supplied as configure argument
+
+builtins/mkbuiltins.c
+       - `-nofunctions': new argument, causes mkbuiltins to not write value
+         for function implementing a particular builtin to struct builtin
+         and to write document file name to `handle' member of struct builtin
+       - no longer writes separate helpfiles; that is left to gen-helpfiles
+
+                                   2/8
+                                   ---
+subst.c
+       - make sure last_command_exit_value is set to a non-zero value before
+         any calls to report_error, since `-e' set will short-circuit
+         report_error.  Fixes bug reported by Ewan Mellor
+         <Ewan.Mellor@eu.citrix.com>
+
+variables.c
+       - make_local_array_variable: added second argument; if non-zero,
+         function will return an existing local associative array variable
+         instead of insisting on an indexed array
+
+variable.h,subst.c
+       - make_local_array_variable: changed prototype and caller
+
+builtins/declare.def
+       - declare_internal: add second arg to call to make_local_array_variable;
+         making_array_special, which indicates we're processing an
+         assignment like declare a[b]=c.  Fixes seg fault resulting from
+         a being an already-declared local associative array variable in a
+         function.  Ubuntu bash bug 928900.
+
+                                  2/14
+                                  ----
+
+execute_cmd.c
+       - execute_command_internal: if redirections into or out of a loop fail,
+         don't try to free ofifo_list unless saved_fifo is non-zero.  It's
+         only valid if saved_fifo is set
+
+                                  2/15
+                                  ----
+{arrayfunc,braces,variables}.c
+       - last_command_exit_value: make sure it's set before any calls to
+         report_error, since -e will cause that to exit the shell
+
+builtins/common.c
+       - get_job_by_name: call internal_error instead of report_error so this
+         doesn't exit the shell
+
+                                  2/18
+                                  ----
+builtins/evalstring.c
+       - parse_and_execute: make sure the file descriptor to be redirected to
+         is 1 before calling cat_file.  One fix for bug reported by Dan Douglas
+         <ormaaj@gmail.com>
+
+parse.y
+       - read_token_word: don't return NUMBER if a string of all digits
+         resolves to a number that overflows the bounds of an intmax_t.
+         Other fix for bug reported by Dan Douglas <ormaaj@gmail.com>
+
+                                  2/19
+                                  ----
+lib/sh/strtrans.c
+       - ansicstr: use 0x7f as the boundary for characters that translate
+         directly from ASCII to unicode (\u and \U escapes) instead of
+         UCHAR_MAX, since everything >= 0x80 requires more than one byte.
+         Bug and fix from John Kearney <dethrophes@web.de>
+
+builtins/printf.def
+       - tescape: ditto for printf \u and \U escape sequences
+
+                                  2/20
+                                  ----
+lib/sh/unicode.c
+       - u32toutf8: fix to handle encodings up to six bytes long correctly
+         (though technically UTF-8 only has characters up to 4 bytes long).
+         Report and fix from John Kearney <dethrophes@web.de>
+       - u32toutf8: first argument is now an unsigned 32-bit quantity,
+         changed callers (u32cconv) to pass c instead of wc
+       - u32reset: new function, resets local static state to uninitialized
+         (locale information, currently)
+
+locale.c
+       - call u32reset whenever LC_CTYPE/LC_ALL/LANG is changed to reset the
+         cached locale information used by u32cconv.  From a report from
+         John Kearney <dethrophes@web.de>
+
+                                  2/21
+                                  ----
+doc/{bash,builtins}.1
+       - minor changes from Bjarni Ingi Gislason <bjarniig@rhi.hi.is>
+
+lib/sh/unicode.c
+       - u32cconv: only assume you can directly call wctomb on the passed
+         value if __STDC_ISO_10646__ is defined and the value is <=
+         0x7fffffff
+       - stub_charset: return locale as default instead of "ASCII", let
+         rest of code decide what to do with it
+
+lib/readline/parens.c
+       - _rl_enable_paren_matching: make paren matching work in vi insert
+         mode.  Bug report from <derflob@derflob.de>
+
+                                  2/22
+                                  ----
+lib/sh/shquote.c
+       - sh_backslash_quote: quote tilde in places where it would be
+         expanded.  From a report from John Kearney <dethrophes@web.de>
+
+                                  2/23
+                                  ----
+execute_cmd.c
+       - execute_pipeline: wrap the discard_unwind_frame call in #ifdef
+         JOB_CONTROL, since the frame is only created if JOB_CONTROL is
+         defined.  Bug and fix from Doug Kehn <rdkehn@yahoo.com>
+
+                                  2/25
+                                  ----
+error.c
+       - report_error: make sure last_command_exit_value is non-zero before
+         we call exit_shell, since the exit trap may reference it.  Call
+         exit_shell with last_command_exit_value to allow exit statuses
+         other than 1
+
+unicode.c
+       - stub_charset: use local static buffer to hold charset, don't change
+         value returned by get_locale_var.  Based on idea and code from
+         John Kearney <dethrophes@web.de>
+       - u32toutf16: function to convert unsigned 32-bit value (unicode) to
+         UTF-16.  From John Kearney <dethrophes@web.de>
+       - u32cconv: call u32toutf16 if __STDC_ISO_10646__ defined and wchar_t
+         is two bytes, send result to wcstombs, return if not encoding error.
+         From John Kearney <dethrophes@web.de>
+       - u32cconv: return UTF-8 conversion if iconv conversion to local
+         charset is unsupported
+
+                                   3/2
+                                   ---
+lib/readline/complete.c
+       - print_filename: if there is no directory hook, but there is a stat
+         hook, and we want to append a slash to directories, call the stat
+         hook before calling path_isdir on the expanded directory name.
+         Report and pointer to fix from Steve Rago <sar@nec-labs.com>
+
+                                   3/3
+                                   ---
+builtins/evalstring.c
+       - parse_and_execute: fix to change of 2/18: make sure the file
+         descriptor being redirected to is 0 before calling cat_file when
+         we see something like $(< file).  Real fix for bug reported by
+         Dan Douglas <ormaaj@gmail.com>
+
+subst.c
+       - parameter_brace_patsub: run the replacement string through quote
+         removal even if the expansion is within double quotes, because
+         the parser and string extract functions treat the quotes and
+         backslashes as special.  If they're treated as special, quote
+         removal should remove them (this is the Posix position and
+         compatible with ksh93).  THIS IS NOT BACKWARDS COMPATIBLE.
+
+                                   3/4
+                                   ---
+lib/readline/complete.c
+       - rl_menu_complete: fix to make show-all-if-ambiguous and
+         menu-complete-display-prefix work together if both are set.  Fix
+         from Sami Pietila <sami.pietila@gmail.com>
+
+                                   3/5
+                                   ---
+bashline.c
+       - dircomplete_expand_relpath: new variable, if non-zero, means that
+         `shopt -s direxpand' should expand relative pathnames.  Zero by
+         default, not user-settable yet
+       - bash_directory_completion_hook: if we have a relative pathname that
+         isn't changed by canonicalization or spell checking after being
+         appended to $PWD, then don't change what the user typed.  Controlled
+         by dircomplete_expand_relpath
+
+                                   3/7
+                                   ---
+m4/timespec.m4
+       - new macros, cribbed from gnulib and coreutils: find out whether we
+         have `struct timespec' and what file includes it
+
+m4/stat-time.m4
+       - new macros, cribbed from gnulib and coreutils: find out whether the
+         mtime/atime/ctime/etctime fields of struct stat are of type
+         struct timespec, and what the name is
+
+include/stat-time.h
+       - new file, cribbed from gnulib, with additions from coreutils: include
+         the right file to get the struct timespec define, or provide our own
+         replacement.  Provides a bunch of inline functions to turn the
+         appropriate members of struct stat into `struct timespec' values,
+         zeroing out the tv_nsec field if necessary
+
+test.c
+       - include "stat-time.h" for the nanosecond timestamp resolution stuff
+       - stat_mtime: new function, returns struct stat and the mod time
+         normalized into a `struct timespec' for the filename passed as the
+         first argument
+       - filecomp: call stat_mtime instead of sh_stat for each filename
+         argument to get the mtime as a struct timespec
+       - filecomp: call timespec_cmp instead of using a straight arithmetic
+         comparison for the -nt and -ot operators, using timespec returned by
+         stat_mtime.  Added functionality requested by by Werner Fink
+         <werner@suse.de> for systems that can support it
+
+                                  3/10
+                                  ----
+include/posixdir.h
+       - REAL_DIR_ENTRY: remove dependency on _POSIX_SOURCE, only use feature
+         test macros to decide whether dirent.d_ino is present and usable;
+         define D_INO_AVAILABLE.  Report and fix from Fabrizion Gennari
+         <fabrizio.ge@tiscali.it>
+       - D_FILENO_AVAILABLE: define if we can use dirent.d_fileno
+
+lib/sh/getcwd.c
+       - use D_FILENO_AVAILABLE to decide whether or not to compile in
+         _path_checkino and whether or not to call it.  Report and initial
+         fix from Fabrizion Gennari <fabrizio.ge@tiscali.it>
+
+lib/readline/signals.c
+       - make sure all occurrences of SIGWINCH are protected by #ifdef
+
+sig.c
+       - make sure all occurrences of SIGCHLD are protected by #ifdef
+
+nojobs.c
+       - make sure SA_RESTART is defined to 0 if the OS doesn't define it
+
+version.c
+       - show_shell_version: don't use string literals in printf, use %s.
+         Has added benefit of removing newline from string to be translated
+
+trap.c
+       - queue_sigchld_trap: new function, increments the number of pending
+         SIGCHLD signals by the argument, which is by convention the number
+         of children reaped in a call to waitchld()
+
+trap.h
+       - queue_sigchld_trap: new extern declaration
+
+jobs.c
+       - waitchld: if called from the SIGCHLD signal handler (sigchld > 0),
+         then call queue_sigchld_trap to avoid running the trap in a signal
+         handler context.  Report and original fix from Siddhesh Poyarekar
+         <siddhesh@redhat.com>
+
+lib/sh/unicode.c
+       - u32tocesc: take an unsigned 32-bit quantity and encode it using
+         ISO C99 string notation (\u/\U)
+       - u32cconv: call u32tocesc as a fallback instead of u32cchar
+       - u32cconv: call u32tocesc if iconv cannot convert the character.
+         Maybe do the same thing if iconv_open fails
+       - u32reset: call iconv_close on localconv if u32init == 1
+
+                                  3/11
+                                  ----
+config-top.h
+       - CHECKWINSIZE_DEFAULT: new define, set to initial value of
+         check_window_size (shopt checkwinsize): 0 for off, 1 for on.
+         Default is 0
+
+{jobs,nojobs}.c
+       - check_window_size: default initial value to CHECKWINSIZE_DEFAULT
+
+                                  3/13
+                                  ----
+doc/bashref.texi
+       - change text referring to the copying restrictions to that
+         recommended by the FSF (no Front-Cover Texts and no Back-Cover
+         Texts)
+
+lib/readline/doc/{history,rlman,rluserman}.texi
+       - change text referring to the copying restrictions to that
+         recommended by the FSF (no Front-Cover Texts and no Back-Cover
+         Texts)
+
+                                  3/15
+                                  ----
+array.c
+       - LASTREF_START: new macro to set the starting position for an array
+         traversal to `lastref' if that's valid, and to the start of the array
+         if not.  Used in array_reference, array_insert, array_remove
+       - array_remove: try to be a little smarter with lastref instead of
+         unconditionally invalidating it
+
+                                  3/16
+                                  ----
+array.c
+       - array_insert: fix memory leak by deleting element to be added in the
+         case of an error
+
+                                  3/18
+                                  ----
+lib/sh/mbschr.c
+       - mbschr: don't call mbrlen unless is_basic is false; devolves to a
+         straight character-by-character run through the string
+
+                                  3/19
+                                  ----
+stringlib.c
+       - substring: use memcpy instead of strncpy, since we know the length
+         and are going to add our own NUL terminator
+
+                                  3/20
+                                  ----
+subst.c
+       - parameter_brace_expand_rhs: if expand_string_for_rhs returns a quoted
+         null string (a list with one element for which
+         QUOTED_NULL(list->word->word) returns true), return the quoted null
+         and set the flags in the returned word to indicate it.  Fixes bug
+         reported by Mark Edgar <medgar123@gmail.com>
+
+lib/sh/tmpfile.c
+       - use random(3) instead of get_random_number to avoid perturbing the
+         random sequence you get using $RANDOM.  Bug report and fix from
+         Jurij Mihelic <jurij.mihelic@fri.uni-lj.si>
+
+                                  3/21
+                                  ----
+config-top.h
+       - OPTIMIZE_SEQUENTIAL_ARRAY_ASSIGNMENT: define to 1 to optimize
+         sequential indexed array assignment patterns.  Defined to 1 by
+         default
+
+array.c
+       - array_insert: if OPTIMIZE_SEQUENTIAL_ARRAY_ASSIGNMENT is defined,
+         start the search at lastref (see change from 3/15)
+
+                                  3/27
+                                  ----
+print_cmd.c
+       - debug_print_word_list: new debugging function, prints a word list
+         preceded by an optional string and using a caller-specified
+         separator
+
+                                   4/1
+                                   ---
+command.h
+       - W_ASSNGLOBAL: new flag, set to indicate declare -g
+
+execute_cmd.c
+       - fix_assignment_words: note that we have a -g argument to an assignment
+         builtin and set the W_ASSNGLOBAL flag in the variable word
+
+subst.c
+       - dump_word_flags: print out W_ASSNGLOBAL if present
+       - do_assignment_internal: only set ASS_MKLOCAL if W_ASSIGNARG is set
+         and W_ASSNGLOBAL is not.  Don't want to create a local variable even
+         if variable_context is non-zero if ASSNGLOBAL is set.  Fixes bug
+         reported by Bill Gradwohl <bill@ycc.com>
+
+                                   4/7
+                                   ---
+lib/readline/readline.c
+       - _rl_dispatch_subseq: make the `keyseq-timeout' variable apply to
+         ESC processing when in vi mode.  After hitting ESC, readline will
+         wait up to _rl_keyseq_timeout*1000 microseconds (if set) for
+         additional input before dispatching on the ESC and switching to
+         command/movement mode.  Completes timeout work suggested by
+         <rogerx.oss@gmail.com>; this prompted by report from Barry Downes
+         <barry.downes@gmail.com>
+
+lib/sh/shmbchar.c
+       - sh_mbsnlen: new function, returns the number of (possibly multibyte)
+         characters in a passed string with a passed length, examining at most
+         maxlen (third argument) bytes
+
+externs.h
+       - sh_mbsnlen: extern declaration for new function
+
+shell.c
+       - exit_shell: call maybe_save_shell_history if remember_on_history is
+         set, not just in interactive shells.  That means the history is
+         saved if history is enabled, regardless of whether or not the shell
+         is interactive
+
+doc/{bash.1,bashref.texi}
+       - TMOUT: fix description to make it explicit that TMOUT is the timeout
+         period for a complete line of input, not just any input.  Fixes
+         problem reported in Ubuntu bug 957303:
+         https://bugs.launchpad.net/ubuntu/+source/bash/+bug/957303
+       - HISTFILE: document change to write history list to history file in
+         any shell with history enabled, not just interactive shells.  This
+         seems to be more logical behavior.  Suggested by Greg Wooledge
+         <wooledg@eeg.ccf.org>
+
+                                  4/12
+                                  ----
+lib/readline/colors.h
+       - only include stdbool.h if HAVE_STDBOOL_H is defined
+       - if HAVE_STDBOOL_H is not defined, provide enough definition for the
+         library to use `bool', `true', and `false'
+
+lib/readline/parse-colors.[ch]
+       - don't try to include <stdbool.h> at all; rely on colors.h to do it
+
+lib/sh/snprintf.c
+       - vsnprintf_internal: only treat '0' as a flag to indicate zero padding
+         if `.' hasn't been encountered ((flags&PF_DOT) == 0); otherwise treat
+         it as the first digit of a precision specifier.  Fixes bug reported
+         by Petr Sumbera <petr.sumbera@sun.com>
+
+                                  4/15
+                                  ----
+lib/sh/snprintf.c
+       - vsnprintf_internal: if the '0' and '-' flags both occur, the '0'
+         flag is ignored -- Posix.  Start of a series of fixes based on
+         tests and patches from Petr Sumbera <petr.sumbera@sun.com>
+       - PUT_PLUS: make sure PF_PLUS flag is specified before putting the `+'
+       - vsnprintf_internal: when '+' is read as a flag, don't set right-
+         justify flag if the LADJUST (`-') flag has already been supplied
+       - floating: make sure to output space padding before the `+', zero
+         padding after
+       - exponent: make sure to output space padding before the `+', zero
+         padding after
+       - exponent: only subtract one from the width for the decimal point
+         if we're really going to print one
+       - floating: use presence of PF_PLUS flag to decide whether to account
+         for the `+' in the padded field width.  Ditto for exponent()
+
+                                  4/16
+                                  ----
+lib/sh/snprintf.c
+       - vsnprint_internal: only reduce precision by 1 when processing the `g'
+         format if it's > 0.  A precision of 0 should stay 0; otherwise it
+         gets set to -1 (NOT_FOUND) and converted to the default
+       - number, lnumber: if an explicit precision is supplied, turn off the
+         zero-padding flag and set the pad character back to space
+       - number, lnumber: only account for a `+' when performing the field
+         width calculation if the coversion is base 10; we don't add a `+'
+         for other bases
+
+                                  4/18
+                                  ----
+tests/printf3.sub
+       - try using "perl -e 'print time'" to get the current time in seconds
+         since the epoch if "date +%s" is not available (solaris 8-10)
+
+                                  4/19
+                                  ----
+tests/run-printf
+       - use cat -v instead of relying on diff -a being available to convert
+         control characters to ascii and avoid the dreaded "Binary files
+         /tmp/xx and printf.right differ"
+
+                                  4/20
+                                  ----
+lib/sh/strftime.c
+       - incoporated new version from Aharon Robbins <arnold@skeeve.com>
+
+                                  4/22
+                                  ----
+doc/{bash.1,bashref.texi}
+       - slight change to the description of /dev/tcp and /dev/udp
+
+subst.c
+       - match_wpattern: logic fix to the calculation of `simple' (was |=,
+         needs to be &=).  Bug report from Mike Frysinger <vapier@gentoo.org>,
+         fix from Andreas Schwab <schwab@linux-m68k.org>
+
+bashline.c
+       - bash_filename_stat_hook: add code from bash_directory_completion_hook
+         that performs pathname canonicalization in the same way that cd and
+         other builtins will do
+
+                                  4/25
+                                  ----
+execute_cmd.c
+       - execute_pipeline: change the call to move_to_high_fd to make it use
+         getdtablesize() and to not stomp on existing open file descriptors,
+         like the fd the shell is using to read a script.  Bug report from
+         Greg Wooledge <wooledg@eeg.ccf.org>
+
+                                   5/6
+                                   ---
+subst.c
+       - expand_word_internal: case '$': after calling param_expand and
+         setting had_quoted_null, set TEMP to null.  The code that builds the
+         returned string at the end of the function will take care of making
+         and returning a quoted null string if there's nothing else in
+         ISTRING.  If there is, the quoted null should just go away.  Part of
+         fix for bug reported by Ruediger Kuhlmann <RKuhlmann@orga-systems.com>
+       - expand_word_internal: when processing ISTRING to build return value,
+         only set W_HASQUOTEDNULL in the returned word flags if the word is
+         a quoted null string AND had_quoted_null is set.  Rest of fix
+
+                                   5/9
+                                   ---
+variables.c
+       - bind_variable_internal: if we get an array variable here (implicit
+         assignment to index 0), call make_array_variable_value, which
+         dummies up a fake SHELL_VAR * from array[0].  This matters when
+         we're appending and have to use the current value
+       - bind_variable_internal: after computing the new value, treat assoc
+         variables with higher precedence than simple array variables; it
+         might be that a variable has both attributes set
+
+arrayfunc.c
+       - bind_array_var_internal: break code out that handles creating the
+         new value to be assigned to an array variable index into a new
+         function, make_array_variable_value.  This handles creating a
+         dummy SHELL_VAR * for implicit array[0] assignment.  Fixes bug
+         reported by Dan Douglas <ormaaj@gmail.com>
+
+arrayfunc.h
+       - make_array_variable_value: new extern declaration
+
+                                  5/19
+                                  ----
+variables.c
+       - bind_int_variable: if an assignment statement like x=y comes in
+         from the expression evaluator, and x is an array, handle it like
+         x[0]=y.  Fixes bug reported by Dan Douglas <ormaaj@gmail.com>
+
+                                  5/24
+                                  ----
+
+braces.c
+       - mkseq: handle possible overflow and break the sequence generating
+         loop if it occurs.  Fixes OpenSUSE bug 763591:
+         https://bugzilla.novell.com/show_bug.cgi?id=763591
+
+                                  5/25
+                                  ----
+Makefile.in
+       - LDFLAGS_FOR_BUILD: add to compilation recipes for build tools
+         buildversion, mksignames, mksyntax
+       - LDFLAGS_FOR_BUILD: add to compilation recipes for test tools
+         recho, zecho, printenv, xcase
+
+builtins/Makefile.in
+       - LDFLAGS_FOR_BUILD: add to compilation recipes for build tools
+         gen-helpfiles, psize.aux
+
+variables.c
+       - bind_int_variable: if LHS is a simple variable name without an array
+         reference, but resolves to an array variable, call
+         bind_array_variable with index 0 to make x=1 equivalent to x[0]=1.
+         Fixes bug reported by Dan Douglas <ormaaj@gmail.com>
+
+                                  5/27
+                                  ----
+subst.c
+       - expand_word_internal: make sure has_dollar_at doesn't get reset before
+         recursive calls to param_expand or expand_word_internal, since it has
+         to save state of what came before.  Use temp variable and make sure
+         has_dollar_at is incremented if recursive call processes "$@".
+         Fixes bug reported by gregrwm <backuppc-users@whitleymott.net> and
+         supplemented by Dan Douglas <ormaaj@gmail.com>
+
+doc/{bash.1,bashref.texi}
+       - changes to the description of substring expansion inspired by
+         suggestions from Bill Gradwohl <bill@ycc.com>
+
+doc/bashref.texi
+       - added substring expansion examples inspired by suggestions from
+         Bill Gradwohl <bill@ycc.com>
+
+variables.c
+       - find_shell_variable: search for a variable in the list of shell
+         contexts, ignore the temporary environment
+       - find_variable_tempenv: search for a variable in the list of shell
+         contexts, force search of the temporary environment
+       - find_variable_notempenv: search for a variable in the list of shell
+         contexts, don't force search of the temporary environment
+
+variables.h
+       - find_shell_variable: extern declaration
+       - find_variable_tempenv: extern declaration
+       - find_variable_notempenv: extern declaration
+
+arrayfunc.c
+       - bind_array_variable: call find_shell_variable instead of calling
+         var_lookup directly
+
+findcmd.c
+       - search_for_command: call find_variable_tempenv instead of
+         find_variable_internal directly
+       - _find_user_command_internal: call find_variable_tempenv instead of
+         find_variable_internal directly
+
+builtins/setattr.def
+       - set_var_attribute: call find_variable_notempenv instead of
+         find_variable_internal directly
+       - show_name_attributes:  call find_variable_tempenv instead of
+         find_variable_internal directly
+
+                                   6/1
+                                   ---
+sig.c
+       - termsig_handler: don't try to save the shell history on a terminating
+         signal any more, since it just causes too many problems on Linux
+         systems using glibc and glibc malloc
+
+lib/readline/vi_mode.c
+       - rl_vi_change_to: change to correctly redo `cc', since `c' is not a vi
+         motion character.  From Red Hat bug 813289
+       - rl_vi_delete_to: change to correctly redo `dd', since `d' is not a vi
+         motion character
+       - rl_vi_yank_to: change to correctly redo `yy', since `y' is not a vi
+         motion character
+
+                                   6/4
+                                   ---
+lib/sh/mktime.c
+       - current versions of VMS do not need to include <stddef.h>.  Fix from
+         John E. Malmberg <wb8tyw@qsl.net>
+
+                                   6/5
+                                   ---
+lib/sh/eaccess.c
+       - sh_stat: instead of using a static buffer to do the DEV_FD_PREFIX
+         translation, use a dynamically-allocated buffer that we keep
+         resizing.  Fixes potential security hole reported by David Leverton
+         <levertond@googlemail.com>
+
+                                   6/5
+                                   ---
+braces.c
+       - expand_seqterm: check errno == ERANGE after calling strtoimax for
+         rhs and incr.  Part of a set of fixes from Scott McMillan
+         <scotty.mcmillan@gmail.com>
+       - expand_seqterm: incr now of type `intmax_t', which changes
+         arguments to mkseq
+       - mkseq: a better fix for detecting overflow and underflow since it's
+         undefined in C and compilers `optimize' out overflow checks.  Uses
+         ADDOVERFLOW and SUBOVERFLOW macros
+       - mkseq: use sh_imaxabs (new macro) instead of abs() for intmax_t
+         variables
+       - mkseq: don't allow incr to be converted to -INTMAX_MIN
+       - mkseq: make sure that strvec_create isn't called with a size argument
+         greater than INT_MAX, since it only takes an int
+
+                                   6/6
+                                   ---
+braces.c
+       - mkseq: try and be smarter about not overallocating elements in
+         the return array if the increment is not 1 or -1
+
+                                   6/7
+                                   ---
+parse.y
+       - history_delimiting_chars: if the parser says we're in the middle of
+         a compound assignment (PST_COMPASSIGN), just return a space to avoid
+         adding a stray semicolon to the history entry.  Fixes bug reported
+         by "Davide Brini" <dave_br@gmx.com>
+
+                                   6/8
+                                   ---
+bashline.c
+       - bash_directory_completion_hook: don't attempt spelling correction
+         on the directory name unless the direxpand option is set and we are
+         going to replace the directory name with the corrected one in the
+         readline line.  Suggested by Linda Walsh <bash@tlinx.org>
+
+lib/sh/shquote.c
+       - sh_backslash_quote: now takes a third argument: flags.  If non-zero,
+         tildes are not backslash-escaped.  Have to handle both printf %q,
+         where they should be escaped, and filename completion, where they
+         should not when used as usernames
+
+externs.h
+       - sh_backslash_quote: declaration now takes a third argument
+
+builtins/printf.def
+       - printf_builtin: call sh_backslash_quote with 1 as third argument
+         so tildes get escaped
+
+{bashline,bracecomp}.c
+       - call sh_backslash_quote with 0 as third argument so tildes are not
+         escaped in completed words
+
+doc/bash.1
+       - add `coproc' to the list of reserved words.  From a report by
+         Jens Schweikhardt <schweikh@schweikhardt.net>
+
+                                  6/10
+                                  ----
+execute_cmd.c
+       - line_number_for_err_trap: now global, so parse_and_execute can save
+         and restore it with unwind-protect
+
+builtins/evalstring.c
+       - parse_prologue: save and restore line_number_for_err_trap along
+         with line_number
+       - restore_lastcom: new function, unwind-protect to restore
+         the_printed_command_except_trap
+       - parse_prologue: use restore_lastcom to save and restore the value
+         of the_printed_command_except_trap around calls to parse_and_execute
+         (eval/source/.)
+
+                                  6/15
+                                  ----
+lib/readline/complete.c
+       - complete_fncmp: change filename comparison code to understand
+         multibyte characters, even when doing case-sensitive or case-mapping
+         comparisons.  Fixes problem reported by Nikolay Shirokovskiy
+         <nshyrokovskiy@gmail.com>
+
+                                  6/20
+                                  ----
+builtins/mapfile.def
+       - mapfile: move the line count increment and check for having read
+         the specified number of lines to the end of the loop to avoid
+         reading an additional line with zgetline.  Fixes bug reported by
+         Dan Douglas <ormaaj@gmail.com>
+
+                                  6/21
+                                  ----
+
+execute_cmd.c
+       - execute_pipeline: make sure `lastpipe_flag' is initialized to 0 on
+         all systems, since it's tested later in the function.  Fixes bug
+         reported by John E. Malmberg <wb8tyw@qsl.net>
+
+                                  6/22
+                                  ----
+mailcheck.c
+       - file_mod_date_changed: return 0 right away if mailstat() does not
+         return success.  Fixes bug with using uninitialized values reported
+         by szymon.kalasz@uj.edu.pl
+
+builtins/set.def
+       - the `monitor' option is not available when the shell is compiled
+         without job control, since the underlying `m' flag is not available
+
+nojobs.c
+       - job_control: now declared as int variable, initialized to 0, never
+         modified
+
+jobs.h
+       - job_control: extern declaration no longer dependent on JOB_CONTROL
+
+execute_cmd.c
+       - execute_pipeline: made necessary changes so `lastpipe' shell option
+         is now available in all shells, even those compiled without
+         JOB_CONTROL defined
+
+                                  6/23
+                                  ----
+lib/glob/glob.c
+       - glob_filename: check for interrupts before returning if glob_vector
+         returns NULL or an error.  Bug reported by Serge van den Boom
+         <svdb@stack.nl>, fix from Andreas Schwab <schwab@linux-m68k.org>
+       - call run_pending_traps after each call to QUIT or test of
+         interrupt_state, like we do in mainline shell code
+       - glob_vector: don't call QUIT; in `if (lose)' code block; just free
+         memory, return NULL, and let callers deal with interrupt_state or
+         other signals and traps
+
+                                  6/25
+                                  ----
+lib/readline/input.c
+       - rl_read_key: restructure the loop that calls the event hook a little,
+         so that the hook is called only after rl_gather_tyi returns no input,
+         and any pending input is returned first.  This results in better
+         efficiency for processing pending input without calling the hook
+         on every input character as bash-4.1 did.  From a report from
+         Max Horn <max@quendi.de>
+
+                                  6/26
+                                  ----
+trap.c
+       - signal_is_pending: return TRUE if SIG argument has been received and
+         a trap is waiting to execute
+
+trap.h
+       - signal_is_pending: extern declaration
+
+lib/glob/glob.c
+       - glob_vector: check for pending SIGINT trap each time through the loop,
+         just like we check for interrupt_state or terminating_signal, and
+         set `lose = 1' so we clean up after ourselves and interrupt the
+         operation before running the trap.  This may require a change later,
+         maybe call run_pending_traps and do that if run_pending_traps returns?
+
+variables.c
+       - sv_histtimefmt: set history_comment_character to default (`#') if
+         it's 0 when we're turning on history timestamps.  The history code
+         uses the history comment character to prefix timestamps, and
+         leaving it at 0 effectively removes them from the history.  From a
+         report to help-bash by Dennis Williamson <dennistwilliamson@gmail.com>
+
+                                  6/27
+                                  ----
+lib/readline/signals.c
+       - rl_maybe_restore_sighandler: new function, sets handler for SIG to
+         HANDLER->sa_handler only if it's not SIG_IGN.  Needs to be called
+         on same signals set using rl_maybe_set_sighandler, which does not
+         override an existing SIG_IGN handler (SIGALRM is ok since it does
+         the check inline; doesn't mess with SIGWINCH)
+
+                                  6/30
+                                  ----
+variables.h
+       - additional defines for the new `nameref' variable attribute
+         (att_nameref): nameref_p, nameref_cell, var_setref
+
+variables.c
+       - find_variable_nameref: resolve SHELL_VAR V through chain of namerefs
+       - find_variable_last_nameref: resolve variable NAME until last in a
+         chain of possibly more than one nameref starting at shell_variables
+       - find_global_variable_last_nameref: resolve variable NAME until last
+         in a chain of possibly more than one nameref starting at
+         global_variables
+       - find_nameref_at_context: resolve SHELL_VAR V through chain of namerefs        
+         in a specific variable context (usually a local variable hash table)
+       - find_variable_nameref_context: resolve SHELL_VAR V through chain of
+         namerefs following a chain of varible contexts
+       - find_variable_last_nameref_context: resolve SHELL_VAR V as in
+         find_variable_last_context, but return the final nameref instead of
+         what the final nameref resolves to
+       - find_variable_tempenv, find_variable_notempenv, find_global_variable,
+         find_shell_variable, find_variable: modified to follow namerefs
+       - find_global_variable_noref: look up a global variable without following
+         any namerefs
+       - find_variable_noref: look up a shell variable without following any
+         namerefs
+       - bind_variable_internal: modify to follow a chain of namerefs in the
+         global variables table; change to handle assignments to a nameref by
+         following nameref chain
+       - bind_variable: modify to follow chain of namerefs when binding to a
+         local variable
+       - unbind_variable: changes to unset nameref variables (unsets both
+         nameref and variable it resolves to)
+
+subst.c
+       - parameter_brace_expand_word: change to handle expanding nameref whose
+         value is x[n]
+       - parameter_brace_expand_indir: change to expand in ksh93-compatible
+         way if variable to be indirected is nameref and a simple (non-array)
+         expansion
+       - param_expand: change to expand $foo where foo is a nameref whose value
+         is x[n]
+
+execute_cmd.c
+       - execute_for_command: changes to implement ksh93 semantics when index
+         variable is a nameref
+
+builtins/setattr.def
+       - show_var_attributes: change to add `n' to flags list if att_nameref
+         is set
+
+builtins/set.def
+       - unset_builtin: changes to error messages to follow nameref variables
+
+builtins/declare.def
+       - document new -n option
+       - declare_internal: new `-n' and `+n' options
+       - declare_internal: handle declare -n var[=value] and
+         declare +n var[=value] for existing and non-existant variables.
+         Enforce restriction that nameref variables cannot be arrays.
+         Implement semi-peculiar ksh93 semantics for typeset +n ref=value
+
+                                   7/5
+                                   ---
+variables.c
+       - unbind_variable: unset whatever a nameref resolves to, leaving the
+         nameref variable itself alone
+       - unbind_nameref: new function, unsets a nameref variable, not the
+         variable it references
+
+variables.h
+       - unbind_nameref: extern declaration
+
+builtins/set.def
+       - unset_builtin: modify to add -n option, which calls unbind_nameref
+         leaving unbind_variable for the usual case.  This required slight
+         changes and additions to the test suite
+
+doc/{bash.1,bashref.texi}
+       - document namerefs and typeset/declare/local/unset -n
+
+                                  7/13
+                                  ----
+lib/sh/casemod.c
+       - include shmbchar.h for is_basic and supporting pieces
+       - sh_casemod: use _to_wupper and _to_wlower to convert wide character
+         case instead of TOUPPER and TOLOWER.  Fixes bug reported by
+         Dennis Williamson <dennistwilliamson@gmail.com>, fix from
+         Andreas Schwab <schwab@linux-m68k.org>
+       - cval: short-circuit and return ascii value if is_basic tests true
+       - sh_casemod: short-circuit and use non-multibyte case modification
+         and toggling code if is_basic tests true
+
+lib/readline/signals.c
+       - _rl_{block,release}_sigint: remove the code that actually blocks and
+         releases the signals, since we defer signal handling until calls to
+         RL_CHECK_SIGNALS()
+
+lib/readline/{callback,readline,util}.c
+       - if HAVE_POSIX_SIGSETJMP is defined, use sigsetjmp/siglongjmp without
+         saving and restoring the signal mask instead of setjmp/longjmp
+
+lib/readline/rltty.c
+       - prepare_terminal_settings: don't mess with IXOFF setting if
+         USE_XON_XOFF defined
+
+doc/{bash.1,bashref.texi}
+       - add some text to the description of set -e clarifying its effect
+         on shell functions and shell function execution.  Suggested by
+         Rainer Blome <rainer.blome@gmx.de>
+
+bashline.c
+       - edit_and_execute_command: increment current_command_line_count before
+         adding partial line to command history (for command-oriented-history
+         because of rl_newline at beginning of function), then reset it to 0
+         before adding the dummy history entry to make sure the dummy entry
+         doesn't get added to previous incomplete command.  Partial fix for
+         problem reported by Peng Yu <pengyu.ut@gmail.com>
+
+                                  7/24
+                                  ----
+configure.in
+       - interix: define RECYCLES_PIDS.  Based on a report from Michael
+         Haubenwallner <michael.haubenwallner@salomon.at>
+
+                                  7/26
+                                  ----
+jobs.c
+       - make_child: call bgp_delete on the newly-created pid unconditionally.
+         Some systems reuse pids before cycling through an entire set of
+         CHILD_MAX/_SC_CHILD_MAX unique pids.  This is no longer dependent
+         on RECYCLES_PIDS.  Based on a report from Michael Haubenwallner
+         <michael.haubenwallner@salomon.at>
+
+support/shobj-conf
+       - Mac OS X: drop MACOSX_DEPLOYMENT_TARGET=10.3 from the LDFLAGS. We
+         can finally kill Panther
+
+                                  7/28
+                                  ----
+subst.c
+       - command_substitute: make sure last_made_pid gets reset if make_child
+         fails
+
+execute_cmd.c
+       - execute_command_internal: case cm_simple: decide whether or not to
+         wait_for a child if already_making_children is non-zero, indicates
+         that there is an unwaited-for child.  More of fix for bug report
+         from Michael Haubenwallner <michael.haubenwallner@salomon.at>
+
+jobs.c
+       - make_child: call delete_old_job (new_pid) unconditionally, don't
+         bother to check whether or not pid wrap occurred.  Rest of fix for
+         bug report from Michael Haubenwallner
+         <michael.haubenwallner@salomon.at>
+
+                                  7/29
+                                  ----
+shell.c
+       - subshell_exit: new function, exits the shell (via call to sh_exit())
+         after calling any defined exit trap
+
+externs.h
+       - subshell_exit: new extern declaration
+
+execute_cmd.c
+       - execute_command_internal: make sure to call subshell_exit for
+         {} group commands executed asynchronously (&).  Part of fix for
+         EXIT trap bug reported by Maarten Billemont <lhunath@lyndir.com>
+
+sig.c
+       - reset_terminating_signals: make sure to set termsigs_initialized back
+         to 0, so a subsequent call to initialize_terminating_signals works
+         right.  Rest of fix for bug reported by Maarten Billemont
+         <lhunath@lyndir.com>
+
+{execute_cmd,general,jobs,mailcheck,mksyntax,test}.c
+builtins/{cd,fc,pushd,ulimit}.def
+lib/malloc/getpagesize.h
+lib/sh/{clktck,fpurge,inet_aton,mailstat,oslib,pathcanon,pathphys,spell,strerror}.c
+       - make inclusion of <sys/param.h> dependent on HAVE_SYS_PARAM_H
+         consistently
+
+                                   8/6
+                                   ---
+lib/readline/histexpand.c
+       - history_expand_internal: now takes an additional argument saying
+         whether the history expansion occurs within a quoted string, set to
+         the open quote character
+       - history_expand_internal: use new argument instead of checking prev
+         char and initializing quoted_search_delimiter, pass qc directly to
+         get_history_event, where it allows a matching quote to terminate a
+         string defining an event
+       - history_expand: change single-quote handling code so that if
+         history_quotes_inhibit_expansion is 0, single quotes are treated
+         like double quotes
+       - history_expand: change call to history_expand_internal to pass new
+         argument of `"' if double-quoted string, `'' if single-quoted string;
+         this lets history_expand decide what is a quoted string and what
+         is not
+
+                                   8/7
+                                   ---
+configure.in
+       - AC_CANONICAL_BUILD: invoke for later use
+
+lib/readline/macro.c
+       - _rl_prev_macro_key: new function, inverse of _rl_next_macro_key:
+         backs up the index into the current macro by 1
+
+lib/readline/rlprivate.h
+       - _rl_prev_macro_key: extern declaration
+
+
+lib/readline/readline.c
+       - _rl_dispatch_subseq, _rl_subseq_result: don't call _rl_unget_char
+         if we're currently reading from a macro; call _rl_prev_macro_key
+         instead.  Fixes bug reported by Clark Wang <clark.wang@oracle.com>
+
+                                  8/13
+                                  ----
+builtins/evalstring.c
+       - evalstring(): new function, wrapper around parse_and_execute.
+         make sure we handle cases where parse_and_execute can call `return'
+         and short-circuit without cleaning up properly.  We call
+         parse_and_execute_cleanup() then jump to the previous-saved return
+         location
+
+builtins/common.h
+       - extern declaration for evalstring()
+
+builtins/eval.def
+       - eval_builtin: make sure we handle `eval " ... return"' in contexts
+         where `return' is valid by calling evalstring().  Fixes bug with
+         `eval return' in sourced files reported by Clark Wang
+         <dearvoid@gmail.com>
+
+trap.c
+       - run_pending_traps: call evalstring instead of parse_and_execute.
+         XXX - still needs to handle saving and restoring token state in the
+         presence of `return'; could use unwind_protects for that
+
+builtins/mapfile.def
+       - run_callback: call evalstring instead of parse_and_execute
+
+                                  8/15
+                                  ----
+bashline.c
+       - bash_filename_stat_hook: make sure we don't free local_dirname
+         before using it to canonicalize any expanded filename.  Make sure
+         it always points to *dirname and only free it if we're replacing
+         it.
+
+lib/readline/complete.c
+       - append_to_match: make sure we call rl_filename_stat_hook with
+         newly-allocated memory to avoid problems with freeing it twice
+
+                                  8/17
+                                  ----
+variables.c,config-top.h
+       - if ARRAY_EXPORT is defined to 1 when variables.c is compiled, the
+         code that allows indexed arrays to be exported is enabled and
+         included
+
+                                  8/19
+                                  ----
+shell.c
+       - call start_debugger from main() only if dollar_vars[1] != 0 (close
+         enough to a non-interactive shell, since we can be interactive with
+         -i while running a shell script).  Fixes oddity reported by
+         Techlive Zheng <techlivezheng@gmail.com>
+
+                                  8/20
+                                  ----
+arrayfunc.c
+       - quote_array_assignment_chars: don't bother quoting if the word has
+         not been marked as an assignment (W_ASSIGNMENT)
+       - quote_array_assignment_chars: turn on W_NOGLOB in the word flags
+         so assignment statements don't undergo globbing.  Partial fix for
+         problems reported by Dan Douglas <ormaaj@gmail.com>
+
+                                  8/21
+                                  ----
+command.h
+       - W_NOBRACE: new word flag that means to inhibit brace expansion
+
+subst.c
+       - brace_expand_word_list: suppress brace expansion for words with
+         W_NOBRACE flag
+
+                                  8/22
+                                  ----
+builtins/read.def
+       - read_builtin: don't call dequote_string on what we've read, even if
+         we saw an escape character, unless (input_string && *input_string).
+         We may have escaped an IFS whitespace character.  Fixes seg fault
+         reported by <armandsl@gmail.com>
+
+execute_cmd.c
+       - execute_command_internal: set the_printed_command_except trap when
+         about to execute a ( ... ) user subshell.  For now, set it only if
+         ERR is trapped; can relax that later.  Fixes bug reported by
+         Mike Frysinger <vapier@gentoo.org>
+
+                                  8/23
+                                  ----
+jobs.c
+       - remove references to first_pid and pid_wrap, since we're not using
+         them for anything anymore
+
+                                  8/24
+                                  ----
+subst.c
+       - changes for W_NOBRACE everywhere appropriate: so it can be displayed
+         for debugging, and passed out of expand_word_internal
+
+doc/{bash.1,bashref.texi}
+       - small changes to make it clearer that the = and == operators are
+         equivalent, and will cause pattern matching when used with [[.
+         From a question from Michal Soltys <soltys@ziu.info>
+
+doc/bashref.texi
+       - some small formatting changes from Karl Berry <karl@freefriends.org>
+
+                                  8/27
+                                  ----
+lib/readline/doc/{history,rlman,rluserman}.texi
+       - some small formatting changes from Karl Berry <karl@freefriends.org>
+
+arrayfunc.c
+       - assign_array_element_internal, assign_compound_array_list,
+         unbind_array_element, array_value_internal: changes to make
+         assignment statements to negative indices (a[-1]=2) and unsetting
+         array elements using negative indices (unset 'a[-1]') work.
+         From suggestions by Dennis Williamson <dennistwilliamson@gmail.com>
+         and Chris F. A. Johnson <chris@cfajohnson.com>
+
+subst.c
+       - array_length_reference: changes to make length references to array
+         elements using negative indices (${#a[-1]}) work
+
+                                  8/28
+                                  ----
+doc/{bash.1,bashref.texi}
+       - document new treatment of negative indices to indexed arrays when
+         assigning, referencing, calculating length, and unsetting
+
+                                  8/29
+                                  ----
+shell.c
+       - show_shell_usage: add -l to list of shell invocation options (short
+         for --login).  From Red Hat bug 852469
+
+configure.ac
+       - renamed from configure.in, as latest autoconf versions want.  Patches
+         Stefano Lattarini <stefano.lattarini@gmail.com>
+
+MANIFEST,Makefile.in,doc/bashref.texi,support/mkconffiles
+       - configure.in -> configure.ac
+
+                                   9/1
+                                   ---
+
+parse.y
+       - read_token_word: allow words like {array[ind]} to be valid redirection
+         words for constructs like {x}<file
+
+redir.c
+       - redir_varassign: bind_var_to_int already handles array assignments,
+         so don't need to do anything more for things like {a[i]}<file
+       - redir_varvalue: changes to allow references to {a[i]} when
+         performing redirections using valid_array_reference and
+         get_array_value.  Adds functionality requested most recently by
+         <unknown@vmw-les.eng.vmware.com>
+
+lib/readline/display.c
+       - update_line: if the first difference between the old and new lines
+         is completely before any invisible characters in the prompt, we
+         should not adjust _rl_last_c_pos, since it's before any invisible
+         characters.  Fixed in two places
+       - prompt_modechar: return a character indicating the editing mode:
+         emacs (@), vi command (:), or vi insert (+)
+       - _rl_reset_prompt: new function, just calls rl_expand_prompt.  Will be
+         inlined, placeholder for more changes
+       - expand_prompt: if show-mode-in-prompt is enabled, add a character to
+         the front of the prompt indicating the editing mode, adjusting the
+         various variables as appropriate to keep track of the number of
+         visible characters and number of screen positions
+
+lib/readline/bind.c
+       - show-mode-in-prompt: new bindable boolean variable, shadowed by
+         _rl_show_mode_in_prompt variable
+       - hack_special_boolean_var: call _rl_reset_prompt when toggling or
+         setting show-mode-in-prompt
+
+lib/readline/readline.c
+       - readline_internal_setup: make sure the correct vi mode keymap is set
+         before expanding the prompt string for the first time
+
+lib/readline/misc.c
+       - rl_emacs_editing_mode: make sure to call _rl_reset_prompt if we're
+         showing the editing mode in the prompt
+
+lib/readline/rlprivate.h
+       - _rl_reset_prompt, _rl_show_mode_in_prompt: extern declarations
+
+lib/readline/vi_mode.c
+       - rl_vi_insertion_mode: call _rl_reset_prompt
+       - rl_vi_movement_mode: call _rl_reset_prompt.  Finishes changes for
+         showing mode in prompt string, originally requested by Miroslav
+         Koskar <mkoskar@gmail.com> and most recently by Jordan Michael
+         Ziegler <jziegler@bnl.gov>
+
+doc/bash.1,lib/readline/doc/{readline.3,rluser.texi}
+       - document new show-mode-in-prompt variable, off by default
+
+                                   9/3
+                                   ---
+
+jobs.c
+       - set_childmax: new function, external mechanism for other parts of
+         the shell to set js.c_childmax, the number of saved exited child
+         statuses to remember
+jobs.h
+       - set_childmax: extern declaration
+
+variables.c
+       - CHILD_MAX: new special variable, with sv_childmax function to
+         run when it changes.  Setting CHILD_MAX to a value greater than
+         zero but less than some maximum (currently 8192) sets the number of
+         exited child statuses to remember.  set_childmax (jobs.c) ensures
+         that the number does not drop below the posix-mandated minimum
+         (CHILD_MAX)
+
+doc/{bash.1,bashref.texi}
+       - CHILD_MAX: document new meaning and action when variable is set
+
+                                   9/5
+                                   ---
+redir.c
+       - redir_varassign: call stupidly_hack_special_variables after
+         assigning fd number to specified variable, so we can use constructs
+         like {BASH_XTRACEFD}>foo.  Suggested by Pierre Gaston
+         <pierre.gaston@gmail.com>
+
+                                   9/8
+                                   ---
+expr.c
+       - readtok: invalidate previous contents of `curlval' before freeing
+         and reallocating tokstr (which, chances are, will get the same
+         pointer as before and render curlval inconsistent).  Fixes other
+         bug reported by Dan Douglas <ormaaj@gmail.com>
+
+                                   9/9
+                                   ---
+lib/readline/complete.c
+       - rl_username_completion_function: protect call to setpwent() with
+         #ifdef (HAVE_GETPWENT)/#endif.  Fixes bug reported by
+         Gerd Hofmann <gerd.hofmann.nbg@googlemail.com>
+
+lib/readline/display.c
+       - rl_message: second and subsequent calls to rl_message can result in
+         local_prompt being overwritten with new values (e.g., from the
+         successive calls displaying the incremental search string).  Need
+         to free before overwriting if it's not the same as the value saved
+         in saved_local_prompt.  Fixes memory leak reported by
+         Wouter Vermaelen <vermaelen.wouter@gmail.com>
+
+lib/readline/{terminal.c,rlprivate.h}
+       - move CUSTOM_REDISPLAY_FUNC and CUSTOM_INPUT_FUNC defines from
+         terminal.c to rlprivate.h so other files can use them
+
+expr.c
+       - expr_streval: if noeval is non-zero, just return 0 right away,
+         short-circuiting evaluation completely.  readtok will leave curtok
+         set correctly without re-entering the evaluator at all.  Rest of
+         fix for bug reported by Dan Douglas <ormaaj@gmail.com>
+
+                                  9/11
+                                  ----
+
+parse.y
+       - parse_comsub: make sure the `reserved word ok in this context' flag
+         is preserved after we read `do' followed by whitespace.  Fixes bug
+         reported by Benoit Vaugon <benoit.vaugon@gmail.com>
+
+                                  9/13
+                                  ----
+configure.ac,config.h.in
+       - enable-direxpand-default: new configure option, turns the `direxpand'
+         shell option on by default
+
+bashline.c
+       - dircomplete_expand, dircomplete_expand_relpath: initialize to 1 if
+         DIRCOMPLETE_EXPAND_DEFAULT is defined and non-zero
+
+doc/bashref.texi
+       - enable-direxpand-default: document new configure option
+
+                                  9/14
+                                  ----
+shell.c
+       - --protected: make option valid only when wordexp is compiled into
+         the shell.  Fix from Roman Rakus <rrakus@redhat.com>
+
+configure.ac
+       - HP NonStop (*-nsk*): compile --without-bash-malloc. Change from
+         Joachim Schmitz <jojo@schmitz-digital.de>
+
+                                  9/16
+                                  ----
+subst.c,execute_cmd.c,lib/glob/sm_loop.c,lib/sh/shquote.c
+       - minor code cleanups from Joachim Schmitz <jojo@schmitz-digital.de>
+
+lib/readline/colors.h
+       - workaround for HP NonStop compiler issue with <stdbool.h> from
+         Joachim Schmitz <jojo@schmitz-digital.de>
+
+                                  9/17
+                                  ----
+builtins/printf.def
+       - printf_builtin: handle localtime returning NULL, as can happen when
+         encountering overflow.  Bug report and initial fix from
+         Eduardo A. Bustamante López <dualbus@gmail.com>
+
+doc/{bash.1,bashref.texi}
+       - emphasize that brace expansion using character ranges ({a..c}) acts
+         as if the C locale were in use.  Prompted by message from
+         Marcel Giannelia <info@skeena.net>
+
+                                  9/20
+                                  ----
+lib/sh/wcsnwidth.c
+       - wcsnwidth: new function, variant of wcwidth, returns the number of
+         wide characters from a string that will be displayed to not exceed
+         a specified max column position
+
+                                  9/21
+                                  ----
+builtins/help.def
+       - show_builtin_command_help: break code that displays the short-doc
+         for each builtin in two columns into a new function: dispcolumn
+       - wdispcolumn: multibyte-char version of dispcolumn; uses wide
+         chars and printf "%ls" format.  Fixes problem reported by
+         Nguyá»n Thái Ngá»c Duy <pclouds@gmail.com>
+
+                                  9/22
+                                  ----
+execute_cmd.c
+       - execute_disk_command: before running the command-not-found hook,
+         call kill_current_pipeline() to make sure we don't add processes
+         to an existing pipeline or wait for processes erroneously
+
+                                  9/23
+                                  ----
+lib/readline/input.c
+       - rl_input_available_hook: new hook function, called from
+         _rl_input_available (or _rl_input_queued) to return whether or not
+         input is available wherever the input source is
+
+lib/readline/doc/rltech.texi
+       - rl_input_available_hook: document
+
+                                  9/27
+                                  ----
+lib/glob/sm_loop.c:
+       - GMATCH: after one or more `*', an instance of ?(x) can match zero or
+         1 times (unlike ?, which has to match one character).  The old code
+         failed if it didn't match at least once.  Fixes `a*?(x)' bug.
+       - GMATCH: if we hit the end of the search string, but not the end of
+         the pattern, and the rest of the pattern is something that can
+         match the NUL at the end of the search string, we should successfully
+         match.  Fixes `a*!(x)' bug reported by <hans1worst@gmail.com>
+
+                                  10/2
+                                  ----
+command.h
+       - add c_lock member to coproc structure for future use to tell who is
+         manipulating it
+
+execute_cmd.c
+       - execute_coproc: block SIGCHLD while parent is forking coproc
+         process and adding pid to sh_coproc struct to avoid race condition
+         where child is reaped before the pid is assigned and the coproc is
+         never marked as having died.  Fixes race condition identified by
+         Davide Baldini <baldiniebaldini@gmail.com>
+       - add assignments to c_lock member of struct coproc in various
+         functions that manipulate it; was used to identify race condition
+       - coproc_pidchk: don't call coproc_dispose to avoid using malloc and
+         other functions in a signal handler context
+       - coproc_dispose: call BLOCK_SIGNAL/UNBLOCK_SIGNAL for SIGCHLD while
+         manipulating the sh_coproc struct
+
+                                  10/6
+                                  ----
+lib/readline/complete.c
+       - rl_display_match_list: if printing completions horizontally, don't
+         bother with spacing calculations if limit == 1, which means we are
+         printing one completion per line no matter what.  Fixes bug
+         reported by David Kaasen <kaasen@nvg.ntnu.no>
+
+                                  10/7
+                                  ----
+builtins/declare.def
+       - declare_internal: add error checking for nameref attribute and
+         variable assignments: self-references, attempts to make an array
+         variable a nameref
+
+subst.c
+       - parameter_brace_expand: handle parameter_brace_expand_word returning
+         &expand_param_fatal or &expand_param_error and return the appropriate
+         error value
+       - parameter_brace_expand_word: if a nameref variable's value is not a
+         valid identifier, return an error
+       - param_expand: if a nameref variable's value is not a valid identifier,
+         return an error
+
+test.c
+       - unary_operator: add new -R variable, returns true if variable is set
+         and has the nameref attribute. From ksh93
+
+builtins/test.def
+       - add -R to description of conditional commands for help test
+
+doc/{bash.1,bashref.texi}
+       - document new -R unary conditional operator
+
+                                  10/13
+                                  -----
+trap.c
+       - check_signals_and_traps: new function, convenience function for the
+         rest of the shell to check for pending terminating and interrupt
+         signals, and to check for and process any pending traps
+       - any_signals_trapped: new function, returns non-zero if any signals
+         are trapped and -1 if not
+
+trap.h
+       - extern declaration for check_signals_and_traps
+
+bashline.c
+       - bashline_reset: make sure we reset the event hook
+       - bash_event_hook: call check_signals_and_traps instead of just
+         checking for terminating signals so we can run pending traps and
+         react to interrupts, and reset the event hook when we're done
+
+
+                                  10/14
+                                  -----
+trap.c
+       - trap_handler: if executing in a readline signal handler context,
+         call bashline_set_event_hook to install bash_event_hook to process
+         the signal (if bash cares about it)
+
+sig.c
+       - sigint_sighandler: call bashline_set_event_hook to set the event
+         hook if we're executing in a readline signal handler context
+
+lib/readline/input.c
+       - rl_getc: call RL_CHECK_SIGNALS if read returns -1/EINTR and the caught
+         signal is SIGINT or SIGQUIT rather than waiting until the next time
+         around the loop
+       - rl_getc: call rl_event_hook after calling RL_CHECK_SIGNALS to allow
+         an application signal handler to set the event hook in its own
+         signal handler (e.g., like bash trap_handler or sigint_sighandler)
+
+
+parse.y
+       - yy_readline_get: don't set interrupt_immediately before we call
+         readline().  Inspired by report from lanshun zhou
+         <zls.sogou@gmail.com>
+
+input.c
+       - getc_with_restart: add call to run_pending_traps after call to
+         CHECK_TERMSIG
+
+lib/sh/zread.c
+       - zread: call check_signals_and_traps if read() returns -1/EINTR
+         instead of just ignoring the EINTR and deferring handling any
+         signal that generated it
+
+builtins/mapfile.def
+       - mapfile: don't set interrupt_immediately before calling zgetline()
+         (which uses zread internally)
+
+builtins/read.def
+       - read_builtin: don't set interrupt_immediately before calling zread
+         (moved code around so that it was only being set right around calls
+         to zread to avoid signal handler conflicts).  Inspired by report
+         from lanshun zhou <zls.sogou@gmail.com>
+       - edit_line: don't set interrupt_immediately around call to readline()
+       - include shmbutil.h
+       - read_builtin: don't call read_mbchar unless is_basic(c) returns
+         false for the character we just read
+
+                                  10/15
+                                  -----
+sig.c
+       - throw_to_top_level: if interrupt_state is non-zero, make sure that
+         last_command_exit_value reflects 128+SIGINT if it's not already
+         greater than 128
+
+                                  10/20
+                                  -----
+builtins/wait.def
+       - WAIT_RETURN: set wait_signal_received back to 0 for the potential
+         next call to wait
+
+quit.h
+       - CHECK_WAIT_INTR: macro to check whether trap_handler handled a
+         signal and set wait_signal_received; longjmp to wait_intr_buf in
+         that case
+
+jobs.c
+       - wait_for, waitchld: call CHECK_WAIT_INTR at the same places we call
+         CHECK_TERMSIG to check for terminating signals
+       - wait_sigint_handler: don't longjmp out of the wait builtin unless
+         interrupt_immediately is set; otherwise just SIGRETURN from the
+         handler
+       - wait_sigint_handler: if interrupt_immediately not set, but we are
+         executing in the wait builtin and SIGINT is not trapped, treat it
+         as a `normally received' SIGINT: restore the signal handler and
+         send SIGINT to ourselves
+       - waitchld: when in posix mode and running SIGCHLD traps, don't longjmp
+         to wait_intr_buf (and let wait be interrupted) if we're running from
+         a signal handler.  Wait for CHECK_WAIT_INTR to do the longjmp.
+         run_pending_traps will run the SIGCHLD trap later
+
+nojobs.c
+       - reap_zombie_children, wait_for_single_pid, wait_for: call
+         CHECK_WAIT_INTR where we call CHECK_TERMSIG
+       - wait_sigint_handler: don't longjmp out of the wait builtin unless
+         interrupt_immediately is set; otherwise just SIGRETURN from the
+         handler
+
+trap.c
+       - trap_handler: make sure wait_signal_received is set if the wait
+         builtin is executing, and only longjmp if interrupt_immediately is
+         set.  This whole set of fixes was prompted by report from
+         lanshun zhou <zls.sogou@gmail.com>
+
+                                  10/24
+                                  -----
+lib/glob/glob.c
+       - glob_filename: only check directory_name for globbing chars if
+         it's of non-zero length
+
+lib/sh/strchrnul.c
+       - new simpler implementation
+
+subst.c
+       - command_substitute: call set_shellopts after turning off errexit
+         in subshells so it's reflected in $SHELLOPTS
+
+                                  11/7
+                                  ----
+builtins/evalstring.c
+       - parse_and_execute: treat ERREXIT case like reader_loop does: set
+         variable_context to 0 before longjmping back to top_level. Don't
+         run the unwind-protect context to avoid side effects from popping
+         function contexts.  Part of fix for problem reported by Nikolai
+         Kondrashov <nikolai.kondrashov@redhat.com>
+
+execute_cmd.c
+       - execute_simple_command: call unlink_fifo_list only if this is the
+         last element of a pipeline (or not in a pipeline), rather than for
+         every child.  Fixes difference in behavior between /dev/fd and
+         FIFOs reported by Zev Weiss <zev@bewilderbeest.net>
+       - execute_null_command: do the same thing in the parent branch after
+         make_child
+
+                                  11/14
+                                  -----
+subst.c
+       - parameter_brace_expand: a variable is null if it's special ($@, $*),
+         the expansion occurs within double quotes, and the expansion turns
+         into a quoted null.  Fixes debian bug 692447 reported by
+         Matrosov Dmitriy <sgf.dma@gmail.com>
+
+jobs.c
+       - run_sigchld_trap: make sure `running_trap' sentinel is set
+         appropriately
+       - waitchld: only run the sigchld trap if we're not in a signal
+         handler, not running a trap, and executing the wait builtin.
+         Otherwise, queue for later handling.  We still run one instance
+         of the trap handler per exited child.  Bulk of fix for bug
+         reported by Elliott Forney <idfah@cs.colostate.edu>
+
+trap.c
+       - queue_sigchld_trap: set catch_flag so run_pending_traps notices,
+         and set trapped_signal_received for completeness.  Rest of fix
+         for bug reported by Elliott Forney <idfah@cs.colostate.edu>
+
+lib/malloc/malloc.c
+       - block_signals: renamed to _malloc_block_signals, made public
+       - unblock_signals: renamed to _malloc_unblock_signals, made public
+
+lib/malloc/imalloc.h
+       - extern declarations for _malloc_{un,}block_signals
+
+lib/malloc/table.c
+       - mregister_alloc, mregister_free: block signals around table
+         manipulation
+
+                                  11/15
+                                  -----
+trap.c
+       - run_pending_traps: set SIG_INPROGRESS flag around calls to
+         run_sigchld_handler so other parts of the shell know that the
+         SIGCHLD trap handler is executing
+       - run_pending_traps: if we get a situation where we are looking at
+         running a SIGCHLD trap but the trap string is IMPOSSIBLE_TRAP_HANDLER
+         and the SIG_INPROGRESS flag is set, just skip it.  This is possible
+         if run_pending_traps is called from a SIGCHLD trap handler run by
+         run_sigchld_trap
+
+doc/bash.1,lib/readline/doc/{rluser.texi,readline.3}
+       - corrected description of the effect of `set history-size 0'.  Report
+         from Vesa-Matti J Kari <vmkari@cc.helsinki.fi>
+
+include/stdc.h
+       - CPP_STRING: new define, replaces __STRING
+
+lib/malloc/{malloc.c,imalloc.h}
+       - replace __STRING with CPP_STRING
+
+                                  11/16
+                                  -----
+lib/readline/bind.c
+       - sv_histsize: if argument evaluates to a value < 0, unstifle the
+         history
+
+                                  11/22
+                                  -----
+redir.c
+       - do_redirection_internal: if we have REDIR_VARASSIGN set in the
+         redirection flags and we set up `redirector' using fcntl or dup2,
+         don't add a redirect to make sure it stays open.  Let the
+         script programmer manage the file handle.  Fixes bug reported by
+         Sam Liddicott <sam@liddicott.com>
+
+                                  11/24
+                                  -----
+jobs.c
+       - wait_for_any_job: new function, waits for an unspecified background
+         job to exit and returns its exit status.  Returns -1 on no background
+         jobs or no children or other errors.  Calls wait_for with new
+         sentinel value ANY_PID
+       - wait_for: changes to handle argument of ANY_PID: don't look up or
+         try to modify the child struct, only go through the wait loop once.
+         Return -1 if waitpid returns no children
+
+jobs.h
+       - ANY_PID: new define
+
+builtins/wait.def
+       - new option: -n. Means to wait for the next job and return its exit
+         status.  Returns 127 if there are no background jobs (or no
+         children).  Feature most recently requested by Elliott Forney
+         <idfah@cs.colostate.edu>
+
+doc/{bash.1,bashref.texi}
+       - document new `wait -n' option
+
+execute_cmd.c
+       - execute_command_internal: save make_command_string () result in a
+         temp variable before calling savestring() on it; avoids evaluating
+         make_command_string() result twice.  Fix from John E. Malmberg
+         <wb8tyw@qsl.net>
+
+                                  11/28
+                                  -----
+
+builtins/declare.def
+       - declare_internal: if an array variable is declared using `declare -a'
+         or `declare -A', but not assigned a value, set the `invisible'
+         attribute so the variable does not show up as set.  Fix for bug
+         about variable initialization reported by Tim Friske <me@timfriske.com>
+
+builtins/{mapfile,read}.def
+       - after calling find_or_make_array_variable, make sure the invisible
+         flag is turned off, in case the variable was declared previously
+         using `declare -a' or `declare -A'.  Side effect of above change to
+         declare_internal
+
+subst.c
+       - shell_expand_word_list: handle the W_ASSNGLOBAL flag and put -g into
+         the list of options passed to make_internal_declare as appropriate.
+         Fix for bug reported by Tim Friske <me@timfriske.com>
+
+                                  11/30
+                                  -----
+test.c
+       - unary_op: make sure -v and -n check that the variable is not marked
+         as invisible before calling var_isset.  Fix for bug reported by Tim
+         Friske <me@timfriske.com>
+
+                                  12/2
+                                  ----
+subst.c
+       - process_substitute: turn off the `expanding_redir' flag, which
+         controls whether or not variables.c:find_variable_internal uses the
+         temporary environment to find variables.  We want to use the
+         temp environment, since we don't have to worry about order of
+         evaluation in a subshell.  Fixes bug reported by Andrey Borzenkov
+         <arvidjaar@gmail.com>
+
+                                  12/4
+                                  ----
+lib/glob/glob.c
+       - glob_filename: changes to avoid null filenames and multiple entries
+         returned for patterns like **/** (globstar enabled).  Fixes bug
+         reported by Ulf Magnusson <ulfalizer@gmail.com>
+
+                                  12/10
+                                  -----
+lib/glob/glob.c
+       - glob_filename: finish up a series of changes to make globstar-style   
+         globbing more efficient, avoid more duplicate filenames, and be more
+         compatible with other shells that implement it
+               o collapse a sequence of **/**/** to one **
+               o note when the directory name is all ** or ends in ** so we
+                 can treat it specially when the filename is **
+         All inspired by report from Andrey Borzenkov <arvidjaar@gmail.com>
+
+lib/sh/zread.c
+       - zreadn: new function, like zread, but takes an additional argument
+         saying how many bytes to read into the local buffer.  Can be used to
+         implement `read -N' without so many one-byte calls to zreadc.  Code
+         from Mike Frysinger <vapier@gentoo.org>
+
+                                  12/12
+                                  -----
+lib/glob/sm_loop.c
+       - PATSCAN (glob_patscan): if passed string already points to end of
+         pattern, return NULL immediately.  Fixes problem with
+         extglob_skipname reported by Raphaël Droz <raphael.droz@gmail.com>
+
+                                  12/13
+                                  -----
+execute_cmd.c
+       - execute_coproc: handle the command's exit status being inverted
+         (an oversight).  Fixes bug reported by DJ Mills
+         <danielmills1@gmail.com> and Andreas Schwab <schwab@linux-m68k.org>
+
+                                  12/14
+                                  -----
+lib/readline/readline.c
+       - bind_arrow_keys_internal: add MINGW key bindings for Home, End,
+         Delete, and Insert keys.  Fix from Pierre Muller
+         <pierre.muller@ics-cnrs.unistra.fr>
+
+builtins/printf.def
+       - printf_builtin: '%()T' conversion: if there is no argument supplied,
+         behave as if -1 had been supplied (current time).  ksh93-like feature
+         suggested by Clark Wang <dearvoid@gmail.com>
+
+doc/{bash.1,bashref.texi}
+       - document new printf %()T default argument behavior
+
+                                  12/15
+                                  -----
+lib/readline/display.c
+       - displaying_prompt_first_line: new variable, indicates whether or
+         not the first line of output is displaying the prompt.  Always true
+         in normal mode, sometimes false in horizontal scrolling mode
+       - rl_redisplay: set displaying_prompt_first_line to true unless we
+         are in horizontal mode; set to false in horizontal mode if the left
+         margin of the displayed line is greater than the end of the prompt
+         string
+       - rl_redisplay: when in horizontal scroll mode, don't adjust
+         _rl_last_c_pos by the wrap offset unless the line is displaying
+         a prompt containing invisible chars
+       - update line: don't adjust _rl_last_c_pos by the wrap offset unless
+         the line is displaying a prompt containing invisible chars
+       - update_line: if shrinking the line by reducing the number of
+         displayed characters, but we have already moved the cursor to the
+         beginning of the line where the first difference starts, don't
+         try to delete characters
+
+builtins/read.def
+       - unbuffered_read: set to 2 if invoked as `read -N'
+       - if unbuffered_read is set to 2, compute the number of chars we
+         need to read and read that many with zreadn.  Posix mode still
+         uses zreadintr.  Code from Mike Frysinger <vapier@gentoo.org>
+
+doc/{bash.1,bashref.texi}
+       - read: make it clear that if read times out, it saves any input
+         read to that point into the variable arguments.  Report from
+         Fiedler Roman <Roman.Fiedler@ait.ac.at>
+
+subst.c
+       - command_substitute: change direct assignment of exit_immediately_on_error
+         to use change_flag ('e', FLAG_OFF) instead
+
+flags.c
+       - use errexit_flag as the variable modified by changes to the -e
+         option, reflect those changes to exit_immediately_on_error
+
+execute_cmd.c
+       - execute_builtin: new global variable, builtin_ignoring_errexit, set
+         to 0 by default and set to 1 if eval/source/command executing in a
+         context where -e should be ignored
+       - execute_builtin: set exit_immediately_on_error to errextit_flag
+         after executing eval/source/command in a context where -e should
+         be ignored
+
+flags.c
+       - if builtin_ignoring_errexit is set, changes to errexit_flag are
+         not reflected in the setting of exit_immediately_on_error.  Fixes
+         bug reported by Robert Schiele <rschiele@gmail.com>
+
+                                  12/23
+                                  -----
+include/posixjmp.h
+       - setjmp_nosigs: new define, call setjmp in such a way that it will
+         not manipulate the signal mask
+
+{expr,test,trap}.c
+       - setjmp_nosigs: call instead of setjmp; don't need to manipulate
+         signal mask
+
+builtins/read.def
+       - read_builtin: setjmp_nosigs: call instead of setjmp; don't need
+         to manipulate signal mask
+
+builtins/evalstring.c:
+       - parse_and_execute: setjmp_nosigs: call instead of setjmp; don't need
+         to manipulate signal mask
+       - parse_string: setjmp_nosigs: call instead of setjmp; don't need
+         to manipulate signal mask
+       - parse_and_execute: save and restore the signal mask if we get a
+         longjmp that doesn't cause us to return or exit (case DISCARD)
+
+                                  12/24
+                                  -----
+general.c
+       - bash_tilde_expand: only set interrupt_immediately if there are no
+         signals trapped; we want to jump to top level if interrupted but
+         not run any trap commands
+
+                                  12/25
+                                  -----
+jobs.c
+       - run_sigchld_trap: no longer set interrupt_immediately before calling
+         parse_and_execute, even if this is no longer run in a signal handler
+         context
+
+input.c
+       - getc_with_restart: add call to QUIT instead of CHECK_TERMSIG
+
+parse.y
+       - yy_stream_get: now that getc_with_restart calls QUIT, don't need to
+         set interrupt_immediately (already had call to run_pending_traps)
+
+execute_cmd.c
+       - execute_subshell_builtin_or_function,execute_function,execute_in_subshell:
+         setjmp_nosigs: call instead of setjmp when saving return_catch; don't
+         need to manipulate signal mask
+       - execute_subshell_builtin_or_function,execute_in_subshell:
+         setjmp_nosigs: call instead of setjmp where appropriate when saving
+         top_level; don't need to manipulate signal mask if we're going to
+         exit right away
+
+subst.c
+       - command_substitute: setjmp_nosigs: call instead of setjmp when saving
+         return_catch; don't need to manipulate signal mask
+       - command_substitute: setjmp_nosigs: call instead of setjmp where
+         appropriate when saving top_level; don't need to manipulate signal
+         mask if we're going to exit right away
+
+trap.c
+       - run_exit_trap: setjmp_nosigs: call instead of setjmp when saving
+         return_catch; don't need to manipulate signal mask
+       - run_exit_trap: setjmp_nosigs: call instead of setjmp where
+         appropriate when saving top_level; don't need to manipulate signal
+         mask if we're going to exit right away
+       - _run_trap_internal: setjmp_nosigs: call instead of setjmp when saving
+         return_catch; don't need to manipulate signal mask
+
+builtins/evalfile.c
+       - _evalfile: setjmp_nosigs: call instead of setjmp when saving
+         return_catch; don't need to manipulate signal mask
+
+builtins/evalstring.c
+       - evalstring: setjmp_nosigs: call instead of setjmp when saving
+         return_catch; don't need to manipulate signal mask
+
+shell.c
+       - main: setjmp_nosigs: call instead of setjmp where appropriate when
+         saving top_level; don't need to manipulate signal mask if we're
+         going to exit right away
+       - run_one_command: setjmp_nosigs: call instead of setjmp where
+         appropriate when saving top_level; don't need to manipulate signal
+         mask if we're going to exit right away
+       - run_wordexp: setjmp_nosigs: call instead of setjmp where
+         appropriate when saving top_level; don't need to manipulate signal
+         mask if we're going to exit right away
+
+eval.c
+       - reader_loop: save and restore the signal mask if we get a longjmp
+         that doesn't cause us to return or exit (case DISCARD)
+
+                                  12/26
+                                  -----
+parse.y
+       - shell_input_line_{index,size,len}: now of type size_t; in some cases
+         the unsigned property makes a difference
+       - STRING_SAVER: saved_line_{size,index} now of type size_t
+       - shell_getc: don't allow shell_input_line to grow larger than SIZE_MAX;
+         lines longer than that are truncated until read sees a newline;
+         addresses theoretical buffer overflow described by Paul Eggert
+         <eggert@cs.ucla.edu>
+       - set_line_mbstate: size_t changes like shell_getc
+       - shell_getc: if shell_input_line is larger than 32K, free it and
+         start over to avoid large memory allocations sticking around
+
+variables.c
+       - bind_global_variable: new function, binds value to a variable in
+         the global shell_variables table
+
+variables.h
+       - bind_global_variable: new extern declaration
+
+builtins/declare.def
+       - declare_internal: if -g given with name=value, but variable is not
+         found in the global variable table, make sure to call
+         bind_global_variable so the variable is created and modified at
+         global scope.  Fixes a bug where declare -g x=y could modify `x'
+         at a previous function scope
+
+command.h
+       - W_ASSIGNARRAY: new word flag, compound indexed array assignment
+
+subst.h
+       - ASS_MKGLOBAL: new assignment flag, forcing global assignment even in
+         a function context, used by declare -g
+
+execute_cmd.c
+       - fix_assignment_words: set W_ASSIGNARRAY flag if -a option given to
+         declaration builtin
+
+subst.c
+       - do_assignment_internal: explicitly handle case where we are
+         executing in a function and we want to create a global array or
+         assoc variable
+       - shell_expand_word_list: call make_internal_declare if -a option
+         given to declaration builtin (W_ASSIGNARRAY); handle -g option with
+         it (W_ASSNGLOBAL).  Fixes inconsistency noticed by Vicente Couce
+         Diaz <vituko@gmail.com>, where declare -ag foo=(bar) could modify
+         array variable foo at previous function scope, not global scope
+
+                                  12/27
+                                  -----
+bashline.c
+       - Minix needs the third argument to tputs to be a void funtion taking
+         an int argument, not an int-returning function.  Fix from
+         John E. Malmberg <wb8tyw@qsl.net> as part of VMS bash port
+
+                                  12/29
+                                  -----
+configure.ac,version.c,patchlevel.h
+       - bash-4.3-devel: new version, new shell compatibility level (43)
+
+subst.c
+       - parameter_brace_patsub: put the bash-4.2 code back in from the
+         change of 3/3 that runs the replacement string through quote
+         removal, make it dependent on shell_compatibility_level <= 42
+
+builtins/shopt.def
+       - compat42: new shopt option
+       - set_compatibility_level: change logic to set and unset various
+         compat variables and shell_compatibility_level
+
+COMPAT
+       - new documentation for bash-4.3 compatibility changes
+
+doc/{bash.1,bashref.texi}
+       - compat42: document new shopt option
+
+builtins/shopt.def
+       - set_compatibility_opts: new function, sets the various shopt
+         compat variables based on the value of shell_compatibility_level
+
+builtins/common.h
+       - set_compatibility_opts: new extern declaration
+
+variables.c
+       - BASH_COMPAT: new special variable; sets the shell compatibility
+         level.  Accepts values in decimal (4.2) or integer (42) form;
+         Unsetting variable, setting it to empty string, or setting it to
+         out-of-range value sets the shell's compatibility level to the
+         default for the current version.  Valid values are 3.1/31 through
+         the current version
+       - sv_shcompat: new function implementing logic for BASH_COMPAT
+
+variables.h
+       - sv_shcompat: new extern declaration
+
+doc/{bash.1,bashref.texi}
+       - BASH_COMPAT: description of new variable
+
+lib/readline/complete.c
+       - _rl_colored_stats: default back to 0 for 4.3 release branch
+
+                                1/5/2013
+                                --------
+quit.h
+       - remove spurious call to itrace in CHECK_WAIT_INTR
+
+bashline.c
+       - bash_event_hook: if we're going to jump to top_level, make sure we
+         clean up after readline() by calling rl_cleanup_after_signal().
+         Fixes bug reported against devel branch by Raphaël Droz
+         <raphael.droz@gmail.com>
+       - bash_event_hook: reset the event hook before checking for signals
+         or traps in case we longjmp
+
+doc/{bash.1,bashref.texi}
+       - small additions to the set -e section to make it more clear that
+         contexts where -e is ignored extend to compound commands as well
+         as shell functions
+
+lib/readline/readline.h
+       - rl_signal_event_hook: new extern declaration
+
+lib/readline/input.c
+       - rl_signal_event_hook: new variable, hook function to call when a
+         function (currently just read(2)) is interrupted by a signal and
+         not restarted
+       - rl_getc: call rl_signal_event_hook instead of rl_event_hook
+
+lib/readline/doc/rltech.texi
+       - rl_signal_event_hook: document new function
+
+bashline.c
+       - changes to set rl_signal_event_hook instead of rl_event_hook
+
+lib/readline/readline.h
+       - change readline version numbers to 6.3
+
+                                   1/6
+                                   ---
+doc/{bash.1,bashref.texi}
+       - a couple of changes to the descriptions of the ERR trap and its
+         effects based on a message from Rob Nagler <nagler@bivio.biz>
+
+                                   1/9
+                                   ---
+expr.c
+       - expassign: invalidate curlval before freeing and NULLing tokstr to
+         avoid aliasing issues.  Fixes bug reported by Eduardo A. Bustamante
+         López<dualbus@gmail.com>  and Dan Douglas <ormaaj@gmail.com>
+
+braces.c
+       - array_concat: don't be so aggressive in trying to short-circuit. We
+         can only short-circuit if we have a single-element array where the
+         element is an empty string (array[0] == "" array[1] = 0x0).  Existing
+         practice requires us to replicate arrays and prefix or append empty
+         strings.  Fixes bug reported by Eduardo A. Bustamante López
+         <dualbus@gmail.com>
+
+                                  1/11
+                                  ----
+execute_cmd.c
+       - execute_builtin: since mapfile uses evalstring() to run its callbacks
+         internally, just like eval, so it needs to handle the case where the
+         temp environment given to mapfile persists throughout the entire
+         set of callback commands.  This might be a problem with trap also, but
+         trap isn't run in the same way.  Fixes bug reported by Dan Douglas
+         <ormaaj@gmail.com>
+
+                                  1/13
+                                  ----
+redir.c
+       - redirection_error: before expanding the redirection word (if
+         expandable_redirection_filename returns true), disable command
+         substitution during expansion.  Fixes bug reported by Dan Douglas
+         <ormaaj@gmail.com>
+
+subst.c
+       - expand_word_internal: case '\\': if the next character is an IFS
+         character, and the expansion occurs within double quotes, and the
+         character is not one for which backslash retains its meaning, add
+         the (escaped) '\' and the (escaped) character.  Fixes bug reported
+         by Dan Douglas <ormaaj@gmail.com>
+
+                                  1/15
+                                  ----
+builtins/cd.def
+       - cd_builtin: make sure call to internal_getopt handles -e option.
+         Fixes bug reported by <mashimiao.fnst@cn.fujitsu.com>
+
+                                  1/17
+                                  ----
+subst.c
+       - expand_word_list_internal: make sure tempenv_assign_error is
+         initialized to 0
+
+execute_cmd.c
+       - execute_simple_command: make sure tempenv_assign_error is reset to 0
+         after it's tested to see if an error should force the shell to exit.
+         Fixes problem where a the failure of a tempenv assignment preceding
+         a non-special builtin `sticks' and causes the next special builtin
+         to exit the shell.  From a discussion on bug-bash started by
+         douxin <wq-doux@cn.fujitsu.com>
+
+                                  1/20
+                                  ----
+subst.c
+       - parameter_brace_expand_rhs: call stupidly_hack_special_variables
+         after assigning with ${param[:]=word} even if IFS is changing.
+         Suggested by Dan Douglas <ormaaj@gmail.com> [TENTATIVE, needs work
+         on IFS side effects]
+
+command.h
+       - W_GLOBEXP (which was unused) is now W_SPLITSPACE (which isn't used
+         yet)
+
+{execute_cmd,subst,variables}.c
+       - removed all code that mentioned W_GLOBEXP
+       - removed mention of gnu_argv_flags and code that set it
+
+                                  1/22
+                                  ----
+subst.c
+       - param_expand: set W_SPLITSPACE if we expand (unquoted) $* and
+         IFS is unset or null so we can be sure to split this on spaces
+         no matter what happens with IFS later
+       - expand_word_internal: note that param_expand returns W_SPLITSPACE
+         in the returned word flags and keep track of that state with
+         `split_on_spaces'
+
+                                  1/23
+                                  ----
+subst.c
+       - expand_word_internal: if split_on_spaces is non-zero, make sure
+         we split `istring' on spaces and return the resultant word.  The
+         previous expansions should have quoted spaces in the positional
+         parameters where necessary.  Suggested by Dan Douglas
+         <ormaaj@gmail.com>
+
+execute_cmd.c
+       - execute_command_internal: make sure any subshell forked to run a
+         group command or user subshell at the end of a pipeline runs any
+         EXIT trap it sets.  Fixes debian bash bug 698411
+         http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=698411
+
+subst.c
+       - shell_expand_word_list: fix code that creates args for and calls
+         make_internal_declare to avoid calling it twice (missing `else'
+         in 12/26 change)
+       - do_assignment_internal: fix code from 12/26 change to fix problem
+         where an existing assoc variable could be converted to an array
+         without checking `mkassoc'
+
+                                  1/24
+                                  ----
+builtins/evalfile.c
+       - _evalfile: add missing `close (fd)' calls before returning to
+         avoid fd leaks.  Bug and fix from Roman Rakus <rrakus@redhat.com>
+
+                                  1/25
+                                  ----
+builtins/read.def
+       - read_builtin: don't try to play tricks with the top of the unwind-
+         protect stack after read gets a SIGALRM; save input_string to new
+         memory, run the stack, then restore input_string and assign the
+         variables.  Part of fix for bug reported by konsolebox
+         <konsolebox@gmail.com>; the rest of the fix is with the changes in
+         trap and signal handling and doing away with interrupt_immediately
+
+                                  1/26
+                                  ----
+redir.c
+       - redirection_expand, write_here_string, write_here_document: before
+         calling any of the word expansion functions, after setting
+         expanding_redir to 1 (which bypasses the temp environment in the
+         variable lookup functions), call sv_ifs to reset the cached IFS-
+         related variables set by subst.c:setifs().  This ensures that
+         redirections will not get any IFS values that are set in the
+         temporary environment, as Posix specifies.  Then, after the word
+         expansions, after resetting expanding_redir to 0, call sv_ifs
+         again to make sure the cached IFS values are set from any
+         assignments in the temporary environment.  We force executing_builtin
+         to 1 to `fool' the variable lookup functions into using any temp
+         environment, then reset it to its old value after sv_ifs returns.
+         This is what allows read() to use the (cached) IFS variables set
+         in the temp environment. Fixes inconsistency reported by Dan Douglas
+         <ormaaj@gmail.com>
+
+                                  1/29
+                                  ----
+lib/readline/display.c
+       - update_line: fix off-by-one error when updating vis_lbreaks array
+         in a multibyte locale that occurs when moving multibyte chars from
+         one line down to another.  Bug report and fix from Egmont
+         Koblinger <egmont@gmail.com>
+
+                                  1/30
+                                  ----
+configure.ac
+       - changed version to 4.3-alpha
+
+redir.c
+       - redir_open: handle open returning -1/EINTR, which seems to happen
+         a lot with FIFOs and SIGCHLD, and call QUIT to handle other
+         signals that can interrupt open(2).  Bug report and initial fix
+         from Mike Frysinger <vapier@gentoo.org>
+
+                                  1/31
+                                  ----
+subst.c
+       - parameter_brace_expand: make sure to propagate the PF_ASSIGNRHS flag
+         to parameter_brace_expand_word
+       - parameter_brace_expand_word: make sure that if the PF_ASSIGNRHS flag
+         is set and we are expanding ${a[@]} or ${a[*]} we set quoted to
+         include Q_DOUBLE_QUOTES before calling array_value_internal, mirroring
+         what we do for $@ and $*.  Fixes inconsistency reported by Dan
+         Douglas <ormaaj@gmail.com>
+
+configure.ac
+       - use AC_CHECK_TOOL instead of AC_CHECK_PROG to check for ar, since it
+         will find $host-prefixed versions of utilities.  Report and fix from
+         Mike Frysinger <vapier@gentoo.org>
+
+builtins/setattr.def
+       - set_var_attribute: check whether bind_variable (called when the
+         variable whose attributes are being modified is found in the temp
+         environment) just modified a read-only global variable, and don't
+         bother marking the temporary variable for propagation if so.  The
+         propagation is superfluous and will result in a strange error
+         message
+
+                                   2/2
+                                   ---
+variables.c
+       - initialize_shell_variables: don't try to import function definitions
+         with invalid names from the environment if already in posix mode,
+         but create them as (invisible) exported variables so they pass
+         through the environment.  Print an error message so user knows
+         what's wrong.  Fixes bug reported by Tomas Trnka <ttrnka@mail.muni.cz>
+
+                                   2/9
+                                   ---
+
+builtins/read.def
+       - sigalrm_seen, alrmbuf: now global so the rest of the shell (trap.c)
+         can use them
+       - sigalrm: just sets flag, no longer longjmps to alrmbuf; problem was
+         longjmp without manipulating signal mask, leaving SIGALRM blocked
+
+quit.h
+       - move CHECK_ALRM macro here from builtins/read.def so trap.c:
+         check_signals() can call it
+
+trap.c
+       - check_signals: add call to CHECK_ALRM before QUIT
+       - check_signals_and_traps: call check_signals() instead of including
+         CHECK_ALRM and QUIT inline.  Integrating check for read builtin's
+         SIGALRM (where zread call to check_signals_and_traps can see it)
+         fixes problem reported by Mike Frysinger <vapier@gentoo.org>
+
+                                  2/12
+                                  ----
+lib/glob/xmbsrtowcs.c
+       - xdupmbstowcs2: fixed but where end of string was not handled
+         correctly, causing loop to go past end of string in a bunch of cases.
+         Fixes bug reported by "Dashing" <dashing@hushmail.com>
+
+
+                                  2/13
+                                  ----
+builtins/pushd.def
+       - popd_builtin: treat any argument that isn't -n or of the form
+         [-+][[:digit:]]* as an error.  Fixes problem reported by Bruce
+         Korb <bruce.korb@gmail.com>
+
+                                  2/14
+                                  ----
+configure.ac
+       - add check for sig_atomic_t; already a placeholder for it in
+         config.h.in
+
+                                  2/15
+                                  ----
+subst.c
+       - do_compound_assignment: don't call assign_compound_array_list with
+         a NULL variable in case make_local_xxx_variable returns NULL
+         (it will if you try to shadow a readonly or noassign variable).
+         Fixes bug reported by Richard Tollerton <rich.tollerton@ni.com>
+
+                                  2/16
+                                  ----
+variables.c
+       - make_local_variable: print error messager if an attempt is made to
+         create a local variable shadowing a `noassign' variable.  Previously
+         we just silently refused to do it
+
+trap.[ch]
+       - get_original_signal: now global so rest of the shell can use it
+
+sig.c
+       - initialize_shell_signals: install a signal handler for SIGTERM
+         that does nothing except set a sigterm_received flag instead of
+         ignoring it with SIG_IGN, as long as SIGTERM is not ignored when
+         the shell is started.  Use get_original_signal early to get the
+         original handler, since we will do that later anyway
+       - set_signal_handler: if installing sigterm_sighandler as the SIGTERM
+         handler, make sure to add SA_RESTART flag to make it as close to
+         SIG_IGN as possible
+
+sig.h
+       - sigterm_sighandler: new extern declaration
+
+quit.h
+       - RESET_SIGTERM: set sigterm_receved to 0
+       - CHECK_SIGTERM: check sigterm_received; if it's non-zero, treat it
+         as a fatal signal and call termsig_handler to exit the shell
+
+jobs.c
+       - make_child: call RESET_SIGTERM just before fork() so we can detect
+         if the child process received a SIGTERM before it's able to change
+         the signal handler back to what it was when the shell started
+         (presumably SIG_DFL).  Only has effect if the shell installed
+         sigterm_sighandler for SIGTERM, interactive shells that were not
+         started with SIG_IGN as the SIGTERM handler
+       - make_child: call RESET_SIGTERM in the parent after fork() so the
+         rest of the shell won't react to it
+
+execute_cmd.c
+       - execute_simple_command: call CHECK_SIGTERM after make_child in child
+         to catch SIGTERM received after fork() and before restoring old
+         signal handlers
+       - execute_disk_command: call CHECK_SIGTERM after make_child in child
+         process after restoring old signal handlers and again just before
+         calling shell_execve.  Fixes race condition observed by
+         Padraig Brady <p@draigbrady.com> when testing with his `timeout'
+         program
+
+lib/readline/display.c
+       - open_some_spaces: new function, subset of insert_some_chars that just
+         opens up a specified number of spaces to be overwritten
+       - insert_some_spaces: now just calls to open_some_spaces followed by
+         _rl_output_some_chars
+       - update_line: use col_temp instead of recalculating it using
+         _rl_col_width in the case where we use more columns with fewer bytes
+       - update_line: use open_some_spaces and then output the right number
+         of chars instead of trying to print new characters then overwrite
+         existing characters in two separate calls.  This includes removing
+         some dodgy code and making things simpler.  Fix from Egmont
+         Koblinger <egmont@gmail.com>
+       - use new variable `bytes_to_insert' instead of overloading temp in
+         some code blocks (nls - nfd, bytes that comprise the characters
+         different in the new line from the old)
+
+                                  2/18
+                                  ----
+redir.c
+       - do_redirection_internal: add undoable redirection for the implicit
+         close performed by the <&n- and >&n- redirections.  Fixes bug
+         reported by Stephane Chazelas <stephane.chazelas@gmail.com>
+
+                                  2/19
+                                  ----
+sig.c
+       - termsig_handler: an interactive shell killed by SIGHUP and keeping
+         command history will try to save the shell history before exiting.
+         This is an attempt to preserve the save-history-when-the-terminal-
+         window-is-closed behavior
+
+                                  2/21
+                                  ----
+braces.c
+       - brace_expand: if a sequence expansion fails (e.g. because the
+         integers overflow), treat that expansion as a simple string, including
+         the braces, and try to process any remainder of the string.  The
+         remainder may include brace expansions.  Derived from SuSE bug
+         804551 example (https://bugzilla.novell.com/show_bug.cgi?id=804551)
+
+                                  2/23
+                                  ----
+{quit,sig}.h,sig.c
+       - sigterm_received declaration now in sig.h; type is sig_atomic_t
+       - sigwinch_received type now sig_atomic_t
+       - sig.h includes bashtypes.h and <signal.h> if SIG_DFL not defined
+         (same logic as trap.h) to pick up sig_atomic_t
+
+unwind_prot.c
+       - include sig.h before quit.h (reverse order)
+
+                                  2/27
+                                  ----
+builtins/shopt.def
+       - reset_shopt_options: make sure check_window_size is reset to the
+         default from config.h, not unconditionally to 0
+
+jobs.[ch]
+       - last_made_pid, last_asynchronous_pid: now volatile.  Change from SuSE
+
+jobs.c
+       - wait_for: if we're using sigaction to install a handler for SIGCHLD,
+         make sure we specify SA_RESTART
+
+lib/{tilde,readline}/shell.c
+       - get_home_dir: instead of looking in the password file every time,
+         look once and cache the result
+
+sig.[ch]
+       - sigwinch_received, sigterm_received: now `volatile' qualified
+
+sig.c,quit.h
+       - interrupt_state,terminating_signal: now sig_atomic_t
+
+                                   3/1
+                                   ---
+MANIFEST,examples/*
+       - removed around 120 files without FSF copyrights; requested by
+         Karl Berry in early January
+
+                                   3/2
+                                   ---
+lib/malloc/malloc.c
+       - morecore: only check whether SIGCHLD is trapped if SIGCHLD is defined
+
+doc/bashref.texi
+       - Fixed most of the examples in the GNU Parallel section to use better
+         shell idioms following complaints on bug-bash; added a couple of
+         examples and smoothed out the text
+
+quit.h
+       - include "sig.h" for sig_atomic_t
+
+lib/readline/display.c
+       - update_line: when inserting one or more characters at the end of
+         the display line in a non-multibyte environment, just write from the
+         first difference to the end of the line and return. We don't have
+         to adjust _rl_last_c_pos.  This is needed to adjust from the old
+         two-part copy to a single call to _rl_output_some_chars (change of
+         2/16)
+
+                                   3/4
+                                   ---
+Makefile.in,doc/Makefile.in
+       - PACKAGE_TARNAME, docdir: new variables substituted by autoconf
+       - OTHER_DOCS,OTHER_INSTALLED_DOCS: new variables with auxiliary
+         documentation files to be installed into $(docdir)
+       - install: add new rule to install $(OTHER_DOCS)
+       - uninstall: add new rule to uninstall $(docdir)/$(OTHER_INSTALLED_DOCS)
+
+doc/bash.1
+       - add URL to `POSIX' file in `SEE ALSO' section; put pointer to that
+         section in --posix and set -o posix descriptions
+
+examples/
+       - removed around 110 examples at the request of the FSF due to copyright
+         issues
+
+                                   3/5
+                                   ---
+builtins/setattr.def
+       - readonly: modified help text slightly to make it clearer that
+         functions aren't changed or displayed unless the -f option is given.
+         Report from <gotmynick@gmail.com>
+
+                                   3/9
+                                   ---
+include/typemax.h
+       - SIZE_MAX: define to 65535 (Posix minimum maximum) if not defined
+
+parse.y
+       - include "typemax.h" for possible SIZE_MAX definition, make sure we
+         include it after shell.h
+
+{braces,expr}.c
+       - include "typemax.h" for possible INTMAX_MIN and INTMAX_MAX definitions
+
+                                  3/10
+                                  ----
+bashline.c
+       - bash_default_completion: make sure completion type of `!' (same as
+         TAB but with show-all-if-ambiguous set) and glob-word-completion
+         sets rl_filename_completion_desired to 0 so extra backslashes don't
+         get inserted by `quoting' the completion.  We can't kill all the
+         matches because show-all-if-ambiguous needs them.   Bug report from
+         Marcel (Felix) Giannelia <info@skeena.net>
+
+[bash-4.3-alpha frozen]
+
+                                  3/14
+                                  ----
+general.c
+       - trim_pathname: use memmove instead of memcpy since the source and
+         destination pathnames may overlap.  Report and fix from Matthew
+         Riley <mattdr@google.com>
+
+                                  3/18
+                                  ----
+configure.ac
+       - socklen_t is defined as `unsigned int' if configure can't find it
+
+                                  3/20
+                                  ----
+lib/readline/complete.c
+       - S_ISVTX: since it's not defined on all platforms (Minix), make sure
+         its use is protected with #ifdef
+
+                                  3/21
+                                  ----
+doc/{bash.1,bashref.texi}
+       - Added mention of ${!name[@]} and ${!name[*]} expansions to get all
+         indices of an array.  Suggested by Jonathan Leffler
+         <jonathan.leffler@gmail.com>
+
+                                  3/24
+                                  ----
+subst.h
+       - SD_IGNOREQUOTE: new define for skip_to_delim; if set, means that
+         single quotes (for now) will be treated as ordinary characters
+
+subst.c
+       - skip_to_delim: handle SD_IGNOREQUOTE. no callers use it for now
+
+                                  3/25
+                                  ----
+support/config.{guess,sub}
+       - updated to versions from autoconf-2.69
+
+                                  3/31
+                                  ----
+lib/sh/shquote.c
+       - sh_single_quote: short-circuit quoting a single "'" instead of
+         creating a long string with empty single-quoted strings
+
+parser.h
+       - DOLBRACE_QUOTE2: new define, like DOLBRACE_QUOTE, but need to single-
+         quote results of $'...' expansion because quote removal will be
+         done later.  Right now this is only done for ${word/pat/rep}
+
+parse.y
+       - parse_matched_pair: set state to DOLBRACE_QUOTE2 for pattern
+         substitution word expansion so we don't treat single quote specially
+         in the pattern or replacement string
+       - parse_matched_pair: if we're parsing a dollar-brace word expansion
+         (${...}) and we're not treating single quote specially within
+         double quotes, single-quote the translation of $'...' ansi-c
+         escaped strings.  Original report and fix from Eduardo A.
+         Bustamante López <dualbus@gmail.com>
+
+subst.c
+       - extract_dollar_brace_string: ${word/pat/rep} scanning now sets the
+         DOLBRACE_QUOTE2 flag instead of DOLBRACE_QUOTE so we don't treat
+         single quotes specially within a double-quoted string
+
+execute_cmd.c
+       - fix_assignment_words: skip over assignment statements preceding a
+         command word before trying to figure out whether or not assignment
+         statements following a possible declaration command should be 
+         treated specially.  Fixes bug reported by Dan Douglas
+         <ormaaj@gmail.com>
+
+                                   4/4
+                                   ---
+lib/readline/readline.c
+       - _rl_dispatch_subseq: only call _rl_vi_set_last (and check whether
+         the key is a text modification command) if the key sequence length
+         is 1.  That keeps the arrow keys from setting the last command
+         when called in vi command mode.  Fixes bug reported by Ian A.
+         Watson <watson_ian_a@lilly.com>
+
+                                   4/6
+                                   ---
+lib/readline/bind.c
+       - rl_parse_and_bind: when parsing a double-quoted string as the value
+         of a variable, make sure we skip past the leading double quote.
+         Fix from Andreas Schwab <schwab@linux-m68k.org>
+
+variables.c
+       - hash_lookup: set new local variable last_table_searched to the table
+         a successful lookup appears in; tested in make_local_variable to
+         solve the problem below
+       - make_local_variable: if we find a variable with the tempenv flag
+         set at the same `level' as variable_context', but not found in the
+         temporary_env (temp environment preceding the builtin), return it.
+         The temp environment preceding the function call has already been
+         merged (in execute_function) into the list of variable contexts the
+         function sees as shell_variables by the time this is called.  Fixes
+         inconsistency pointed out by Dan Douglas <ormaaj@gmail.com>
+
+subst.c
+       - expand_arith_string: expanded out contents of expand_string,
+         expand_string_internal, expand_string_if_necessary to create a
+         WORD_DESC and call call_expand_word_internal() on it directly.
+         We don't want process substitution to be performed ( 1<(2) ) should
+         mean something different in an arithmetic expression context.
+         It doesn't work to just turn on the DQUOTE flag, since that means
+         that things like ${x["expression"]} are not expanded correctly.
+         Fixes problem pointed out by Dan Douglas <ormaaj@gmail.com>
+
+                                  4/13
+                                  ----
+subst.c
+       - process_substitute: run the EXIT trap before exiting, as other
+         shells seem to.  Fixes problem pointed out by Dan Douglas
+         <ormaaj@gmail.com>
+
+lib/readline/readline.c
+       - readline_internal_setup: call rl_vi_insertion_mode to enter vi
+         mode instead of rl_vi_insert_mode to avoid resetting the saved last
+         command information.  Posix says that `.' can repeat a command
+         that was entered on a previous line so we need to save the info.
+         Fixes bug reported by Ian A. Watson <watson_ian_a@lilly.com>
+
+                                  4/14
+                                  ----
+lib/readline/complete.c
+       - rl_completion_matches: make sure xrealloc returns something non-null
+         (can happen when interrupted by a signal) before trying to add
+         matches to match_list
+
+subst.c
+       - array_remove_pattern: return NULL right away if array_variable_part
+         returns an invisible variable
+       - array_length_reference: handle array_variable_part returning an
+         invisible variable
+       - get_var_and_type: handle array_variable_part returning an invisible
+         variable
+
+                                  4/15
+                                  ----
+execute_cmd.c
+       - execute_command_internal: make sure to run the EXIT trap for group
+         commands anywhere in pipelines, not just at the end.  From a point
+         raised by Andreas Schwab <schwab@linux-m68k.org>
+
+variables.c
+       - bind_int_variable: make sure invisible flag is unset.  Fixes problems
+         like "declare -ai a; : $(( a[4]=4 ));"
+
+arrayfunc.c
+       - array_variable_part: return variable even if invisible flag set,
+         callers must handle invisible vars
+
+                                  4/18
+                                  ----
+builtins/set.def
+       - unset_builtin: if -n flag given, call unset_nameref instead of
+         unset_variable
+
+variables.c
+       - find_variable_nameref: print warning message if nameref circular
+         reference detected, return NULL and let caller deal with it
+
+builtins/declare.def
+       - declare_builtin: only disallow global references at this point if
+         we are at the global scope
+
+                                  5/16
+                                  ----
+configure.ac
+       - update release status to beta
+
+                                  5/23
+                                  ----
+trap.c
+       - run_pending_traps: save and restore pipeline around calls to
+         evalstring() in case we get a trap while running a trap. Have to
+         figure out the recursive running traps issue elsewhere.  Fixes
+         bug reported by Roman Rakus <rrakus@redhat.com>
+       - run_pending_traps: make sure to set running_trap to the appropriate
+         signal value when running a trap command
+       - run_pending_traps: short-circuit immediately if running_trap set
+         when invoked.  Could change this later to only skip if it would
+         run the same trap as currently being run (running_trap == sig + 1)
+
+configure.ac
+       - add warning if bison not found
+
+lib/readline/doc/rltech.texi
+       - new section with an example program illustrating the callback
+         interface. Suggested by Peng Yu <pengyu.ut@gmail.com>
+
+examples/loadables/Makefile.in
+       - remove references to `cut' and `getconf', which were removed in
+         early March
+
+                                  5/28
+                                  ----
+lib/sh/pathphys.c
+       - sh_realpath: correct inverted two arguments to call to sh_makepath.
+         Report and fix from Julien Thomas <jthomas@exosec.fr>
+
+                                   6/7
+                                   ---
+execute_cmd.c
+       - executing_line_number: the else clauses that are conditional on
+         various options being defined can simply be if clauses -- they are
+         mutually exclusive and all have `return' in the body.  Fixes bug
+         reported by Flavio Medeiros <flaviomotamedeiros@gmail.com>
+
+                                  6/25
+                                  ----
+lib/readline/readline.c
+       - readline_internal_setup: only sent the meta-key enable string to the
+         terminal if we've been told to use one and the terminal has been
+         successfully initialized (RL_ISSTATE (RL_STATE_TERMPREPPED) != 0).
+         Suggested by Dan Mick <dan.mick@inktank.com>
+
+lib/readline/signals.c
+       - _rl_signal_handler: call any defined signal hook after calling
+         rl_resize_terminal when handling a SIGWINCH.  We already have called
+         the original SIGWINCH handler but will not be resending the signal
+         to ourselves
+
+                                  6/27
+                                  ----
+lib/readline/doc/history.3, doc/bash.1
+       - fix description of the `$' modifier to note that it expands to the
+         last *word*, which is not always the last argument.  Report from
+         ariyetz@gmail.com via gnu.org RT
+
+                                  6/29
+                                  ----
+lib/glob/smatch.c
+       - glob_asciiranges: initialize to value of GLOBASCII_DEFAULT instead
+         of 0 (0 if not defined)
+
+configure.ac,config.h.in
+       - --enable-glob-asciiranges-default: new option, controls the value of
+         GLOBASCII_DEFAULT; use it to turn globasciiranges shopt option on
+         by default
+
+doc/bashref.texi
+       - document new --enable-glob-asciiranges-default configure option
+
+variables.c
+       - assign_in_env: implement += value appending semantics for assignments
+         preceding command names
+
+                                   7/4
+                                   ---
+expr.c
+       - set lasttok = NUM in all of the functions that result in a number,
+         even if it's a boolean, to avoid errors with constructs like
+         1 * x = 1, which should be an asignment error.  Fixes problem
+         pointed out by Dan Douglas <ormaaj@gmail.com>
+
+parse.y
+       - decode_prompt_string: don't bother to call strcpy if
+         polite_directory_format returns its argument unchanged.  It's not
+         necessary and Mac OS X 10.9 aborts because of a supposed overlapping
+         string copy.  Bug and fix from simon@hitzemann.org
+
+subst.c
+       - parameter_brace_find_indir: new function, code from
+         parameter_brace_expand_indir that looks up the indirectly-referenced
+         variable, but does not expand it
+       - parameter_brace_expand_indir: call parameter_brace_find_indir to
+         look up indirected variable reference
+       - get_var_and_type: call parameter_brace_find_indir if it looks like we
+         are trying to manipulate an indirect variable reference like
+         ${!b%%foo}.  This makes a difference if !b references an array
+         variable.  Bug report from Dan Douglas <ormaaj@gmail.com>
+
+                                   7/6
+                                   ---
+lib/sh/casemod.c
+       - sh_modcase: make sure argument passed to is_basic is <= UCHAR_MAX,
+         since cval can convert something to a wchar_t greater than UCHAR_MAX.
+         Fixes bug reported by Tomasz Tomasik <scx.mail@gmail.com>
+
+                                   7/8
+                                   ---
+lib/readline/history.c
+       - add_history_time: if history_length == 0, referencing history_length
+         - 1 will result in an array bounds error, so make history_length be
+         at least 1 before going on.  Fixes bug reported by Geng Sheng Liu
+         <gsliu.tju@gmail.com>
+
+builtins/setattr.def
+       - show_func_attributes: display definition (if NODEFS argument is 0) and
+         attributes for a particular function; used by `declare -fp name'
+
+builtins/declare.def
+       - declare_internal: call show_func_attributes if -f supplied with -p.
+         Fixes inconsistency observed by Linda Walsh <bash@tlinx.org>
+
+builtins/common.h
+       - new extern declaration for show_func_attributes
+
+builtins/read.def
+       - read_builtin: check the first supplied variable name for validity
+         before attempting to read any input, since we know we will have to
+         at least use that one.  Don't check any other names yet.  Suggested
+         by jidanni@jidanni.org
+
+                                  7/10
+                                  ----
+redir.c
+       - do_redirection_internal: when closing a file descriptor with
+         r_close_this ([n]<&-) count close errors as redirection errors if
+         errno ends up as EIO or ENOSPC.  Originally reported back in April
+         2012 by Andrey Zaitsev <jstcdr@gmail.com>
+
+                                  7/11
+                                  ----
+redir.c
+       - do_redirection_internal: before calling check_bash_input, make sure
+         that we don't call check_bash_input for an asynchronous process that
+         is replacing stdin with something else. The seek backwards affects
+         the parent process as well, since parents and children share the
+         file pointer. Fixes problem originally reported in March 2013 by
+         Martin Jackson <mjackson220.list@gmail.com>
+
+                                  7/13
+                                  ----
+doc/{bash.1,bashref.texi}
+       - slight change to add a description of `shopt -o' suggested by Bruce
+         Korb <bruce.korb@gmail.com>
+
+                                  7/19
+                                  ----
+lib/readline/histfile.c
+       - history_do_write: if close returns < 0, make sure we restore the
+         backup history file and return a non-zero value
+       - history_truncate_file: if write or close return < 0, make sure we
+         return a non-zero value
+
+[bash-4.3-beta frozen]
+
+                                  7/21
+                                  ----
+lib/readline/isearch.c
+       - rl_display_search: now takes an entire search context flags word as
+         the second argument, instead of just reverse flag; changed callers
+       - rl_display_search: if the search has failed, add `failed ' to the
+         beginning of the search prompt
+       - _rl_isearch_dispatch: if the search has failed, display the entire
+         search string with an indication that the search failed but with the
+         last matching line.  Suggested by jidanni@jidanni.org
+
+command.h
+       - W_ASSIGNINT: new word flag; used internally for make_internal_declare
+         and set by fix_assignment_words
+
+execute_cmd.c
+       - fix_assignment_words: set W_ASSIGNINT if compound assignment and -i
+         given as option.  We don't do anything with the value yet
+
+subst.c
+       - shell_expand_word_list: rework the way the option list that is
+         passed to make_internal_declare is created
+
+                                   8/1
+                                   ---
+doc/{bash.1,bashref.texi}
+       - minor changes to description of $! based on a report from Chris
+         Down <chris@chrisdown.name>
+
+arrayfunc.c
+       - assign_array_element_internal: before trying to get an array's max
+         index to process a negative subscript, make sure the array exists.
+         Bug report from Geir Hauge <geir.hauge@gmail.com>
+
+                                   8/2
+                                   ---
+arrayfunc.c
+       - assign_array_element_internal: before using array_max_index() when
+         processing a negative subscript, make sure the variable is an array.
+         if it's not, use 0 as array_max_index assuming it's a string.
+         Fixes bug report from Geir Hauge <geir.hauge@gmail.com>
+
+                                   8/3
+                                   ---
+Makefile.in
+       - pcomplete.o: add dependency on $(DEFDIR)/builtext.h. Suggested by
+         Curtis Doty <curtis@greenkey.net>
+
+                                   8/5
+                                   ---
+lib/glob/sm_loop.c
+       - strcompare: short-circuit and return FNM_NOMATCH if the lengths of the
+         pattern and string (pe - p  and se - s, respectively) are not equal
+       - strcompare: don't bother trying to set *pe or *se to '\0' if that's
+         what they already are.  Fixes bug reported by Geir Hauge
+         <geir.hauge@gmail.com>
+
+                                   8/6
+                                   ---
+doc/{bash.1,bashref.texi},builtins/hash.def,lib/readline/doc/rluser.texi
+       - minor typo changes from Geir Hauge <geir.hauge@gmail.com>
+
+bultins/help.def
+       - show_longdoc: avoid trying to translate the empty string because it
+         often translates to some boilerplate about the project and
+         translation.  Report and fix from Geir Hauge <geir.hauge@gmail.com>
+
+                                   8/8
+                                   ---
+builtins/help.def
+       - help_builtin: try two passes through the list of help topics for each
+         argument: one doing exact string matching and one, if the first pass
+         fails to find a match, doing string prefix matching like previous
+         versions.  This prevents `help read' from matching both `read' and
+         `readonly', but allows `help r' to match everything beginning with
+         `r'.  Inspired by report from Geir Hauge <geir.hauge@gmail.com>
+
+                                  8/13
+                                  ----
+builtins/fc.def
+       - fc_builtin,fc_gethnum: calculate `real' end of the history list and
+         use it if -0 is specified as the beginning or end of the history
+         range to list.  Doesn't work for fc -e or fc -s by design.  Feature
+         requested by Mike Fied <micfied@gmail.com>
+
+                                  8/16
+                                  ----
+trap.c
+       - _run_trap_internal: use {save,restore}_parser_state instead of
+         {save,restore}_token_state. It's more comprehensive
+
+                                  8/23
+                                  ----
+doc/bash.1
+       - disown: remove repeated text.  Report and fix from Thomas Hood
+         <jdthood@gmail.com>
+
+                                  8/25
+                                  ----
+lib/readline/rltty.c
+       - set_special_char: fix prototype (last arg is rl_command_func_t *)
+
+sig.c
+       - set_signal_handler: return oact.sa_handler only if sigaction
+         succeeds; if it doesn't, return SIG_DFL (reasonable default).  From
+         https://bugzilla.redhat.com/show_bug.cgi?id=911404
+
+bashline.c
+       - attempt_shell_completion: fix to skip assignment statements preceding
+         command name even if there are no programmable completions defined.
+         From https://bugzilla.redhat.com/show_bug.cgi?id=994659
+       - attempt_shell_completion: if still completing command word following
+         assignment statements, do command completion even if programmable
+         completion defined for partial command name entered so far
+
+                                  8/26
+                                  ----
+pcomplete.c
+       - pcomp_filename_completion_function: make sure rl_filename_dequoting_function
+         is non-NULL before trying to call it.  Bug and fix from
+         Andreas Schwab <schwab@linux-m68k.org>
+
+bashline.c
+       - bash_command_name_stat_hook: if *name is not something we're going
+         to look up in $PATH (absolute_program(*name) != 0), just call the
+         usual bash_filename_stat_hook and return those results.  This makes
+         completions like $PWD/exam[TAB] add a trailing slash
+
+                                   9/2
+                                   ---
+builtins/read.def
+       - read_builtin: before comparing what we read to the delim, make sure
+         we are not supposed to be ignoring the delimiter (read -N).  We
+         set the delim to -1, but it's possible to read a character whose
+         int value ends up being between -1 and -128.  Fixes bug
+         reported by Stephane Chazelas <stephane.chazelas@gmail.com>
+
+doc/{bash.1,bashref.texi}
+       - word splitting: crib some language from Posix to make it clear that
+         characters in IFS are treated as field *terminators*, not field
+         *separators*.  Addresses issue raised by DJ Mills
+         <danielmills1@gmail.com>
+
+lib/readline/{util.c,rldefs.h}
+       - _rl_stricmp,_rl_strnicmp: now take const char * string arguments;
+         changed prototype declarations
+
+                                   9/5
+                                   ---
+doc/{bash.1,bashref.texi}
+       - [[: modify description of pattern matching to make it clear that the
+         match is performed as if the extglob option were enabled.  From Red
+         Hat bug https://bugzilla.redhat.com/show_bug.cgi?id=1002078
+
+                                  9/12
+                                  ----
+lib/readline/isearch.c
+       - _rl_isearch_dispatch: if we read an ESC and it's supposed to
+         terminate the search, make sure we check for typeahead with
+         _rl_pushed_input_available, since installing a hook function causes
+         typeahead to be collected in `ibuffer' (input.c).  If there is any,
+         make sure we still use the ESC as a prefix character.  Bug and fix
+         from Mike Miller <mtmiller@ieee.org>
+
+                                  9/16
+                                  ----
+builtins/{caller,cd,kill,pushd,wait}.def
+       - builtin_usage(): make sure call to this sets return status to
+         EX_USAGE
+
+                                  9/18
+                                  ----
+terminal.c
+       - rl_change_environment: new application-settable variable; if non-
+         zero (the default), readline will modify LINES and COLUMNS in the
+         environment when it handles SIGWINCH
+       - _rl_get_screen_size: if rl_change_environment is non-zero, use setenv
+         to modify LINES and COLUMNS environment variables
+
+readline.h
+       - rl_change_environment: new extern declaration for applications
+
+                                  9/22
+                                  ----
+configure.ac
+       - relstatus: bumped version to bash-4.3-beta2
+
+                                  9/24
+                                  ----
+
+lib/readline/readline.c
+       - bind_arrow_keys_internal: added more key bindings for the numeric key
+         pad arrow keys on mingw32.  Patch from Pierre Muller
+         <pierre.muller@ics-cnrs.unistra.fr>
+
+                                  10/19
+                                  -----
+
+bashline.c
+       - maybe_restore_tilde: version of restore_tilde that honors `direxpand';
+         calls restore_tilde after saving directory expansion hook if
+         necessary.  Report from Andreas Schwab <schwab@linux-m68k.org>
+
+builtins/cd.def
+       - -@: new option, allows cd to use `extended attributes' present in
+         NFSv4, ZFS; idea taken from ksh93.  Attributes associated with a
+         file are presented as a directory containing the attributes as
+         individual files.  Original patch contributed by Cedric Blancher
+         <cedric.blancher@gmail.com>
+
+                                  10/20
+                                  -----
+aclocal.m4
+       - BASH_CHECK_MULTIBYTE: check for wcwidth being broken with unicode
+         combining characters needs a value to use when cross-compiling.
+         Bug report from Bert Sutherland <bertsutherland@gmail.com>
+
+doc/{bash.1,bashref.texi}
+       - document new -@ option to cd builtin
+
+                                  10/28
+                                  -----
+lib/glob/{{gmisc,glob}.c,glob.h}
+       - extglob_pattern renamed to extglob_pattern_p, declared in glob.h
+
+subst.c
+       - expand_word_internal: typo fix: case to fix " $@\ " bug in bash-4.2
+         had a typo (& isexp instead of &&)
+
+                                  10/29
+                                  -----
+input.c
+       - getc_with_restart: make sure local_index and local_bufused are
+         reset to 0 before returning EOF, in case we are running an interactive
+         shell without line editing and ignoreeof is set.  Report and fix
+         from Yong Zhang <yong.zhang@windriver.com>
+
+lib/readline/search.c
+       - _rl_nsearch_init: take out extra third argument to rl_message; it
+         only matches prototype (and maybe format) in cases where
+         PREFER_STDARG and USE_VARARGS are both undefined, which is rare
+
+                                  10/31
+                                  -----
+subst.c
+       - process_substitute: when opening the named pipe in the child, open
+         without O_NONBLOCK to avoid race conditions.  Happens often on AIX.
+         Bug report and fix from Michael Haubenwallner
+         <michael.haubenwallner@salomon.at>
+
+builtins/ulimit.def
+       - RLIMIT_NTHR: if RLIMIT_PTHREAD is not defined, but RLIMIT_NTHR is,
+         use RLIMIT_NTHR (NetBSD)
+
+                                  11/5
+                                  ----
+locale.c
+       - set_default_locale_vars,set_locale_var: if TEXTDOMAINDIR has been
+         set, and default_dir has a non-null value, call bindtextdomain(3)
+         when TEXTDOMAIN is assigned a value.  Fixes problem reported by
+         Michael Arlt <qwertologe@googlemail.com>
+
+                                  11/6
+                                  ----
+builtins/cd.def
+       - cdxattr: only create synthetic pathname in `buf' if NDIRP argument
+         is non-null
+       - change_to_directory: if we have specified -@ and cdxattr returns
+         failure, fail immediately.  Fixes bug reported by Joshuah Hurst
+         <joshhurst@gmail.com>
+
+                                  11/12
+                                  -----
+redir.c
+       - print_redirection: change r_err_and_out (&>) and its append form,
+         r_append_err_and_out (&>>) cases to separate redirection operator
+         from filename by a space, in case we have a process substitution.
+         Fixes bug reported by admn ombres <admn.ombres@gmail.com>
+
+                                  11/15
+                                  -----
+execute_cmd.c
+       - execute_simple_command: don't close process substitution fds until
+         we are finished executing any current shell function.  Partial fix
+         for bug reported by John Dawson <john.dawson@gmail.com>
+
+support/shobj-conf
+       - add support for Darwin 13 (Mac OS X 10.9, Mavericks).  Based on a
+         report by Ludwig Schwardt <ludwig.schwardt@gmail.com>
+
+                                  11/20
+                                  -----
+[bash-4.3-rc1 frozen]
+
+                                  11/24
+                                  -----
+builtins/printf.def
+       - bind_printf_variable: make sure that the variable assigned to is
+         no longer marked as invisible. Fixes bug reported by NBaH
+         <nbah@sfr.fr>
+
+                                  11/28
+                                  -----
+jobs.c
+       - delete_old_job: fix off-by-one error in job index in call to
+         internal_warning. Bug report from Peter Cordes <peter@cordes.ca>
+
+                                  11/30
+                                  -----
+doc/bashref.texi
+       - add string to description of special parameters with name of
+         special parameter prefixed by a $, so you can search for $#,
+         for instance
+
+                                  12/2
+                                  ----
+lib/readline/{histexpand.c
+       - get_history_event: account for current_history() possibly returning
+         NULL. Report and fix from Pankaj Sharma <pankaj.s01@samsung.com>
+
+
+                                  12/11
+                                  -----
+
+lib/readline/parse-colors.c
+       - get_funky_string: don't call abort if we see something we can't
+         parse; just return an error
+       - _rl_parse_colors: if we encounter an error while parsing $LS_COLORS
+         we need to leave _rl_color_ext_list as NULL after freeing its
+         elements, then turn off _rl_colored_stats. Report and fix from Martin
+         Wesdorp <mwesdorp@casema.nl>
+
+                                  12/13
+                                  -----
+
+lib/readline/parse-colors.c
+       - _rl_parse_colors: if we encounter an unrecognized prefix, throw an
+         error but try to recover and go on to the next specification
+
+variables.c
+       - make_local_variable: for new variables this function creates, set
+         the att_invisible attribute.  All callers from declare_internal.
+         Indirectly, this is a fix for bug with `declare -n var; var=foo;'
+         reported by Pierre Gaston <pierre.gaston@gmail.com>
+       - bind_variable: if assigning to nameref variable that doesn't have
+         a value yet (e.g., with `declare -n var; var=foo'), don't try to
+         use the unset name. Fixes a segfault reported by Pierre Gaston
+         <pierre.gaston@gmail.com>
+
+execute_cmd.c
+       - execute_command_internal: make sure last_command_exit_value is set
+         to 0 after any command executed in the background.  Fixes bug
+         reported by Martin Kealey <martin@kurahaupo.gen.nz>
+
+                                  12/17
+                                  -----
+support/config.{guess,sub}
+       - updated to latest versions from git
+
+                                  12/19
+                                  -----
+parse.y
+       - struct STRING_SAVER: now has a new `flags' element, to identify the
+         caller: alias expansion, double-paren parsing, or parse_and_execute
+       - push_string: now sets flags to PSH_ALIAS if `ap' argument is non-NULL
+       - push_string: now doesn't attempt to call strlen on a NULL string to
+         set shell_input_line_size
+       - parser_expanding_alias, parser_save_alias, parser_restore_alias: new
+         functions to provide an external interface to push_string and
+         pop_string; parser_save_alias sets flags element to PSH_SOURCE (could
+         be renamed PSH_EXTERN someday)
+       - shell_getc: when yy_getc returns '\0', instead of just testing
+         whether the pushed_string_list is not-empty before popping it, don't
+         pop if if the saved string has flags PSH_SOURCE, indicating that
+         parse_and_execute set it before setting bash_input to the string.
+         We should continue reading to the end of that string before popping
+         back to a potential alias. Partial solution for the problem of aliases
+         with embedded newlines containing `.' commands being executed out of
+         order reported by Andrew Martin <andrew.martin@gmail.com>
+       - shell_getc: when yy_getc returns '\0' and there is a saved string of
+         type PSH_SOURCE, restart the read without popping the string stack
+         if we have not read to the end of bash_input.location.string.  Rest
+         of fix for out-of-order execution problem
+
+externs.h
+       - parser_expanding_alias, parser_save_alias, parser_restore_alias: new
+         extern function declarations
+
+builtins/evalstring.c
+       - pe_prologue: if the parser is expanding an alias, make sure to add
+         an unwind-protect to restore the alias; undoes the work that will be
+         performed by parse_and_execute/parse_string
+       - parse_and_execute,parse_string: after calling push_stream to save
+         bash_input, check whether or not the parser is currently expanding
+         an alias (parser_expanding_alias() != 0). If it is, we want to save
+         that string in the pushed_string_list, which we do with
+         parser_save_alias.
+
+                                  12/23
+                                  -----
+execute_cmd.c
+       - execute_for_command: make sure to set line_number before expanding
+         the word list, so expansion errors have the right line number.
+         From a report from Ben Okopnik <ben@okopnik.com>
+
+expr.c
+       - exp2: save token pointer before calling readtok(), arrange to use
+         saved token pointer when printing error token on a division by 0
+         error
+
+                                  12/27
+                                  -----
+lib/readline/display.c
+       - rl_redisplay: when calculating effects of invisible characters in a
+         prompt that is split across physical screen lines to set the indices
+         of linebreaks, don't bother testing local_prompt_prefix (line 751).
+         That prefix doesn't matter when calculating prompt visible and
+         invisible characters.  Fixes problem reported by Jinesh Choksi
+         <jinesh@onelittlehope.com>
+
+Makefile.in
+       - install: make sure to use $(DESTDIR) when installing OTHER_DOCS.
+         Report and fix from Matthias Klose <doko@debian.org>
+
+doc/texinfo.tex
+       - updated to version of 2013-09-11
+
+                                  12/28
+                                  -----
+lib/readline/undo.c
+       - rl_do_undo: if we are undoing from a history entry (rl_undo_list ==
+         current_history()->data), make sure the change to rl_line_buffer is
+         reflected in the history entry. We use the guts of
+         rl_maybe_replace_line to do the work.  Fixes problem reported by
+         gregrwm <backuppc-users@whitleymott.net>
+
+                                  12/30
+                                  -----
+sig.c
+       - sigint_sighandler: if we get a SIGINT (and this signal handler is
+         installed) while the wait builtin is running, note that we received
+         it in the same way as jobs.c:wait_sigint_handler and return.  The
+         various wait_for functions will look for that with CHECK_WAIT_INTR.
+         This fixes the wait builtin not being interruptible in an interactive
+         job control shell
+
+                                  12/31
+                                  -----
+trap.c
+       - set_signal_hard_ignored: rename set_signal_ignored to this, since it
+         both sets original_signals[sig] and sets the HARD_IGNORE flag
+       - set_signal_ignored: new function, now just sets original_signals[sig]
+
+trap.h
+       - set_signal_hard_ignored: new external declaration
+
+sig.c
+       - initialize_terminating_signals: call set_signal_hard_ignored instead
+         of set_signal_ignored for signals with disposition SIG_IGN when the
+         shell starts
+
+execute_cmd.c
+       - setup_async_signals: make sure we get the original dispositions for
+         SIGINT and SIGQUIT before starting the subshell, and don't call
+         set_signal_ignored  because that sets original_signals[sig].  If we
+         don't, subsequent attempts to reset handling using trap will fail
+         because it thinks the original dispositions were SIG_IGN. Posix
+         interpretation 751 (http://austingroupbugs.net/view.php?id=751)
+
+                                1/2/2014
+                                --------
+lib/sh/stringvec.c
+       - strvec_mcreate, strvec_mresize: versions of create and resize that
+         use malloc and realloc, respectively, instead of xmalloc/xrealloc
+
+braces.c
+       - expand_amble,mkseq: use strvec_mcreate/strvec_mresize so we can
+         catch and handle memory allocation failures instead of aborting
+         with the xmalloc/xrealloc interface
+
+lib/sh/strdup.c
+       - strdup replacement function for ancient systems that don't have it
+
+lib/sh/itos.c
+       - mitos: new function, itos that uses strdup instead of savestring
+
+externs.h
+       - strvec_mcreate/strvec_mresize: new extern declarations
+       - mitos: new extern declaration
+
+configure.ac
+       - bash version moved to 4.3-rc2
+
+                                   1/6
+                                   ---
+doc/bash.1,lib/readline/doc/{rluser.texi,readline.3}
+       - separate the description of what happens when readline reads the
+         tty EOF character from the description of delete-char, leaving a
+         note in the delete-char description about common binding for ^D.
+         From suggestion by Parke <parke.nexus@gmail.com>
+
+lib/readline/doc/{version.texi,history.3,*.texi}
+       - updated email addresses and copyright dates
+
+                                   1/7
+                                   ---
+variables.c
+       - delete_var: new function, just removes a variable from a hash table
+         and frees it, without doing anything else
+       - make_variable_value: if we are trying to assign to a nameref variable,
+         return NULL if the value is null or the empty string or not a valid
+         identifier
+
+variables.h
+       - delete_var: new extern declaration
+
+subst.h
+       - ASS_NAMEREF: new define for assignments, means assigning to a nameref
+         variable
+
+builtins/declare.def
+       - declare_internal: if we are creating and assigning to a nameref
+         variable, make sure the value is a valid variable name (checks done
+         by make_variable_value via bind_variable_value) and display an
+         error message, deleting the variable we just created, if it is not.
+         Fixes bug reported by Peggy Russell <prusselltechgroup@gmail.com>
+
+                                   1/9
+                                   ---
+builtins/declare.def
+       - declare_internal: turning on nameref attribute for an existing
+         variable turns off -i/-l/-u/-c attributes (essentially the ones
+         that cause evaluation at assignment time) for ksh93 compat
+
+builtins/setattr.def
+       - show_name_attributes: if asked to display attributes and values for
+         a nameref variable, don't follow the nameref chain to the end. More
+         ksh93 compat
+
+                                  1/10
+                                  ----
+trap.c
+       - _run_trap_internal: use {save,restore}_parser_state instead of
+         {save,restore}_token_state, like in run_pending_traps(); don't
+         need to save and restore last_command_exit_value as a result
+       - _run_trap_internal: call {save,restore}_pipeline like in
+         run_pending_traps()
+       - run_pending_traps: since we no longer run traps in a signal handler
+         context, do not block and unblock the trapped signal while the
+         trap is executing
+       - run_pending_traps: allow recursive invocations (basically, running
+         traps from a trap handler) with only a warning if the shell is
+         compiled in debug mode.  If a caller doesn't want this to happen,
+         it should test running_trap > 0. signal_in_progress (sig) only works
+         for the signals the shell handles specially
+
+bashline.c
+       - bash_event_hook: make sure we clean up readline if interrupt_state
+         is set, not only when SIGINT is not trapped.  check_signals_and_traps
+         will call check_signals, which calls QUIT, which will longjmp back
+         to top_level, running the interrupt trap along the way.  Fixes the
+         problem of signal handlers being reset out from under readline, and
+         not being set properly the next time readline is called, because
+         signals_set_flag is still set to 1.  XXX - might need to do this
+         for other signals too?
+
+                                  1/11
+                                  ----
+subst.h
+       - SD_GLOB: new define for skip_to_delim; means we are scanning a
+         glob pattern.
+
+subst.c
+       - skip_to_delim: if flags include SD_GLOB, assume we are scanning a
+         glob pattern.  Currently only used to skip bracket expressions
+         which may contain one of the delimiters
+
+                                  1/12
+                                  ----
+subst.c
+       - parameter_brace_expand: when expanding $@ as part of substring
+         expansion, pattern substitution, or case modification, don't turn
+         on the QUOTED_NULL flag.  The code that constructs the word to be
+         returned from expand_word_internal expects a different code path
+         when $@ is being expanded.  Fixes bug reported by Theodoros
+         V. Kalamatianos <thkala@gmail.com>
+
+                                  1/19
+                                  ----
+subst.c
+       - list_dequote_escapes: new function; analogue of list_quote_escapes
+
+pathexp.c
+       - quote_string_for_globbing: fix case where unescaped ^A is last char
+         in string; need to pass it through unaltered instead of turning it
+         into a bare backslash
+       - quote_string_for_globbing: when quoting for regexp matching in [[,
+         don't treat backslash as a quote character; quote the backslash as
+         any other character.  Part of investigation into reports from
+         Eduardo A. Bustamante López <dualbus@gmail.com>
+
+                                  1/25
+                                  ----
+builtins/gen-helpfiles.c
+       - write_helpfiles: add prototype
+       - make sure to #undef xmalloc/xfree/xrealloc/free if USING_BASH_MALLOC
+         is defined. the code does not use them, and we don't link against
+         xmalloc.o. Report from Linda Walsh <bash@tlinx.org>
+
+Makefile.in
+       - variables.o: add dependency on builtins/builtext.h; helps with
+         parallel builds.  Report from Linda Walsh <bash@tlinx.org>
+
+support/shobj-conf
+       - darwin: combine the stanzas into one that will not require them to
+         be updated on each Mac OS X release.  Report and fix from Max Horn
+         <max@quendi.de>
+
+                                  1/27
+                                  ----
+support/shobj-conf
+       - darwin: changed the install_name embedded into the shared library
+         to contain only the major version number, not the minor one. The
+         idea is that the minor versions should all be API/ABI compatible,
+         and it is better to link automatically with the latest one.  Idea
+         from Max Horn <max@quendi.de>
+
+                                  1/29
+                                  ----
+[bash-4.3-rc2 released]
+
+                                  1/30
+                                  ----
+lib/readline/readline.h
+       - rl_clear_history, rl_free_keymap: add extern declarations.  Report
+         from Hiroo Hayashi <hiroo.hayashi@computer.org>
+
+general.c
+       - include trap.h for any_signals_trapped() prototype
+
+lib/sh/unicode.c
+       - include <stdio.h> for sprintf prototype
+
+                                  1/31
+                                  ----
+execute_cmd.c
+       - execute_simple_command: only posix-mode shells should exit on an
+         assignment failure in the temporary environment preceding a special
+         builtin. This is what the documentation and code comments have
+         always said
+       - execute_simple_command: make sure redirection errors, word expansion
+         errors, and assignment errors to Posix special builtins cause a
+         non-interactive posix mode shell to exit.  Previously the shell
+         would not exit if the failed special builtin was on the LHS of ||
+         or &&
+
+pathexp.c
+       - quote_string_for_globbing: when quoting a regular expression
+         (QGLOB_REGEXP), allow an unquoted backslash to pass through
+         unaltered. Don't use it as a quote character or quote it.  More
+         investigation from 1/24 and report by Mike Frysinger
+         <vapier@gentoo.org>
+       - quote_string_for_globbing: when quoting a regular expression
+         (QGLOB_REGEXP), turn CTLESC CTLESC into CTLESC without adding a
+         backslash to quote it. We should not have to quote it because it is
+         not a character special to EREs. More investigation from 1/24
+
+lib/glob/glob.c
+       - glob_testdir: now takes a second flags argument (currently unused);
+         changed prototype and callers
+
+                                   2/1
+                                   ---
+lib/glob/glob.c
+       - glob_testdir: if flags argument includes GX_ALLDIRS (globstar), use
+         lstat so we skip symlinks when traversing the directory tree.
+         Originally reported by Chris Down <chris@chrisdown.name>
+
+                                   2/2
+                                   ---
+lib/readline/undo.c
+       - rl_do_undo: make sure CUR is non-zero before dereferencing it to
+         check cur->data against rl_undo_list.  Report and fix from
+         Andreas Schwab <schwab@linux-m68k.org>
+
+doc/{bash.1,bashref.texi}
+       - added slight clarifying language to the description of $*,
+         describing what happens when the expansion is not within double
+         quotes
+
+                                   2/4
+                                   ---
+test.c
+       - unary_test: add code to -v case so that it interprets `bare' array
+         references (foo[1]) and returns true if that index has a value
+
+                                   2/5
+                                   ---
+trap.c
+       - restore_default_signal: fix SIGCHLD special case for SIG_TRAPPED flag
+         off but SIG_INPROGRESS mode set and handler IMPOSSIBLE_TRAP_HANDLER;
+         continue with resetting handler in this case. maybe_set_sigchld_trap
+         will check these things before resetting sigchld trap from
+         run_sigchld_trap.  Fixes (apparently long-standing?) problem reported
+         by Alexandru Damian <alexandru.damian@intel.com>
+
+                                   2/6
+                                   ---
+lib/sh/strtrans.c
+       - ansic_quote: fixed a bug when copying a printable character that
+         consumes more than one byte; byte counter was not being incremented.
+         Bug report from jidanni@jidanni.org
+
+                                   2/7
+                                   ---
+input.c
+       - getc_with_restart: if read(2) returns -1/EINTR and interrupt_state or
+         terminating_signal is set (which means QUIT; will longjmp out of this
+         function), make sure the local buffer variables are zeroed out to
+         avoid reading past the end of the buffer on the next call.  Bug report
+         from Dan Jacobson <jidanni@jidanni.org>
+
+                                   2/9
+                                   ---
+bashline.c
+       - command_word_completion_function: if a directory in $PATH contains
+         quote characters, we need to quote them before passing the candidate
+         path to rl_filename_completion_function, which performs dequoting on
+         the pathname it's passed.  Fixes bug reported by Ilyushkin Nikita
+         <ilyushkeane@gmail.com>
+
+                                  2/11
+                                  ----
+parse.y
+       - xparse_dolparen: save and restore shell_eof_token around call to
+         parse_string, intead of just leaving it set to ')'
+       - shell_getc: when -v is set, only print the command line when
+         shell_eof_token is 0, so we don't print it multiple times when
+         recursively entering the parser to parse $(...) commands.  Fixes
+         bug reported by Greg Wooledge <wooledg@eeg.ccf.org>
+
+[changed release status to 4.3-release]
+
+                                  2/13
+                                  ----
+lib/sh/strtrans.c
+       - ansic_quote: handle case where mbrtowc reports that the multibyte
+         sequence is incomplete or invalid.  Fixes bug reported by
+         Eduardo A. Bustamante López <dualbus@gmail.com>
+
+                                  2/14
+                                  ----
+variables.c
+       - find_variable_nameref_context: fix a problem that caused the loop
+         to go one context too close to the global context.  In some cases,
+         simple variable assignment would set a variable in the global
+         context instead of a local context.  Bug report from
+         Geir Hauge <geir.hauge@gmail.com>
+
+                                  2/26
+                                  ----
+[bash-4.3 released]
+
+                                  2/27
+                                  ----
+aclocal.m4
+       - broken wcwidth check: fix typo reported by David Michael
+         <fedora.dm0@gmail.com>
+
+                                  2/28
+                                  ----
+support/bashbug.sh
+       - add ${BUGADDR} to error message printed if sending mail fails
+
+trap.c
+       - _run_trap_internal: don't call {save,restore}_pipeline if running
+         DEBUG trap; run_debug_trap calls them itself.  Fixes bug reported
+         by Moe Tunes <moetunes42@gmail.com>
+
+test.c
+       - unary_test: fix 'R' case by using find_variable_noref instead of
+         find_variable
+       - test_unop: add back missing 'R' case.  Fixes bug reported by
+         NBaH <nbah@sfr.fr>
+
+                                   3/2
+                                   ---
+jobs.c
+       - end_job_control: if job control is active, we changed the terminal's
+         process group, so make sure we restore it.  Fixes bug reported by
+         Eduardo A. Bustamante López <dualbus@gmail.com>
+
+                                   3/7
+                                   ---
+pcomplete.c
+       - pcomp_curtxt: new variable, holds the original text to be completed
+         as passed to the programmable completion code
+       - pcomp_filename_completion_function: if we are running compgen
+         (presumably in a shell function completion) and performing readline
+         completion, check the word being completed.  If it's not empty, but
+         the original word passed to the programmable completion code is an
+         empty string (""), call a dequoting function if one is available.
+         This compensates for an assumption in bash-completion.  Reported by
+         Albert Shih <Albert.Shih@obspm.fr>
+
+lib/readline/readline.c
+       - _rl_dispatch_subseq: when deciding whether or not to set vi mode's
+         idea of the last command, use whether or not the dispatching keymap
+         is vi_movement_keymap instead of the key sequence length.  The `c',
+         `d', and `y' commands all take motion commands as `arguments' and
+         will produce key sequences longer than 1 character.  The arrow keys
+         will end up dispatching out of a different keymap, so the test will
+         prevent arrow keys from setting the last command (the problem in
+         bash-4.2). Bug report from Daan van Rossum <daan@flash.uchicago.edu>
+
+lib/readline/vi_mode.c
+       - _rl_vi_motion_command: convenience function to test whether a key is
+         a vi-mode motion command
+
+lib/readline/rlprivate.h
+       - _rl_vi_motion_command: extern declaration
+
+parse.y
+       - parse_matched_pair: we should not skip processing single quotes in
+         posix mode if dolbrace_state == DOLBRACE_QUOTE2 (pattern
+         substitution).  Fixes bug reported by David Sines
+         <dave.gma@googlemail.com>
+
+                                  3/10
+                                  ----
+lib/readline/readline.c
+       - _rl_dispatch_callback: treat a return value of -1 as the end of
+         a command dispatch sequence if the current context doesn't
+         indicate that we're reading a multi-key sequence
+         ((cxt->flags & KSEQ_SUBSEQ) == 0).  Turn off the multikey flag
+         and free the context chain in this case.  Fixes one bug reported
+         by Felix Yan <felixonmars@gmail.com> to bug-readline list
+       - _rl_dispatch_callback: treat a return value of > 0 the same as 0
+         and return from the function, since only values < 0 cause us to
+         simulate recursion.  Rest of fix for bug tracked down by
+         Anatol Pomozov <anatol.pomozov@gmail.com>
+
+                                  3/11
+                                  ----
+
+execute_cmd.c
+       - execute_in_subshell: if a longjmp occurs, set result to
+         EXECUTION_FAILURE only if last_command_exit_value == EXECUTION_SUCCESS;
+         use value of last_command_exit_value otherwise.  Fixes cosmetic
+         issue reported by Dennis Lambe Jr. <malsyned@malsyned.net>
+
+doc/bash.1
+       - shell-kill-word and shell-backward-kill-word should be documented
+         as unbound by default.  Report from Oliver Hartley
+         <ohartley@talktalk.net>
+
+trap.c
+       - run_pending_traps: save value of $? before running trap commands in
+         trap_saved_exit_value, like run_exit_trap
+       - _run_trap_internal: save value of $? before running trap commands in
+         trap_saved_exit_value, like run_exit_trap
+
+builtins/common.c
+       - get_exitstat: when running `return' in a trap action, and it is not
+         supplied an argument, use the saved exit status in
+         trap_saved_exit_value.  Fixes Posix problem reported by
+         Eduardo A. Bustamante López <dualbus@gmail.com>
+
+                                  3/13
+                                  ----
+lib/sh/shquote.c
+       - sh_contains_quotes: new function, returns true if a given string
+         contains any of the shell quote characters (single quote, double
+         quote, or backslash)
+
+externs.h
+       - sh_contains_quotes: new extern declaration
+
+pcomplete.c
+       - pcomp_filename_completion_function: more changes for the benefit of
+         bash-completion: if the argument is not the same as the original
+         argument passed to the programmable completion code (pcomp_curtxt),
+         and we are being run by compgen as part of a completion, dequote the
+         argument as bash-completion expects.  Fix for the complete-word-
+         with-quoted-special-chars problem with bash-completion
+
+                                  3/17
+                                  ----
+execute_cmd.c
+       - execute_intern_function: when in posix mode, make defining a function
+         with the same name as a special builtin a fatal error only when the
+         shell is not interactive. Interactive shells display an error
+         message and go on.  From a discussion with Doug McIlroy
+         <doug@cs.dartmouth.edu>
+
+                                  3/18
+                                  ----
+arrayfunc.c
+       - assign_compound_array_list: when using expand_assignment_string_to_string
+         to expand the value in a ( [x]=y ) compound assignment, make sure
+         that we convert 0x0 to "" when expanding [x]= so it doesn't appear as
+         if the index is unset.  Fixes bug reported by Geir Hauge
+         <geir.hauge@gmail.com>
+
+builtins/common.c
+       - get_exitstat: update fix of 3/11 to allow the DEBUG trap to use the
+         current value of $? instead of the value it had before the trap
+         action was run.  This is one reason the DEBUG trap exists, and
+         extended debug mode uses it.  Might want to do this only in Posix
+         mode
+
+doc/{bash.1,bashref.texi}
+       - return: add language cribbed from Posix saying what happens when
+         return is run without an argument from a trap, including the DEBUG
+         trap exception
+
+                                  3/19
+                                  ----
+lib/glob/gmisc.c
+       - extglob_pattern_p: make sure ?(patlist) is flagged as an extglob
+         pattern
+
+lib/glob/glob.c
+       - extglob_skipname: rewrite to handle patterns that begin but do not
+         end with an extglob pattern; change test for easy case and loop
+         through patterns accordingly.  Fixes problem with matching filenames
+         with a leading dot reported by Stephane Chazelas
+         <stephane.chazelas@gmail.com>
+       - wextglob_skipname: make analogous changes
+
+                                  3/20
+                                  ----
+Makefile.in
+       - pass -DDEBUG down to builds in readline and history directories
+
+lib/readline/util.c
+       - _rl_trace and related functions are now only compiled in if DEBUG
+         is defined
+
+lib/readline/Makefile.in
+       - substitute @DEBUG@ and pass -DDEBUG, if necessary, to compilation
+         in LOCAL_CFLAGS
+
+                                  3/21
+                                  ----
+parse.y
+       - shell_getc: when checking whether or not to reallocate
+         shell_input_line to add trailing newline, don't try to subtract from
+         shell_input_line_size.  size_t is unsigned, so if its value is less
+         than 3 (like, say, 2), size-3 is a very large number and the string
+         will not be reallocated.  Use len+3 > size instead of len > size-3.
+         Fixes bug reported in
+         https://bugs.launchpad.net/ubuntu/+source/bash/+bug/1295467
+
+                                  3/27
+                                  ----
+lib/readline/display.c
+       - _rl_clean_up_for_exit: don't bother to call _rl_move_vert to whatever
+         readline thinks the last displayed line is if it's 0.  Two reasons: a
+         minor optimization, and it protects against unwanted moving if this
+         function is called twice, as it is when ^C is pressed.  Fixes bug
+         reported by Egmont Koblinger <egmont@gmail.com>
+
+                                  3/28
+                                  ----
+bashline.c
+       - invalid_completion: new function, used to identify attempts to
+         complete words that are syntax errors
+       - attempt_shell_completion: if invalid_completion returns true for a
+         word in a command position, punt on all completions.  Fixes cosmetic
+         issue reported by Uwe Storbeck <uwe@ibr.ch>
+       - attempt_shell_completion: add clause so that in_command_position
+         remains set to 1 for an empty word following a command separator like
+         (, &, or |
+
+lib/readline/kill.c
+       - rl_yank, rl_yank_nth_arg_internal: don't return -1 from bindable
+         functions, return 1 instead
+
+lib/readline/text.c
+       - rl_rubout, _rl_rubout_char, rl_delete, rl_change_case,
+         rl_transpose_chars, rl_transpose_words, _rl_set_mark_at_pos,
+         rl_exchange_point_and_mark, _rl_insert_next, _rl_char_search,
+         _rl_char_search_internal:
+         don't return -1 from bindable functions, return 1 instead
+
+lib/readline/vi_mode.c
+       - rl_vi_end_word, rl_vi_rubout, rl_vi_delete, rl_vi_char_search,
+         rl_vi_match, _rl_vi_set_mark, _rl_vi_goto_mark:
+         don't return -1 from bindable functions, return 1 instead
+
+lib/readline/macro.c
+       - rl_start_kbd_macro, rl_end_kbd_macro:
+         don't return -1 from bindable functions, return 1 instead
+
+builtins/setattr.def
+       - set_var_attribute: honor setting of no_invisible_vars when setting
+         att_invisible on a variable
+       - include "../flags.h" for no_invisible_vars
+
+builtins/declare.def
+       - declare_internal: honor setting of no_invisible_vars when setting
+         att_invisible on a variable
+       - include "../flags.h" for no_invisible_vars
+
+Makefile.in,builtins/Makefile.in
+       - make sure declare.o and setattr.o depend on flags.h
index 55c8d1ca01627b227dd1c183bd24995508425478..980ed3b55100bb2ecd669836cb0a981092c1318a 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -940,6 +940,7 @@ tests/extglob.tests f
 tests/extglob.right    f
 tests/extglob1.sub     f
 tests/extglob1a.sub    f
+tests/extglob3.sub     f
 tests/extglob2.tests   f
 tests/extglob2.right   f
 tests/extglob3.tests   f
index 7b86602686b4da042b3463f36887dd1ca87fe983..e590dd165b14c506dd666a218c630f116ebf4dee 100644 (file)
@@ -1302,7 +1302,7 @@ builtins/command.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/std
 builtins/declare.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/declare.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
 builtins/declare.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
-builtins/declare.o: $(DEFSRC)/bashgetopt.h pathnames.h
+builtins/declare.o: $(DEFSRC)/bashgetopt.h pathnames.h flags.h
 builtins/echo.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/echo.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
 builtins/echo.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
@@ -1398,7 +1398,7 @@ builtins/setattr.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.
 builtins/setattr.o: quit.h $(DEFSRC)/common.h $(DEFSRC)/bashgetopt.h
 builtins/setattr.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
 builtins/setattr.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
-builtins/setattr.o: pathnames.h
+builtins/setattr.o: pathnames.h flags.h
 builtins/shift.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/shift.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
 builtins/shift.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
diff --git a/Makefile.in~ b/Makefile.in~
new file mode 100644 (file)
index 0000000..7b86602
--- /dev/null
@@ -0,0 +1,1554 @@
+# Makefile for bash-4.3, version 4.11
+#
+# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+
+#   This program is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, either version 3 of the License, or
+#   (at your option) any later version.
+
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Make sure the first target in the makefile is the right one
+all: .made
+
+PACKAGE = @PACKAGE_NAME@
+VERSION = @PACKAGE_VERSION@
+
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+
+# Include some boilerplate Gnu makefile definitions.
+prefix = @prefix@
+
+exec_prefix = @exec_prefix@
+
+datarootdir = @datarootdir@
+
+bindir = @bindir@
+libdir = @libdir@
+infodir = @infodir@
+includedir = @includedir@
+datadir = @datadir@
+localedir = @localedir@
+
+docdir = @docdir@
+
+mandir = @mandir@
+manpfx = man
+
+man1ext = .1
+man1dir = $(mandir)/$(manpfx)1
+man3ext = .3
+man3dir = $(mandir)/$(manpfx)3
+
+htmldir = @htmldir@
+
+# Support an alternate destination root directory for package building
+DESTDIR =
+
+topdir = @top_srcdir@
+BUILD_DIR = @BUILD_DIR@
+top_builddir = @BUILD_DIR@
+srcdir = @srcdir@
+VPATH = .:@srcdir@
+
+@SET_MAKE@
+CC = @CC@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+YACC = @YACC@
+SHELL = @MAKE_SHELL@
+CP = cp
+RM = rm -f
+AR = @AR@
+ARFLAGS = @ARFLAGS@
+RANLIB = @RANLIB@
+SIZE = @SIZE@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALLMODE= -m 0755
+INSTALLMODE2 = -m 0555
+
+TESTSCRIPT = @TESTSCRIPT@
+
+DEBUGGER_START_FILE = @DEBUGGER_START_FILE@
+
+#If you have purify, and want to use it, uncomment this definition or
+# run the make as `make PURIFY=purify'
+# or run configure with the --with-purify argument.
+PURIFY = @PURIFY@
+
+# Here is a rule for making .o files from .c files that does not
+# force the type of the machine (like -M_MACHINE) into the flags.
+.c.o:
+       $(RM) $@
+       $(CC) $(CCFLAGS) -c $<
+
+EXEEXT = @EXEEXT@
+OBJEXT = @OBJEXT@
+
+# The name of this program and some version information.
+VERSPROG = bashversion$(EXEEXT)
+VERSOBJ = bashversion.$(OBJEXT)
+
+Program = bash$(EXEEXT)
+Version = @BASHVERS@
+PatchLevel = `$(BUILD_DIR)/$(VERSPROG) -p`
+RELSTATUS = @RELSTATUS@
+
+Machine = @host_cpu@
+OS = @host_os@
+VENDOR = @host_vendor@
+MACHTYPE = @host@
+
+# comment out for release
+DEBUG = @DEBUG@
+MALLOC_DEBUG = @MALLOC_DEBUG@
+
+THIS_SH = $(BUILD_DIR)/$(Program)
+
+# PROFILE_FLAGS is either -pg, to generate profiling info for use
+# with gprof, or nothing (the default).
+PROFILE_FLAGS= @PROFILE_FLAGS@
+
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ @CROSS_COMPILE@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+LOCAL_CFLAGS = @LOCAL_CFLAGS@ ${DEBUG} ${MALLOC_DEBUG}
+DEFS = @DEFS@
+LOCAL_DEFS = @LOCAL_DEFS@
+
+LOCALE_DEFS = -DLOCALEDIR='"$(localedir)"' -DPACKAGE='"$(PACKAGE)"'
+
+LOCAL_LIBS = @LOCAL_LIBS@
+LIBS = $(BUILTINS_LIB) $(LIBRARIES) @LIBS@
+LIBS_FOR_BUILD = 
+
+STATIC_LD = @STATIC_LD@
+LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
+
+SYSTEM_FLAGS = -DPROGRAM='"$(Program)"' -DCONF_HOSTTYPE='"$(Machine)"' -DCONF_OSTYPE='"$(OS)"' -DCONF_MACHTYPE='"$(MACHTYPE)"' -DCONF_VENDOR='"$(VENDOR)"' $(LOCALE_DEFS)
+
+BASE_CCFLAGS = $(PROFILE_FLAGS) $(SYSTEM_FLAGS) $(LOCAL_DEFS) \
+         $(DEFS) $(LOCAL_CFLAGS) $(INCLUDES)
+
+CCFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(CFLAGS)
+
+CCFLAGS_FOR_BUILD = $(BASE_CCFLAGS) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD)
+
+LDFLAGS = @LDFLAGS@ $(STATIC_LD) $(LOCAL_LDFLAGS) $(PROFILE_FLAGS) $(CFLAGS)
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ $(LOCAL_LDFLAGS) $(CFLAGS_FOR_BUILD)
+
+INCLUDES = -I. @RL_INCLUDE@ -I$(srcdir) -I$(BASHINCDIR) -I$(LIBSRC) $(INTL_INC)
+
+# Maybe add: -Wextra
+GCC_LINT_FLAGS = -O -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wno-parentheses \
+                -Wcast-align -Wstrict-prototypes -Wconversion -Wformat \
+                -Wformat-nonliteral -Wmissing-braces -Wuninitialized \
+                -Wmissing-declarations  -Winline \
+                -Wmissing-prototypes -Wtraditional -Wredundant-decls -pedantic
+
+GCC_LINT_CFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(GCC_LINT_FLAGS)
+
+#
+# Support libraries
+# 
+
+dot = .
+
+LIBSUBDIR = lib
+LIBSRC = $(srcdir)/$(LIBSUBDIR)
+
+LIBBUILD = ${BUILD_DIR}/${LIBSUBDIR}
+
+SUBDIR_INCLUDES = -I. @RL_INCLUDE@ -I$(topdir) -I$(topdir)/$(LIBSUBDIR)
+
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+
+# the bash library
+# the library is a mix of functions that the C library does not provide on
+# some platforms and general shell utility functions
+SH_LIBSRC = $(LIBSRC)/sh
+SH_LIBDIR = $(dot)/${LIBSUBDIR}/sh
+SH_ABSSRC = ${topdir}/${SH_LIBSRC}
+
+SHLIB_SOURCE = ${SH_LIBSRC}/clktck.c ${SH_LIBSRC}/getcwd.c \
+               ${SH_LIBSRC}/getenv.c ${SH_LIBSRC}/oslib.c \
+               ${SH_LIBSRC}/setlinebuf.c ${SH_LIBSRC}/strchrnul.c \
+               ${SH_LIBSRC}/strcasecmp.c ${SH_LIBSRC}/strdup.c \
+               ${SH_LIBSRC}/strerror.c \
+               ${SH_LIBSRC}/strtod.c ${SH_LIBSRC}/strtol.c \
+               ${SH_LIBSRC}/strtoul.c ${SH_LIBSRC}/vprint.c \
+               ${SH_LIBSRC}/itos.c ${SH_LIBSRC}/rename.c \
+               ${SH_LIBSRC}/zread.c ${SH_LIBSRC}/zwrite.c \
+               ${SH_LIBSRC}/shtty.c ${SH_LIBSRC}/inet_aton.c \
+               ${SH_LIBSRC}/netopen.c ${SH_LIBSRC}/strpbrk.c \
+               ${SH_LIBSRC}/timeval.c ${SH_LIBSRC}/clock.c \
+               ${SH_LIBSRC}/makepath.c ${SH_LIBSRC}/pathcanon.c \
+               ${SH_LIBSRC}/pathphys.c ${SH_LIBSRC}/stringlist.c \
+               ${SH_LIBSRC}/stringvec.c ${SH_LIBSRC}/tmpfile.c \
+               ${SH_LIBSRC}/spell.c ${SH_LIBSRC}/strtrans.c \
+               ${SH_LIBSRC}/strcasestr.c ${SH_LIBSRC}/shquote.c \
+               ${SH_LIBSRC}/snprintf.c ${SH_LIBSRC}/mailstat.c \
+               ${SH_LIBSRC}/fmtulong.c ${SH_LIBSRC}/fmtullong.c \
+               ${SH_LIBSRC}/strtoll.c ${SH_LIBSRC}/strtoull.c \
+               ${SH_LIBSRC}/strtoimax.c ${SH_LIBSRC}/strtoumax.c \
+               ${SH_LIBSRC}/fmtumax.c ${SH_LIBSRC}/netconn.c \
+               ${SH_LIBSRC}/mktime.c ${SH_LIBSRC}/strftime.c \
+               ${SH_LIBSRC}/memset.c ${SH_LIBSRC}/mbschr.c \
+               ${SH_LIBSRC}/zcatfd.c ${SH_LIBSRC}/shmatch.c \
+               ${SH_LIBSRC}/strnlen.c ${SH_LIBSRC}/winsize.c \
+               ${SH_LIBSRC}/eaccess.c ${SH_LIBSRC}/wcsdup.c \
+               ${SH_LIBSRC}/zmapfd.c ${SH_LIBSRC}/fpurge.c \
+               ${SH_LIBSRC}/zgetline.c ${SH_LIBSRC}/mbscmp.c \
+               ${SH_LIBSRC}/casemod.c ${SH_LIBSRC}/uconvert.c \
+               ${SH_LIBSRC}/ufuncs.c ${SH_LIBSRC}/dprintf.c \
+               ${SH_LIBSRC}/input_avail.c ${SH_LIBSRC}/mbscasecmp.c \
+               ${SH_LIBSRC}/fnxform.c ${SH_LIBSRC}/unicode.c \
+               ${SH_LIBSRC}/wcswidth.c ${SH_LIBSRC}/wcsnwidth.c \
+               ${SH_LIBSRC}/shmbchar.c
+
+SHLIB_LIB = -lsh
+SHLIB_LIBNAME = libsh.a
+SHLIB_LIBRARY = ${SH_LIBDIR}/${SHLIB_LIBNAME}
+SHLIB_LDFLAGS = -L${SH_LIBDIR}
+SHLIB_DEP = ${SHLIB_LIBRARY}
+
+# we assume for now that readline source is being shipped with bash
+RL_LIBSRC = $(LIBSRC)/readline
+RL_LIBDOC = $(RL_LIBSRC)/doc
+RL_LIBDIR = @RL_LIBDIR@
+RL_ABSSRC = ${topdir}/$(RL_LIBDIR)
+
+RL_INCLUDEDIR = @RL_INCLUDEDIR@
+
+READLINE_LIB = @READLINE_LIB@
+READLINE_LIBRARY = $(RL_LIBDIR)/libreadline.a
+READLINE_LDFLAGS = -L${RL_LIBDIR}
+READLINE_DEP = @READLINE_DEP@
+
+# The source, object and documentation of the GNU Readline library.
+READLINE_SOURCE        = $(RL_LIBSRC)/rldefs.h $(RL_LIBSRC)/rlconf.h \
+                 $(RL_LIBSRC)/readline.h $(RL_LIBSRC)/tcap.h \
+                 $(RL_LIBSRC)/chardefs.h $(RL_LIBSRC)/keymaps.h \
+                 $(RL_LIBSRC)/history.h $(RL_LIBSRC)/histlib.h \
+                 $(RL_LIBSRC)/posixstat.h $(RL_LIBSRC)/tilde.h \
+                 $(RL_LIBSRC)/rlstdc.h ${RL_LIBSRC}/xmalloc.h \
+                 $(RL_LIBSRC)/rlshell.h ${RL_LIBSRC}/rlprivate.h \
+                 $(RL_LIBSRC)/colors.h  $(RL_LIBSRC)/parse-colors.h \
+                 $(RL_LIBSRC)/funmap.c $(RL_LIBSRC)/emacs_keymap.c \
+                 $(RL_LIBSRC)/search.c $(RL_LIBSRC)/vi_keymap.c \
+                 $(RL_LIBSRC)/keymaps.c $(RL_LIBSRC)/parens.c \
+                 $(RL_LIBSRC)/vi_mode.c $(RL_LIBSRC)/callback.c \
+                 $(RL_LIBSRC)/readline.c $(RL_LIBSRC)/tilde.c \
+                 $(RL_LIBSRC)/rltty.c $(RL_LIBSRC)/complete.c \
+                 $(RL_LIBSRC)/bind.c $(RL_LIBSRC)/isearch.c \
+                 $(RL_LIBSRC)/display.c $(RL_LIBSRC)/signals.c \
+                 $(RL_LIBSRC)/util.c $(RL_LIBSRC)/kill.c $(RL_LIBSRC)/text.c \
+                 $(RL_LIBSRC)/undo.c $(RL_LIBSRC)/macro.c \
+                 $(RL_LIBSRC)/terminal.c $(RL_LIBSRC)/nls.c \
+                 $(RL_LIBSRC)/input.c $(RL_LIBSRC)/xmalloc.c \
+                 $(RL_LIBSRC)/shell.c $(RL_LIBSRC)/savestring.c \
+                 $(RL_LIBSRC)/colors.c $(RL_LIBSRC)/parse-colors.c \
+                 $(RL_LIBSRC)/misc.c $(RL_LIBSRC)/mbutil.c $(RL_LIBSRC)/compat.c \
+                 $(RL_LIBSRC)/histexpand.c $(RL_LIBSRC)/history.c \
+                 $(RL_LIBSRC)/histsearch.c $(RL_LIBSRC)/histfile.c
+
+READLINE_OBJ   = $(RL_LIBDIR)/readline.o $(RL_LIBDIR)/funmap.o \
+                 $(RL_LIBDIR)/parens.o $(RL_LIBDIR)/search.o \
+                 $(RL_LIBDIR)/keymaps.o $(RL_LIBDIR)/xmalloc.o \
+                 $(RL_LIBDIR)/rltty.o $(RL_LIBDIR)/complete.o \
+                 $(RL_LIBDIR)/bind.o $(RL_LIBDIR)/isearch.o \
+                 $(RL_LIBDIR)/display.o $(RL_LIBDIR)/signals.o \
+                 $(RL_LIBDIR)/tilde.o $(RL_LIBDIR)/util.o \
+                 $(RL_LIBDIR)/kill.o $(RL_LIBDIR)/undo.o $(RL_LIBDIR)/nls.o \
+                 $(RL_LIBDIR)/macro.o $(RL_LIBDIR)/input.o \
+                 $(RL_LIBDIR)/terminal.o $(RL_LIBDIR)/callback.o \
+                 $(RL_LIBDIR)/shell.o $(RL_LIBDIR)/savestring.o \
+                 $(RL_LIBDIR)/mbutil.o $(RL_LIBDIR)/compat.o \
+                 $(RL_LIBDIR)/history.o $(RL_LIBDIR)/histexpand.o \
+                 $(RL_LIBDIR)/histsearch.o $(RL_LIBDIR)/histfile.o \
+                 $(RL_LIBDIR)/colors.o $(RL_LIBDIR)/parse-colors.o
+
+HIST_LIBSRC = $(LIBSRC)/readline
+HIST_LIBDIR = @HIST_LIBDIR@
+HIST_ABSSRC = ${topdir}/$(HIST_LIBDIR)
+
+HISTORY_LIB = @HISTORY_LIB@
+HISTORY_LIBRARY = $(HIST_LIBDIR)/libhistory.a
+HISTORY_LDFLAGS = -L$(HIST_LIBDIR)
+HISTORY_DEP = @HISTORY_DEP@
+
+# The source, object and documentation of the history library.
+HISTORY_SOURCE = $(HIST_LIBSRC)/history.c $(HIST_LIBSRC)/histexpand.c \
+                 $(HIST_LIBSRC)/histsearch.c $(HIST_LIBSRC)/histfile.c \
+                 $(HIST_LIBSRC)/shell.c \
+                 $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/histlib.h
+HISTORY_OBJ    = $(HIST_LIBDIR)/history.o $(HIST_LIBDIR)/histexpand.o \
+                 $(HIST_LIBDIR)/histsearch.o $(HIST_LIBDIR)/histfile.o \
+                 $(HIST_LIBDIR)/shell.o
+
+# You only need termcap (or curses) if you are linking with GNU Readline.
+TERM_LIBSRC = $(LIBSRC)/termcap
+TERM_LIBDIR = $(dot)/$(LIBSUBDIR)/termcap
+TERM_ABSSRC = ${topdir}/$(TERM_LIBDIR)
+
+TERMCAP_LIB = @TERMCAP_LIB@
+TERMCAP_LIBRARY = $(TERM_LIBDIR)/libtermcap.a
+TERMCAP_LDFLAGS = -L$(TERM_LIBDIR)
+TERMCAP_DEP = @TERMCAP_DEP@
+
+TERMCAP_SOURCE = $(TERM_LIBSRC)/termcap.c $(TERM_LIBSRC)/tparam.c
+TERMCAP_OBJ    = $(TERM_LIBDIR)/termcap.o $(TERM_LIBDIR)/tparam.o
+
+GLOB_LIBSRC = $(LIBSRC)/glob
+GLOB_LIBDIR = $(dot)/$(LIBSUBDIR)/glob
+GLOB_ABSSRC = ${topdir}/$(GLOB_LIBDIR)
+
+GLOB_LIB     = -lglob
+GLOB_LIBRARY = $(GLOB_LIBDIR)/libglob.a
+GLOB_LDFLAGS = -L$(GLOB_LIBDIR)
+GLOB_DEP = $(GLOB_LIBRARY)
+
+GLOB_SOURCE = $(GLOB_LIBSRC)/glob.c $(GLOB_LIBSRC)/strmatch.c \
+             $(GLOB_LIBSRC)/smatch.c $(GLOB_LIBSRC)/xmbsrtowcs.c \
+             $(GLOB_LIBSRC)/glob_loop.c $(GLOB_LIBSRC)/sm_loop.c \
+             $(GLOB_LIBSRC)/gmisc.c \
+             $(GLOB_LIBSRC)/glob.h $(GLOB_LIBSRC)/strmatch.h
+GLOB_OBJ    = $(GLOB_LIBDIR)/glob.o $(GLOB_LIBDIR)/strmatch.o \
+             $(GLOB_LIBDIR)/smatch.o $(GLOB_LIBDIR)/xmbsrtowcs.o \
+             $(GLOB_LIBDIR)/gmisc.o
+
+# The source, object and documentation for the GNU Tilde library.
+TILDE_LIBSRC = $(LIBSRC)/tilde
+TILDE_LIBDIR = $(dot)/$(LIBSUBDIR)/tilde
+TILDE_ABSSRC = ${topdir}/$(TILDE_LIBDIR)
+
+TILDE_LIB = @TILDE_LIB@
+TILDE_LIBRARY = $(TILDE_LIBDIR)/libtilde.a
+TILDE_LDFLAGS = -L$(TILDE_LIBDIR)
+TILDE_DEP = $(TILDE_LIBRARY)
+
+TILDE_SOURCE   = $(TILDE_LIBSRC)/tilde.c $(TILDE_LIBSRC)/tilde.h
+TILDE_OBJ      = $(TILDE_LIBDIR)/tilde.o
+
+# libintl
+INTL_LIBSRC = $(LIBSRC)/intl
+INTL_LIBDIR = $(dot)/$(LIBSUBDIR)/intl
+INTL_ABSSRC = ${topdir}/$(INTL_LIB)
+INTL_BUILDDIR = ${LIBBUILD}/intl
+
+INTL_LIB     = @LIBINTL@
+INTL_LIBRARY = $(INTL_LIBDIR)/libintl.a
+INTL_DEP = @INTL_DEP@
+INTL_INC = @INTL_INC@
+
+LIBINTL_H = @LIBINTL_H@
+
+# libiconv
+LIBICONV = @LIBICONV@
+
+# tests
+LIBINTL = @LIBINTL@
+LTLIBINTL = @LTLIBINTL@
+INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+
+# Our malloc.
+MALLOC_TARGET = @MALLOC_TARGET@
+
+# set to alloca.o if we are using the C alloca in lib/malloc
+ALLOCA = @ALLOCA@
+
+ALLOC_LIBSRC = $(LIBSRC)/malloc
+ALLOC_LIBDIR = $(dot)/$(LIBSUBDIR)/malloc
+ALLOC_ABSSRC = ${topdir}/$(ALLOC_LIBDIR)
+
+MALLOC_SRC = @MALLOC_SRC@
+MALLOC_OTHERSRC = ${ALLOC_LIBSRC}/trace.c ${ALLOC_LIBSRC}/stats.c \
+                 ${ALLOC_LIBSRC}/table.c ${ALLOC_LIBSRC}/watch.c
+MALLOC_SOURCE = ${ALLOC_LIBSRC}/${MALLOC_SRC} ${MALLOC_OTHERSRC}
+MALLOC_CFLAGS = -DRCHECK -Dbotch=programming_error ${MALLOC_DEBUG}
+
+MALLOC_LIB     = @MALLOC_LIB@
+MALLOC_LIBRARY = @MALLOC_LIBRARY@
+MALLOC_LDFLAGS = @MALLOC_LDFLAGS@
+MALLOC_DEP = @MALLOC_DEP@
+
+ALLOC_HEADERS = $(ALLOC_LIBSRC)/getpagesize.h $(ALLOC_LIBSRC)/shmalloc.h \
+               $(ALLOC_LIBSRC)/imalloc.h $(ALLOC_LIBSRC)/mstats.h \
+               $(ALLOC_LIBSRC)/table.h $(ALLOC_LIBSRC)/watch.h
+
+$(MALLOC_LIBRARY):     ${MALLOC_SOURCE} ${ALLOC_HEADERS} config.h
+               @(cd $(ALLOC_LIBDIR) && \
+                $(MAKE) $(MFLAGS) \
+                MALLOC_CFLAGS="$(MALLOC_CFLAGS)" ${MALLOC_TARGET} ) || exit 1
+
+BASHINCDIR = ${srcdir}/include
+BASHINCFILES =  $(BASHINCDIR)/posixstat.h $(BASHINCDIR)/ansi_stdlib.h \
+                $(BASHINCDIR)/filecntl.h $(BASHINCDIR)/posixdir.h \
+                $(BASHINCDIR)/memalloc.h $(BASHINCDIR)/stdc.h \
+                $(BASHINCDIR)/posixjmp.h $(BASHINCDIR)/posixwait.h \
+                $(BASHINCDIR)/posixtime.h $(BASHINCDIR)/systimes.h \
+                $(BASHINCDIR)/unionwait.h $(BASHINCDIR)/maxpath.h \
+                $(BASHINCDIR)/shtty.h $(BASHINCDIR)/typemax.h \
+                $(BASHINCDIR)/ocache.h
+
+LIBRARIES = $(GLOB_LIB) $(SHLIB_LIB) $(READLINE_LIB) $(HISTORY_LIB) $(TERMCAP_LIB) \
+           $(TILDE_LIB) $(MALLOC_LIB) $(INTL_LIB) $(LIBICONV) $(LOCAL_LIBS)
+
+LIBDEP = $(GLOB_DEP) $(SHLIB_DEP) $(INTL_DEP) $(READLINE_DEP) $(HISTORY_DEP) $(TERMCAP_DEP) \
+        $(TILDE_DEP) $(MALLOC_DEP)
+
+LIBRARY_LDFLAGS = $(READLINE_LDFLAGS) $(HISTORY_LDFLAGS) $(GLOB_LDFLAGS) \
+                 $(TILDE_LDFLAGS) $(MALLOC_LDFLAGS) $(SHLIB_LDFLAGS)
+
+#
+# The shell itself
+#
+
+# The main source code for the Bourne Again SHell.
+CSOURCES = shell.c eval.c parse.y general.c make_cmd.c print_cmd.c y.tab.c \
+          dispose_cmd.c execute_cmd.c variables.c $(GLOBC) version.c \
+          expr.c copy_cmd.c flags.c subst.c hashcmd.c hashlib.c mailcheck.c \
+          test.c trap.c alias.c jobs.c nojobs.c $(ALLOC_FILES) braces.c \
+          input.c bashhist.c array.c arrayfunc.c assoc.c sig.c pathexp.c \
+          unwind_prot.c siglist.c bashline.c bracecomp.c error.c \
+          list.c stringlib.c locale.c findcmd.c redir.c \
+          pcomplete.c pcomplib.c syntax.c xmalloc.c
+
+HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \
+          general.h variables.h config.h $(ALLOC_HEADERS) alias.h \
+          quit.h unwind_prot.h syntax.h ${GRAM_H} \
+          command.h input.h error.h bashansi.h dispose_cmd.h make_cmd.h \
+          subst.h externs.h siglist.h bashhist.h bashline.h bashtypes.h \
+          array.h arrayfunc.h sig.h mailcheck.h bashintl.h bashjmp.h \
+          execute_cmd.h parser.h pathexp.h pathnames.h pcomplete.h assoc.h \
+          $(BASHINCFILES)
+
+SOURCES         = $(CSOURCES) $(HSOURCES) $(BUILTIN_DEFS)
+
+# header files chosen based on running of configure
+SIGNAMES_H = @SIGNAMES_H@
+
+# object files chosen based on running of configure
+JOBS_O = @JOBS_O@
+SIGLIST_O = @SIGLIST_O@
+SIGNAMES_O = @SIGNAMES_O@
+
+# Matching object files.
+OBJECTS         = shell.o eval.o y.tab.o general.o make_cmd.o print_cmd.o $(GLOBO) \
+          dispose_cmd.o execute_cmd.o variables.o copy_cmd.o error.o \
+          expr.o flags.o $(JOBS_O) subst.o hashcmd.o hashlib.o mailcheck.o \
+          trap.o input.o unwind_prot.o pathexp.o sig.o test.o version.o \
+          alias.o array.o arrayfunc.o assoc.o braces.o bracecomp.o bashhist.o \
+          bashline.o $(SIGLIST_O) list.o stringlib.o locale.o findcmd.o redir.o \
+          pcomplete.o pcomplib.o syntax.o xmalloc.o $(SIGNAMES_O)
+
+# Where the source code of the shell builtins resides.
+BUILTIN_SRCDIR=$(srcdir)/builtins
+DEFSRC=$(BUILTIN_SRCDIR)
+BUILTIN_ABSSRC=${topdir}/builtins
+DEFDIR = $(dot)/builtins
+DEBUGGER_DIR = $(dot)/debugger
+
+BUILTIN_DEFS = $(DEFSRC)/alias.def $(DEFSRC)/bind.def $(DEFSRC)/break.def \
+              $(DEFSRC)/builtin.def $(DEFSRC)/cd.def $(DEFSRC)/colon.def \
+              $(DEFSRC)/command.def ${DEFSRC}/complete.def \
+              $(DEFSRC)/caller.def $(DEFSRC)/declare.def \
+              $(DEFSRC)/echo.def $(DEFSRC)/enable.def $(DEFSRC)/eval.def \
+              $(DEFSRC)/exec.def $(DEFSRC)/exit.def $(DEFSRC)/fc.def \
+              $(DEFSRC)/fg_bg.def $(DEFSRC)/hash.def $(DEFSRC)/help.def \
+              $(DEFSRC)/history.def $(DEFSRC)/jobs.def $(DEFSRC)/kill.def \
+              $(DEFSRC)/let.def $(DEFSRC)/read.def $(DEFSRC)/return.def \
+              $(DEFSRC)/set.def $(DEFSRC)/setattr.def $(DEFSRC)/shift.def \
+              $(DEFSRC)/source.def $(DEFSRC)/suspend.def $(DEFSRC)/test.def \
+              $(DEFSRC)/times.def $(DEFSRC)/trap.def $(DEFSRC)/type.def \
+              $(DEFSRC)/ulimit.def $(DEFSRC)/umask.def $(DEFSRC)/wait.def \
+              $(DEFSRC)/getopts.def $(DEFSRC)/reserved.def \
+              $(DEFSRC)/pushd.def $(DEFSRC)/shopt.def $(DEFSRC)/printf.def \
+              $(DEFSRC)/mapfile.def
+BUILTIN_C_SRC  = $(DEFSRC)/mkbuiltins.c $(DEFSRC)/common.c \
+                $(DEFSRC)/evalstring.c $(DEFSRC)/evalfile.c \
+                $(DEFSRC)/bashgetopt.c $(GETOPT_SOURCE)
+BUILTIN_C_OBJ  = $(DEFDIR)/common.o $(DEFDIR)/evalstring.o \
+                $(DEFDIR)/evalfile.o $(DEFDIR)/bashgetopt.o
+BUILTIN_OBJS = $(DEFDIR)/alias.o $(DEFDIR)/bind.o $(DEFDIR)/break.o \
+              $(DEFDIR)/builtin.o $(DEFDIR)/cd.o $(DEFDIR)/colon.o \
+              $(DEFDIR)/command.o $(DEFDIR)/caller.o $(DEFDIR)/declare.o \
+              $(DEFDIR)/echo.o $(DEFDIR)/enable.o $(DEFDIR)/eval.o \
+              $(DEFDIR)/exec.o $(DEFDIR)/exit.o $(DEFDIR)/fc.o \
+              $(DEFDIR)/fg_bg.o $(DEFDIR)/hash.o $(DEFDIR)/help.o \
+              $(DEFDIR)/history.o $(DEFDIR)/jobs.o $(DEFDIR)/kill.o \
+              $(DEFDIR)/let.o $(DEFDIR)/pushd.o $(DEFDIR)/read.o \
+              $(DEFDIR)/return.o $(DEFDIR)/shopt.o $(DEFDIR)/printf.o \
+              $(DEFDIR)/set.o $(DEFDIR)/setattr.o $(DEFDIR)/shift.o \
+              $(DEFDIR)/source.o $(DEFDIR)/suspend.o $(DEFDIR)/test.o \
+              $(DEFDIR)/times.o $(DEFDIR)/trap.o $(DEFDIR)/type.o \
+              $(DEFDIR)/ulimit.o $(DEFDIR)/umask.o $(DEFDIR)/wait.o \
+              $(DEFDIR)/getopts.o $(DEFDIR)/mapfile.o $(BUILTIN_C_OBJ)
+GETOPT_SOURCE   = $(DEFSRC)/getopt.c $(DEFSRC)/getopt.h
+PSIZE_SOURCE   = $(DEFSRC)/psize.sh $(DEFSRC)/psize.c
+
+BUILTINS_LIBRARY = $(DEFDIR)/libbuiltins.a
+BUILTINS_LIB = -lbuiltins
+BUILTINS_LDFLAGS = -L$(DEFDIR)
+BUILTINS_DEP = $(BUILTINS_LIBRARY)
+
+# Documentation for the shell.
+DOCSRC = $(srcdir)/doc
+DOCDIR = $(dot)/doc
+
+# Translations and other i18n support files
+PO_SRC = $(srcdir)/po/
+PO_DIR = $(dot)/po/
+
+SIGNAMES_SUPPORT = $(SUPPORT_SRC)mksignames.c
+
+SUPPORT_SRC = $(srcdir)/support/
+SDIR = $(dot)/support/
+
+TESTS_SUPPORT = recho$(EXEEXT) zecho$(EXEEXT) printenv$(EXEEXT) xcase$(EXEEXT)
+CREATED_SUPPORT = signames.h recho$(EXEEXT) zecho$(EXEEXT) printenv$(EXEEXT) \
+                 tests/recho$(EXEEXT) tests/zecho$(EXEEXT) \
+                 tests/printenv$(EXEEXT) xcase$(EXEEXT) tests/xcase$(EXEEXT) \
+                 mksignames$(EXEEXT) lsignames.h \
+                 mksyntax${EXEEXT} syntax.c $(VERSPROG) $(VERSOBJ) \
+                 buildversion.o mksignames.o signames.o buildsignames.o
+CREATED_CONFIGURE = config.h config.cache config.status config.log \
+                   stamp-h po/POTFILES config.status.lineno
+CREATED_MAKEFILES = Makefile builtins/Makefile doc/Makefile \
+                   lib/readline/Makefile lib/glob/Makefile \
+                   lib/sh/Makefile lib/tilde/Makefile lib/malloc/Makefile \
+                   lib/termcap/Makefile examples/loadables/Makefile \
+                   examples/loadables/perl/Makefile support/Makefile \
+                   lib/intl/Makefile po/Makefile po/Makefile.in
+
+OTHER_DOCS = $(srcdir)/CHANGES $(srcdir)/COMPAT $(srcdir)/NEWS $(srcdir)/POSIX \
+       $(srcdir)/RBASH $(srcdir)/README
+OTHER_INSTALLED_DOCS = CHANGES COMPAT NEWS POSIX RBASH README
+
+# Keep GNU Make from exporting the entire environment for small machines.
+.NOEXPORT:
+
+.made: $(Program) bashbug
+       @echo "$(Program) last made for a $(Machine) running $(OS)" >.made
+
+$(Program):  .build $(OBJECTS) $(BUILTINS_DEP) $(LIBDEP)
+       $(RM) $@
+       $(PURIFY) $(CC) $(BUILTINS_LDFLAGS) $(LIBRARY_LDFLAGS) $(LDFLAGS) -o $(Program) $(OBJECTS) $(LIBS)
+       ls -l $(Program)
+       -$(SIZE) $(Program)
+
+.build:        $(SOURCES) config.h Makefile version.h $(VERSPROG)
+       @echo
+       @echo "   ***********************************************************"
+       @echo "   *                                                         *"
+       @echo "   * `$(BUILD_DIR)/$(VERSPROG) -l`"
+       @echo "   *                                                         *"
+       @echo "   ***********************************************************"
+       @echo
+
+bashbug: $(SUPPORT_SRC)bashbug.sh config.h Makefile $(VERSPROG)
+       @sed -e "s%!MACHINE!%$(Machine)%" -e "s%!OS!%$(OS)%" \
+            -e "s%!CFLAGS!%$(CCFLAGS)%" -e "s%!CC!%$(CC)%" \
+            -e "s%!RELEASE!%$(Version)%" -e "s%!PATCHLEVEL!%$(PatchLevel)%" \
+            -e "s%!MACHTYPE!%$(MACHTYPE)%" -e "s%!RELSTATUS!%$(RELSTATUS)%" \
+            $(SUPPORT_SRC)bashbug.sh > $@
+       @chmod a+rx bashbug
+
+strip: $(Program) .made
+       strip $(Program)
+       ls -l $(Program)
+       -$(SIZE) $(Program)
+
+lint:
+       ${MAKE} ${MFLAGS} CFLAGS='${GCC_LINT_FLAGS}' .made
+
+version.h:  $(SOURCES) config.h Makefile patchlevel.h
+       $(SHELL) $(SUPPORT_SRC)mkversion.sh -b -S ${topdir} -s $(RELSTATUS) -d $(Version) -o newversion.h \
+               && mv newversion.h version.h
+
+bashversion$(EXEEXT):  patchlevel.h conftypes.h version.h buildversion.o $(SUPPORT_SRC)bashversion.c
+       $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) ${LDFLAGS_FOR_BUILD} -o $@ $(SUPPORT_SRC)bashversion.c buildversion.o ${LIBS_FOR_BUILD}
+
+buildversion.o: version.h conftypes.h patchlevel.h $(srcdir)/version.c
+       $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -DBUILDTOOL -c -o $@ $(srcdir)/version.c
+
+# old rules
+GRAM_H = parser-built
+y.tab.o: y.tab.h y.tab.c ${GRAM_H} command.h ${BASHINCDIR}/stdc.h input.h
+${GRAM_H}:     y.tab.h
+       @-if test -f y.tab.h ; then \
+               cmp -s $@ y.tab.h 2>/dev/null || cp -p y.tab.h $@; \
+       fi
+
+y.tab.c: parse.y
+#      -if test -f y.tab.h; then mv -f y.tab.h old-y.tab.h; fi
+       $(YACC) -d $(srcdir)/parse.y
+       touch parser-built
+#      -if cmp -s old-y.tab.h y.tab.h; then mv old-y.tab.h y.tab.h; else cp -p y.tab.h ${GRAM_H}; fi
+
+y.tab.h: y.tab.c
+       @true
+
+# Subdirs will often times want version.h, so they'll change back up to
+# the top level and try to create it.  This causes parallel build issues
+# so just force top level sanity before we descend.
+$(LIBDEP): .build
+#$(LIBDEP): version.h
+
+$(READLINE_LIBRARY): config.h $(READLINE_SOURCE)
+       @echo making $@ in ${RL_LIBDIR}
+       @( { test "${RL_LIBDIR}" = "${libdir}" && exit 0; } || \
+               cd ${RL_LIBDIR} && $(MAKE) $(MFLAGS) DEBUG=${DEBUG} libreadline.a) || exit 1
+
+$(HISTORY_LIBRARY): config.h $(HISTORY_SOURCE) $(READLINE_DEP)
+       @echo making $@ in ${HIST_LIBDIR}
+       @( { test "${HIST_LIBDIR}" = "${libdir}" && exit 0; } || \
+               cd ${HIST_LIBDIR} && $(MAKE) $(MFLAGS) DEBUG=${DEBUG} libhistory.a) || exit 1
+
+$(GLOB_LIBRARY): config.h $(GLOB_SOURCE)
+       @echo making $@ in ${GLOB_LIBDIR}
+       @(cd ${GLOB_LIBDIR} && \
+               $(MAKE) $(MFLAGS) DEBUG=${DEBUG} libglob.a) || exit 1
+
+$(TILDE_LIBRARY): config.h $(TILDE_SOURCE)
+       @echo making $@ in ${TILDE_LIBDIR}
+       @(cd ${TILDE_LIBDIR} && \
+               $(MAKE) $(MFLAGS) libtilde.a) || exit 1
+
+$(TERMCAP_LIBRARY): config.h ${TERMCAP_SOURCE}
+       @echo making $@ in ${TERM_LIBDIR}       
+       @(cd ${TERM_LIBDIR} && \
+               $(MAKE) $(MFLAGS) libtermcap.a) || exit 1
+
+$(SHLIB_LIBRARY): config.h ${SHLIB_SOURCE}
+       @echo making $@ in ${SH_LIBDIR}
+       @(cd ${SH_LIBDIR} && \
+               $(MAKE) $(MFLAGS) DEBUG=${DEBUG} ${SHLIB_LIBNAME}) || exit 1
+
+${INTL_LIBRARY}: config.h ${INTL_LIBDIR}/Makefile
+       @echo making $@ in ${INTL_LIBDIR}
+       @(cd ${INTL_LIBDIR} && \
+               $(MAKE) $(MFLAGS) all) || exit 1
+
+${LIBINTL_H}:  ${INTL_DEP}
+
+signames.o: $(SUPPORT_SRC)signames.c
+       $(RM) $@
+       $(CC) $(CCFLAGS) -c $(SUPPORT_SRC)signames.c
+
+buildsignames.o:       $(SUPPORT_SRC)signames.c
+       $(RM) $@
+       $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -DBUILDTOOL -o $@ -c $(SUPPORT_SRC)signames.c
+
+mksignames.o:  $(SUPPORT_SRC)mksignames.c
+       $(RM) $@
+       $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -DBUILDTOOL -c $(SUPPORT_SRC)mksignames.c
+
+mksignames$(EXEEXT):   mksignames.o buildsignames.o
+       $(RM) $@
+       $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) ${LDFLAGS_FOR_BUILD} -o $@ mksignames.o buildsignames.o ${LIBS_FOR_BUILD}
+
+mksyntax$(EXEEXT):     ${srcdir}/mksyntax.c config.h syntax.h ${BASHINCDIR}/chartypes.h
+       $(RM) $@
+       ${CC_FOR_BUILD} ${CCFLAGS_FOR_BUILD} ${LDFLAGS_FOR_BUILD} -o $@ ${srcdir}/mksyntax.c ${LIBS_FOR_BUILD}
+
+# make a list of signals for the local system -- this is done when we're
+# *not* cross-compiling
+lsignames.h:   mksignames$(EXEEXT)
+       $(RM) $@
+       ./mksignames$(EXEEXT) $@
+
+# copy the correct signames header file to signames.h
+signames.h: $(SIGNAMES_H)
+       -if cmp -s $(SIGNAMES_H) $@ ; then :; else $(RM) $@ ; $(CP) $(SIGNAMES_H) $@ ; fi
+
+syntax.c:      mksyntax${EXEEXT} $(srcdir)/syntax.h 
+       $(RM) $@
+       ./mksyntax$(EXEEXT) -o $@
+
+$(BUILTINS_LIBRARY): $(BUILTIN_DEFS) $(BUILTIN_C_SRC) config.h ${BASHINCDIR}/memalloc.h $(DEFDIR)/builtext.h version.h
+       @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) DEBUG=${DEBUG} targets ) || exit 1
+
+# these require special rules to circumvent make builtin rules
+${DEFDIR}/common.o:    $(BUILTIN_SRCDIR)/common.c
+       @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) DEBUG=${DEBUG} common.o) || exit 1
+
+${DEFDIR}/bashgetopt.o:        $(BUILTIN_SRCDIR)/bashgetopt.c
+       @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) DEBUG=${DEBUG} bashgetopt.o) || exit 1
+
+${DEFDIR}/builtext.h: $(BUILTIN_DEFS)
+       @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) builtext.h ) || exit 1
+
+# For the justification of the following Makefile rules, see node
+# `Automatic Remaking' in GNU Autoconf documentation.
+
+Makefile makefile:     config.status $(srcdir)/Makefile.in
+       CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) ./config.status
+
+Makefiles makefiles:   config.status $(srcdir)/Makefile.in
+       @for mf in $(CREATED_MAKEFILES); do \
+               CONFIG_FILES=$$mf CONFIG_HEADERS= $(SHELL) ./config.status ; \
+       done
+
+config.h:      stamp-h 
+
+stamp-h:       config.status $(srcdir)/config.h.in $(srcdir)/config-top.h $(srcdir)/config-bot.h
+       CONFIG_FILES= CONFIG_HEADERS=config.h $(SHELL) ./config.status
+
+config.status: $(srcdir)/configure
+       $(SHELL) ./config.status --recheck
+
+pathnames.h:           Makefile $(srcdir)/pathnames.h.in
+       @sed -e 's|@DEBUGGER_START_FILE\@|${DEBUGGER_START_FILE}|g' $(srcdir)/pathnames.h.in > pathnames.tmp
+       @if test -f $@; then \
+               cmp -s pathnames.tmp $@ || mv pathnames.tmp $@; \
+       else \
+               mv pathnames.tmp $@; \
+       fi
+       @${RM} pathnames.tmp
+
+# comment out for distribution
+$(srcdir)/configure:   $(srcdir)/configure.ac $(srcdir)/aclocal.m4 $(srcdir)/config.h.in
+       cd $(srcdir) && autoconf
+
+# for chet
+reconfig: force
+       sh $(srcdir)/configure -C
+
+#newversion:   mkversion
+#      $(RM) .build
+#      ./mkversion -dir $(srcdir) -dist
+#      mv -f newversion.h version.h
+#      $(MAKE) -f $(srcdir)/Makefile $(MFLAGS) srcdir=$(srcdir)
+
+doc documentation:  force
+       @(cd $(DOCDIR) ; $(MAKE) $(MFLAGS) )
+
+info dvi ps: force
+       @(cd $(DOCDIR) ; $(MAKE) $(MFLAGS) CFLAGS='$(CCFLAGS)' $@ )
+
+force:
+
+# unused
+TAGS:  $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE)
+       etags $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE)
+
+tags:  $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE)
+       ctags -x $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE) > $@
+
+# Targets that actually do things not part of the build
+
+installdirs:
+       @${SHELL} $(SUPPORT_SRC)mkinstalldirs $(DESTDIR)$(bindir)
+       @${SHELL} $(SUPPORT_SRC)mkinstalldirs $(DESTDIR)$(man1dir)
+       @${SHELL} $(SUPPORT_SRC)mkinstalldirs $(DESTDIR)$(infodir)
+       @${SHELL} $(SUPPORT_SRC)mkinstalldirs $(DESTDIR)$(docdir)
+       -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+
+install:       .made installdirs
+       $(INSTALL_PROGRAM) $(INSTALLMODE) $(Program) $(DESTDIR)$(bindir)/$(Program)
+       $(INSTALL_SCRIPT) $(INSTALLMODE2) bashbug $(DESTDIR)$(bindir)/bashbug
+       $(INSTALL_DATA) $(OTHER_DOCS) $(DESTDIR)$(docdir)
+       -( cd $(DOCDIR) ; $(MAKE) $(MFLAGS) \
+               man1dir=$(man1dir) man1ext=$(man1ext) \
+               man3dir=$(man3dir) man3ext=$(man3ext) \
+               infodir=$(infodir) htmldir=$(htmldir) DESTDIR=$(DESTDIR) $@ )
+       -( cd $(DEFDIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+       -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+
+install-strip:
+       $(MAKE) $(MFLAGS) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' \
+               prefix=${prefix} exec_prefix=${exec_prefix} \
+               DESTDIR=$(DESTDIR) install
+
+uninstall:     .made
+       $(RM) $(DESTDIR)$(bindir)/$(Program) $(DESTDIR)$(bindir)/bashbug
+       -( cd $(DESTDIR)$(docdir) && ${RM} ${OTHER_INSTALLED_DOCS} )
+       -( cd $(DOCDIR) ; $(MAKE) $(MFLAGS) \
+               man1dir=$(man1dir) man1ext=$(man1ext) \
+               man3dir=$(man3dir) man3ext=$(man3ext) \
+               infodir=$(infodir) htmldir=$(htmldir) DESTDIR=$(DESTDIR) $@ )
+       -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+
+.PHONY: basic-clean clean realclean maintainer-clean distclean mostlyclean maybe-clean
+
+LIB_SUBDIRS = ${RL_LIBDIR}  ${HIST_LIBDIR} ${TERM_LIBDIR} ${GLOB_LIBDIR} \
+               ${INTL_LIBDIR} ${TILDE_LIBDIR} ${ALLOC_LIBDIR} ${SH_LIBDIR}
+
+basic-clean:
+       $(RM) $(OBJECTS) $(Program) bashbug
+       $(RM) .build .made version.h 
+
+clean: basic-clean
+       ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+       ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+       -( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
+       -for libdir in ${LIB_SUBDIRS}; do \
+               (cd $$libdir && test -f Makefile && $(MAKE) $(MFLAGS) $@) ;\
+       done
+       -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+       $(RM) $(CREATED_SUPPORT)
+
+mostlyclean: basic-clean
+       ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+       ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+       -( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
+       -for libdir in ${LIB_SUBDIRS}; do \
+               (cd $$libdir && test -f Makefile && $(MAKE) $(MFLAGS) $@) ;\
+       done
+       -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+
+distclean:     basic-clean maybe-clean
+       ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+       ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+       -( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
+       -for libdir in ${LIB_SUBDIRS}; do \
+               (cd $$libdir && test -f Makefile && $(MAKE) $(MFLAGS) $@) ;\
+       done
+       -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+       $(RM) $(CREATED_CONFIGURE) tags TAGS 
+       $(RM) $(CREATED_SUPPORT) Makefile $(CREATED_MAKEFILES) pathnames.h
+
+maintainer-clean:      basic-clean
+       @echo This command is intended for maintainers to use.
+       @echo It deletes files that may require special tools to rebuild.
+       $(RM) y.tab.c y.tab.h parser-built tags TAGS
+       ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+       ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+       ( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
+       -for libdir in ${LIB_SUBDIRS}; do \
+               (cd $$libdir && test -f Makefile && $(MAKE) $(MFLAGS) $@) ;\
+       done
+       -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+       $(RM) $(CREATED_CONFIGURE) $(CREATED_MAKEFILES)
+       $(RM) $(CREATED_SUPPORT) Makefile pathnames.h
+
+maybe-clean:
+       -if test "X$(topdir)" != "X$(BUILD_DIR)" ; then \
+               $(RM) parser-built y.tab.c y.tab.h ; \
+       fi
+
+recho$(EXEEXT):                $(SUPPORT_SRC)recho.c
+       @$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) ${LDFLAGS_FOR_BUILD} -o $@ $(SUPPORT_SRC)recho.c ${LIBS_FOR_BUILD}
+
+zecho$(EXEEXT):                $(SUPPORT_SRC)zecho.c
+       @$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) ${LDFLAGS_FOR_BUILD} -o $@ $(SUPPORT_SRC)zecho.c ${LIBS_FOR_BUILD}
+
+printenv$(EXEEXT):     $(SUPPORT_SRC)printenv.c
+       @$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) ${LDFLAGS_FOR_BUILD} -o $@ $(SUPPORT_SRC)printenv.c ${LIBS_FOR_BUILD}
+
+xcase$(EXEEXT):        $(SUPPORT_SRC)xcase.c
+       @$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) ${LDFLAGS_FOR_BUILD} -o $@ $(SUPPORT_SRC)xcase.c ${LIBS_FOR_BUILD}
+
+test tests check:      force $(Program) $(TESTS_SUPPORT)
+       @-test -d tests || mkdir tests
+       @cp $(TESTS_SUPPORT) tests
+       @( cd $(srcdir)/tests && \
+               PATH=$(BUILD_DIR)/tests:$$PATH THIS_SH=$(THIS_SH) $(SHELL) ${TESTSCRIPT} )
+
+symlinks:
+       $(SHELL) $(SUPPORT_SRC)fixlinks -s $(srcdir)
+
+dist:  force
+       @echo Bash distributions are created using $(srcdir)/support/mkdist.
+       @echo Here is a sample of the necessary commands:
+       @echo $(Program) $(srcdir)/support/mkdist -m $(srcdir)/MANIFEST -s $(srcdir) -r ${PACKAGE} $(PACKAGE_VERSION)
+       @echo tar cf $(PACKAGE)-${PACKAGE_VERSION}.tar ${PACKAGE}-$(PACKAGE_VERSION)
+       @echo gzip $(PACKAGE)-$(PACKAGE_VERSION).tar
+
+depend:        depends
+
+depends: force
+       $(Program) $(SUPPORT_SRC)mkdep -c ${CC} -- ${CCFLAGS} ${CSOURCES}
+
+#### PRIVATE TARGETS ####
+hashtest:      hashlib.c
+       $(CC) -DTEST_HASHING $(CCFLAGS) -o $@ $(srcdir)/hashlib.c
+
+############################ DEPENDENCIES ###############################
+
+# Files that depend on the definitions in config-top.h, which are not meant
+# to be changed
+bashhist.o: config-top.h
+shell.o: config-top.h
+input.o: config-top.h
+y.tab.o: config-top.h
+jobs.o: config-top.h
+nojobs.o: config-top.h
+execute_cmd.o: config-top.h
+variables.o: config-top.h
+builtins/command.o: config-top.h
+builtins/common.o: config-top.h
+builtins/break.o: config-top.h
+builtins/echo.o: config-top.h
+builtins/evalstring.o: config-top.h
+builtins/exit.o: config-top.h
+builtins/kill.o: config-top.h
+
+# shell basics
+copy_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+copy_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+copy_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+copy_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+dispose_cmd.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+dispose_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h
+dispose_cmd.o: error.h general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+dispose_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+dispose_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+dispose_cmd.o: ${BASHINCDIR}/ocache.h
+error.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h flags.h ${BASHINCDIR}/stdc.h error.h
+error.o: command.h general.h xmalloc.h externs.h input.h bashhist.h
+error.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+error.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+error.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+error.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+error.o: input.h execute_cmd.h 
+eval.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h trap.h flags.h ${DEFSRC}/common.h
+eval.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+eval.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+eval.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+eval.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+eval.o: input.h execute_cmd.h 
+execute_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+execute_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+execute_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+execute_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+execute_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+execute_cmd.o: ${BASHINCDIR}/memalloc.h ${GRAM_H} flags.h builtins.h jobs.h quit.h siglist.h
+execute_cmd.o: execute_cmd.h findcmd.h redir.h trap.h test.h pathexp.h
+execute_cmd.o: $(DEFSRC)/common.h ${DEFDIR}/builtext.h ${GLOB_LIBSRC}/strmatch.h
+execute_cmd.o: ${BASHINCDIR}/posixtime.h ${BASHINCDIR}/chartypes.h
+expr.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h 
+expr.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+expr.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+expr.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+expr.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+expr.o: ${BASHINCDIR}/chartypes.h
+findcmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h
+findcmd.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/memalloc.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h
+findcmd.o: ${BASHINCDIR}/stdc.h error.h general.h xmalloc.h variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h
+findcmd.o: dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h externs.h
+findcmd.o: flags.h hashlib.h pathexp.h hashcmd.h 
+findcmd.o: ${BASHINCDIR}/chartypes.h
+flags.o: config.h flags.h 
+flags.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+flags.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+flags.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+flags.o: make_cmd.h subst.h sig.h pathnames.h externs.h bashhist.h
+general.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+general.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+general.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+general.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+general.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+general.o: ${BASHINCDIR}/maxpath.h ${BASHINCDIR}/posixtime.h
+general.o: ${BASHINCDIR}/chartypes.h
+hashcmd.o: config.h ${BASHINCDIR}/posixstat.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+hashcmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+hashcmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashcmd.h
+hashcmd.o: execute_cmd.h findcmd.h ${BASHINCDIR}/stdc.h pathnames.h hashlib.h
+hashlib.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+hashlib.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+hashlib.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+hashlib.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+hashlib.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+input.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+input.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h input.h error.h externs.h
+input.o: quit.h
+list.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+list.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+list.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+list.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+locale.o: config.h bashtypes.h bashintl.h ${LIBINTL_H} bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+locale.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+locale.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+locale.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+locale.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+locale.o: ${BASHINCDIR}/chartypes.h
+mailcheck.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+mailcheck.o: ${BASHINCDIR}/posixtime.h
+mailcheck.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+mailcheck.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+mailcheck.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+mailcheck.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+mailcheck.o: execute_cmd.h mailcheck.h 
+make_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h bashansi.h
+make_cmd.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h error.h flags.h make_cmd.h
+make_cmd.o: variables.h arrayfunc.h conftypes.h array.h hashlib.h subst.h input.h externs.h
+make_cmd.o: jobs.h quit.h siglist.h syntax.h dispose_cmd.h parser.h
+make_cmd.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h ${BASHINCDIR}/ocache.h
+y.tab.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/memalloc.h
+y.tab.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+y.tab.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+y.tab.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+y.tab.o: make_cmd.h subst.h sig.h pathnames.h externs.h test.h
+y.tab.o: trap.h flags.h parser.h input.h mailcheck.h $(DEFSRC)/common.h
+y.tab.o: $(DEFDIR)/builtext.h bashline.h bashhist.h jobs.h siglist.h alias.h
+pathexp.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+pathexp.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+pathexp.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+pathexp.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+pathexp.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+pathexp.o: pathexp.h flags.h 
+pathexp.o: $(GLOB_LIBSRC)/glob.h $(GLOB_LIBSRC)/strmatch.h
+pathexp.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
+print_cmd.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+print_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+print_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+print_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+print_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+print_cmd.o: ${GRAM_H} $(DEFSRC)/common.h
+redir.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/filecntl.h
+redir.o: ${BASHINCDIR}/memalloc.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+redir.o: general.h xmalloc.h variables.h arrayfunc.h conftypes.h array.h hashlib.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h
+redir.o: dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h externs.h 
+redir.o: flags.h execute_cmd.h redir.h input.h
+shell.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/filecntl.h
+shell.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+shell.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+shell.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+shell.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+shell.o: flags.h trap.h mailcheck.h builtins.h $(DEFSRC)/common.h
+shell.o: jobs.h siglist.h input.h execute_cmd.h findcmd.h bashhist.h bashline.h
+shell.o: ${GLOB_LIBSRC}/strmatch.h ${BASHINCDIR}/posixtime.h
+sig.o: config.h bashtypes.h
+sig.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+sig.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+sig.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+sig.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+sig.o: jobs.h siglist.h trap.h $(DEFSRC)/common.h bashline.h bashhist.h
+sig.o: ${DEFDIR}/builtext.h
+siglist.o: config.h bashtypes.h siglist.h trap.h 
+stringlib.o: bashtypes.h ${BASHINCDIR}/chartypes.h
+stringlib.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+stringlib.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+stringlib.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+stringlib.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+stringlib.o: ${GLOB_LIBSRC}/glob.h ${GLOB_LIBSRC}/strmatch.h
+subst.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/posixstat.h
+subst.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+subst.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+subst.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+subst.o: make_cmd.h subst.h sig.h pathnames.h externs.h parser.h
+subst.o: flags.h jobs.h siglist.h execute_cmd.h ${BASHINCDIR}/filecntl.h trap.h pathexp.h
+subst.o: mailcheck.h input.h $(DEFSRC)/getopt.h $(DEFSRC)/common.h
+subst.o: bashline.h bashhist.h ${GLOB_LIBSRC}/strmatch.h
+subst.o: ${BASHINCDIR}/chartypes.h
+subst.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
+subst.o: ${DEFDIR}/builtext.h
+test.o: bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
+test.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+test.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+test.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+test.o: make_cmd.h subst.h sig.h pathnames.h externs.h test.h
+test.o: ${DEFSRC}/common.h 
+trap.o: config.h bashtypes.h trap.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+trap.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+trap.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+trap.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+trap.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+trap.o: signames.h $(DEFSRC)/common.h
+trap.o: ${DEFDIR}/builtext.h jobs.h
+unwind_prot.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h command.h ${BASHINCDIR}/stdc.h
+unwind_prot.o: general.h xmalloc.h unwind_prot.h quit.h sig.h
+variables.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+variables.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+variables.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+variables.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+variables.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+variables.o: flags.h execute_cmd.h mailcheck.h input.h $(DEFSRC)/common.h
+variables.o: findcmd.h bashhist.h hashcmd.h pathexp.h
+variables.o: pcomplete.h  ${BASHINCDIR}/chartypes.h
+variables.o: ${BASHINCDIR}/posixtime.h assoc.h
+variables.o: version.h $(DEFDIR)/builtext.h
+version.o:  conftypes.h patchlevel.h version.h
+xmalloc.o: config.h bashtypes.h ${BASHINCDIR}/ansi_stdlib.h error.h
+
+# job control
+
+jobs.o: config.h bashtypes.h trap.h ${BASHINCDIR}/filecntl.h input.h ${BASHINCDIR}/shtty.h
+jobs.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+jobs.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+jobs.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+jobs.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+jobs.o: execute_cmd.h make_cmd.h subst.h sig.h pathnames.h externs.h 
+jobs.o: jobs.h flags.h $(DEFSRC)/common.h $(DEFDIR)/builtext.h
+jobs.o: ${BASHINCDIR}/posixwait.h ${BASHINCDIR}/unionwait.h
+jobs.o: ${BASHINCDIR}/posixtime.h
+nojobs.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h bashjmp.h ${BASHINCDIR}/posixjmp.h
+nojobs.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h jobs.h quit.h siglist.h externs.h
+nojobs.o: sig.h error.h ${BASHINCDIR}/shtty.h input.h
+nojobs.o: $(DEFDIR)/builtext.h
+
+# shell features that may be compiled in
+
+array.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+array.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+array.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+array.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+array.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+array.o: $(DEFSRC)/common.h
+arrayfunc.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+arrayfunc.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+arrayfunc.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+arrayfunc.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+arrayfunc.o: make_cmd.h subst.h sig.h pathnames.h externs.h pathexp.h
+arrayfunc.o: $(DEFSRC)/common.h
+arrayfunc.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
+assoc.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+assoc.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h
+assoc.o: command.h ${BASHINCDIR}/stdc.h error.h
+assoc.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h
+assoc.o: assoc.h hashlib.h
+assoc.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+assoc.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+assoc.o: $(DEFSRC)/common.h
+braces.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+braces.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+braces.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+braces.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+braces.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+braces.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
+alias.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h command.h ${BASHINCDIR}/stdc.h
+alias.o: general.h xmalloc.h bashtypes.h externs.h alias.h
+alias.o: pcomplete.h 
+alias.o: ${BASHINCDIR}/chartypes.h
+
+pcomplib.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h bashtypes.h
+pcomplib.o: ${BASHINCDIR}/stdc.h hashlib.h pcomplete.h shell.h syntax.h
+pcomplib.o: bashjmp.h command.h general.h xmalloc.h error.h variables.h arrayfunc.h conftypes.h quit.h
+pcomplib.o: unwind_prot.h dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h
+pcomplib.o: externs.h ${BASHINCDIR}/maxpath.h
+
+pcomplete.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h bashtypes.h
+pcomplete.o: ${BASHINCDIR}/stdc.h hashlib.h pcomplete.h shell.h syntax.h
+pcomplete.o: bashjmp.h command.h general.h xmalloc.h error.h variables.h arrayfunc.h conftypes.h quit.h
+pcomplete.o: unwind_prot.h dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h
+pcomplete.o: externs.h ${BASHINCDIR}/maxpath.h execute_cmd.h 
+pcomplete.o: ${DEFDIR}/builtext.h
+
+# library support files
+
+bashhist.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/posixstat.h
+bashhist.o: ${BASHINCDIR}/filecntl.h
+bashhist.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+bashhist.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+bashhist.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+bashhist.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+bashhist.o: flags.h input.h parser.h pathexp.h $(DEFSRC)/common.h bashline.h
+bashhist.o: $(GLOB_LIBSRC)/strmatch.h
+bashline.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+bashline.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+bashline.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+bashline.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+bashline.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+bashline.o: builtins.h bashhist.h bashline.h execute_cmd.h findcmd.h pathexp.h
+bashline.o: $(DEFSRC)/common.h $(GLOB_LIBSRC)/glob.h alias.h
+bashline.o: pcomplete.h ${BASHINCDIR}/chartypes.h input.h
+bashline.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
+bracecomp.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+bracecomp.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h
+bracecomp.o: command.h ${BASHINCDIR}/stdc.h error.h
+bracecomp.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h
+bracecomp.o: array.h hashlib.h alias.h builtins.h 
+bracecomp.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+bracecomp.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+
+# library dependencies
+
+bashline.o: $(RL_LIBSRC)/rlconf.h
+bashline.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/rlstdc.h
+bashline.o: $(RL_LIBSRC)/chardefs.h $(RL_LIBSRC)/readline.h
+bracecomp.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/chardefs.h
+bracecomp.o: $(RL_LIBSRC)/readline.h $(RL_LIBSRC)/rlstdc.h
+y.tab.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/chardefs.h
+y.tab.o: $(RL_LIBSRC)/readline.h $(RL_LIBSRC)/rlstdc.h
+subst.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/chardefs.h
+subst.o: $(RL_LIBSRC)/readline.h $(RL_LIBSRC)/rlstdc.h
+
+shell.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+subst.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+bashline.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+bashhist.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+y.tab.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+
+execute_cmd.o: $(TILDE_LIBSRC)/tilde.h
+general.o: $(TILDE_LIBSRC)/tilde.h
+mailcheck.o: $(TILDE_LIBSRC)/tilde.h
+shell.o: $(TILDE_LIBSRC)/tilde.h
+subst.o: $(TILDE_LIBSRC)/tilde.h
+variables.o: $(TILDE_LIBSRC)/tilde.h
+
+# libintl dependencies
+arrayfunc.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+bashhist.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+bashline.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+braces.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+error.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+eval.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+execute_cmd.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+expr.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+general.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+input.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+jobs.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+mailcheck.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+make_cmd.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+nojobs.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+y.tab.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+pcomplete.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+pcomplib.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+print_cmd.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+redir.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+shell.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+sig.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+siglist.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+subst.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+test.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+trap.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+variables.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+version.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+xmalloc.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+
+signames.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+
+# XXX - dependencies checked through here
+
+# builtin c sources
+builtins/bashgetopt.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/bashgetopt.o: shell.h syntax.h config.h bashjmp.h command.h general.h xmalloc.h error.h
+builtins/bashgetopt.o: variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+builtins/bashgetopt.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+builtins/bashgetopt.o: $(DEFSRC)/common.h
+builtins/bashgetopt.o: ${BASHINCDIR}/chartypes.h
+builtins/common.o: bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/common.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h command.h
+builtins/common.o: ${BASHINCDIR}/memalloc.h variables.h arrayfunc.h conftypes.h input.h siglist.h
+builtins/common.o: quit.h unwind_prot.h ${BASHINCDIR}/maxpath.h jobs.h builtins.h
+builtins/common.o: dispose_cmd.h make_cmd.h subst.h externs.h bashhist.h 
+builtins/common.o: execute_cmd.h ${BASHINCDIR}/stdc.h general.h xmalloc.h error.h pathnames.h
+builtins/common.o: ${DEFDIR}/builtext.h
+builtins/common.o: ${BASHINCDIR}/chartypes.h
+builtins/evalfile.o: bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/evalfile.o: shell.h syntax.h config.h bashjmp.h command.h general.h xmalloc.h error.h
+builtins/evalfile.o: variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+builtins/evalfile.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+builtins/evalfile.o: jobs.h builtins.h flags.h input.h execute_cmd.h
+builtins/evalfile.o: bashhist.h $(DEFSRC)/common.h
+builtins/evalstring.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/evalstring.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h command.h siglist.h
+builtins/evalstring.o: ${BASHINCDIR}/memalloc.h variables.h arrayfunc.h conftypes.h input.h
+builtins/evalstring.o: quit.h unwind_prot.h ${BASHINCDIR}/maxpath.h jobs.h builtins.h
+builtins/evalstring.o: dispose_cmd.h make_cmd.h subst.h externs.h 
+builtins/evalstring.o: jobs.h builtins.h flags.h input.h execute_cmd.h
+builtins/evalstring.o: bashhist.h $(DEFSRC)/common.h pathnames.h
+builtins/getopt.o: config.h ${BASHINCDIR}/memalloc.h
+builtins/getopt.o: shell.h syntax.h bashjmp.h command.h general.h xmalloc.h error.h
+builtins/getopt.o: variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+builtins/getopt.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+builtins/getopt.o: $(DEFSRC)/getopt.h
+builtins/mkbuiltins.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
+builtins/mkbuiltins.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+
+# builtin def files
+builtins/alias.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/alias.o: quit.h $(DEFSRC)/common.h pathnames.h
+builtins/alias.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h command.h ${BASHINCDIR}/stdc.h unwind_prot.h
+builtins/alias.o: dispose_cmd.h make_cmd.h subst.h externs.h variables.h arrayfunc.h conftypes.h 
+builtins/bind.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/bind.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/bind.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/bind.o: $(DEFSRC)/bashgetopt.h pathnames.h
+builtins/break.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/break.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/break.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/break.o: pathnames.h
+builtins/builtin.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/builtin.o: quit.h $(DEFSRC)/common.h $(DEFSRC)/bashgetopt.h
+builtins/builtin.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/builtin.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/builtin.o: pathnames.h
+builtins/caller.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/caller.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/caller.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/caller.o: $(DEFSRC)/common.h quit.h 
+builtins/caller.o: ${BASHINCDIR}/chartypes.h bashtypes.h
+builtins/caller.o: ${DEFDIR}/builtext.h pathnames.h
+builtins/cd.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/cd.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/cd.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/cd.o: $(DEFSRC)/common.h quit.h pathnames.h
+builtins/command.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/command.o: quit.h $(DEFSRC)/bashgetopt.h
+builtins/command.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/command.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h pathnames.h
+builtins/declare.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/declare.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/declare.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/declare.o: $(DEFSRC)/bashgetopt.h pathnames.h
+builtins/echo.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/echo.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/echo.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/echo.o: pathnames.h
+builtins/enable.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/enable.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/enable.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/enable.o: pcomplete.h pathnames.h
+builtins/eval.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/eval.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h 
+builtins/eval.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/eval.o: pathnames.h
+builtins/exec.o: bashtypes.h pathnames.h
+builtins/exec.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/exec.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/exec.o: dispose_cmd.h make_cmd.h subst.h externs.h execute_cmd.h 
+builtins/exec.o: findcmd.h flags.h quit.h $(DEFSRC)/common.h ${BASHINCDIR}/stdc.h
+builtins/exec.o: pathnames.h
+builtins/exit.o: bashtypes.h 
+builtins/exit.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/exit.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/exit.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/exit.o: pathnames.h
+builtins/fc.o: bashtypes.h ${BASHINCDIR}/posixstat.h
+builtins/fc.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h builtins.h command.h ${BASHINCDIR}/stdc.h 
+builtins/fc.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/fc.o: flags.h unwind_prot.h variables.h arrayfunc.h conftypes.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h 
+builtins/fc.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h quit.h 
+builtins/fc.o: $(DEFSRC)/bashgetopt.h bashhist.h pathnames.h
+builtins/fc.o: ${BASHINCDIR}/chartypes.h
+builtins/fg_bg.o: bashtypes.h $(DEFSRC)/bashgetopt.h 
+builtins/fg_bg.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/fg_bg.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/fg_bg.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/fg_bg.o: pathnames.h
+builtins/getopts.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/getopts.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h 
+builtins/getopts.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/getopts.o: pathnames.h
+builtins/hash.o: bashtypes.h 
+builtins/hash.o: builtins.h command.h findcmd.h ${BASHINCDIR}/stdc.h $(DEFSRC)/common.h
+builtins/hash.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/hash.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h 
+builtins/hash.o: pathnames.h
+builtins/help.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/help.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/help.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/help.o: $(GLOB_LIBSRC)/glob.h pathnames.h
+builtins/history.o: bashtypes.h pathnames.h
+builtins/history.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/history.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/history.o: ${BASHINCDIR}/filecntl.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h
+builtins/history.o: bashhist.h variables.h arrayfunc.h conftypes.h 
+builtins/inlib.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/inlib.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h 
+builtins/inlib.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/inlib.o: pathnames.h
+builtins/jobs.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/jobs.o: quit.h $(DEFSRC)/bashgetopt.h
+builtins/jobs.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/jobs.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/jobs.o: pathnames.h
+builtins/kill.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/kill.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/kill.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h trap.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/kill.o: pathnames.h
+builtins/let.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/let.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/let.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/let.o: pathnames.h
+builtins/printf.o: config.h ${BASHINCDIR}/memalloc.h bashjmp.h command.h error.h
+builtins/printf.o: general.h xmalloc.h quit.h dispose_cmd.h make_cmd.h subst.h
+builtins/printf.o: externs.h sig.h pathnames.h shell.h syntax.h unwind_prot.h
+builtins/printf.o: variables.h arrayfunc.h conftypes.h ${BASHINCDIR}/stdc.h $(DEFSRC)/bashgetopt.h
+builtins/printf.o: ${BASHINCDIR}/chartypes.h 
+builtins/pushd.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/pushd.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/pushd.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/pushd.o: $(DEFSRC)/common.h pathnames.h
+builtins/read.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/read.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/read.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/read.o: pathnames.h
+builtins/return.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/return.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/return.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/return.o: pathnames.h
+builtins/set.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/set.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/set.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h flags.h
+builtins/set.o: pathnames.h
+builtins/setattr.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/setattr.o: quit.h $(DEFSRC)/common.h $(DEFSRC)/bashgetopt.h
+builtins/setattr.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/setattr.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/setattr.o: pathnames.h
+builtins/shift.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/shift.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/shift.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/shift.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/shift.o: pathnames.h
+builtins/shopt.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h
+builtins/shopt.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h
+builtins/shopt.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h unwind_prot.h variables.h arrayfunc.h conftypes.h ${BASHINCDIR}/maxpath.h
+builtins/shopt.o: $(DEFSRC)/common.h $(DEFSRC)/bashgetopt.h pathnames.h
+builtins/shopt.o: bashhist.h bashline.h
+builtins/source.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/source.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/source.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/source.o: findcmd.h $(DEFSRC)/bashgetopt.h flags.h trap.h
+builtins/source.o: pathnames.h
+builtins/suspend.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/suspend.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/suspend.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/suspend.o: pathnames.h
+builtins/test.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/test.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/test.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/test.o: test.h pathnames.h
+builtins/times.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/times.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/times.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/times.o: pathnames.h
+builtins/trap.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/trap.o: quit.h $(DEFSRC)/common.h
+builtins/trap.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/trap.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/trap.o: pathnames.h
+builtins/type.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/type.o: quit.h $(DEFSRC)/common.h findcmd.h
+builtins/type.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/type.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/type.o: pathnames.h
+builtins/ulimit.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/ulimit.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/ulimit.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/ulimit.o: pathnames.h
+builtins/umask.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/umask.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/umask.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/umask.o: ${BASHINCDIR}/chartypes.h pathnames.h
+builtins/wait.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/wait.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/wait.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/wait.o: ${BASHINCDIR}/chartypes.h pathnames.h
+
+builtins/complete.o: config.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h
+builtins/complete.o: unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/complete.o: bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/complete.o: builtins.h pathnames.h
+builtins/complete.o: pcomplete.h
+builtins/complete.o: ${DEFSRC}/common.h ${DEFSRC}/bashgetopt.h
+builtins/mapfile.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/mapfile.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/mapfile.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/mapfile.o: pathnames.h
+
+# libintl dependencies
+builtins/bind.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/break.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/caller.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/cd.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/common.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/complete.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/declare.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/enable.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/evalfile.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/exec.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/exit.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/fc.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/fg_bg.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/getopt.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/hash.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/help.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/history.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/inlib.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/jobs.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/kill.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/let.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/mapfile.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/mkbuiltins.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/printf.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/pushd.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/read.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/return.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/set.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/setattr.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/shift.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/shopt.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/source.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/suspend.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/type.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/ulimit.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/umask.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+
+# builtin library dependencies
+builtins/bind.o: $(RL_LIBSRC)/chardefs.h $(RL_LIBSRC)/readline.h
+builtins/bind.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/rlstdc.h
+
+builtins/bind.o: $(HIST_LIBSRC)/history.h $(RL_LIBSRC)/rlstdc.h
+builtins/fc.o: $(HIST_LIBSRC)/history.h $(RL_LIBSRC)/rlstdc.h
+builtins/history.o: $(HIST_LIBSRC)/history.h $(RL_LIBSRC)/rlstdc.h
+
+builtins/common.o: $(TILDE_LIBSRC)/tilde.h
+builtins/cd.o: $(TILDE_LIBSRC)/tilde.h 
+
+builtins/alias.o: $(DEFSRC)/alias.def
+builtins/bind.o: $(DEFSRC)/bind.def
+builtins/break.o: $(DEFSRC)/break.def
+builtins/builtin.o: $(DEFSRC)/builtin.def
+builtins/caller.o: $(DEFSRC)/caller.def
+builtins/cd.o: $(DEFSRC)/cd.def
+builtins/colon.o: $(DEFSRC)/colon.def
+builtins/command.o: $(DEFSRC)/command.def
+builtins/complete.o: $(DEFSRC)/complete.def
+builtins/declare.o: $(DEFSRC)/declare.def
+builtins/echo.o: $(DEFSRC)/echo.def
+builtins/enable.o: $(DEFSRC)/enable.def
+builtins/eval.o: $(DEFSRC)/eval.def
+builtins/exec.o: $(DEFSRC)/exec.def
+builtins/exit.o: $(DEFSRC)/exit.def
+builtins/fc.o: $(DEFSRC)/fc.def
+builtins/fg_bg.o: $(DEFSRC)/fg_bg.def
+builtins/getopts.o: $(DEFSRC)/getopts.def
+builtins/hash.o: $(DEFSRC)/hash.def
+builtins/help.o: $(DEFSRC)/help.def
+builtins/history.o: $(DEFSRC)/history.def
+builtins/inlib.o: $(DEFSRC)/inlib.def
+builtins/jobs.o: $(DEFSRC)/jobs.def
+builtins/kill.o: $(DEFSRC)/kill.def
+builtins/let.o: $(DEFSRC)/let.def
+builtins/mapfile.o: $(DEFSRC)/mapfile.def
+builtins/pushd.o: $(DEFSRC)/pushd.def
+builtins/read.o: $(DEFSRC)/read.def
+builtins/reserved.o: $(DEFSRC)/reserved.def
+builtins/return.o: $(DEFSRC)/return.def
+builtins/set.o: $(DEFSRC)/set.def
+builtins/setattr.o: $(DEFSRC)/setattr.def
+builtins/shift.o: $(DEFSRC)/shift.def
+builtins/shopt.o: $(DEFSRC)/shopt.def
+builtins/source.o: $(DEFSRC)/source.def
+builtins/suspend.o: $(DEFSRC)/suspend.def
+builtins/test.o: $(DEFSRC)/test.def
+builtins/times.o: $(DEFSRC)/times.def
+builtins/trap.o: $(DEFSRC)/trap.def
+builtins/type.o: $(DEFSRC)/type.def
+builtins/ulimit.o: $(DEFSRC)/ulimit.def
+builtins/umask.o: $(DEFSRC)/umask.def
+builtins/wait.o: $(DEFSRC)/wait.def
index 1f127644a6654da8394baacc54162592f8e73f22..446a98baedd54aa197bee4f52de14e88369a2a50 100644 (file)
@@ -1367,6 +1367,34 @@ prog_complete_return (text, matchnum)
 
 #endif /* PROGRAMMABLE_COMPLETION */
 
+/* Try and catch completion attempts that are syntax errors or otherwise
+   invalid. */
+static int
+invalid_completion (text, ind)
+     const char *text;
+     int ind;
+{
+  int pind;
+
+  /* If we don't catch these here, the next clause will */
+  if (ind > 0 && rl_line_buffer[ind] == '(' && /*)*/
+                member (rl_line_buffer[ind-1], "$<>"))
+    return 0;
+
+  pind = ind - 1;
+  while (pind > 0 && whitespace (rl_line_buffer[pind]))
+    pind--;
+  /* If we have only whitespace preceding a paren, it's valid */
+  if (ind >= 0 && pind <= 0 && rl_line_buffer[ind] == '(')     /*)*/
+    return 0;
+  /* Flag the invalid completions, which are mostly syntax errors */
+  if (ind > 0 && rl_line_buffer[ind] == '(' && /*)*/
+                member (rl_line_buffer[pind], COMMAND_SEPARATORS) == 0)
+    return 1;
+
+  return 0;
+}
+
 /* Do some completion on TEXT.  The indices of TEXT in RL_LINE_BUFFER are
    at START and END.  Return an array of matches, or NULL if none. */
 static char **
@@ -1435,6 +1463,12 @@ attempt_shell_completion (text, start, end)
         assignments. */
     }
 
+  if (in_command_position && invalid_completion (text, ti))
+    {
+      rl_attempted_completion_over = 1;
+      return ((char **)NULL);
+    }
+
   /* Check that we haven't incorrectly flagged a closed command substitution
      as indicating we're in a command position. */
   if (in_command_position && ti >= 0 && rl_line_buffer[ti] == '`' &&
@@ -1511,6 +1545,13 @@ attempt_shell_completion (text, start, end)
          /* command completion if programmable completion fails */
          in_command_position = s == start && STREQ (n, text);  /* XXX */
        }
+      /* empty command name following command separator */
+      else if (s >= e && n[0] == '\0' && text[0] == '\0' && start > 0 &&
+               was_assignment == 0 && member (rl_line_buffer[start-1], COMMAND_SEPARATORS))
+       {
+         foundcs = 0;
+         in_command_position = 1;
+       }
       else if (s >= e && n[0] == '\0' && text[0] == '\0' && start > 0)
         {
           foundcs = 0; /* empty command name following assignments */
diff --git a/bashline.c~ b/bashline.c~
new file mode 100644 (file)
index 0000000..47fa42d
--- /dev/null
@@ -0,0 +1,4253 @@
+/* bashline.c -- Bash's interface to the readline library. */
+
+/* Copyright (C) 1987-2013 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Bash is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#if defined (READLINE)
+
+#include "bashtypes.h"
+#include "posixstat.h"
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#if defined (HAVE_GRP_H)
+#  include <grp.h>
+#endif
+
+#if defined (HAVE_NETDB_H)
+#  include <netdb.h>
+#endif
+
+#include <signal.h>
+
+#include <stdio.h>
+#include "chartypes.h"
+#include "bashansi.h"
+#include "bashintl.h"
+
+#include "shell.h"
+#include "input.h"
+#include "builtins.h"
+#include "bashhist.h"
+#include "bashline.h"
+#include "execute_cmd.h"
+#include "findcmd.h"
+#include "pathexp.h"
+#include "shmbutil.h"
+#include "trap.h"
+
+#include "builtins/common.h"
+
+#include <readline/rlconf.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#include <glob/glob.h>
+
+#if defined (ALIAS)
+#  include "alias.h"
+#endif
+
+#if defined (PROGRAMMABLE_COMPLETION)
+#  include "pcomplete.h"
+#endif
+
+/* These should agree with the defines for emacs_mode and vi_mode in
+   rldefs.h, even though that's not a public readline header file. */
+#ifndef EMACS_EDITING_MODE
+#  define NO_EDITING_MODE      -1
+#  define EMACS_EDITING_MODE    1
+#  define VI_EDITING_MODE       0
+#endif
+
+#define RL_BOOLEAN_VARIABLE_VALUE(s)   ((s)[0] == 'o' && (s)[1] == 'n' && (s)[2] == '\0')
+
+#if defined (BRACE_COMPLETION)
+extern int bash_brace_completion __P((int, int));
+#endif /* BRACE_COMPLETION */
+
+/* To avoid including curses.h/term.h/termcap.h and that whole mess. */
+#ifdef _MINIX
+extern int tputs __P((const char *string, int nlines, void (*outx)(int)));
+#else
+extern int tputs __P((const char *string, int nlines, int (*outx)(int)));
+#endif
+
+/* Forward declarations */
+
+/* Functions bound to keys in Readline for Bash users. */
+static int shell_expand_line __P((int, int));
+static int display_shell_version __P((int, int));
+static int operate_and_get_next __P((int, int));
+
+static int bash_ignore_filenames __P((char **));
+static int bash_ignore_everything __P((char **));
+
+#if defined (BANG_HISTORY)
+static char *history_expand_line_internal __P((char *));
+static int history_expand_line __P((int, int));
+static int tcsh_magic_space __P((int, int));
+#endif /* BANG_HISTORY */
+#ifdef ALIAS
+static int alias_expand_line __P((int, int));
+#endif
+#if defined (BANG_HISTORY) && defined (ALIAS)
+static int history_and_alias_expand_line __P((int, int));
+#endif
+
+static int bash_forward_shellword __P((int, int));
+static int bash_backward_shellword __P((int, int));
+static int bash_kill_shellword __P((int, int));
+static int bash_backward_kill_shellword __P((int, int));
+
+/* Helper functions for Readline. */
+static char *restore_tilde __P((char *, char *));
+static char *maybe_restore_tilde __P((char *, char *));
+
+static char *bash_filename_rewrite_hook __P((char *, int));
+
+static void bash_directory_expansion __P((char **));
+static int bash_filename_stat_hook __P((char **));
+static int bash_command_name_stat_hook __P((char **));
+static int bash_directory_completion_hook __P((char **));
+static int filename_completion_ignore __P((char **));
+static int bash_push_line __P((void));
+
+static int executable_completion __P((const char *, int));
+
+static rl_icppfunc_t *save_directory_hook __P((void));
+static void restore_directory_hook __P((rl_icppfunc_t));
+
+static void cleanup_expansion_error __P((void));
+static void maybe_make_readline_line __P((char *));
+static void set_up_new_line __P((char *));
+
+static int check_redir __P((int));
+static char **attempt_shell_completion __P((const char *, int, int));
+static char *variable_completion_function __P((const char *, int));
+static char *hostname_completion_function __P((const char *, int));
+static char *command_subst_completion_function __P((const char *, int));
+
+static void build_history_completion_array __P((void));
+static char *history_completion_generator __P((const char *, int));
+static int dynamic_complete_history __P((int, int));
+static int bash_dabbrev_expand __P((int, int));
+
+static void initialize_hostname_list __P((void));
+static void add_host_name __P((char *));
+static void snarf_hosts_from_file __P((char *));
+static char **hostnames_matching __P((char *));
+
+static void _ignore_completion_names __P((char **, sh_ignore_func_t *));
+static int name_is_acceptable __P((const char *));
+static int test_for_directory __P((const char *));
+static int return_zero __P((const char *));
+
+static char *bash_dequote_filename __P((char *, int));
+static char *quote_word_break_chars __P((char *));
+static void set_filename_bstab __P((const char *));
+static char *bash_quote_filename __P((char *, int, char *));
+
+#ifdef _MINIX
+static void putx __P((int));
+#else
+static int putx __P((int));
+#endif
+static int bash_execute_unix_command __P((int, int));
+static void init_unix_command_map __P((void));
+static int isolate_sequence __P((char *, int, int, int *));
+
+static int set_saved_history __P((void));
+
+#if defined (ALIAS)
+static int posix_edit_macros __P((int, int));
+#endif
+
+static int bash_event_hook __P((void));
+
+#if defined (PROGRAMMABLE_COMPLETION)
+static int find_cmd_start __P((int));
+static int find_cmd_end __P((int));
+static char *find_cmd_name __P((int, int *, int *));
+static char *prog_complete_return __P((const char *, int));
+
+static char **prog_complete_matches;
+#endif
+
+/* Variables used here but defined in other files. */
+#if defined (BANG_HISTORY)
+extern int hist_verify;
+#endif
+
+extern int current_command_line_count, saved_command_line_count;
+extern int last_command_exit_value;
+extern int array_needs_making;
+extern int posixly_correct, no_symbolic_links;
+extern char *current_prompt_string, *ps1_prompt;
+extern STRING_INT_ALIST word_token_alist[];
+extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
+
+/* SPECIFIC_COMPLETION_FUNCTIONS specifies that we have individual
+   completion functions which indicate what type of completion should be
+   done (at or before point) that can be bound to key sequences with
+   the readline library. */
+#define SPECIFIC_COMPLETION_FUNCTIONS
+
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+static int bash_specific_completion __P((int, rl_compentry_func_t *));
+
+static int bash_complete_filename_internal __P((int));
+static int bash_complete_username_internal __P((int));
+static int bash_complete_hostname_internal __P((int));
+static int bash_complete_variable_internal __P((int));
+static int bash_complete_command_internal __P((int));
+
+static int bash_complete_filename __P((int, int));
+static int bash_possible_filename_completions __P((int, int));
+static int bash_complete_username __P((int, int));
+static int bash_possible_username_completions __P((int, int));
+static int bash_complete_hostname __P((int, int));
+static int bash_possible_hostname_completions __P((int, int));
+static int bash_complete_variable __P((int, int));
+static int bash_possible_variable_completions __P((int, int));
+static int bash_complete_command __P((int, int));
+static int bash_possible_command_completions __P((int, int));
+
+static char *glob_complete_word __P((const char *, int));
+static int bash_glob_completion_internal __P((int));
+static int bash_glob_complete_word __P((int, int));
+static int bash_glob_expand_word __P((int, int));
+static int bash_glob_list_expansions __P((int, int));
+
+#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
+
+static int edit_and_execute_command __P((int, int, int, char *));
+#if defined (VI_MODE)
+static int vi_edit_and_execute_command __P((int, int));
+static int bash_vi_complete __P((int, int));
+#endif
+static int emacs_edit_and_execute_command __P((int, int));
+
+/* Non-zero once initalize_readline () has been called. */
+int bash_readline_initialized = 0;
+
+/* If non-zero, we do hostname completion, breaking words at `@' and
+   trying to complete the stuff after the `@' from our own internal
+   host list. */
+int perform_hostname_completion = 1;
+
+/* If non-zero, we don't do command completion on an empty line. */
+int no_empty_command_completion;
+
+/* Set FORCE_FIGNORE if you want to honor FIGNORE even if it ignores the
+   only possible matches.  Set to 0 if you want to match filenames if they
+   are the only possible matches, even if FIGNORE says to. */
+int force_fignore = 1;
+
+/* Perform spelling correction on directory names during word completion */
+int dircomplete_spelling = 0;
+
+/* Expand directory names during word/filename completion. */
+#if DIRCOMPLETE_EXPAND_DEFAULT
+int dircomplete_expand = 1;
+int dircomplete_expand_relpath = 1;
+#else
+int dircomplete_expand = 0;
+int dircomplete_expand_relpath = 0;
+#endif
+
+/* When non-zero, perform `normal' shell quoting on completed filenames
+   even when the completed name contains a directory name with a shell
+   variable referene, so dollar signs in a filename get quoted appropriately.
+   Set to zero to remove dollar sign (and braces or parens as needed) from
+   the set of characters that will be quoted. */
+int complete_fullquote = 1;
+
+static char *bash_completer_word_break_characters = " \t\n\"'@><=;|&(:";
+static char *bash_nohostname_word_break_characters = " \t\n\"'><=;|&(:";
+/* )) */
+
+static const char *default_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{~";        /*}*/
+static char *custom_filename_quote_characters = 0;
+static char filename_bstab[256];
+
+static rl_hook_func_t *old_rl_startup_hook = (rl_hook_func_t *)NULL;
+
+static int dot_in_path = 0;
+
+/* Set to non-zero when dabbrev-expand is running */
+static int dabbrev_expand_active = 0;
+
+/* What kind of quoting is performed by bash_quote_filename:
+       COMPLETE_DQUOTE = double-quoting the filename
+       COMPLETE_SQUOTE = single_quoting the filename
+       COMPLETE_BSQUOTE = backslash-quoting special chars in the filename
+*/
+#define COMPLETE_DQUOTE  1
+#define COMPLETE_SQUOTE  2
+#define COMPLETE_BSQUOTE 3
+static int completion_quoting_style = COMPLETE_BSQUOTE;
+
+/* Flag values for the final argument to bash_default_completion */
+#define DEFCOMP_CMDPOS         1
+
+/* Change the readline VI-mode keymaps into or out of Posix.2 compliance.
+   Called when the shell is put into or out of `posix' mode. */
+void
+posix_readline_initialize (on_or_off)
+     int on_or_off;
+{
+  if (on_or_off)
+    rl_variable_bind ("comment-begin", "#");
+#if defined (VI_MODE)
+  rl_bind_key_in_map (CTRL ('I'), on_or_off ? rl_insert : rl_complete, vi_insertion_keymap);
+#endif
+}
+
+void
+reset_completer_word_break_chars ()
+{
+  rl_completer_word_break_characters = perform_hostname_completion ? savestring (bash_completer_word_break_characters) : savestring (bash_nohostname_word_break_characters);
+}
+
+/* When this function returns, rl_completer_word_break_characters points to
+   dynamically allocated memory. */
+int
+enable_hostname_completion (on_or_off)
+     int on_or_off;
+{
+  int old_value;
+  char *at, *nv, *nval;
+
+  old_value = perform_hostname_completion;
+
+  if (on_or_off)
+    {
+      perform_hostname_completion = 1;
+      rl_special_prefixes = "$@";
+    }
+  else
+    {
+      perform_hostname_completion = 0;
+      rl_special_prefixes = "$";
+    }
+
+  /* Now we need to figure out how to appropriately modify and assign
+     rl_completer_word_break_characters depending on whether we want
+     hostname completion on or off. */
+
+  /* If this is the first time this has been called
+     (bash_readline_initialized == 0), use the sames values as before, but
+     allocate new memory for rl_completer_word_break_characters. */
+
+  if (bash_readline_initialized == 0 &&
+      (rl_completer_word_break_characters == 0 || 
+       rl_completer_word_break_characters == rl_basic_word_break_characters))
+    {
+      if (on_or_off)
+       rl_completer_word_break_characters = savestring (bash_completer_word_break_characters);
+      else
+       rl_completer_word_break_characters = savestring (bash_nohostname_word_break_characters);
+    }
+  else
+    {
+      /* See if we have anything to do. */
+      at = strchr (rl_completer_word_break_characters, '@');
+      if ((at == 0 && on_or_off == 0) || (at != 0 && on_or_off != 0))
+        return old_value;
+
+      /* We have something to do.  Do it. */
+      nval = (char *)xmalloc (strlen (rl_completer_word_break_characters) + 1 + on_or_off);
+
+      if (on_or_off == 0)
+       {
+         /* Turn it off -- just remove `@' from word break chars.  We want
+            to remove all occurrences of `@' from the char list, so we loop
+            rather than just copy the rest of the list over AT. */
+         for (nv = nval, at = rl_completer_word_break_characters; *at; )
+           if (*at != '@')
+             *nv++ = *at++;
+           else
+             at++;
+         *nv = '\0';
+       }
+      else
+       {
+         nval[0] = '@';
+         strcpy (nval + 1, rl_completer_word_break_characters);
+        }
+
+      free (rl_completer_word_break_characters);
+      rl_completer_word_break_characters = nval;
+    }
+
+  return (old_value);
+}
+
+/* Called once from parse.y if we are going to use readline. */
+void
+initialize_readline ()
+{
+  rl_command_func_t *func;
+  char kseq[2];
+
+  if (bash_readline_initialized)
+    return;
+
+  rl_terminal_name = get_string_value ("TERM");
+  rl_instream = stdin;
+  rl_outstream = stderr;
+
+  /* Allow conditional parsing of the ~/.inputrc file. */
+  rl_readline_name = "Bash";
+
+  /* Add bindable names before calling rl_initialize so they may be
+     referenced in the various inputrc files. */
+  rl_add_defun ("shell-expand-line", shell_expand_line, -1);
+#ifdef BANG_HISTORY
+  rl_add_defun ("history-expand-line", history_expand_line, -1);
+  rl_add_defun ("magic-space", tcsh_magic_space, -1);
+#endif
+
+  rl_add_defun ("shell-forward-word", bash_forward_shellword, -1);
+  rl_add_defun ("shell-backward-word", bash_backward_shellword, -1);
+  rl_add_defun ("shell-kill-word", bash_kill_shellword, -1);
+  rl_add_defun ("shell-backward-kill-word", bash_backward_kill_shellword, -1);
+
+#ifdef ALIAS
+  rl_add_defun ("alias-expand-line", alias_expand_line, -1);
+#  ifdef BANG_HISTORY
+  rl_add_defun ("history-and-alias-expand-line", history_and_alias_expand_line, -1);
+#  endif
+#endif
+
+  /* Backwards compatibility. */
+  rl_add_defun ("insert-last-argument", rl_yank_last_arg, -1);
+
+  rl_add_defun ("operate-and-get-next", operate_and_get_next, -1);
+  rl_add_defun ("display-shell-version", display_shell_version, -1);
+  rl_add_defun ("edit-and-execute-command", emacs_edit_and_execute_command, -1);
+
+#if defined (BRACE_COMPLETION)
+  rl_add_defun ("complete-into-braces", bash_brace_completion, -1);
+#endif
+
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+  rl_add_defun ("complete-filename", bash_complete_filename, -1);
+  rl_add_defun ("possible-filename-completions", bash_possible_filename_completions, -1);
+  rl_add_defun ("complete-username", bash_complete_username, -1);
+  rl_add_defun ("possible-username-completions", bash_possible_username_completions, -1);
+  rl_add_defun ("complete-hostname", bash_complete_hostname, -1);
+  rl_add_defun ("possible-hostname-completions", bash_possible_hostname_completions, -1);
+  rl_add_defun ("complete-variable", bash_complete_variable, -1);
+  rl_add_defun ("possible-variable-completions", bash_possible_variable_completions, -1);
+  rl_add_defun ("complete-command", bash_complete_command, -1);
+  rl_add_defun ("possible-command-completions", bash_possible_command_completions, -1);
+  rl_add_defun ("glob-complete-word", bash_glob_complete_word, -1);
+  rl_add_defun ("glob-expand-word", bash_glob_expand_word, -1);
+  rl_add_defun ("glob-list-expansions", bash_glob_list_expansions, -1);
+#endif
+
+  rl_add_defun ("dynamic-complete-history", dynamic_complete_history, -1);
+  rl_add_defun ("dabbrev-expand", bash_dabbrev_expand, -1);
+
+  /* Bind defaults before binding our custom shell keybindings. */
+  if (RL_ISSTATE(RL_STATE_INITIALIZED) == 0)
+    rl_initialize ();
+
+  /* Bind up our special shell functions. */
+  rl_bind_key_if_unbound_in_map (CTRL('E'), shell_expand_line, emacs_meta_keymap);
+
+#ifdef BANG_HISTORY
+  rl_bind_key_if_unbound_in_map ('^', history_expand_line, emacs_meta_keymap);
+#endif
+
+  rl_bind_key_if_unbound_in_map (CTRL ('O'), operate_and_get_next, emacs_standard_keymap);
+  rl_bind_key_if_unbound_in_map (CTRL ('V'), display_shell_version, emacs_ctlx_keymap);
+
+  /* In Bash, the user can switch editing modes with "set -o [vi emacs]",
+     so it is not necessary to allow C-M-j for context switching.  Turn
+     off this occasionally confusing behaviour. */
+  kseq[0] = CTRL('J');
+  kseq[1] = '\0';
+  func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
+  if (func == rl_vi_editing_mode)
+    rl_unbind_key_in_map (CTRL('J'), emacs_meta_keymap);
+  kseq[0] = CTRL('M');
+  func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
+  if (func == rl_vi_editing_mode)
+    rl_unbind_key_in_map (CTRL('M'), emacs_meta_keymap);
+#if defined (VI_MODE)
+  rl_unbind_key_in_map (CTRL('E'), vi_movement_keymap);
+#endif
+
+#if defined (BRACE_COMPLETION)
+  rl_bind_key_if_unbound_in_map ('{', bash_brace_completion, emacs_meta_keymap); /*}*/
+#endif /* BRACE_COMPLETION */
+
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+  rl_bind_key_if_unbound_in_map ('/', bash_complete_filename, emacs_meta_keymap);
+  rl_bind_key_if_unbound_in_map ('/', bash_possible_filename_completions, emacs_ctlx_keymap);
+
+  /* Have to jump through hoops here because there is a default binding for
+     M-~ (rl_tilde_expand) */
+  kseq[0] = '~';
+  kseq[1] = '\0';
+  func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
+  if (func == 0 || func == rl_tilde_expand)
+    rl_bind_keyseq_in_map (kseq, bash_complete_username, emacs_meta_keymap);
+
+  rl_bind_key_if_unbound_in_map ('~', bash_possible_username_completions, emacs_ctlx_keymap);
+
+  rl_bind_key_if_unbound_in_map ('@', bash_complete_hostname, emacs_meta_keymap);
+  rl_bind_key_if_unbound_in_map ('@', bash_possible_hostname_completions, emacs_ctlx_keymap);
+
+  rl_bind_key_if_unbound_in_map ('$', bash_complete_variable, emacs_meta_keymap);
+  rl_bind_key_if_unbound_in_map ('$', bash_possible_variable_completions, emacs_ctlx_keymap);
+
+  rl_bind_key_if_unbound_in_map ('!', bash_complete_command, emacs_meta_keymap);
+  rl_bind_key_if_unbound_in_map ('!', bash_possible_command_completions, emacs_ctlx_keymap);
+
+  rl_bind_key_if_unbound_in_map ('g', bash_glob_complete_word, emacs_meta_keymap);
+  rl_bind_key_if_unbound_in_map ('*', bash_glob_expand_word, emacs_ctlx_keymap);
+  rl_bind_key_if_unbound_in_map ('g', bash_glob_list_expansions, emacs_ctlx_keymap);
+
+#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
+
+  kseq[0] = TAB;
+  kseq[1] = '\0';
+  func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
+  if (func == 0 || func == rl_tab_insert)
+    rl_bind_key_in_map (TAB, dynamic_complete_history, emacs_meta_keymap);
+
+  /* Tell the completer that we want a crack first. */
+  rl_attempted_completion_function = attempt_shell_completion;
+
+  /* Tell the completer that we might want to follow symbolic links or
+     do other expansion on directory names. */
+  set_directory_hook ();
+
+  rl_filename_rewrite_hook = bash_filename_rewrite_hook;
+
+  rl_filename_stat_hook = bash_filename_stat_hook;
+
+  /* Tell the filename completer we want a chance to ignore some names. */
+  rl_ignore_some_completions_function = filename_completion_ignore;
+
+  /* Bind C-xC-e to invoke emacs and run result as commands. */
+  rl_bind_key_if_unbound_in_map (CTRL ('E'), emacs_edit_and_execute_command, emacs_ctlx_keymap);
+#if defined (VI_MODE)
+  rl_bind_key_if_unbound_in_map ('v', vi_edit_and_execute_command, vi_movement_keymap);
+#  if defined (ALIAS)
+  rl_bind_key_if_unbound_in_map ('@', posix_edit_macros, vi_movement_keymap);
+#  endif
+
+  rl_bind_key_in_map ('\\', bash_vi_complete, vi_movement_keymap);
+  rl_bind_key_in_map ('*', bash_vi_complete, vi_movement_keymap);
+  rl_bind_key_in_map ('=', bash_vi_complete, vi_movement_keymap);
+#endif
+
+  rl_completer_quote_characters = "'\"";
+
+  /* This sets rl_completer_word_break_characters and rl_special_prefixes
+     to the appropriate values, depending on whether or not hostname
+     completion is enabled. */
+  enable_hostname_completion (perform_hostname_completion);
+
+  /* characters that need to be quoted when appearing in filenames. */
+  rl_filename_quote_characters = default_filename_quote_characters;
+  set_filename_bstab (rl_filename_quote_characters);
+
+  rl_filename_quoting_function = bash_quote_filename;
+  rl_filename_dequoting_function = bash_dequote_filename;
+  rl_char_is_quoted_p = char_is_quoted;
+
+#if 0
+  /* This is superfluous and makes it impossible to use tab completion in
+     vi mode even when explicitly binding it in ~/.inputrc.  sv_strict_posix()
+     should already have called posix_readline_initialize() when
+     posixly_correct was set. */
+  if (posixly_correct)
+    posix_readline_initialize (1);
+#endif
+
+  bash_readline_initialized = 1;
+}
+
+void
+bashline_reinitialize ()
+{
+  bash_readline_initialized = 0;
+}
+
+void
+bashline_set_event_hook ()
+{
+  rl_signal_event_hook = bash_event_hook;
+}
+
+void
+bashline_reset_event_hook ()
+{
+  rl_signal_event_hook = 0;
+}
+
+/* On Sun systems at least, rl_attempted_completion_function can end up
+   getting set to NULL, and rl_completion_entry_function set to do command
+   word completion if Bash is interrupted while trying to complete a command
+   word.  This just resets all the completion functions to the right thing.
+   It's called from throw_to_top_level(). */
+void
+bashline_reset ()
+{
+  tilde_initialize ();
+  rl_attempted_completion_function = attempt_shell_completion;
+  rl_completion_entry_function = NULL;
+  rl_ignore_some_completions_function = filename_completion_ignore;
+  rl_filename_quote_characters = default_filename_quote_characters;
+  set_filename_bstab (rl_filename_quote_characters);
+
+  set_directory_hook ();
+  rl_filename_stat_hook = bash_filename_stat_hook;
+
+  bashline_reset_event_hook ();
+}
+
+/* Contains the line to push into readline. */
+static char *push_to_readline = (char *)NULL;
+
+/* Push the contents of push_to_readline into the
+   readline buffer. */
+static int
+bash_push_line ()
+{
+  if (push_to_readline)
+    {
+      rl_insert_text (push_to_readline);
+      free (push_to_readline);
+      push_to_readline = (char *)NULL;
+      rl_startup_hook = old_rl_startup_hook;
+    }
+  return 0;
+}
+
+/* Call this to set the initial text for the next line to read
+   from readline. */
+int
+bash_re_edit (line)
+     char *line;
+{
+  FREE (push_to_readline);
+
+  push_to_readline = savestring (line);
+  old_rl_startup_hook = rl_startup_hook;
+  rl_startup_hook = bash_push_line;
+
+  return (0);
+}
+
+static int
+display_shell_version (count, c)
+     int count, c;
+{
+  rl_crlf ();
+  show_shell_version (0);
+  putc ('\r', rl_outstream);
+  fflush (rl_outstream);
+  rl_on_new_line ();
+  rl_redisplay ();
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                          Readline Stuff                         */
+/*                                                                 */
+/* **************************************************************** */
+
+/* If the user requests hostname completion, then simply build a list
+   of hosts, and complete from that forever more, or at least until
+   HOSTFILE is unset. */
+
+/* THIS SHOULD BE A STRINGLIST. */
+/* The kept list of hostnames. */
+static char **hostname_list = (char **)NULL;
+
+/* The physical size of the above list. */
+static int hostname_list_size;
+
+/* The number of hostnames in the above list. */
+static int hostname_list_length;
+
+/* Whether or not HOSTNAME_LIST has been initialized. */
+int hostname_list_initialized = 0;
+
+/* Initialize the hostname completion table. */
+static void
+initialize_hostname_list ()
+{
+  char *temp;
+
+  temp = get_string_value ("HOSTFILE");
+  if (temp == 0)
+    temp = get_string_value ("hostname_completion_file");
+  if (temp == 0)
+    temp = DEFAULT_HOSTS_FILE;
+
+  snarf_hosts_from_file (temp);
+
+  if (hostname_list)
+    hostname_list_initialized++;
+}
+
+/* Add NAME to the list of hosts. */
+static void
+add_host_name (name)
+     char *name;
+{
+  if (hostname_list_length + 2 > hostname_list_size)
+    {
+      hostname_list_size = (hostname_list_size + 32) - (hostname_list_size % 32);
+      hostname_list = strvec_resize (hostname_list, hostname_list_size);
+    }
+
+  hostname_list[hostname_list_length++] = savestring (name);
+  hostname_list[hostname_list_length] = (char *)NULL;
+}
+
+#define cr_whitespace(c) ((c) == '\r' || (c) == '\n' || whitespace(c))
+
+static void
+snarf_hosts_from_file (filename)
+     char *filename;
+{
+  FILE *file;
+  char *temp, buffer[256], name[256];
+  register int i, start;
+
+  file = fopen (filename, "r");
+  if (file == 0)
+    return;
+
+  while (temp = fgets (buffer, 255, file))
+    {
+      /* Skip to first character. */
+      for (i = 0; buffer[i] && cr_whitespace (buffer[i]); i++)
+       ;
+
+      /* If comment or blank line, ignore. */
+      if (buffer[i] == '\0' || buffer[i] == '#')
+       continue;
+
+      /* If `preprocessor' directive, do the include. */
+      if (strncmp (buffer + i, "$include ", 9) == 0)
+       {
+         char *incfile, *t;
+
+         /* Find start of filename. */
+         for (incfile = buffer + i + 9; *incfile && whitespace (*incfile); incfile++)
+           ;
+
+         /* Find end of filename. */
+         for (t = incfile; *t && cr_whitespace (*t) == 0; t++)
+           ;
+
+         *t = '\0';
+
+         snarf_hosts_from_file (incfile);
+         continue;
+       }
+
+      /* Skip internet address if present. */
+      if (DIGIT (buffer[i]))
+       for (; buffer[i] && cr_whitespace (buffer[i]) == 0; i++);
+
+      /* Gobble up names.  Each name is separated with whitespace. */
+      while (buffer[i])
+       {
+         for (; cr_whitespace (buffer[i]); i++)
+           ;
+         if (buffer[i] == '\0' || buffer[i] ==  '#')
+           break;
+
+         /* Isolate the current word. */
+         for (start = i; buffer[i] && cr_whitespace (buffer[i]) == 0; i++)
+           ;
+         if (i == start)
+           continue;
+         strncpy (name, buffer + start, i - start);
+         name[i - start] = '\0';
+         add_host_name (name);
+       }
+    }
+  fclose (file);
+}
+
+/* Return the hostname list. */
+char **
+get_hostname_list ()
+{
+  if (hostname_list_initialized == 0)
+    initialize_hostname_list ();
+  return (hostname_list);
+}
+
+void
+clear_hostname_list ()
+{
+  register int i;
+
+  if (hostname_list_initialized == 0)
+    return;
+  for (i = 0; i < hostname_list_length; i++)
+    free (hostname_list[i]);
+  hostname_list_length = hostname_list_initialized = 0;
+}
+
+/* Return a NULL terminated list of hostnames which begin with TEXT.
+   Initialize the hostname list the first time if necessary.
+   The array is malloc ()'ed, but not the individual strings. */
+static char **
+hostnames_matching (text)
+     char *text;
+{
+  register int i, len, nmatch, rsize;
+  char **result;
+
+  if (hostname_list_initialized == 0)
+    initialize_hostname_list ();
+
+  if (hostname_list_initialized == 0)
+    return ((char **)NULL);
+
+  /* Special case.  If TEXT consists of nothing, then the whole list is
+     what is desired. */
+  if (*text == '\0')
+    {
+      result = strvec_create (1 + hostname_list_length);
+      for (i = 0; i < hostname_list_length; i++)
+       result[i] = hostname_list[i];
+      result[i] = (char *)NULL;
+      return (result);
+    }
+
+  /* Scan until found, or failure. */
+  len = strlen (text);
+  result = (char **)NULL;
+  for (i = nmatch = rsize = 0; i < hostname_list_length; i++)
+    {
+      if (STREQN (text, hostname_list[i], len) == 0)
+       continue;
+
+      /* OK, it matches.  Add it to the list. */
+      if (nmatch >= (rsize - 1))
+       {
+         rsize = (rsize + 16) - (rsize % 16);
+         result = strvec_resize (result, rsize);
+       }
+
+      result[nmatch++] = hostname_list[i];
+    }
+  if (nmatch)
+    result[nmatch] = (char *)NULL;
+  return (result);
+}
+
+/* The equivalent of the Korn shell C-o operate-and-get-next-history-line
+   editing command. */
+static int saved_history_line_to_use = -1;
+static int last_saved_history_line = -1;
+
+#define HISTORY_FULL() (history_is_stifled () && history_length >= history_max_entries)
+
+static int
+set_saved_history ()
+{
+  /* XXX - compensate for assumption that history was `shuffled' if it was
+     actually not. */
+  if (HISTORY_FULL () &&
+      hist_last_line_added == 0 &&
+      saved_history_line_to_use < history_length - 1)
+    saved_history_line_to_use++;
+
+  if (saved_history_line_to_use >= 0)
+    {
+     rl_get_previous_history (history_length - saved_history_line_to_use, 0);
+     last_saved_history_line = saved_history_line_to_use;
+    }
+  saved_history_line_to_use = -1;
+  rl_startup_hook = old_rl_startup_hook;
+  return (0);
+}
+
+static int
+operate_and_get_next (count, c)
+     int count, c;
+{
+  int where;
+
+  /* Accept the current line. */
+  rl_newline (1, c);
+
+  /* Find the current line, and find the next line to use. */
+  where = where_history ();
+
+  if (HISTORY_FULL () || (where >= history_length - 1))
+    saved_history_line_to_use = where;
+  else
+    saved_history_line_to_use = where + 1;
+
+  old_rl_startup_hook = rl_startup_hook;
+  rl_startup_hook = set_saved_history;
+
+  return 0;
+}
+
+/* This vi mode command causes VI_EDIT_COMMAND to be run on the current
+   command being entered (if no explicit argument is given), otherwise on
+   a command from the history file. */
+
+#define VI_EDIT_COMMAND                "fc -e \"${VISUAL:-${EDITOR:-vi}}\""
+#define EMACS_EDIT_COMMAND     "fc -e \"${VISUAL:-${EDITOR:-emacs}}\""
+#define POSIX_VI_EDIT_COMMAND  "fc -e vi"
+
+static int
+edit_and_execute_command (count, c, editing_mode, edit_command)
+     int count, c, editing_mode;
+     char *edit_command;
+{
+  char *command, *metaval;
+  int r, rrs, metaflag;
+  sh_parser_state_t ps;
+
+  rrs = rl_readline_state;
+  saved_command_line_count = current_command_line_count;
+
+  /* Accept the current line. */
+  rl_newline (1, c);
+
+  if (rl_explicit_arg)
+    {
+      command = (char *)xmalloc (strlen (edit_command) + 8);
+      sprintf (command, "%s %d", edit_command, count);
+    }
+  else
+    {
+      /* Take the command we were just editing, add it to the history file,
+        then call fc to operate on it.  We have to add a dummy command to
+        the end of the history because fc ignores the last command (assumes
+        it's supposed to deal with the command before the `fc'). */
+      /* This breaks down when using command-oriented history and are not
+        finished with the command, so we should not ignore the last command */
+      using_history ();
+      current_command_line_count++;    /* for rl_newline above */
+      bash_add_history (rl_line_buffer);
+      current_command_line_count = 0;  /* for dummy history entry */
+      bash_add_history ("");
+      history_lines_this_session++;
+      using_history ();
+      command = savestring (edit_command);
+    }
+
+  metaval = rl_variable_value ("input-meta");
+  metaflag = RL_BOOLEAN_VARIABLE_VALUE (metaval);
+  
+  /* Now, POSIX.1-2001 and SUSv3 say that the commands executed from the
+     temporary file should be placed into the history.  We don't do that
+     yet. */
+  if (rl_deprep_term_function)
+    (*rl_deprep_term_function) ();
+  save_parser_state (&ps);
+  r = parse_and_execute (command, (editing_mode == VI_EDITING_MODE) ? "v" : "C-xC-e", SEVAL_NOHIST);
+  restore_parser_state (&ps);
+  if (rl_prep_term_function)
+    (*rl_prep_term_function) (metaflag);
+
+  current_command_line_count = saved_command_line_count;
+
+  /* Now erase the contents of the current line and undo the effects of the
+     rl_accept_line() above.  We don't even want to make the text we just
+     executed available for undoing. */
+  rl_line_buffer[0] = '\0';    /* XXX */
+  rl_point = rl_end = 0;
+  rl_done = 0;
+  rl_readline_state = rrs;
+
+  rl_forced_update_display ();
+
+  return r;
+}
+
+#if defined (VI_MODE)
+static int
+vi_edit_and_execute_command (count, c)
+     int count, c;
+{
+  if (posixly_correct)
+    return (edit_and_execute_command (count, c, VI_EDITING_MODE, POSIX_VI_EDIT_COMMAND));
+  else
+    return (edit_and_execute_command (count, c, VI_EDITING_MODE, VI_EDIT_COMMAND));
+}
+#endif /* VI_MODE */
+
+static int
+emacs_edit_and_execute_command (count, c)
+     int count, c;
+{
+  return (edit_and_execute_command (count, c, EMACS_EDITING_MODE, EMACS_EDIT_COMMAND));
+}
+
+#if defined (ALIAS)
+static int
+posix_edit_macros (count, key)
+     int count, key;
+{
+  int c;
+  char alias_name[3], *alias_value, *macro;
+
+  c = rl_read_key ();
+  alias_name[0] = '_';
+  alias_name[1] = c;
+  alias_name[2] = '\0';
+
+  alias_value = get_alias_value (alias_name);
+  if (alias_value && *alias_value)
+    {
+      macro = savestring (alias_value);
+      rl_push_macro_input (macro);
+    }
+  return 0;
+}
+#endif
+
+/* Bindable commands that move `shell-words': that is, sequences of
+   non-unquoted-metacharacters. */
+
+#define WORDDELIM(c)   (shellmeta(c) || shellblank(c))
+
+static int
+bash_forward_shellword (count, key)
+     int count, key;
+{
+  size_t slen;
+  int sindex, c, p;
+  DECLARE_MBSTATE;
+
+  if (count < 0)
+    return (bash_backward_shellword (-count, key));
+
+  /* The tricky part of this is deciding whether or not the first character
+     we're on is an unquoted metacharacter.  Not completely handled yet. */
+  /* XXX - need to test this stuff with backslash-escaped shell
+     metacharacters and unclosed single- and double-quoted strings. */
+
+  p = rl_point;
+  slen = rl_end;
+
+  while (count)
+    {
+      if (p == rl_end)
+       {
+         rl_point = rl_end;
+         return 0;
+       }
+
+      /* Are we in a quoted string?  If we are, move to the end of the quoted
+         string and continue the outer loop. We only want quoted strings, not
+         backslash-escaped characters, but char_is_quoted doesn't
+         differentiate. */
+      if (char_is_quoted (rl_line_buffer, p) && p > 0 && rl_line_buffer[p-1] != '\\')
+       {
+         do
+           ADVANCE_CHAR (rl_line_buffer, slen, p);
+         while (p < rl_end && char_is_quoted (rl_line_buffer, p));
+         count--;
+         continue;
+       }
+
+      /* Rest of code assumes we are not in a quoted string. */
+      /* Move forward until we hit a non-metacharacter. */
+      while (p < rl_end && (c = rl_line_buffer[p]) && WORDDELIM (c))
+       {
+         switch (c)
+           {
+           default:
+             ADVANCE_CHAR (rl_line_buffer, slen, p);
+             continue;         /* straight back to loop, don't increment p */
+           case '\\':
+             if (p < rl_end && rl_line_buffer[p])
+               ADVANCE_CHAR (rl_line_buffer, slen, p);
+             break;
+           case '\'':
+             p = skip_to_delim (rl_line_buffer, ++p, "'", SD_NOJMP);
+             break;
+           case '"':
+             p = skip_to_delim (rl_line_buffer, ++p, "\"", SD_NOJMP);
+             break;
+           }
+
+         if (p < rl_end)
+           p++;
+       }
+
+      if (rl_line_buffer[p] == 0 || p == rl_end)
+        {
+         rl_point = rl_end;
+         rl_ding ();
+         return 0;
+        }
+       
+      /* Now move forward until we hit a non-quoted metacharacter or EOL */
+      while (p < rl_end && (c = rl_line_buffer[p]) && WORDDELIM (c) == 0)
+       {
+         switch (c)
+           {
+           default:
+             ADVANCE_CHAR (rl_line_buffer, slen, p);
+             continue;         /* straight back to loop, don't increment p */
+           case '\\':
+             if (p < rl_end && rl_line_buffer[p])
+               ADVANCE_CHAR (rl_line_buffer, slen, p);
+             break;
+           case '\'':
+             p = skip_to_delim (rl_line_buffer, ++p, "'", SD_NOJMP);
+             break;
+           case '"':
+             p = skip_to_delim (rl_line_buffer, ++p, "\"", SD_NOJMP);
+             break;
+           }
+
+         if (p < rl_end)
+           p++;
+       }
+
+      if (p == rl_end || rl_line_buffer[p] == 0)
+       {
+         rl_point = rl_end;
+         return (0);
+       }
+
+      count--;      
+    }
+
+  rl_point = p;
+  return (0);
+}
+
+static int
+bash_backward_shellword (count, key)
+     int count, key;
+{
+  size_t slen;
+  int sindex, c, p;
+  DECLARE_MBSTATE;
+  
+  if (count < 0)
+    return (bash_forward_shellword (-count, key));
+
+  p = rl_point;
+  slen = rl_end;
+  
+  while (count)
+    {
+      if (p == 0)
+       {
+         rl_point = 0;
+         return 0;
+       }
+
+      /* Move backward until we hit a non-metacharacter. */
+      while (p > 0)
+       {
+         c = rl_line_buffer[p];
+         if (WORDDELIM (c) && char_is_quoted (rl_line_buffer, p) == 0)
+           BACKUP_CHAR (rl_line_buffer, slen, p);
+         break;
+       }
+
+      if (p == 0)
+       {
+         rl_point = 0;
+         return 0;
+       }
+
+      /* Now move backward until we hit a metacharacter or BOL. */
+      while (p > 0)
+       {
+         c = rl_line_buffer[p];
+         if (WORDDELIM (c) && char_is_quoted (rl_line_buffer, p) == 0)
+           break;
+         BACKUP_CHAR (rl_line_buffer, slen, p);
+       }
+
+      count--;
+    }
+
+  rl_point = p;
+  return 0;
+}
+
+static int
+bash_kill_shellword (count, key)
+     int count, key;
+{
+  int p;
+
+  if (count < 0)
+    return (bash_backward_kill_shellword (-count, key));
+
+  p = rl_point;
+  bash_forward_shellword (count, key);
+
+  if (rl_point != p)
+    rl_kill_text (p, rl_point);
+
+  rl_point = p;
+  if (rl_editing_mode == 1)    /* 1 == emacs_mode */
+    rl_mark = rl_point;
+
+  return 0;
+}
+
+static int
+bash_backward_kill_shellword (count, key)
+     int count, key;
+{
+  int p;
+
+  if (count < 0)
+    return (bash_kill_shellword (-count, key));
+
+  p = rl_point;
+  bash_backward_shellword (count, key);
+
+  if (rl_point != p)
+    rl_kill_text (p, rl_point);
+
+  if (rl_editing_mode == 1)    /* 1 == emacs_mode */
+    rl_mark = rl_point;
+
+  return 0;
+}
+
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     How To Do Shell Completion                  */
+/*                                                                 */
+/* **************************************************************** */
+
+#define COMMAND_SEPARATORS ";|&{(`"
+/* )} */ 
+#define COMMAND_SEPARATORS_PLUS_WS ";|&{(` \t"
+/* )} */ 
+
+/* check for redirections and other character combinations that are not
+   command separators */
+static int
+check_redir (ti)
+     int ti;
+{
+  register int this_char, prev_char;
+
+  /* Handle the two character tokens `>&', `<&', and `>|'.
+     We are not in a command position after one of these. */
+  this_char = rl_line_buffer[ti];
+  prev_char = rl_line_buffer[ti - 1];
+
+  if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) ||
+      (this_char == '|' && prev_char == '>'))
+    return (1);
+  else if (this_char == '{' && prev_char == '$') /*}*/
+    return (1);
+#if 0  /* Not yet */
+  else if (this_char == '(' && prev_char == '$') /*)*/
+    return (1);
+  else if (this_char == '(' && prev_char == '<') /*)*/
+    return (1);
+#if defined (EXTENDED_GLOB)
+  else if (extended_glob && this_char == '(' && prev_char == '!') /*)*/
+    return (1);
+#endif
+#endif
+  else if (char_is_quoted (rl_line_buffer, ti))
+    return (1);
+  return (0);
+}
+
+#if defined (PROGRAMMABLE_COMPLETION)
+/*
+ * XXX - because of the <= start test, and setting os = s+1, this can
+ * potentially return os > start.  This is probably not what we want to
+ * happen, but fix later after 2.05a-release.
+ */
+static int
+find_cmd_start (start)
+     int start;
+{
+  register int s, os;
+
+  os = 0;
+  /* Flags == SD_NOJMP only because we want to skip over command substitutions
+     in assignment statements.  Have to test whether this affects `standalone'
+     command substitutions as individual words. */
+  while (((s = skip_to_delim (rl_line_buffer, os, COMMAND_SEPARATORS, SD_NOJMP/*|SD_NOSKIPCMD*/)) <= start) &&
+        rl_line_buffer[s])
+    os = s+1;
+  return os;
+}
+
+static int
+find_cmd_end (end)
+     int end;
+{
+  register int e;
+
+  e = skip_to_delim (rl_line_buffer, end, COMMAND_SEPARATORS, SD_NOJMP);
+  return e;
+}
+
+static char *
+find_cmd_name (start, sp, ep)
+     int start;
+     int *sp, *ep;
+{
+  char *name;
+  register int s, e;
+
+  for (s = start; whitespace (rl_line_buffer[s]); s++)
+    ;
+
+  /* skip until a shell break character */
+  e = skip_to_delim (rl_line_buffer, s, "()<>;&| \t\n", SD_NOJMP);
+
+  name = substring (rl_line_buffer, s, e);
+
+  if (sp)
+    *sp = s;
+  if (ep)
+    *ep = e;
+
+  return (name);
+}
+
+static char *
+prog_complete_return (text, matchnum)
+     const char *text;
+     int matchnum;
+{
+  static int ind;
+
+  if (matchnum == 0)
+    ind = 0;
+
+  if (prog_complete_matches == 0 || prog_complete_matches[ind] == 0)
+    return (char *)NULL;
+  return (prog_complete_matches[ind++]);
+}
+
+#endif /* PROGRAMMABLE_COMPLETION */
+
+/* Try and catch completion attempts that are syntax errors or otherwise
+   invalid. */
+static int
+invalid_completion (text, ind)
+     const char *text;
+     int ind;
+{
+  int pind;
+
+  /* If we don't catch these here, the next clause will */
+  if (ind > 0 && rl_line_buffer[ind] == '(' && /*)*/
+                member (rl_line_buffer[ind-1], "$<>"))
+    return 0;
+
+  pind = ind - 1;
+  while (pind > 0 && whitespace (rl_line_buffer[pind]))
+    pind--;
+  /* If we have only whitespace preceding a paren, it's valid */
+  if (ind >= 0 && pind <= 0 && rl_line_buffer[ind] == '(')     /*)*/
+    return 0;
+  /* Flag the invalid completions, which are mostly syntax errors */
+  if (ind > 0 && rl_line_buffer[ind] == '(' && /*)*/
+                member (rl_line_buffer[pind], COMMAND_SEPARATORS) == 0)
+    return 1;
+
+  return 0;
+}
+
+/* Do some completion on TEXT.  The indices of TEXT in RL_LINE_BUFFER are
+   at START and END.  Return an array of matches, or NULL if none. */
+static char **
+attempt_shell_completion (text, start, end)
+     const char *text;
+     int start, end;
+{
+  int in_command_position, ti, saveti, qc, dflags;
+  char **matches, *command_separator_chars;
+#if defined (PROGRAMMABLE_COMPLETION)
+  int have_progcomps, was_assignment;
+#endif
+
+  command_separator_chars = COMMAND_SEPARATORS;
+  matches = (char **)NULL;
+  rl_ignore_some_completions_function = filename_completion_ignore;
+
+  rl_filename_quote_characters = default_filename_quote_characters;
+  set_filename_bstab (rl_filename_quote_characters);
+  set_directory_hook ();
+  rl_filename_stat_hook = bash_filename_stat_hook;
+
+  /* Determine if this could be a command word.  It is if it appears at
+     the start of the line (ignoring preceding whitespace), or if it
+     appears after a character that separates commands.  It cannot be a
+     command word if we aren't at the top-level prompt. */
+  ti = start - 1;
+  saveti = qc = -1;
+
+  while ((ti > -1) && (whitespace (rl_line_buffer[ti])))
+    ti--;
+
+#if 1
+  /* If this is an open quote, maybe we're trying to complete a quoted
+     command name. */
+  if (ti >= 0 && (rl_line_buffer[ti] == '"' || rl_line_buffer[ti] == '\''))
+    {
+      qc = rl_line_buffer[ti];
+      saveti = ti--;
+      while (ti > -1 && (whitespace (rl_line_buffer[ti])))
+       ti--;
+    }
+#endif
+      
+  in_command_position = 0;
+  if (ti < 0)
+    {
+      /* Only do command completion at the start of a line when we
+        are prompting at the top level. */
+      if (current_prompt_string == ps1_prompt)
+       in_command_position++;
+      else if (parser_in_command_position ())
+       in_command_position++;
+    }
+  else if (member (rl_line_buffer[ti], command_separator_chars))
+    {
+      in_command_position++;
+
+      if (check_redir (ti) == 1)
+       in_command_position = 0;
+    }
+  else
+    {
+      /* This still could be in command position.  It is possible
+        that all of the previous words on the line are variable
+        assignments. */
+    }
+
+  if (in_command_position && invalid_completion (text, ti))
+    {
+      rl_attempted_completion_over = 1;
+      return ((char **)NULL);
+    }
+
+  /* Check that we haven't incorrectly flagged a closed command substitution
+     as indicating we're in a command position. */
+  if (in_command_position && ti >= 0 && rl_line_buffer[ti] == '`' &&
+       *text != '`' && unclosed_pair (rl_line_buffer, end, "`") == 0)
+    in_command_position = 0;
+
+  /* Special handling for command substitution.  If *TEXT is a backquote,
+     it can be the start or end of an old-style command substitution, or
+     unmatched.  If it's unmatched, both calls to unclosed_pair will
+     succeed.  Don't bother if readline found a single quote and we are
+     completing on the substring.  */
+  if (*text == '`' && rl_completion_quote_character != '\'' &&
+       (in_command_position || (unclosed_pair (rl_line_buffer, start, "`") &&
+                                unclosed_pair (rl_line_buffer, end, "`"))))
+    matches = rl_completion_matches (text, command_subst_completion_function);
+
+#if defined (PROGRAMMABLE_COMPLETION)
+  /* Attempt programmable completion. */
+  have_progcomps = prog_completion_enabled && (progcomp_size () > 0);
+  if (matches == 0 && (in_command_position == 0 || text[0] == '\0') &&
+      current_prompt_string == ps1_prompt)
+    {
+      int s, e, s1, e1, os, foundcs;
+      char *n;
+
+      /* XXX - don't free the members */
+      if (prog_complete_matches)
+       free (prog_complete_matches);
+      prog_complete_matches = (char **)NULL;
+
+      os = start;
+      n = 0;
+      s = find_cmd_start (os);
+      e = find_cmd_end (end);
+      do
+       {
+         /* Skip over assignment statements preceding a command name.  If we
+            don't find a command name at all, we can perform command name
+            completion.  If we find a partial command name, we should perform
+            command name completion on it. */
+         FREE (n);
+         n = find_cmd_name (s, &s1, &e1);
+         s = e1 + 1;
+       }
+      while (was_assignment = assignment (n, 0));
+      s = s1;          /* reset to index where name begins */
+
+      /* s == index of where command name begins (reset above)
+        e == end of current command, may be end of line
+         s1 = index of where command name begins
+         e1 == index of where command name ends
+        start == index of where word to be completed begins
+        end == index of where word to be completed ends
+        if (s == start) we are doing command word completion for sure
+        if (e1 == end) we are at the end of the command name and completing it */
+      if (start == 0 && end == 0 && e != 0 && text[0] == '\0') /* beginning of non-empty line */
+        foundcs = 0;
+      else if (start == end && start == s1 && e != 0 && e1 > end)      /* beginning of command name, leading whitespace */
+       foundcs = 0;
+      else if (e == 0 && e == s && text[0] == '\0' && have_progcomps)  /* beginning of empty line */
+        prog_complete_matches = programmable_completions ("_EmptycmD_", text, s, e, &foundcs);
+      else if (start == end && text[0] == '\0' && s1 > start && whitespace (rl_line_buffer[start]))
+        foundcs = 0;           /* whitespace before command name */
+      else if (e > s && was_assignment == 0 && e1 == end && rl_line_buffer[e] == 0 && whitespace (rl_line_buffer[e-1]) == 0)
+       {
+         /* not assignment statement, but still want to perform command
+            completion if we are composing command word. */
+         foundcs = 0;
+         in_command_position = s == start && STREQ (n, text);  /* XXX */
+       }
+      else if (e > s && was_assignment == 0 && have_progcomps)
+       {
+         prog_complete_matches = programmable_completions (n, text, s, e, &foundcs);
+         /* command completion if programmable completion fails */
+         in_command_position = s == start && STREQ (n, text);  /* XXX */
+       }
+      /* empty command name following command separator */
+      else if (s >= e && n[0] == '\0' && text[0] == '\0' && start > 0 &&
+               was_assignment == 0 && member (rl_line_buffer[start], COMMAND_SEPARATORS))
+       {
+         foundcs = 0;
+         in_command_position = 1;
+       }
+      else if (s >= e && n[0] == '\0' && text[0] == '\0' && start > 0)
+        {
+          foundcs = 0; /* empty command name following assignments */
+          in_command_position = was_assignment;
+        }
+      else if (s == start && e == end && STREQ (n, text) && start > 0)
+        {
+          foundcs = 0; /* partial command name following assignments */
+          in_command_position = 1;
+        }
+      else
+       foundcs = 0;
+      FREE (n);
+      /* XXX - if we found a COMPSPEC for the command, just return whatever
+        the programmable completion code returns, and disable the default
+        filename completion that readline will do unless the COPT_DEFAULT
+        option has been set with the `-o default' option to complete or
+        compopt. */
+      if (foundcs)
+       {
+         pcomp_set_readline_variables (foundcs, 1);
+         /* Turn what the programmable completion code returns into what
+            readline wants.  I should have made compute_lcd_of_matches
+            external... */
+         matches = rl_completion_matches (text, prog_complete_return);
+         if ((foundcs & COPT_DEFAULT) == 0)
+           rl_attempted_completion_over = 1;   /* no default */
+         if (matches || ((foundcs & COPT_BASHDEFAULT) == 0))
+           return (matches);
+       }
+    }
+#endif
+
+  if (matches == 0)
+    {
+      dflags = 0;
+      if (in_command_position)
+       dflags |= DEFCOMP_CMDPOS;
+      matches = bash_default_completion (text, start, end, qc, dflags);
+    }
+
+  return matches;
+}
+
+char **
+bash_default_completion (text, start, end, qc, compflags)
+     const char *text;
+     int start, end, qc, compflags;
+{
+  char **matches, *t;
+
+  matches = (char **)NULL;
+
+  /* New posix-style command substitution or variable name? */
+  if (!matches && *text == '$')
+    {
+      if (qc != '\'' && text[1] == '(') /* ) */
+       matches = rl_completion_matches (text, command_subst_completion_function);
+      else
+       {
+         matches = rl_completion_matches (text, variable_completion_function);
+         if (matches && matches[0] && matches[1] == 0)
+           {
+             t = savestring (matches[0]);
+             bash_filename_stat_hook (&t);
+             /* doesn't use test_for_directory because that performs tilde
+                expansion */
+             if (file_isdir (t))
+               rl_completion_append_character = '/';
+             free (t);
+           }
+       }
+    }
+
+  /* If the word starts in `~', and there is no slash in the word, then
+     try completing this word as a username. */
+  if (matches == 0 && *text == '~' && mbschr (text, '/') == 0)
+    matches = rl_completion_matches (text, rl_username_completion_function);
+
+  /* Another one.  Why not?  If the word starts in '@', then look through
+     the world of known hostnames for completion first. */
+  if (matches == 0 && perform_hostname_completion && *text == '@')
+    matches = rl_completion_matches (text, hostname_completion_function);
+
+  /* And last, (but not least) if this word is in a command position, then
+     complete over possible command names, including aliases, functions,
+     and command names. */
+  if (matches == 0 && (compflags & DEFCOMP_CMDPOS))
+    {
+      /* If END == START and text[0] == 0, we are trying to complete an empty
+        command word. */
+      if (no_empty_command_completion && end == start && text[0] == '\0')
+       {
+         matches = (char **)NULL;
+         rl_ignore_some_completions_function = bash_ignore_everything;
+       }
+      else
+       {
+#define CMD_IS_DIR(x)  (absolute_pathname(x) == 0 && absolute_program(x) == 0 && *(x) != '~' && test_for_directory (x))
+
+         dot_in_path = 0;
+         matches = rl_completion_matches (text, command_word_completion_function);
+
+         /* If we are attempting command completion and nothing matches, we
+            do not want readline to perform filename completion for us.  We
+            still want to be able to complete partial pathnames, so set the
+            completion ignore function to something which will remove
+            filenames and leave directories in the match list. */
+         if (matches == (char **)NULL)
+           rl_ignore_some_completions_function = bash_ignore_filenames;
+         else if (matches[1] == 0 && CMD_IS_DIR(matches[0]) && dot_in_path == 0)
+           /* If we found a single match, without looking in the current
+              directory (because it's not in $PATH), but the found name is
+              also a command in the current directory, suppress appending any
+              terminating character, since it's ambiguous. */
+           {
+             rl_completion_suppress_append = 1;
+             rl_filename_completion_desired = 0;
+           }
+         else if (matches[0] && matches[1] && STREQ (matches[0], matches[1]) && CMD_IS_DIR (matches[0]))
+           /* There are multiple instances of the same match (duplicate
+              completions haven't yet been removed).  In this case, all of
+              the matches will be the same, and the duplicate removal code
+              will distill them all down to one.  We turn on
+              rl_completion_suppress_append for the same reason as above.
+              Remember: we only care if there's eventually a single unique
+              completion.  If there are multiple completions this won't
+              make a difference and the problem won't occur. */
+           {
+             rl_completion_suppress_append = 1;
+             rl_filename_completion_desired = 0;
+           }
+       }
+    }
+
+  /* This could be a globbing pattern, so try to expand it using pathname
+     expansion. */
+  if (!matches && glob_pattern_p (text))
+    {
+      matches = rl_completion_matches (text, glob_complete_word);
+      /* A glob expression that matches more than one filename is problematic.
+        If we match more than one filename, punt. */
+      if (matches && matches[1] && rl_completion_type == TAB)
+       {
+         strvec_dispose (matches);
+         matches = (char **)0;
+       }
+      else if (matches && matches[1] && rl_completion_type == '!')
+       {
+         rl_completion_suppress_append = 1;
+         rl_filename_completion_desired = 0;
+       }
+    }
+
+  return (matches);
+}
+
+static int
+bash_command_name_stat_hook (name)
+     char **name;
+{
+  char *cname, *result;
+
+  /* If it's not something we're going to look up in $PATH, just call the
+     normal filename stat hook. */
+  if (absolute_program (*name))
+    return (bash_filename_stat_hook (name));
+
+  cname = *name;
+  /* XXX - we could do something here with converting aliases, builtins,
+     and functions into something that came out as executable, but we don't. */
+  result = search_for_command (cname, 0);
+  if (result)
+    {
+      *name = result;
+      return 1;
+    }
+  return 0;
+}
+
+static int
+executable_completion (filename, searching_path)
+     const char *filename;
+     int searching_path;
+{
+  char *f;
+  int r;
+
+  f = savestring (filename);
+  bash_directory_completion_hook (&f);
+  
+  r = searching_path ? executable_file (f) : executable_or_directory (f);
+  free (f);
+  return r;
+}
+
+/* This is the function to call when the word to complete is in a position
+   where a command word can be found.  It grovels $PATH, looking for commands
+   that match.  It also scans aliases, function names, and the shell_builtin
+   table. */
+char *
+command_word_completion_function (hint_text, state)
+     const char *hint_text;
+     int state;
+{
+  static char *hint = (char *)NULL;
+  static char *path = (char *)NULL;
+  static char *val = (char *)NULL;
+  static char *filename_hint = (char *)NULL;
+  static char *fnhint = (char *)NULL;
+  static char *dequoted_hint = (char *)NULL;
+  static char *directory_part = (char *)NULL;
+  static char **glob_matches = (char **)NULL;
+  static int path_index, hint_len, dequoted_len, istate, igncase;
+  static int mapping_over, local_index, searching_path, hint_is_dir;
+  static int old_glob_ignore_case, globpat;
+  static SHELL_VAR **varlist = (SHELL_VAR **)NULL;
+#if defined (ALIAS)
+  static alias_t **alias_list = (alias_t **)NULL;
+#endif /* ALIAS */
+  char *temp, *cval;
+
+  /* We have to map over the possibilities for command words.  If we have
+     no state, then make one just for that purpose. */
+  if (state == 0)
+    {
+      rl_filename_stat_hook = bash_command_name_stat_hook;
+
+      if (dequoted_hint && dequoted_hint != hint)
+       free (dequoted_hint);
+      if (hint)
+       free (hint);
+
+      mapping_over = searching_path = 0;
+      hint_is_dir = CMD_IS_DIR (hint_text);
+      val = (char *)NULL;
+
+      temp = rl_variable_value ("completion-ignore-case");
+      igncase = RL_BOOLEAN_VARIABLE_VALUE (temp);
+
+      if (glob_matches)
+       {
+         free (glob_matches);
+         glob_matches = (char **)NULL;
+       }
+
+      globpat = glob_pattern_p (hint_text);
+
+      /* If this is an absolute program name, do not check it against
+        aliases, reserved words, functions or builtins.  We must check
+        whether or not it is unique, and, if so, whether that filename
+        is executable. */
+      if (globpat || absolute_program (hint_text))
+       {
+         /* Perform tilde expansion on what's passed, so we don't end up
+            passing filenames with tildes directly to stat(). */
+         if (*hint_text == '~')
+           {
+             hint = bash_tilde_expand (hint_text, 0);
+             directory_part = savestring (hint_text);
+             temp = strchr (directory_part, '/');
+             if (temp)
+               *temp = 0;
+             else
+               {
+                 free (directory_part);
+                 directory_part = (char *)NULL;
+               }
+           }
+         else
+           hint = savestring (hint_text);
+
+         dequoted_hint = hint;
+         /* If readline's completer found a quote character somewhere, but
+            didn't set the quote character, there must have been a quote
+            character embedded in the filename.  It can't be at the start of
+            the filename, so we need to dequote the filename before we look
+            in the file system for it. */
+         if (rl_completion_found_quote && rl_completion_quote_character == 0)
+           {
+             dequoted_hint = bash_dequote_filename (hint, 0);
+             free (hint);
+             hint = dequoted_hint;
+           }
+         dequoted_len = hint_len = strlen (hint);
+
+         if (filename_hint)
+           free (filename_hint);
+
+         fnhint = filename_hint = savestring (hint);
+
+         istate = 0;
+
+         if (globpat)
+           {
+             mapping_over = 5;
+             goto globword;
+           }
+         else
+           {
+            if (dircomplete_expand && path_dot_or_dotdot (filename_hint))
+               {
+                 dircomplete_expand = 0;
+                 set_directory_hook ();
+                 dircomplete_expand = 1;
+               }
+             mapping_over = 4;
+             goto inner;
+           }
+       }
+
+      dequoted_hint = hint = savestring (hint_text);
+      dequoted_len = hint_len = strlen (hint);
+
+      if (rl_completion_found_quote && rl_completion_quote_character == 0)
+       {
+         dequoted_hint = bash_dequote_filename (hint, 0);
+         dequoted_len = strlen (dequoted_hint);
+       }
+      
+      path = get_string_value ("PATH");
+      path_index = dot_in_path = 0;
+
+      /* Initialize the variables for each type of command word. */
+      local_index = 0;
+
+      if (varlist)
+       free (varlist);
+
+      varlist = all_visible_functions ();
+
+#if defined (ALIAS)
+      if (alias_list)
+       free (alias_list);
+
+      alias_list = all_aliases ();
+#endif /* ALIAS */
+    }
+
+  /* mapping_over says what we are currently hacking.  Note that every case
+     in this list must fall through when there are no more possibilities. */
+
+  switch (mapping_over)
+    {
+    case 0:                    /* Aliases come first. */
+#if defined (ALIAS)
+      while (alias_list && alias_list[local_index])
+       {
+         register char *alias;
+
+         alias = alias_list[local_index++]->name;
+
+         if (STREQN (alias, hint, hint_len))
+           return (savestring (alias));
+       }
+#endif /* ALIAS */
+      local_index = 0;
+      mapping_over++;
+
+    case 1:                    /* Then shell reserved words. */
+      {
+       while (word_token_alist[local_index].word)
+         {
+           register char *reserved_word;
+
+           reserved_word = word_token_alist[local_index++].word;
+
+           if (STREQN (reserved_word, hint, hint_len))
+             return (savestring (reserved_word));
+         }
+       local_index = 0;
+       mapping_over++;
+      }
+
+    case 2:                    /* Then function names. */
+      while (varlist && varlist[local_index])
+       {
+         register char *varname;
+
+         varname = varlist[local_index++]->name;
+
+         if (STREQN (varname, hint, hint_len))
+           return (savestring (varname));
+       }
+      local_index = 0;
+      mapping_over++;
+
+    case 3:                    /* Then shell builtins. */
+      for (; local_index < num_shell_builtins; local_index++)
+       {
+         /* Ignore it if it doesn't have a function pointer or if it
+            is not currently enabled. */
+         if (!shell_builtins[local_index].function ||
+             (shell_builtins[local_index].flags & BUILTIN_ENABLED) == 0)
+           continue;
+
+         if (STREQN (shell_builtins[local_index].name, hint, hint_len))
+           {
+             int i = local_index++;
+
+             return (savestring (shell_builtins[i].name));
+           }
+       }
+      local_index = 0;
+      mapping_over++;
+    }
+
+globword:
+  /* Limited support for completing command words with globbing chars.  Only
+     a single match (multiple matches that end up reducing the number of
+     characters in the common prefix are bad) will ever be returned on
+     regular completion. */
+  if (globpat)
+    {
+      if (state == 0)
+       {
+         glob_ignore_case = igncase;
+         glob_matches = shell_glob_filename (hint);
+         glob_ignore_case = old_glob_ignore_case;
+
+         if (GLOB_FAILED (glob_matches) || glob_matches == 0)
+           {
+             glob_matches = (char **)NULL;
+             return ((char *)NULL);
+           }
+
+         local_index = 0;
+               
+         if (glob_matches[1] && rl_completion_type == TAB)     /* multiple matches are bad */
+           return ((char *)NULL);
+       }
+
+      while (val = glob_matches[local_index++])
+        {
+         if (executable_or_directory (val))
+           {
+             if (*hint_text == '~' && directory_part)
+               {
+                 temp = maybe_restore_tilde (val, directory_part);
+                 free (val);
+                 val = temp;
+               }
+             return (val);
+           }
+         free (val);
+        }
+
+      glob_ignore_case = old_glob_ignore_case;
+      return ((char *)NULL);
+    }
+
+  /* If the text passed is a directory in the current directory, return it
+     as a possible match.  Executables in directories in the current
+     directory can be specified using relative pathnames and successfully
+     executed even when `.' is not in $PATH. */
+  if (hint_is_dir)
+    {
+      hint_is_dir = 0; /* only return the hint text once */
+      return (savestring (hint_text));
+    }
+    
+  /* Repeatedly call filename_completion_function while we have
+     members of PATH left.  Question:  should we stat each file?
+     Answer: we call executable_file () on each file. */
+ outer:
+
+  istate = (val != (char *)NULL);
+
+  if (istate == 0)
+    {
+      char *current_path;
+
+      /* Get the next directory from the path.  If there is none, then we
+        are all done. */
+      if (path == 0 || path[path_index] == 0 ||
+         (current_path = extract_colon_unit (path, &path_index)) == 0)
+       return ((char *)NULL);
+
+      searching_path = 1;
+      if (*current_path == 0)
+       {
+         free (current_path);
+         current_path = savestring (".");
+       }
+
+      if (*current_path == '~')
+       {
+         char *t;
+
+         t = bash_tilde_expand (current_path, 0);
+         free (current_path);
+         current_path = t;
+       }
+
+      if (current_path[0] == '.' && current_path[1] == '\0')
+       dot_in_path = 1;
+
+      if (fnhint && fnhint != filename_hint)
+       free (fnhint);
+      if (filename_hint)
+       free (filename_hint);
+
+      filename_hint = sh_makepath (current_path, hint, 0);
+      /* Need a quoted version (though it doesn't matter much in most
+        cases) because rl_filename_completion_function dequotes the
+        filename it gets, assuming that it's been quoted as part of
+        the input line buffer. */
+      if (strpbrk (filename_hint, "\"'\\"))
+       fnhint = sh_backslash_quote (filename_hint, filename_bstab, 0);
+      else
+       fnhint = filename_hint;
+      free (current_path);             /* XXX */
+    }
+
+ inner:
+  val = rl_filename_completion_function (fnhint, istate);
+  if (mapping_over == 4 && dircomplete_expand)
+    set_directory_hook ();
+
+  istate = 1;
+
+  if (val == 0)
+    {
+      /* If the hint text is an absolute program, then don't bother
+        searching through PATH. */
+      if (absolute_program (hint))
+       return ((char *)NULL);
+
+      goto outer;
+    }
+  else
+    {
+      int match, freetemp;
+
+      if (absolute_program (hint))
+       {
+         if (igncase == 0)
+           match = strncmp (val, hint, hint_len) == 0;
+         else
+           match = strncasecmp (val, hint, hint_len) == 0;
+
+         /* If we performed tilde expansion, restore the original
+            filename. */
+         if (*hint_text == '~')
+           temp = maybe_restore_tilde (val, directory_part);
+         else
+           temp = savestring (val);
+         freetemp = 1;
+       }
+      else
+       {
+         temp = strrchr (val, '/');
+
+         if (temp)
+           {
+             temp++;
+             if (igncase == 0)
+               freetemp = match = strncmp (temp, hint, hint_len) == 0;
+             else
+               freetemp = match = strncasecmp (temp, hint, hint_len) == 0;
+             if (match)
+               temp = savestring (temp);
+           }
+         else
+           freetemp = match = 0;
+       }
+
+      /* If we have found a match, and it is an executable file, return it.
+        We don't return directory names when searching $PATH, since the
+        bash execution code won't find executables in directories which
+        appear in directories in $PATH when they're specified using
+        relative pathnames.  */
+#if 0
+      /* If we're not searching $PATH and we have a relative pathname, we
+        need to re-canonicalize it before testing whether or not it's an
+        executable or a directory so the shell treats .. relative to $PWD
+        according to the physical/logical option.  The shell already
+        canonicalizes the directory name in order to tell readline where
+        to look, so not doing it here will be inconsistent. */
+      /* XXX -- currently not used -- will introduce more inconsistency,
+        since shell does not canonicalize ../foo before passing it to
+        shell_execve().  */
+      if (match && searching_path == 0 && *val == '.')
+       {
+         char *t, *t1;
+
+         t = get_working_directory ("command-word-completion");
+         t1 = make_absolute (val, t);
+         free (t);
+         cval = sh_canonpath (t1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
+       }
+      else
+#endif
+       cval = val;
+
+      if (match && executable_completion ((searching_path ? val : cval), searching_path))
+       {
+         if (cval != val)
+           free (cval);
+         free (val);
+         val = "";             /* So it won't be NULL. */
+         return (temp);
+       }
+      else
+       {
+         if (freetemp)
+           free (temp);
+         if (cval != val)
+           free (cval);
+         free (val);
+         goto inner;
+       }
+    }
+}
+
+/* Completion inside an unterminated command substitution. */
+static char *
+command_subst_completion_function (text, state)
+     const char *text;
+     int state;
+{
+  static char **matches = (char **)NULL;
+  static const char *orig_start;
+  static char *filename_text = (char *)NULL;
+  static int cmd_index, start_len;
+  char *value;
+
+  if (state == 0)
+    {
+      if (filename_text)
+       free (filename_text);
+      orig_start = text;
+      if (*text == '`')
+       text++;
+      else if (*text == '$' && text[1] == '(') /* ) */
+       text += 2;
+      /* If the text was quoted, suppress any quote character that the
+        readline completion code would insert. */
+      rl_completion_suppress_quote = 1;
+      start_len = text - orig_start;
+      filename_text = savestring (text);
+      if (matches)
+       free (matches);
+
+      /*
+       * At this point we can entertain the idea of re-parsing
+       * `filename_text' into a (possibly incomplete) command name and
+       * arguments, and doing completion based on that.  This is
+       * currently very rudimentary, but it is a small improvement.
+       */
+      for (value = filename_text + strlen (filename_text) - 1; value > filename_text; value--)
+        if (whitespace (*value) || member (*value, COMMAND_SEPARATORS))
+          break;
+      if (value <= filename_text)
+       matches = rl_completion_matches (filename_text, command_word_completion_function);
+      else
+       {
+         value++;
+         start_len += value - filename_text;
+         if (whitespace (value[-1]))
+           matches = rl_completion_matches (value, rl_filename_completion_function);
+         else
+           matches = rl_completion_matches (value, command_word_completion_function);
+       }
+
+      /* If there is more than one match, rl_completion_matches has already
+        put the lcd in matches[0].  Skip over it. */
+      cmd_index = matches && matches[0] && matches[1];
+
+      /* If there's a single match and it's a directory, set the append char
+        to the expected `/'.  Otherwise, don't append anything. */
+      if (matches && matches[0] && matches[1] == 0 && test_for_directory (matches[0]))
+       rl_completion_append_character = '/';
+      else
+       rl_completion_suppress_append = 1;
+    }
+
+  if (matches == 0 || matches[cmd_index] == 0)
+    {
+      rl_filename_quoting_desired = 0; /* disable quoting */
+      return ((char *)NULL);
+    }
+  else
+    {
+      value = (char *)xmalloc (1 + start_len + strlen (matches[cmd_index]));
+
+      if (start_len == 1)
+       value[0] = *orig_start;
+      else
+       strncpy (value, orig_start, start_len);
+
+      strcpy (value + start_len, matches[cmd_index]);
+
+      cmd_index++;
+      return (value);
+    }
+}
+
+/* Okay, now we write the entry_function for variable completion. */
+static char *
+variable_completion_function (text, state)
+     const char *text;
+     int state;
+{
+  static char **varlist = (char **)NULL;
+  static int varlist_index;
+  static char *varname = (char *)NULL;
+  static int namelen;
+  static int first_char, first_char_loc;
+
+  if (!state)
+    {
+      if (varname)
+       free (varname);
+
+      first_char_loc = 0;
+      first_char = text[0];
+
+      if (first_char == '$')
+       first_char_loc++;
+
+      if (text[first_char_loc] == '{')
+       first_char_loc++;
+
+      varname = savestring (text + first_char_loc);
+
+      namelen = strlen (varname);
+      if (varlist)
+       strvec_dispose (varlist);
+
+      varlist = all_variables_matching_prefix (varname);
+      varlist_index = 0;
+    }
+
+  if (!varlist || !varlist[varlist_index])
+    {
+      return ((char *)NULL);
+    }
+  else
+    {
+      char *value;
+
+      value = (char *)xmalloc (4 + strlen (varlist[varlist_index]));
+
+      if (first_char_loc)
+       {
+         value[0] = first_char;
+         if (first_char_loc == 2)
+           value[1] = '{';
+       }
+
+      strcpy (value + first_char_loc, varlist[varlist_index]);
+      if (first_char_loc == 2)
+       strcat (value, "}");
+
+      varlist_index++;
+      return (value);
+    }
+}
+
+/* How about a completion function for hostnames? */
+static char *
+hostname_completion_function (text, state)
+     const char *text;
+     int state;
+{
+  static char **list = (char **)NULL;
+  static int list_index = 0;
+  static int first_char, first_char_loc;
+
+  /* If we don't have any state, make some. */
+  if (state == 0)
+    {
+      FREE (list);
+
+      list = (char **)NULL;
+
+      first_char_loc = 0;
+      first_char = *text;
+
+      if (first_char == '@')
+       first_char_loc++;
+
+      list = hostnames_matching ((char *)text+first_char_loc);
+      list_index = 0;
+    }
+
+  if (list && list[list_index])
+    {
+      char *t;
+
+      t = (char *)xmalloc (2 + strlen (list[list_index]));
+      *t = first_char;
+      strcpy (t + first_char_loc, list[list_index]);
+      list_index++;
+      return (t);
+    }
+
+  return ((char *)NULL);
+}
+
+/*
+ * A completion function for service names from /etc/services (or wherever).
+ */
+char *
+bash_servicename_completion_function (text, state)
+     const char *text;
+     int state;
+{
+#if defined (__WIN32__) || defined (__OPENNT) || !defined (HAVE_GETSERVENT)
+  return ((char *)NULL);
+#else
+  static char *sname = (char *)NULL;
+  static struct servent *srvent;
+  static int snamelen, firstc;
+  char *value;
+  char **alist, *aentry;
+  int afound;
+
+  if (state == 0)
+    {
+      FREE (sname);
+      firstc = *text;
+
+      sname = savestring (text);
+      snamelen = strlen (sname);
+      setservent (0);
+    }
+
+  while (srvent = getservent ())
+    {
+      afound = 0;
+      if (snamelen == 0 || (STREQN (sname, srvent->s_name, snamelen)))
+       break;
+      /* Not primary, check aliases */
+      for (alist = srvent->s_aliases; *alist; alist++)
+       {
+         aentry = *alist;
+         if (STREQN (sname, aentry, snamelen))
+           {
+             afound = 1;
+             break;
+           }
+       }
+
+      if (afound)
+       break;
+    }
+
+  if (srvent == 0)
+    {
+      endservent ();
+      return ((char *)NULL);
+    }
+
+  value = afound ? savestring (aentry) : savestring (srvent->s_name);
+  return value;
+#endif
+}
+
+/*
+ * A completion function for group names from /etc/group (or wherever).
+ */
+char *
+bash_groupname_completion_function (text, state)
+     const char *text;
+     int state;
+{
+#if defined (__WIN32__) || defined (__OPENNT) || !defined (HAVE_GRP_H)
+  return ((char *)NULL);
+#else
+  static char *gname = (char *)NULL;
+  static struct group *grent;
+  static int gnamelen;
+  char *value;
+
+  if (state == 0)
+    {
+      FREE (gname);
+      gname = savestring (text);
+      gnamelen = strlen (gname);
+
+      setgrent ();
+    }
+
+  while (grent = getgrent ())
+    {
+      if (gnamelen == 0 || (STREQN (gname, grent->gr_name, gnamelen)))
+        break;
+    }
+
+  if (grent == 0)
+    {
+      endgrent ();
+      return ((char *)NULL);
+    }
+
+  value = savestring (grent->gr_name);
+  return (value);
+#endif
+}
+
+/* Functions to perform history and alias expansions on the current line. */
+
+#if defined (BANG_HISTORY)
+/* Perform history expansion on the current line.  If no history expansion
+   is done, pre_process_line() returns what it was passed, so we need to
+   allocate a new line here. */
+static char *
+history_expand_line_internal (line)
+     char *line;
+{
+  char *new_line;
+  int old_verify;
+
+  old_verify = hist_verify;
+  hist_verify = 0;
+  new_line = pre_process_line (line, 0, 0);
+  hist_verify = old_verify;
+
+  return (new_line == line) ? savestring (line) : new_line;
+}
+#endif
+
+/* There was an error in expansion.  Let the preprocessor print
+   the error here. */
+static void
+cleanup_expansion_error ()
+{
+  char *to_free;
+#if defined (BANG_HISTORY)
+  int old_verify;
+
+  old_verify = hist_verify;
+  hist_verify = 0;
+#endif
+
+  fprintf (rl_outstream, "\r\n");
+  to_free = pre_process_line (rl_line_buffer, 1, 0);
+#if defined (BANG_HISTORY)
+  hist_verify = old_verify;
+#endif
+  if (to_free != rl_line_buffer)
+    FREE (to_free);
+  putc ('\r', rl_outstream);
+  rl_forced_update_display ();
+}
+
+/* If NEW_LINE differs from what is in the readline line buffer, add an
+   undo record to get from the readline line buffer contents to the new
+   line and make NEW_LINE the current readline line. */
+static void
+maybe_make_readline_line (new_line)
+     char *new_line;
+{
+  if (strcmp (new_line, rl_line_buffer) != 0)
+    {
+      rl_point = rl_end;
+
+      rl_add_undo (UNDO_BEGIN, 0, 0, 0);
+      rl_delete_text (0, rl_point);
+      rl_point = rl_end = rl_mark = 0;
+      rl_insert_text (new_line);
+      rl_add_undo (UNDO_END, 0, 0, 0);
+    }
+}
+
+/* Make NEW_LINE be the current readline line.  This frees NEW_LINE. */
+static void
+set_up_new_line (new_line)
+     char *new_line;
+{
+  int old_point, at_end;
+
+  old_point = rl_point;
+  at_end = rl_point == rl_end;
+
+  /* If the line was history and alias expanded, then make that
+     be one thing to undo. */
+  maybe_make_readline_line (new_line);
+  free (new_line);
+
+  /* Place rl_point where we think it should go. */
+  if (at_end)
+    rl_point = rl_end;
+  else if (old_point < rl_end)
+    {
+      rl_point = old_point;
+      if (!whitespace (rl_line_buffer[rl_point]))
+       rl_forward_word (1, 0);
+    }
+}
+
+#if defined (ALIAS)
+/* Expand aliases in the current readline line. */
+static int
+alias_expand_line (count, ignore)
+     int count, ignore;
+{
+  char *new_line;
+
+  new_line = alias_expand (rl_line_buffer);
+
+  if (new_line)
+    {
+      set_up_new_line (new_line);
+      return (0);
+    }
+  else
+    {
+      cleanup_expansion_error ();
+      return (1);
+    }
+}
+#endif
+
+#if defined (BANG_HISTORY)
+/* History expand the line. */
+static int
+history_expand_line (count, ignore)
+     int count, ignore;
+{
+  char *new_line;
+
+  new_line = history_expand_line_internal (rl_line_buffer);
+
+  if (new_line)
+    {
+      set_up_new_line (new_line);
+      return (0);
+    }
+  else
+    {
+      cleanup_expansion_error ();
+      return (1);
+    }
+}
+
+/* Expand history substitutions in the current line and then insert a
+   space (hopefully close to where we were before). */
+static int
+tcsh_magic_space (count, ignore)
+     int count, ignore;
+{
+  int dist_from_end, old_point;
+
+  old_point = rl_point;
+  dist_from_end = rl_end - rl_point;
+  if (history_expand_line (count, ignore) == 0)
+    {
+      /* Try a simple heuristic from Stephen Gildea <gildea@intouchsys.com>.
+        This works if all expansions were before rl_point or if no expansions
+        were performed. */
+      rl_point = (old_point == 0) ? old_point : rl_end - dist_from_end;
+      rl_insert (1, ' ');
+      return (0);
+    }
+  else
+    return (1);
+}
+#endif /* BANG_HISTORY */
+
+/* History and alias expand the line. */
+static int
+history_and_alias_expand_line (count, ignore)
+     int count, ignore;
+{
+  char *new_line;
+
+  new_line = 0;
+#if defined (BANG_HISTORY)
+  new_line = history_expand_line_internal (rl_line_buffer);
+#endif
+
+#if defined (ALIAS)
+  if (new_line)
+    {
+      char *alias_line;
+
+      alias_line = alias_expand (new_line);
+      free (new_line);
+      new_line = alias_line;
+    }
+#endif /* ALIAS */
+
+  if (new_line)
+    {
+      set_up_new_line (new_line);
+      return (0);
+    }
+  else
+    {
+      cleanup_expansion_error ();
+      return (1);
+    }
+}
+
+/* History and alias expand the line, then perform the shell word
+   expansions by calling expand_string.  This can't use set_up_new_line()
+   because we want the variable expansions as a separate undo'able
+   set of operations. */
+static int
+shell_expand_line (count, ignore)
+     int count, ignore;
+{
+  char *new_line;
+  WORD_LIST *expanded_string;
+
+  new_line = 0;
+#if defined (BANG_HISTORY)
+  new_line = history_expand_line_internal (rl_line_buffer);
+#endif
+
+#if defined (ALIAS)
+  if (new_line)
+    {
+      char *alias_line;
+
+      alias_line = alias_expand (new_line);
+      free (new_line);
+      new_line = alias_line;
+    }
+#endif /* ALIAS */
+
+  if (new_line)
+    {
+      int old_point = rl_point;
+      int at_end = rl_point == rl_end;
+
+      /* If the line was history and alias expanded, then make that
+        be one thing to undo. */
+      maybe_make_readline_line (new_line);
+      free (new_line);
+
+      /* If there is variable expansion to perform, do that as a separate
+        operation to be undone. */
+      new_line = savestring (rl_line_buffer);
+      expanded_string = expand_string (new_line, 0);
+      FREE (new_line);
+      if (expanded_string == 0)
+       {
+         new_line = (char *)xmalloc (1);
+         new_line[0] = '\0';
+       }
+      else
+       {
+         new_line = string_list (expanded_string);
+         dispose_words (expanded_string);
+       }
+
+      maybe_make_readline_line (new_line);
+      free (new_line);
+
+      /* Place rl_point where we think it should go. */
+      if (at_end)
+       rl_point = rl_end;
+      else if (old_point < rl_end)
+       {
+         rl_point = old_point;
+         if (!whitespace (rl_line_buffer[rl_point]))
+           rl_forward_word (1, 0);
+       }
+      return 0;
+    }
+  else
+    {
+      cleanup_expansion_error ();
+      return 1;
+    }
+}
+
+/* If FIGNORE is set, then don't match files with the given suffixes when
+   completing filenames.  If only one of the possibilities has an acceptable
+   suffix, delete the others, else just return and let the completer
+   signal an error.  It is called by the completer when real
+   completions are done on filenames by the completer's internal
+   function, not for completion lists (M-?) and not on "other"
+   completion types, such as hostnames or commands. */
+
+static struct ignorevar fignore =
+{
+  "FIGNORE",
+  (struct ign *)0,
+  0,
+  (char *)0,
+  (sh_iv_item_func_t *) 0,
+};
+
+static void
+_ignore_completion_names (names, name_func)
+     char **names;
+     sh_ignore_func_t *name_func;
+{
+  char **newnames;
+  int idx, nidx;
+  char **oldnames;
+  int oidx;
+
+  /* If there is only one completion, see if it is acceptable.  If it is
+     not, free it up.  In any case, short-circuit and return.  This is a
+     special case because names[0] is not the prefix of the list of names
+     if there is only one completion; it is the completion itself. */
+  if (names[1] == (char *)0)
+    {
+      if (force_fignore)
+       if ((*name_func) (names[0]) == 0)
+         {
+           free (names[0]);
+           names[0] = (char *)NULL;
+         }
+
+      return;
+    }
+
+  /* Allocate space for array to hold list of pointers to matching
+     filenames.  The pointers are copied back to NAMES when done. */
+  for (nidx = 1; names[nidx]; nidx++)
+    ;
+  newnames = strvec_create (nidx + 1);
+
+  if (force_fignore == 0)
+    {
+      oldnames = strvec_create (nidx - 1);
+      oidx = 0;
+    }
+
+  newnames[0] = names[0];
+  for (idx = nidx = 1; names[idx]; idx++)
+    {
+      if ((*name_func) (names[idx]))
+       newnames[nidx++] = names[idx];
+      else if (force_fignore == 0)
+       oldnames[oidx++] = names[idx];
+      else
+       free (names[idx]);
+    }
+
+  newnames[nidx] = (char *)NULL;
+
+  /* If none are acceptable then let the completer handle it. */
+  if (nidx == 1)
+    {
+      if (force_fignore)
+       {
+         free (names[0]);
+         names[0] = (char *)NULL;
+       }
+      else
+       free (oldnames);
+
+      free (newnames);
+      return;
+    }
+
+  if (force_fignore == 0)
+    {
+      while (oidx)
+       free (oldnames[--oidx]);
+      free (oldnames);
+    }
+
+  /* If only one is acceptable, copy it to names[0] and return. */
+  if (nidx == 2)
+    {
+      free (names[0]);
+      names[0] = newnames[1];
+      names[1] = (char *)NULL;
+      free (newnames);
+      return;
+    }
+
+  /* Copy the acceptable names back to NAMES, set the new array end,
+     and return. */
+  for (nidx = 1; newnames[nidx]; nidx++)
+    names[nidx] = newnames[nidx];
+  names[nidx] = (char *)NULL;
+  free (newnames);
+}
+
+static int
+name_is_acceptable (name)
+     const char *name;
+{
+  struct ign *p;
+  int nlen;
+
+  for (nlen = strlen (name), p = fignore.ignores; p->val; p++)
+    {
+      if (nlen > p->len && p->len > 0 && STREQ (p->val, &name[nlen - p->len]))
+       return (0);
+    }
+
+  return (1);
+}
+
+#if 0
+static int
+ignore_dot_names (name)
+     char *name;
+{
+  return (name[0] != '.');
+}
+#endif
+
+static int
+filename_completion_ignore (names)
+     char **names;
+{
+#if 0
+  if (glob_dot_filenames == 0)
+    _ignore_completion_names (names, ignore_dot_names);
+#endif
+
+  setup_ignore_patterns (&fignore);
+
+  if (fignore.num_ignores == 0)
+    return 0;
+
+  _ignore_completion_names (names, name_is_acceptable);
+
+  return 0;
+}
+
+/* Return 1 if NAME is a directory.  NAME undergoes tilde expansion. */
+static int
+test_for_directory (name)
+     const char *name;
+{
+  char *fn;
+  int r;
+
+  fn = bash_tilde_expand (name, 0);
+  r = file_isdir (fn);
+  free (fn);
+
+  return (r);
+}
+
+/* Remove files from NAMES, leaving directories. */
+static int
+bash_ignore_filenames (names)
+     char **names;
+{
+  _ignore_completion_names (names, test_for_directory);
+  return 0;
+}
+
+static int
+return_zero (name)
+     const char *name;
+{
+  return 0;
+}
+
+static int
+bash_ignore_everything (names)
+     char **names;
+{
+  _ignore_completion_names (names, return_zero);
+  return 0;
+}
+
+/* Replace a tilde-prefix in VAL with a `~', assuming the user typed it.  VAL
+   is an expanded filename.  DIRECTORY_PART is the tilde-prefix portion
+   of the un-tilde-expanded version of VAL (what the user typed). */
+static char *
+restore_tilde (val, directory_part)
+     char *val, *directory_part;
+{
+  int l, vl, dl2, xl;
+  char *dh2, *expdir, *ret;
+
+  vl = strlen (val);
+
+  /* We need to duplicate the expansions readline performs on the directory
+     portion before passing it to our completion function. */
+  dh2 = directory_part ? bash_dequote_filename (directory_part, 0) : 0;
+  bash_directory_expansion (&dh2);
+  dl2 = strlen (dh2);
+
+  expdir = bash_tilde_expand (directory_part, 0);
+  xl = strlen (expdir);
+  free (expdir);
+
+  /*
+     dh2 = unexpanded but dequoted tilde-prefix
+     dl2 = length of tilde-prefix
+     expdir = tilde-expanded tilde-prefix
+     xl = length of expanded tilde-prefix
+     l = length of remainder after tilde-prefix
+  */
+  l = (vl - xl) + 1;
+
+  ret = (char *)xmalloc (dl2 + 2 + l);
+  strcpy (ret, dh2);
+  strcpy (ret + dl2, val + xl);
+
+  free (dh2);
+  return (ret);
+}
+
+static char *
+maybe_restore_tilde (val, directory_part)
+     char *val, *directory_part;
+{
+  rl_icppfunc_t *save;
+  char *ret;
+
+  save = (dircomplete_expand == 0) ? save_directory_hook () : (rl_icppfunc_t *)0;
+  ret = restore_tilde (val, directory_part);
+  if (save)
+    restore_directory_hook (save);
+  return ret;
+}
+
+/* Simulate the expansions that will be performed by
+   rl_filename_completion_function.  This must be called with the address of
+   a pointer to malloc'd memory. */
+static void
+bash_directory_expansion (dirname)
+     char **dirname;
+{
+  char *d, *nd;
+
+  d = savestring (*dirname);
+
+  if ((rl_directory_rewrite_hook) && (*rl_directory_rewrite_hook) (&d))
+    {
+      free (*dirname);
+      *dirname = d;
+    }
+  else if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&d))
+    {
+      free (*dirname);
+      *dirname = d;
+    }
+  else if (rl_completion_found_quote)
+    {
+      nd = bash_dequote_filename (d, rl_completion_quote_character);
+      free (*dirname);
+      free (d);
+      *dirname = nd;
+    }
+}
+
+/* If necessary, rewrite directory entry */
+static char *
+bash_filename_rewrite_hook (fname, fnlen)
+     char *fname;
+     int fnlen;
+{
+  char *conv;
+
+  conv = fnx_fromfs (fname, fnlen);
+  if (conv != fname)
+    conv = savestring (conv);
+  return conv;
+}
+
+/* Functions to save and restore the appropriate directory hook */
+/* This is not static so the shopt code can call it */
+void
+set_directory_hook ()
+{
+  if (dircomplete_expand)
+    {
+      rl_directory_completion_hook = bash_directory_completion_hook;
+      rl_directory_rewrite_hook = (rl_icppfunc_t *)0;
+    }
+  else
+    {
+      rl_directory_rewrite_hook = bash_directory_completion_hook;
+      rl_directory_completion_hook = (rl_icppfunc_t *)0;
+    }
+}
+
+static rl_icppfunc_t *
+save_directory_hook ()
+{
+  rl_icppfunc_t *ret;
+
+  if (dircomplete_expand)
+    {
+      ret = rl_directory_completion_hook;
+      rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
+    }
+  else
+    {
+      ret = rl_directory_rewrite_hook;
+      rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
+    }
+
+  return ret;
+}
+
+static void
+restore_directory_hook (hookf)
+     rl_icppfunc_t *hookf;
+{
+  if (dircomplete_expand)
+    rl_directory_completion_hook = hookf;
+  else
+    rl_directory_rewrite_hook = hookf;
+}
+
+/* Expand a filename before the readline completion code passes it to stat(2).
+   The filename will already have had tilde expansion performed. */
+static int
+bash_filename_stat_hook (dirname)
+     char **dirname;
+{
+  char *local_dirname, *new_dirname, *t;
+  int should_expand_dirname, return_value;
+  WORD_LIST *wl;
+  struct stat sb;
+
+  local_dirname = *dirname;
+  should_expand_dirname = return_value = 0;
+  if (t = mbschr (local_dirname, '$'))
+    should_expand_dirname = '$';
+  else if (t = mbschr (local_dirname, '`'))    /* XXX */
+    should_expand_dirname = '`';
+
+#if defined (HAVE_LSTAT)
+  if (should_expand_dirname && lstat (local_dirname, &sb) == 0)
+#else
+  if (should_expand_dirname && stat (local_dirname, &sb) == 0)
+#endif
+    should_expand_dirname = 0;
+  
+  if (should_expand_dirname)  
+    {
+      new_dirname = savestring (local_dirname);
+      wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB);  /* does the right thing */
+      if (wl)
+       {
+         free (new_dirname);
+         new_dirname = string_list (wl);
+         /* Tell the completer we actually expanded something and change
+            *dirname only if we expanded to something non-null -- stat
+            behaves unpredictably when passed null or empty strings */
+         if (new_dirname && *new_dirname)
+           {
+             free (local_dirname);     /* XXX */
+             local_dirname = *dirname = new_dirname;
+             return_value = STREQ (local_dirname, *dirname) == 0;
+           }
+         else
+           free (new_dirname);
+         dispose_words (wl);
+       }
+      else
+       free (new_dirname);
+    }  
+
+  /* This is very similar to the code in bash_directory_completion_hook below,
+     but without spelling correction and not worrying about whether or not
+     we change relative pathnames. */
+  if (no_symbolic_links == 0 && (local_dirname[0] != '.' || local_dirname[1]))
+    {
+      char *temp1, *temp2;
+
+      t = get_working_directory ("symlink-hook");
+      temp1 = make_absolute (local_dirname, t);
+      free (t);
+      temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
+
+      /* If we can't canonicalize, bail. */
+      if (temp2 == 0)
+       {
+         free (temp1);
+         return return_value;
+       }
+
+      free (local_dirname);
+      *dirname = temp2;
+      free (temp1);
+    }
+
+  return (return_value);
+}
+
+/* Handle symbolic link references and other directory name
+   expansions while hacking completion.  This should return 1 if it modifies
+   the DIRNAME argument, 0 otherwise.  It should make sure not to modify
+   DIRNAME if it returns 0. */
+static int
+bash_directory_completion_hook (dirname)
+     char **dirname;
+{
+  char *local_dirname, *new_dirname, *t;
+  int return_value, should_expand_dirname, nextch, closer;
+  WORD_LIST *wl;
+  struct stat sb;
+
+  return_value = should_expand_dirname = nextch = closer = 0;
+  local_dirname = *dirname;
+
+  if (t = mbschr (local_dirname, '$'))
+    {
+      should_expand_dirname = '$';
+      nextch = t[1];
+      /* Deliberately does not handle the deprecated $[...] arithmetic
+        expansion syntax */
+      if (nextch == '(')
+       closer = ')';
+      else if (nextch == '{')
+       closer = '}';
+      else
+       nextch = 0;
+    }
+  else if (local_dirname[0] == '~')
+    should_expand_dirname = '~';
+  else
+    {
+      t = mbschr (local_dirname, '`');
+      if (t && unclosed_pair (local_dirname, strlen (local_dirname), "`") == 0)
+       should_expand_dirname = '`';
+    }
+
+#if defined (HAVE_LSTAT)
+  if (should_expand_dirname && lstat (local_dirname, &sb) == 0)
+#else
+  if (should_expand_dirname && stat (local_dirname, &sb) == 0)
+#endif
+    should_expand_dirname = 0;
+
+  if (should_expand_dirname)  
+    {
+      new_dirname = savestring (local_dirname);
+      wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB);  /* does the right thing */
+      if (wl)
+       {
+         *dirname = string_list (wl);
+         /* Tell the completer to replace the directory name only if we
+            actually expanded something. */
+         return_value = STREQ (local_dirname, *dirname) == 0;
+         free (local_dirname);
+         free (new_dirname);
+         dispose_words (wl);
+         local_dirname = *dirname;
+         /* XXX - change rl_filename_quote_characters here based on
+            should_expand_dirname/nextch/closer.  This is the only place
+            custom_filename_quote_characters is modified. */
+         if (rl_filename_quote_characters && *rl_filename_quote_characters)
+           {
+             int i, j, c;
+             i = strlen (default_filename_quote_characters);
+             custom_filename_quote_characters = xrealloc (custom_filename_quote_characters, i+1);
+             for (i = j = 0; c = default_filename_quote_characters[i]; i++)
+               {
+                 if (c == should_expand_dirname || c == nextch || c == closer)
+                   continue;
+                 custom_filename_quote_characters[j++] = c;
+               }
+             custom_filename_quote_characters[j] = '\0';
+             rl_filename_quote_characters = custom_filename_quote_characters;
+             set_filename_bstab (rl_filename_quote_characters);
+           }
+       }
+      else
+       {
+         free (new_dirname);
+         free (local_dirname);
+         *dirname = (char *)xmalloc (1);
+         **dirname = '\0';
+         return 1;
+       }
+    }
+  else 
+    {
+      /* Dequote the filename even if we don't expand it. */
+      new_dirname = bash_dequote_filename (local_dirname, rl_completion_quote_character);
+      return_value = STREQ (local_dirname, new_dirname) == 0;
+      free (local_dirname);
+      local_dirname = *dirname = new_dirname;
+    }
+
+  /* no_symbolic_links == 0 -> use (default) logical view of the file system.
+     local_dirname[0] == '.' && local_dirname[1] == '/' means files in the
+     current directory (./).
+     local_dirname[0] == '.' && local_dirname[1] == 0 means relative pathnames
+     in the current directory (e.g., lib/sh).
+     XXX - should we do spelling correction on these? */
+
+  /* This is test as it was in bash-4.2: skip relative pathnames in current
+     directory.  Change test to
+      (local_dirname[0] != '.' || (local_dirname[1] && local_dirname[1] != '/'))
+     if we want to skip paths beginning with ./ also. */
+  if (no_symbolic_links == 0 && (local_dirname[0] != '.' || local_dirname[1]))
+    {
+      char *temp1, *temp2;
+      int len1, len2;
+
+      /* If we have a relative path
+               (local_dirname[0] != '/' && local_dirname[0] != '.')
+        that is canonical after appending it to the current directory, then
+               temp1 = temp2+'/'
+        That is,
+               strcmp (temp1, temp2) == 0
+        after adding a slash to temp2 below.  It should be safe to not
+        change those.
+      */
+      t = get_working_directory ("symlink-hook");
+      temp1 = make_absolute (local_dirname, t);
+      free (t);
+      temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
+
+      /* Try spelling correction if initial canonicalization fails.  Make
+        sure we are set to replace the directory name with the results so
+        subsequent directory checks don't fail. */
+      if (temp2 == 0 && dircomplete_spelling && dircomplete_expand)
+       {
+         temp2 = dirspell (temp1);
+         if (temp2)
+           {
+             free (temp1);
+             temp1 = temp2;
+             temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
+             return_value |= temp2 != 0;
+           }
+       }
+      /* If we can't canonicalize, bail. */
+      if (temp2 == 0)
+       {
+         free (temp1);
+         return return_value;
+       }
+      len1 = strlen (temp1);
+      if (temp1[len1 - 1] == '/')
+       {
+         len2 = strlen (temp2);
+         if (len2 > 2)         /* don't append `/' to `/' or `//' */
+           {
+             temp2 = (char *)xrealloc (temp2, len2 + 2);
+             temp2[len2] = '/';
+             temp2[len2 + 1] = '\0';
+           }
+       }
+
+      /* dircomplete_expand_relpath == 0 means we want to leave relative
+        pathnames that are unchanged by canonicalization alone.
+        *local_dirname != '/' && *local_dirname != '.' == relative pathname
+        (consistent with general.c:absolute_pathname())
+        temp1 == temp2 (after appending a slash to temp2) means the pathname
+        is not changed by canonicalization as described above. */
+      if (dircomplete_expand_relpath || ((local_dirname[0] != '/' && local_dirname[0] != '.') && STREQ (temp1, temp2) == 0))
+       return_value |= STREQ (local_dirname, temp2) == 0;
+      free (local_dirname);
+      *dirname = temp2;
+      free (temp1);
+    }
+
+  return (return_value);
+}
+
+static char **history_completion_array = (char **)NULL;
+static int harry_size;
+static int harry_len;
+
+static void
+build_history_completion_array ()
+{
+  register int i, j;
+  HIST_ENTRY **hlist;
+  char **tokens;
+
+  /* First, clear out the current dynamic history completion list. */
+  if (harry_size)
+    {
+      strvec_dispose (history_completion_array);
+      history_completion_array = (char **)NULL;
+      harry_size = 0;
+      harry_len = 0;
+    }
+
+  /* Next, grovel each line of history, making each shell-sized token
+     a separate entry in the history_completion_array. */
+  hlist = history_list ();
+
+  if (hlist)
+    {
+      for (i = 0; hlist[i]; i++)
+       ;
+      for ( --i; i >= 0; i--)
+       {
+         /* Separate each token, and place into an array. */
+         tokens = history_tokenize (hlist[i]->line);
+
+         for (j = 0; tokens && tokens[j]; j++)
+           {
+             if (harry_len + 2 > harry_size)
+               history_completion_array = strvec_resize (history_completion_array, harry_size += 10);
+
+             history_completion_array[harry_len++] = tokens[j];
+             history_completion_array[harry_len] = (char *)NULL;
+           }
+         free (tokens);
+       }
+
+      /* Sort the complete list of tokens. */
+      if (dabbrev_expand_active == 0)
+        qsort (history_completion_array, harry_len, sizeof (char *), (QSFUNC *)strvec_strcmp);
+    }
+}
+
+static char *
+history_completion_generator (hint_text, state)
+     const char *hint_text;
+     int state;
+{
+  static int local_index, len;
+  static const char *text;
+
+  /* If this is the first call to the generator, then initialize the
+     list of strings to complete over. */
+  if (state == 0)
+    {
+      if (dabbrev_expand_active)       /* This is kind of messy */
+       rl_completion_suppress_append = 1;
+      local_index = 0;
+      build_history_completion_array ();
+      text = hint_text;
+      len = strlen (text);
+    }
+
+  while (history_completion_array && history_completion_array[local_index])
+    {
+      if (strncmp (text, history_completion_array[local_index++], len) == 0)
+       return (savestring (history_completion_array[local_index - 1]));
+    }
+  return ((char *)NULL);
+}
+
+static int
+dynamic_complete_history (count, key)
+     int count, key;
+{
+  int r;
+  rl_compentry_func_t *orig_func;
+  rl_completion_func_t *orig_attempt_func;
+  rl_compignore_func_t *orig_ignore_func;
+
+  orig_func = rl_completion_entry_function;
+  orig_attempt_func = rl_attempted_completion_function;
+  orig_ignore_func = rl_ignore_some_completions_function;
+
+  rl_completion_entry_function = history_completion_generator;
+  rl_attempted_completion_function = (rl_completion_func_t *)NULL;
+  rl_ignore_some_completions_function = filename_completion_ignore;
+
+  /* XXX - use rl_completion_mode here? */
+  if (rl_last_func == dynamic_complete_history)
+    r = rl_complete_internal ('?');
+  else
+    r = rl_complete_internal (TAB);
+
+  rl_completion_entry_function = orig_func;
+  rl_attempted_completion_function = orig_attempt_func;
+  rl_ignore_some_completions_function = orig_ignore_func;
+
+  return r;
+}
+
+static int
+bash_dabbrev_expand (count, key)
+     int count, key;
+{
+  int r, orig_suppress, orig_sort;
+  rl_compentry_func_t *orig_func;
+  rl_completion_func_t *orig_attempt_func;
+  rl_compignore_func_t *orig_ignore_func;
+
+  orig_func = rl_menu_completion_entry_function;
+  orig_attempt_func = rl_attempted_completion_function;
+  orig_ignore_func = rl_ignore_some_completions_function;
+  orig_suppress = rl_completion_suppress_append;
+  orig_sort = rl_sort_completion_matches;
+
+  rl_menu_completion_entry_function = history_completion_generator;
+  rl_attempted_completion_function = (rl_completion_func_t *)NULL;
+  rl_ignore_some_completions_function = filename_completion_ignore;
+  rl_filename_completion_desired = 0;
+  rl_completion_suppress_append = 1;
+  rl_sort_completion_matches = 0;
+
+  /* XXX - use rl_completion_mode here? */
+  dabbrev_expand_active = 1;
+  if (rl_last_func == bash_dabbrev_expand)
+    rl_last_func = rl_menu_complete;
+  r = rl_menu_complete (count, key);
+  dabbrev_expand_active = 0;
+
+  rl_last_func = bash_dabbrev_expand;
+  rl_menu_completion_entry_function = orig_func;
+  rl_attempted_completion_function = orig_attempt_func;
+  rl_ignore_some_completions_function = orig_ignore_func;
+  rl_completion_suppress_append = orig_suppress;
+  rl_sort_completion_matches = orig_sort;
+
+  return r;
+}
+
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+static int
+bash_complete_username (ignore, ignore2)
+     int ignore, ignore2;
+{
+  return bash_complete_username_internal (rl_completion_mode (bash_complete_username));
+}
+
+static int
+bash_possible_username_completions (ignore, ignore2)
+     int ignore, ignore2;
+{
+  return bash_complete_username_internal ('?');
+}
+
+static int
+bash_complete_username_internal (what_to_do)
+     int what_to_do;
+{
+  return bash_specific_completion (what_to_do, rl_username_completion_function);
+}
+
+static int
+bash_complete_filename (ignore, ignore2)
+     int ignore, ignore2;
+{
+  return bash_complete_filename_internal (rl_completion_mode (bash_complete_filename));
+}
+
+static int
+bash_possible_filename_completions (ignore, ignore2)
+     int ignore, ignore2;
+{
+  return bash_complete_filename_internal ('?');
+}
+
+static int
+bash_complete_filename_internal (what_to_do)
+     int what_to_do;
+{
+  rl_compentry_func_t *orig_func;
+  rl_completion_func_t *orig_attempt_func;
+  rl_icppfunc_t *orig_dir_func;
+  rl_compignore_func_t *orig_ignore_func;
+  /*const*/ char *orig_rl_completer_word_break_characters;
+  int r;
+
+  orig_func = rl_completion_entry_function;
+  orig_attempt_func = rl_attempted_completion_function;
+  orig_ignore_func = rl_ignore_some_completions_function;
+  orig_rl_completer_word_break_characters = rl_completer_word_break_characters;
+
+  orig_dir_func = save_directory_hook ();
+
+  rl_completion_entry_function = rl_filename_completion_function;
+  rl_attempted_completion_function = (rl_completion_func_t *)NULL;
+  rl_ignore_some_completions_function = filename_completion_ignore;
+  rl_completer_word_break_characters = " \t\n\"\'";
+
+  r = rl_complete_internal (what_to_do);
+
+  rl_completion_entry_function = orig_func;
+  rl_attempted_completion_function = orig_attempt_func;
+  rl_ignore_some_completions_function = orig_ignore_func;
+  rl_completer_word_break_characters = orig_rl_completer_word_break_characters;
+
+  restore_directory_hook (orig_dir_func);
+
+  return r;
+}
+
+static int
+bash_complete_hostname (ignore, ignore2)
+     int ignore, ignore2;
+{
+  return bash_complete_hostname_internal (rl_completion_mode (bash_complete_hostname));
+}
+
+static int
+bash_possible_hostname_completions (ignore, ignore2)
+     int ignore, ignore2;
+{
+  return bash_complete_hostname_internal ('?');
+}
+
+static int
+bash_complete_variable (ignore, ignore2)
+     int ignore, ignore2;
+{
+  return bash_complete_variable_internal (rl_completion_mode (bash_complete_variable));
+}
+
+static int
+bash_possible_variable_completions (ignore, ignore2)
+     int ignore, ignore2;
+{
+  return bash_complete_variable_internal ('?');
+}
+
+static int
+bash_complete_command (ignore, ignore2)
+     int ignore, ignore2;
+{
+  return bash_complete_command_internal (rl_completion_mode (bash_complete_command));
+}
+
+static int
+bash_possible_command_completions (ignore, ignore2)
+     int ignore, ignore2;
+{
+  return bash_complete_command_internal ('?');
+}
+
+static int
+bash_complete_hostname_internal (what_to_do)
+     int what_to_do;
+{
+  return bash_specific_completion (what_to_do, hostname_completion_function);
+}
+
+static int
+bash_complete_variable_internal (what_to_do)
+     int what_to_do;
+{
+  return bash_specific_completion (what_to_do, variable_completion_function);
+}
+
+static int
+bash_complete_command_internal (what_to_do)
+     int what_to_do;
+{
+  return bash_specific_completion (what_to_do, command_word_completion_function);
+}
+
+static char *globtext;
+static char *globorig;
+
+static char *
+glob_complete_word (text, state)
+     const char *text;
+     int state;
+{
+  static char **matches = (char **)NULL;
+  static int ind;
+  int glen;
+  char *ret, *ttext;
+
+  if (state == 0)
+    {
+      rl_filename_completion_desired = 1;
+      FREE (matches);
+      if (globorig != globtext)
+       FREE (globorig);
+      FREE (globtext);
+
+      ttext = bash_tilde_expand (text, 0);
+
+      if (rl_explicit_arg)
+       {
+         globorig = savestring (ttext);
+         glen = strlen (ttext);
+         globtext = (char *)xmalloc (glen + 2);
+         strcpy (globtext, ttext);
+         globtext[glen] = '*';
+         globtext[glen+1] = '\0';
+       }
+      else
+        globtext = globorig = savestring (ttext);
+
+      if (ttext != text)
+       free (ttext);
+
+      matches = shell_glob_filename (globtext);
+      if (GLOB_FAILED (matches))
+       matches = (char **)NULL;
+      ind = 0;
+    }
+
+  ret = matches ? matches[ind] : (char *)NULL;
+  ind++;
+  return ret;
+}
+
+static int
+bash_glob_completion_internal (what_to_do)
+     int what_to_do;
+{
+  return bash_specific_completion (what_to_do, glob_complete_word);
+}
+
+/* A special quoting function so we don't end up quoting globbing characters
+   in the word if there are no matches or multiple matches. */
+static char *
+bash_glob_quote_filename (s, rtype, qcp)
+     char *s;
+     int rtype;
+     char *qcp;
+{
+  if (globorig && qcp && *qcp == '\0' && STREQ (s, globorig))
+    return (savestring (s));
+  else
+    return (bash_quote_filename (s, rtype, qcp));
+}
+
+static int
+bash_glob_complete_word (count, key)
+     int count, key;
+{
+  int r;
+  rl_quote_func_t *orig_quoting_function;
+
+  if (rl_editing_mode == EMACS_EDITING_MODE)
+    rl_explicit_arg = 1;       /* force `*' append */
+  orig_quoting_function = rl_filename_quoting_function;
+  rl_filename_quoting_function = bash_glob_quote_filename;
+  
+  r = bash_glob_completion_internal (rl_completion_mode (bash_glob_complete_word));
+
+  rl_filename_quoting_function = orig_quoting_function;
+  return r;
+}
+
+static int
+bash_glob_expand_word (count, key)
+     int count, key;
+{
+  return bash_glob_completion_internal ('*');
+}
+
+static int
+bash_glob_list_expansions (count, key)
+     int count, key;
+{
+  return bash_glob_completion_internal ('?');
+}
+
+static int
+bash_specific_completion (what_to_do, generator)
+     int what_to_do;
+     rl_compentry_func_t *generator;
+{
+  rl_compentry_func_t *orig_func;
+  rl_completion_func_t *orig_attempt_func;
+  rl_compignore_func_t *orig_ignore_func;
+  int r;
+
+  orig_func = rl_completion_entry_function;
+  orig_attempt_func = rl_attempted_completion_function;
+  orig_ignore_func = rl_ignore_some_completions_function;
+  rl_completion_entry_function = generator;
+  rl_attempted_completion_function = NULL;
+  rl_ignore_some_completions_function = orig_ignore_func;
+
+  r = rl_complete_internal (what_to_do);
+
+  rl_completion_entry_function = orig_func;
+  rl_attempted_completion_function = orig_attempt_func;
+  rl_ignore_some_completions_function = orig_ignore_func;
+
+  return r;
+}
+
+#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
+
+#if defined (VI_MODE)
+/* Completion, from vi mode's point of view.  This is a modified version of
+   rl_vi_complete which uses the bash globbing code to implement what POSIX
+   specifies, which is to append a `*' and attempt filename generation (which
+   has the side effect of expanding any globbing characters in the word). */
+static int
+bash_vi_complete (count, key)
+     int count, key;
+{
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+  int p, r;
+  char *t;
+
+  if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
+    {
+      if (!whitespace (rl_line_buffer[rl_point + 1]))
+       rl_vi_end_word (1, 'E');
+      rl_point++;
+    }
+
+  /* Find boundaries of current word, according to vi definition of a
+     `bigword'. */
+  t = 0;
+  if (rl_point > 0)
+    {
+      p = rl_point;
+      rl_vi_bWord (1, 'B');
+      r = rl_point;
+      rl_point = p;
+      p = r;
+
+      t = substring (rl_line_buffer, p, rl_point);
+    }      
+
+  if (t && glob_pattern_p (t) == 0)
+    rl_explicit_arg = 1;       /* XXX - force glob_complete_word to append `*' */
+  FREE (t);
+
+  if (key == '*')      /* Expansion and replacement. */
+    r = bash_glob_expand_word (count, key);
+  else if (key == '=') /* List possible completions. */
+    r = bash_glob_list_expansions (count, key);
+  else if (key == '\\')        /* Standard completion */
+    r = bash_glob_complete_word (count, key);
+  else
+    r = rl_complete (0, key);
+
+  if (key == '*' || key == '\\')
+    rl_vi_start_inserting (key, 1, 1);
+
+  return (r);
+#else
+  return rl_vi_complete (count, key);
+#endif /* !SPECIFIC_COMPLETION_FUNCTIONS */
+}
+#endif /* VI_MODE */
+
+/* Filename quoting for completion. */
+/* A function to strip unquoted quote characters (single quotes, double
+   quotes, and backslashes).  It allows single quotes to appear
+   within double quotes, and vice versa.  It should be smarter. */
+static char *
+bash_dequote_filename (text, quote_char)
+     char *text;
+     int quote_char;
+{
+  char *ret, *p, *r;
+  int l, quoted;
+
+  l = strlen (text);
+  ret = (char *)xmalloc (l + 1);
+  for (quoted = quote_char, p = text, r = ret; p && *p; p++)
+    {
+      /* Allow backslash-escaped characters to pass through unscathed. */
+      if (*p == '\\')
+       {
+         /* Backslashes are preserved within single quotes. */
+         if (quoted == '\'')
+           *r++ = *p;
+         /* Backslashes are preserved within double quotes unless the
+            character is one that is defined to be escaped */
+         else if (quoted == '"' && ((sh_syntaxtab[p[1]] & CBSDQUOTE) == 0))
+           *r++ = *p;
+
+         *r++ = *++p;
+         if (*p == '\0')
+           return ret;         /* XXX - was break; */
+         continue;
+       }
+      /* Close quote. */
+      if (quoted && *p == quoted)
+       {
+         quoted = 0;
+         continue;
+       }
+      /* Open quote. */
+      if (quoted == 0 && (*p == '\'' || *p == '"'))
+       {
+         quoted = *p;
+         continue;
+       }
+      *r++ = *p;
+    }
+  *r = '\0';
+  return ret;
+}
+
+/* Quote characters that the readline completion code would treat as
+   word break characters with backslashes.  Pass backslash-quoted
+   characters through without examination. */
+static char *
+quote_word_break_chars (text)
+     char *text;
+{
+  char *ret, *r, *s;
+  int l;
+
+  l = strlen (text);
+  ret = (char *)xmalloc ((2 * l) + 1);
+  for (s = text, r = ret; *s; s++)
+    {
+      /* Pass backslash-quoted characters through, including the backslash. */
+      if (*s == '\\')
+       {
+         *r++ = '\\';
+         *r++ = *++s;
+         if (*s == '\0')
+           break;
+         continue;
+       }
+      /* OK, we have an unquoted character.  Check its presence in
+        rl_completer_word_break_characters. */
+      if (mbschr (rl_completer_word_break_characters, *s))
+       *r++ = '\\';
+      /* XXX -- check for standalone tildes here and backslash-quote them */
+      if (s == text && *s == '~' && file_exists (text))
+        *r++ = '\\';
+      *r++ = *s;
+    }
+  *r = '\0';
+  return ret;
+}
+
+/* Use characters in STRING to populate the table of characters that should
+   be backslash-quoted.  The table will be used for sh_backslash_quote from
+   this file. */
+static void
+set_filename_bstab (string)
+     const char *string;
+{
+  const char *s;
+
+  memset (filename_bstab, 0, sizeof (filename_bstab));
+  for (s = string; s && *s; s++)
+    filename_bstab[*s] = 1;
+}
+
+/* Quote a filename using double quotes, single quotes, or backslashes
+   depending on the value of completion_quoting_style.  If we're
+   completing using backslashes, we need to quote some additional
+   characters (those that readline treats as word breaks), so we call
+   quote_word_break_chars on the result.  This returns newly-allocated
+   memory. */
+static char *
+bash_quote_filename (s, rtype, qcp)
+     char *s;
+     int rtype;
+     char *qcp;
+{
+  char *rtext, *mtext, *ret;
+  int rlen, cs;
+
+  rtext = (char *)NULL;
+
+  /* If RTYPE == MULT_MATCH, it means that there is
+     more than one match.  In this case, we do not add
+     the closing quote or attempt to perform tilde
+     expansion.  If RTYPE == SINGLE_MATCH, we try
+     to perform tilde expansion, because single and double
+     quotes inhibit tilde expansion by the shell. */
+
+  cs = completion_quoting_style;
+  /* Might need to modify the default completion style based on *qcp,
+     since it's set to any user-provided opening quote.  We also change
+     to single-quoting if there is no user-provided opening quote and
+     the word being completed contains newlines, since those are not
+     quoted correctly using backslashes (a backslash-newline pair is
+     special to the shell parser). */
+  if (*qcp == '\0' && cs == COMPLETE_BSQUOTE && mbschr (s, '\n'))
+    cs = COMPLETE_SQUOTE;
+  else if (*qcp == '"')
+    cs = COMPLETE_DQUOTE;
+  else if (*qcp == '\'')
+    cs = COMPLETE_SQUOTE;
+#if defined (BANG_HISTORY)
+  else if (*qcp == '\0' && history_expansion && cs == COMPLETE_DQUOTE &&
+          history_expansion_inhibited == 0 && mbschr (s, '!'))
+    cs = COMPLETE_BSQUOTE;
+
+  if (*qcp == '"' && history_expansion && cs == COMPLETE_DQUOTE &&
+       history_expansion_inhibited == 0 && mbschr (s, '!'))
+    {
+      cs = COMPLETE_BSQUOTE;
+      *qcp = '\0';
+    }
+#endif
+
+  /* Don't tilde-expand backslash-quoted filenames, since only single and
+     double quotes inhibit tilde expansion. */
+  mtext = s;
+  if (mtext[0] == '~' && rtype == SINGLE_MATCH && cs != COMPLETE_BSQUOTE)
+    mtext = bash_tilde_expand (s, 0);
+
+  switch (cs)
+    {
+    case COMPLETE_DQUOTE:
+      rtext = sh_double_quote (mtext);
+      break;
+    case COMPLETE_SQUOTE:
+      rtext = sh_single_quote (mtext);
+      break;
+    case COMPLETE_BSQUOTE:
+      rtext = sh_backslash_quote (mtext, complete_fullquote ? 0 : filename_bstab, 0);
+      break;
+    }
+
+  if (mtext != s)
+    free (mtext);
+
+  /* We may need to quote additional characters: those that readline treats
+     as word breaks that are not quoted by backslash_quote. */
+  if (rtext && cs == COMPLETE_BSQUOTE)
+    {
+      mtext = quote_word_break_chars (rtext);
+      free (rtext);
+      rtext = mtext;
+    }
+
+  /* Leave the opening quote intact.  The readline completion code takes
+     care of avoiding doubled opening quotes. */
+  if (rtext)
+    {
+      rlen = strlen (rtext);
+      ret = (char *)xmalloc (rlen + 1);
+      strcpy (ret, rtext);
+    }
+  else
+    {
+      ret = (char *)xmalloc (rlen = 1);
+      ret[0] = '\0';
+    }
+
+  /* If there are multiple matches, cut off the closing quote. */
+  if (rtype == MULT_MATCH && cs != COMPLETE_BSQUOTE)
+    ret[rlen - 1] = '\0';
+  free (rtext);
+  return ret;
+}
+
+/* Support for binding readline key sequences to Unix commands. */
+static Keymap cmd_xmap;
+
+#ifdef _MINIX
+static void
+#else
+static int
+#endif
+putx(c)
+     int c;
+{
+  int x;
+  x = putc (c, rl_outstream);
+#ifndef _MINIX
+  return x;
+#endif
+}
+  
+static int
+bash_execute_unix_command (count, key)
+     int count;        /* ignored */
+     int key;
+{
+  Keymap ckmap;                /* current keymap */
+  Keymap xkmap;                /* unix command executing keymap */
+  rl_command_func_t *func;
+  int type;
+  register int i, r;
+  intmax_t mi;
+  sh_parser_state_t ps;
+  char *cmd, *value, *l, *l1, *ce;
+  SHELL_VAR *v;
+  char ibuf[INT_STRLEN_BOUND(int) + 1];
+
+  /* First, we need to find the right command to execute.  This is tricky,
+     because we might have already indirected into another keymap, so we
+     have to walk cmd_xmap using the entire key sequence. */
+  cmd = (char *)rl_function_of_keyseq (rl_executing_keyseq, cmd_xmap, &type);
+    
+  if (cmd == 0 || type != ISMACR)
+    {
+      rl_crlf ();
+      internal_error (_("bash_execute_unix_command: cannot find keymap for command"));
+      rl_forced_update_display ();
+      return 1;
+    }
+
+  ce = rl_get_termcap ("ce");
+  if (ce)      /* clear current line */
+    {
+      fprintf (rl_outstream, "\r");
+      tputs (ce, 1, putx);
+      fflush (rl_outstream);
+    }
+  else
+    rl_crlf ();        /* move to a new line */
+
+  v = bind_variable ("READLINE_LINE", rl_line_buffer, 0);
+  if (v)
+    VSETATTR (v, att_exported);
+  l = v ? value_cell (v) : 0;
+  value = inttostr (rl_point, ibuf, sizeof (ibuf));
+  v = bind_int_variable ("READLINE_POINT", value);
+  if (v)
+    VSETATTR (v, att_exported);
+  array_needs_making = 1;
+
+  save_parser_state (&ps);
+  r = parse_and_execute (cmd, "bash_execute_unix_command", SEVAL_NOHIST|SEVAL_NOFREE);
+  restore_parser_state (&ps);
+
+  v = find_variable ("READLINE_LINE");
+  l1 = v ? value_cell (v) : 0;
+  if (l1 != l)
+    maybe_make_readline_line (value_cell (v));
+  v = find_variable ("READLINE_POINT");
+  if (v && legal_number (value_cell (v), &mi))
+    {
+      i = mi;
+      if (i != rl_point)
+       {
+         rl_point = i;
+         if (rl_point > rl_end)
+           rl_point = rl_end;
+         else if (rl_point < 0)
+           rl_point = 0;
+       }
+    }      
+
+  unbind_variable ("READLINE_LINE");
+  unbind_variable ("READLINE_POINT");
+  array_needs_making = 1;
+
+  /* and restore the readline buffer and display after command execution. */
+  rl_forced_update_display ();
+  return 0;
+}
+
+int
+print_unix_command_map ()
+{
+  Keymap save;
+
+  save = rl_get_keymap ();
+  rl_set_keymap (cmd_xmap);
+  rl_macro_dumper (1);
+  rl_set_keymap (save);
+  return 0;
+}
+
+static void
+init_unix_command_map ()
+{
+  cmd_xmap = rl_make_bare_keymap ();
+}
+
+static int
+isolate_sequence (string, ind, need_dquote, startp)
+     char *string;
+     int ind, need_dquote, *startp;
+{
+  register int i;
+  int c, passc, delim;
+
+  for (i = ind; string[i] && whitespace (string[i]); i++)
+    ;
+  /* NEED_DQUOTE means that the first non-white character *must* be `"'. */
+  if (need_dquote && string[i] != '"')
+    {
+      builtin_error (_("%s: first non-whitespace character is not `\"'"), string);
+      return -1;
+    }
+
+  /* We can have delimited strings even if NEED_DQUOTE == 0, like the command
+     string to bind the key sequence to. */
+  delim = (string[i] == '"' || string[i] == '\'') ? string[i] : 0;
+    
+  if (startp)
+    *startp = delim ? ++i : i;
+
+  for (passc = 0; c = string[i]; i++)
+    {
+      if (passc)
+       {
+         passc = 0;
+         continue;
+       }
+      if (c == '\\')
+       {
+         passc++;
+         continue;
+       }
+      if (c == delim)
+       break;
+    }
+
+  if (delim && string[i] != delim)
+    {
+      builtin_error (_("no closing `%c' in %s"), delim, string);
+      return -1;
+    }
+
+  return i;
+}
+
+int
+bind_keyseq_to_unix_command (line)
+     char *line;
+{
+  Keymap kmap;
+  char *kseq, *value;
+  int i, kstart;
+
+  if (cmd_xmap == 0)
+    init_unix_command_map ();
+
+  kmap = rl_get_keymap ();
+
+  /* We duplicate some of the work done by rl_parse_and_bind here, but
+     this code only has to handle `"keyseq": ["]command["]' and can
+     generate an error for anything else. */
+  i = isolate_sequence (line, 0, 1, &kstart);
+  if (i < 0)
+    return -1;
+
+  /* Create the key sequence string to pass to rl_generic_bind */
+  kseq = substring (line, kstart, i);
+
+  for ( ; line[i] && line[i] != ':'; i++)
+    ;
+  if (line[i] != ':')
+    {
+      builtin_error (_("%s: missing colon separator"), line);
+      FREE (kseq);
+      return -1;
+    }
+
+  i = isolate_sequence (line, i + 1, 0, &kstart);
+  if (i < 0)
+    {
+      FREE (kseq);
+      return -1;
+    }
+
+  /* Create the value string containing the command to execute. */
+  value = substring (line, kstart, i);
+
+  /* Save the command to execute and the key sequence in the CMD_XMAP */
+  rl_generic_bind (ISMACR, kseq, value, cmd_xmap);
+
+  /* and bind the key sequence in the current keymap to a function that
+     understands how to execute from CMD_XMAP */
+  rl_bind_keyseq_in_map (kseq, bash_execute_unix_command, kmap);
+
+  free (kseq);  
+  return 0;
+}
+
+/* Used by the programmable completion code.  Complete TEXT as a filename,
+   but return only directories as matches.  Dequotes the filename before
+   attempting to find matches. */
+char **
+bash_directory_completion_matches (text)
+     const char *text;
+{
+  char **m1;
+  char *dfn;
+  int qc;
+
+  qc = rl_dispatching ? rl_completion_quote_character : 0;  
+  dfn = bash_dequote_filename ((char *)text, qc);
+  m1 = rl_completion_matches (dfn, rl_filename_completion_function);
+  free (dfn);
+
+  if (m1 == 0 || m1[0] == 0)
+    return m1;
+  /* We don't bother recomputing the lcd of the matches, because it will just
+     get thrown away by the programmable completion code and recomputed
+     later. */
+  (void)bash_ignore_filenames (m1);
+  return m1;
+}
+
+char *
+bash_dequote_text (text)
+     const char *text;
+{
+  char *dtxt;
+  int qc;
+
+  qc = (text[0] == '"' || text[0] == '\'') ? text[0] : 0;
+  dtxt = bash_dequote_filename ((char *)text, qc);
+  return (dtxt);
+}
+
+/* This event hook is designed to be called after readline receives a signal
+   that interrupts read(2).  It gives reasonable responsiveness to interrupts
+   and fatal signals without executing too much code in a signal handler
+   context. */
+static int
+bash_event_hook ()
+{
+  /* If we're going to longjmp to top_level, make sure we clean up readline.
+     check_signals will call QUIT, which will eventually longjmp to top_level,
+     calling run_interrupt_trap along the way. */
+  if (interrupt_state)
+    rl_cleanup_after_signal ();
+  bashline_reset_event_hook ();
+  check_signals_and_traps ();  /* XXX */
+  return 0;
+}
+
+#endif /* READLINE */
index a2e7911bfecf0d04427f157e5353f25299647349..f745c1da185fef409b217d16cad4e62cfe62d3ac 100644 (file)
@@ -419,7 +419,7 @@ declare.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
 declare.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
 declare.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
 declare.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-declare.o: $(topdir)/arrayfunc.h $(srcdir)/bashgetopt.h
+declare.o: $(topdir)/arrayfunc.h $(srcdir)/bashgetopt.h $(topdir)/flags.h
 declare.o: ./builtext.h ../pathnames.h
 echo.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
 echo.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/subst.h $(topdir)/externs.h
@@ -558,7 +558,7 @@ setattr.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
 setattr.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(BASHINCDIR)/maxpath.h
 setattr.o: $(topdir)/quit.h $(srcdir)/common.h $(srcdir)/bashgetopt.h
 setattr.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
-setattr.o: $(topdir)/externs.h 
+setattr.o: $(topdir)/externs.h $(topdir)/flags.h
 setattr.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h 
 setattr.o: $(topdir)/arrayfunc.h ../pathnames.h
 shift.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
diff --git a/builtins/Makefile.in~ b/builtins/Makefile.in~
new file mode 100644 (file)
index 0000000..a2e7911
--- /dev/null
@@ -0,0 +1,686 @@
+# This Makefile for building libbuiltins.a is in -*- text -*- for Emacs.
+#
+# Copyright (C) 1996-2009 Free Software Foundation, Inc.
+
+#   This program is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, either version 3 of the License, or
+#   (at your option) any later version.
+
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+PACKAGE = @PACKAGE_NAME@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+
+#
+SHELL = @MAKE_SHELL@
+RANLIB = @RANLIB@
+CC = @CC@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+AR = @AR@
+ARFLAGS = @ARFLAGS@
+RM = rm -f
+CP = cp
+
+EXEEXT = @EXEEXT@
+
+prefix = @prefix@
+
+srcdir = @srcdir@
+VPATH = .:@srcdir@
+topdir = @top_srcdir@
+
+datarootdir = @datarootdir@
+
+includedir = @includedir@
+datadir = @datadir@
+localedir = @localedir@
+
+# Support an alternate destination root directory for package building
+DESTDIR =
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+BUILD_DIR = @BUILD_DIR@
+
+LIBBUILD = ${BUILD_DIR}/lib
+
+PROFILE_FLAGS = @PROFILE_FLAGS@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ @CROSS_COMPILE@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+LOCAL_CFLAGS = @LOCAL_CFLAGS@ ${DEBUG}
+DEFS = @DEFS@
+LOCAL_DEFS = @LOCAL_DEFS@
+
+LIBS = @LIBS@
+LDFLAGS = @LDFLAGS@ $(LOCAL_LDFLAGS) $(CFLAGS)
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ $(LOCAL_LDFLAGS) $(CFLAGS_FOR_BUILD)
+LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
+LIBS_FOR_BUILD = @LIBS_FOR_BUILD@
+#LIBS_FOR_BUILD = $(LIBS)
+
+BASHINCDIR = ${topdir}/include
+
+RL_INCLUDEDIR = @RL_INCLUDEDIR@
+
+INTL_LIBSRC = ${topdir}/lib/intl
+INTL_BUILDDIR = ${LIBBUILD}/intl
+INTL_LIBDIR = ${INTL_BUILDDIR}
+INTL_LIBRARY = ${INTL_BUILDDIR}/libintl.a
+INTL_INC = @INTL_INC@
+INTL_DEP = @INTL_DEP@
+LIBINTL_H = @LIBINTL_H@
+
+HELPDIR = @HELPDIR@
+MKDIRS = ${topdir}/support/mkdirs
+
+HELPFILES_TARGET = @HELPFILES_TARGET@
+
+INCLUDES = -I. -I.. @RL_INCLUDE@ -I$(topdir) -I$(BASHINCDIR) -I$(topdir)/lib -I$(srcdir) ${INTL_INC}
+
+BASE_CCFLAGS = ${PROFILE_FLAGS} $(DEFS) $(LOCAL_DEFS) $(SYSTEM_FLAGS) \
+        ${INCLUDES} $(LOCAL_CFLAGS)
+
+CCFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(CFLAGS)
+
+CCFLAGS_FOR_BUILD = $(BASE_CCFLAGS) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD)
+
+GCC_LINT_FLAGS = -Wall -Wshadow -Wpointer-arith -Wcast-qual \
+                -Wcast-align -Wstrict-prototypes -Wconversion \
+                -Wmissing-prototypes -Wtraditional -Wredundant-decls -pedantic
+
+MKBUILTINS = mkbuiltins$(EXEEXT)
+DIRECTDEFINE = -D $(srcdir)
+HELPDIRDEFINE = @HELPDIRDEFINE@
+HELPSTRINGS = @HELPSTRINGS@
+
+# xxx this is bad style
+RL_LIBSRC = $(topdir)/lib/readline
+
+.SUFFIXES:
+.SUFFIXES: .def .c .o
+# How to make a .o file from a .def file.
+.def.o:
+       $(RM) $@
+       ./$(MKBUILTINS) $(DIRECTDEFINE) $<
+       $(CC) -c $(CCFLAGS) $*.c || ( $(RM) $*.c ; exit 1 )
+       $(RM) $*.c
+
+# How to make a .c file from a .def file.
+.def.c:
+       $(RM) $@
+       ./$(MKBUILTINS) $(DIRECTDEFINE) $<
+
+# default rule for making a .o file from a .c file
+.c.o:
+       $(RM) $@
+       $(CC) -c $(CCFLAGS) $<
+
+DEFSRC =  $(srcdir)/alias.def $(srcdir)/bind.def $(srcdir)/break.def \
+         $(srcdir)/builtin.def $(srcdir)/caller.def \
+         $(srcdir)/cd.def $(srcdir)/colon.def \
+         $(srcdir)/command.def $(srcdir)/declare.def $(srcdir)/echo.def \
+         $(srcdir)/enable.def $(srcdir)/eval.def $(srcdir)/getopts.def \
+         $(srcdir)/exec.def $(srcdir)/exit.def $(srcdir)/fc.def \
+         $(srcdir)/fg_bg.def $(srcdir)/hash.def $(srcdir)/help.def \
+         $(srcdir)/history.def $(srcdir)/jobs.def $(srcdir)/kill.def \
+         $(srcdir)/let.def $(srcdir)/read.def $(srcdir)/return.def \
+         $(srcdir)/set.def $(srcdir)/setattr.def $(srcdir)/shift.def \
+         $(srcdir)/source.def $(srcdir)/suspend.def $(srcdir)/test.def \
+         $(srcdir)/times.def $(srcdir)/trap.def $(srcdir)/type.def \
+         $(srcdir)/ulimit.def $(srcdir)/umask.def $(srcdir)/wait.def \
+         $(srcdir)/reserved.def $(srcdir)/pushd.def $(srcdir)/shopt.def \
+         $(srcdir)/printf.def $(srcdir)/complete.def $(srcdir)/mapfile.def
+
+STATIC_SOURCE = common.c evalstring.c evalfile.c getopt.c bashgetopt.c \
+               getopt.h 
+
+OFILES = builtins.o \
+       alias.o bind.o break.o builtin.o caller.o cd.o colon.o command.o \
+       common.o declare.o echo.o enable.o eval.o evalfile.o \
+       evalstring.o exec.o exit.o fc.o fg_bg.o hash.o help.o history.o \
+       jobs.o kill.o let.o mapfile.o \
+       pushd.o read.o return.o set.o setattr.o shift.o source.o \
+       suspend.o test.o times.o trap.o type.o ulimit.o umask.o \
+       wait.o getopts.o shopt.o printf.o getopt.o bashgetopt.o complete.o
+
+CREATED_FILES = builtext.h builtins.c psize.aux pipesize.h tmpbuiltins.c \
+       tmpbuiltins.h
+CREATED_OBJECTS = tmpbuiltins.o gen-helpfiles.o mkbuiltins.o
+
+all: $(MKBUILTINS) libbuiltins.a $(HELPFILES_TARGET)
+targets: libbuiltins.a $(HELPFILES_TARGET)
+
+libbuiltins.a: $(MKBUILTINS) $(OFILES) builtins.o
+       $(RM) $@
+       $(AR) $(ARFLAGS) $@ $(OFILES)
+       -$(RANLIB) $@
+
+tmpbuiltins.c: $(MKBUILTINS) $(DEFSRC)
+       ./$(MKBUILTINS) -externfile tmpbuiltins.h -structfile $@ \
+               -noproduction -nofunctions \
+               $(DIRECTDEFINE) $(HELPSTRINGS) $(DEFSRC)
+
+tmpbuiltins.h: tmpbuiltins.c
+
+gen-helpfiles.o: ../config.h
+gen-helpfiles.o: gen-helpfiles.c
+       $(RM) $@
+       $(CC_FOR_BUILD) -c $(CCFLAGS_FOR_BUILD) $<
+
+gen-helpfiles: tmpbuiltins.o gen-helpfiles.o
+       $(CC_FOR_BUILD) ${CCFLAGS_FOR_BUILD} $(LDFLAGS_FOR_BUILD) -o $@ gen-helpfiles.o tmpbuiltins.o $(LIBS_FOR_BUILD)
+
+builtext.h builtins.c: $(MKBUILTINS) $(DEFSRC)
+       @-if test -f builtins.c; then mv -f builtins.c old-builtins.c; fi
+       @-if test -f builtext.h; then mv -f builtext.h old-builtext.h; fi
+       ./$(MKBUILTINS) -externfile builtext.h -structfile builtins.c \
+           -noproduction $(DIRECTDEFINE) $(HELPDIRDEFINE) $(HELPSTRINGS) $(DEFSRC)
+       @-if cmp -s old-builtext.h builtext.h 2>/dev/null; then \
+               mv old-builtext.h builtext.h; \
+        else \
+               $(RM) old-builtext.h; \
+        fi
+       @-if cmp -s old-builtins.c builtins.c 2>/dev/null; then \
+               mv old-builtins.c builtins.c; \
+        else \
+               $(RM) old-builtins.c; \
+        fi
+
+helpdoc:       gen-helpfiles
+       ./gen-helpfiles ${HELPDIRDEFINE}
+
+install-help:
+       @-if test -n "${HELPDIR}" && test -d helpfiles ; then \
+               test -d $(DESTDIR)${HELPDIR} || ${SHELL} ${MKDIRS} $(DESTDIR)$(HELPDIR) ;\
+               ( for f in helpfiles/*; do \
+                       echo installing $$f; \
+                       ${INSTALL_DATA} $$f $(DESTDIR)$(HELPDIR); \
+                 done; ) ; \
+       fi
+
+install:       @HELPINSTALL@
+
+mkbuiltins.o: ../config.h
+mkbuiltins.o: mkbuiltins.c
+       $(RM) $@
+       $(CC_FOR_BUILD) -c $(CCFLAGS_FOR_BUILD) $<
+
+mkbuiltins$(EXEEXT): mkbuiltins.o
+       $(CC_FOR_BUILD) $(LDFLAGS_FOR_BUILD) -o $(MKBUILTINS) mkbuiltins.o $(LIBS_FOR_BUILD)
+
+# rules for deficient makes, like SunOS
+mkbuiltins.o: mkbuiltins.c
+builtins.o: builtins.c
+common.o: common.c
+bashgetopt.o: bashgetopt.c
+getopt.o: getopt.c
+evalstring.o: evalstring.c          
+evalfile.o: evalfile.c
+
+tmpbuiltins.o: tmpbuiltins.c
+gen-helpfiles.o: gen-helpfiles.c
+
+ulimit.o: pipesize.h
+
+pipesize.h:    psize.aux
+       $(SHELL) $(srcdir)/psize.sh > $@
+
+# Technically this is wrong; the pipe size should be for the target system,
+# not the build host.
+psize.aux:     psize.c
+       $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) ${LDFLAGS_FOR_BUILD} -o $@ $(srcdir)/psize.c
+
+documentation: builtins.texi
+
+builtins.texi: $(MKBUILTINS)
+       ./$(MKBUILTINS) -documentonly $(DEFSRC)
+
+clean:
+       $(RM) $(OFILES) $(CREATED_FILES) libbuiltins.a
+       $(RM) $(MKBUILTINS) gen-helpfiles $(CREATED_OBJECTS)
+       -test -d helpfiles && $(RM) -r helpfiles
+
+mostlyclean: 
+       $(RM) $(OFILES) libbuiltins.a
+
+distclean maintainer-clean: clean
+       $(RM) Makefile
+
+$(OFILES):     $(MKBUILTINS) ../config.h
+
+../version.h: ../config.h ../Makefile Makefile
+       -( cd ${BUILD_DIR} && ${MAKE} ${MFLAGS} version.h )
+
+# maintainer special - for now
+po:    builtins.c
+       xgettext -L C -o $(topdir)/po/builtins.pot --keyword='N_' builtins.c 2>/dev/null
+
+${LIBINTL_H}:
+       @echo making $@ in ${INTL_BUILDDIR}
+       @(cd ${INTL_BUILDDIR} && \
+               $(MAKE) $(MFLAGS) libintl.h) || exit 1
+
+# dependencies
+
+alias.o: alias.def
+bind.o: bind.def
+break.o: break.def
+builtin.o: builtin.def
+caller.o: caller.def
+cd.o: cd.def
+colon.o: colon.def
+command.o: command.def
+declare.o: declare.def
+echo.o: echo.def
+enable.o: enable.def
+eval.o: eval.def
+exec.o: exec.def
+exit.o: exit.def
+fc.o: fc.def
+fg_bg.o: fg_bg.def
+hash.o: hash.def
+help.o: help.def
+history.o: history.def
+jobs.o: jobs.def
+kill.o: kill.def
+let.o: let.def
+mapfile.o: mapfile.def
+printf.o: printf.def
+pushd.o: pushd.def
+read.o: read.def
+return.o: return.def
+set.o: set.def
+setattr.o: setattr.def
+shift.o: shift.def
+shopt.o: shopt.def
+source.o: source.def
+suspend.o: suspend.def
+test.o: test.def
+times.o: times.def
+trap.o: trap.def
+type.o: type.def
+ulimit.o: ulimit.def
+umask.o: umask.def
+wait.o: wait.def
+getopts.o: getopts.def
+reserved.o: reserved.def
+complete.o: complete.def
+
+# C files
+bashgetopt.o: ../config.h $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h
+bashgetopt.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/bashjmp.h
+bashgetopt.o: $(topdir)/command.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/error.h
+bashgetopt.o: $(topdir)/variables.h $(topdir)/conftypes.h $(topdir)/quit.h $(BASHINCDIR)/maxpath.h
+bashgetopt.o: $(topdir)/unwind_prot.h $(topdir)/dispose_cmd.h
+bashgetopt.o: $(topdir)/make_cmd.h $(topdir)/subst.h $(topdir)/sig.h
+bashgetopt.o: ../pathnames.h $(topdir)/externs.h $(srcdir)/common.h
+bashgetopt.o: $(BASHINCDIR)/chartypes.h
+common.o: $(topdir)/bashtypes.h $(BASHINCDIR)/posixstat.h $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h
+common.o: $(topdir)/shell.h $(topdir)/syntax.h ../config.h $(topdir)/bashjmp.h $(BASHINCDIR)/posixjmp.h
+common.o: $(topdir)/sig.h $(topdir)/command.h
+common.o: $(topdir)/general.h $(topdir)/xmalloc.h $(BASHINCDIR)/stdc.h $(BASHINCDIR)/memalloc.h
+common.o: $(topdir)/variables.h $(topdir)/conftypes.h $(topdir)/input.h
+common.o: $(topdir)/siglist.h $(topdir)/bashhist.h $(topdir)/quit.h
+common.o: $(topdir)/unwind_prot.h $(BASHINCDIR)/maxpath.h $(topdir)/jobs.h
+common.o: $(topdir)/builtins.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+common.o: $(topdir)/subst.h $(topdir)/execute_cmd.h $(topdir)/error.h
+common.o: $(topdir)/externs.h ../pathnames.h ./builtext.h
+common.o: $(BASHINCDIR)/chartypes.h
+evalfile.o: $(topdir)/bashtypes.h $(BASHINCDIR)/posixstat.h ${BASHINCDIR}/filecntl.h
+evalfile.o: $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h
+evalfile.o: $(topdir)/shell.h $(topdir)/syntax.h ../config.h $(topdir)/bashjmp.h
+evalfile.o: $(topdir)/command.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/error.h
+evalfile.o: $(topdir)/variables.h $(topdir)/conftypes.h $(topdir)/quit.h $(BASHINCDIR)/maxpath.h
+evalfile.o: $(topdir)/unwind_prot.h $(topdir)/dispose_cmd.h
+evalfile.o: $(topdir)/make_cmd.h $(topdir)/subst.h $(topdir)/sig.h
+evalfile.o: ../pathnames.h $(topdir)/externs.h
+evalfile.o: $(topdir)/jobs.h $(topdir)/builtins.h $(topdir)/flags.h
+evalfile.o: $(topdir)/input.h $(topdir)/execute_cmd.h
+evalfile.o: $(topdir)/bashhist.h $(srcdir)/common.h
+evalstring.o: ../config.h $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h
+evalstring.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/bashjmp.h $(BASHINCDIR)/posixjmp.h
+evalstring.o: $(topdir)/sig.h $(topdir)/command.h $(topdir)/siglist.h
+evalstring.o: $(BASHINCDIR)/memalloc.h $(topdir)/variables.h $(topdir)/conftypes.h $(topdir)/input.h
+evalstring.o: $(topdir)/quit.h $(topdir)/unwind_prot.h
+evalstring.o: $(BASHINCDIR)/maxpath.h $(topdir)/jobs.h $(topdir)/builtins.h
+evalstring.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
+evalstring.o: $(topdir)/externs.h $(topdir)/jobs.h $(topdir)/builtins.h
+evalstring.o: $(topdir)/flags.h $(topdir)/input.h $(topdir)/execute_cmd.h
+evalstring.o: $(topdir)/bashhist.h $(srcdir)/common.h
+evalstring.o: $(topdir)/trap.h $(topdir)/redir.h ../pathnames.h
+#evalstring.o: $(topdir)/y.tab.h
+getopt.o: ../config.h $(BASHINCDIR)/memalloc.h
+getopt.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/bashjmp.h $(topdir)/command.h
+getopt.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/error.h $(topdir)/variables.h $(topdir)/conftypes.h
+getopt.o: $(topdir)/quit.h $(BASHINCDIR)/maxpath.h $(topdir)/unwind_prot.h
+getopt.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
+getopt.o: $(topdir)/sig.h ../pathnames.h $(topdir)/externs.h
+getopt.o: $(srcdir)/getopt.h 
+mkbuiltins.o: ../config.h $(topdir)/bashtypes.h $(BASHINCDIR)/posixstat.h
+mkbuiltins.o: ${BASHINCDIR}/filecntl.h
+mkbuiltins.o: $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h
+
+# def files
+alias.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+alias.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(BASHINCDIR)/maxpath.h
+alias.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+alias.o: $(topdir)/subst.h $(topdir)/externs.h $(srcdir)/common.h
+alias.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+alias.o: ../pathnames.h
+bind.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
+bind.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+bind.o: $(topdir)/subst.h $(topdir)/externs.h $(srcdir)/bashgetopt.h
+bind.o: $(topdir)/general.h $(topdir)/xmalloc.h $(BASHINCDIR)/maxpath.h $(topdir)/bashline.h
+bind.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h 
+bind.o: ../pathnames.h
+break.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h 
+break.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+break.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+break.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+break.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+break.o: ../pathnames.h
+builtin.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+builtin.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/externs.h
+builtin.o: $(topdir)/quit.h $(srcdir)/common.h $(BASHINCDIR)/maxpath.h
+builtin.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
+builtin.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h 
+builtin.o: $(srcdir)/bashgetopt.h ../pathnames.h
+caller.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
+caller.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/quit.h $(topdir)/dispose_cmd.h
+caller.o: $(topdir)/make_cmd.h $(topdir)/subst.h $(topdir)/externs.h
+caller.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+caller.o: $(srcdir)/common.h $(BASHINCDIR)/maxpath.h ./builtext.h
+caller.o: ${BASHINCDIR}/chartypes.h $(topdir)/bashtypes.h ../pathnames.h
+cd.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
+cd.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/quit.h $(topdir)/dispose_cmd.h
+cd.o: $(topdir)/make_cmd.h $(topdir)/subst.h $(topdir)/externs.h
+cd.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+cd.o: $(srcdir)/common.h $(BASHINCDIR)/maxpath.h ../pathnames.h
+command.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+command.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/externs.h
+command.o: $(topdir)/quit.h $(srcdir)/bashgetopt.h $(BASHINCDIR)/maxpath.h
+command.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
+command.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h 
+command.o: ../pathnames.h
+declare.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+declare.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+declare.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+declare.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+declare.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+declare.o: $(topdir)/arrayfunc.h $(srcdir)/bashgetopt.h
+declare.o: ./builtext.h ../pathnames.h
+echo.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
+echo.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/subst.h $(topdir)/externs.h
+echo.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+echo.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+echo.o: $(BASHINCDIR)/maxpath.h ../pathnames.h
+enable.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+enable.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+enable.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+enable.o: $(topdir)/subst.h $(topdir)/externs.h
+enable.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+enable.o: $(BASHINCDIR)/maxpath.h ../pathnames.h
+enable.o: $(topdir)/pcomplete.h
+eval.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+eval.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+eval.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+eval.o: $(topdir)/subst.h $(topdir)/externs.h 
+eval.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+eval.o: $(BASHINCDIR)/maxpath.h ../pathnames.h
+exec.o: $(topdir)/bashtypes.h
+exec.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+exec.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+exec.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+exec.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/flags.h
+exec.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+exec.o: $(srcdir)/common.h $(topdir)/execute_cmd.h $(BASHINCDIR)/maxpath.h
+exec.o: $(topdir)/findcmd.h $(topdir)/jobs.h ../pathnames.h
+exit.o: $(topdir)/bashtypes.h
+exit.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+exit.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+exit.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+exit.o: $(topdir)/subst.h $(topdir)/externs.h  $(topdir)/jobs.h
+exit.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+exit.o: $(BASHINCDIR)/maxpath.h ./builtext.h ../pathnames.h
+fc.o: $(topdir)/bashtypes.h $(BASHINCDIR)/posixstat.h
+fc.o: $(topdir)/builtins.h $(topdir)/command.h $(srcdir)/bashgetopt.h
+fc.o: $(topdir)/bashhist.h
+fc.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
+fc.o: $(topdir)/general.h $(topdir)/xmalloc.h $(BASHINCDIR)/maxpath.h
+fc.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+fc.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/shell.h $(topdir)/syntax.h
+fc.o: $(topdir)/flags.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+fc.o: $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h $(BASHINCDIR)/chartypes.h
+fc.o: ../pathnames.h
+fg_bg.o: $(topdir)/bashtypes.h $(srcdir)/bashgetopt.h
+fg_bg.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+fg_bg.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+fg_bg.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+fg_bg.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+fg_bg.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+fg_bg.o: $(topdir)/jobs.h ../pathnames.h
+getopts.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+getopts.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+getopts.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+getopts.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+getopts.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+getopts.o: ../pathnames.h
+hash.o: $(topdir)/builtins.h $(topdir)/command.h $(topdir)/quit.h
+hash.o: $(topdir)/findcmd.h $(topdir)/hashlib.h
+hash.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+hash.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+hash.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+hash.o: $(srcdir)/common.h $(BASHINCDIR)/maxpath.h ../pathnames.h
+help.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+help.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+help.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+help.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+help.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+help.o: ${srcdir}/common.h ../pathnames.h
+history.o: $(topdir)/bashtypes.h
+history.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+history.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+history.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+history.o: $(topdir)/subst.h $(topdir)/externs.h 
+history.o: ${BASHINCDIR}/filecntl.h $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h
+history.o: $(topdir)/variables.h $(topdir)/conftypes.h $(topdir)/bashhist.h $(BASHINCDIR)/maxpath.h
+history.o: ../pathnames.h
+inlib.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+inlib.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+inlib.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+inlib.o: $(BASHINCDIR)/maxpath.h $(topdir)/subst.h $(topdir)/externs.h
+inlib.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h ../pathnames.h
+jobs.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
+jobs.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/quit.h $(srcdir)/bashgetopt.h
+jobs.o: $(BASHINCDIR)/maxpath.h $(topdir)/externs.h $(topdir)/jobs.h
+jobs.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
+jobs.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h 
+jobs.o: ../pathnames.h
+kill.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
+kill.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/subst.h $(topdir)/externs.h
+kill.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+kill.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/trap.h $(topdir)/unwind_prot.h
+kill.o: $(topdir)/variables.h $(topdir)/conftypes.h $(BASHINCDIR)/maxpath.h
+kill.o: $(topdir)/jobs.h ../pathnames.h
+let.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+let.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+let.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+let.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+let.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+let.o: ../pathnames.h
+printf.o: ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/bashjmp.h
+printf.o: $(topdir)/command.h $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+printf.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+printf.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/sig.h
+printf.o: ../pathnames.h $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h
+printf.o: $(topdir)/variables.h $(topdir)/conftypes.h $(BASHINCDIR)/stdc.h $(srcdir)/bashgetopt.h
+printf.o: $(topdir)/bashtypes.h ${srcdir}/common.h $(BASHINCDIR)/chartypes.h
+printf.o: ../pathnames.h
+pushd.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+pushd.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+pushd.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+pushd.o: $(topdir)/subst.h $(topdir)/externs.h 
+pushd.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+pushd.o: $(BASHINCDIR)/maxpath.h $(srcdir)/common.h ./builtext.h
+pushd.o: ../pathnames.h
+read.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+read.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+read.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+read.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+read.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+read.o: $(BASHINCDIR)/shtty.h
+read.o: $(topdir)/arrayfunc.h ../pathnames.h
+return.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+return.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+return.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+return.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+return.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+return.o: ../pathnames.h
+set.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+set.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/subst.h $(topdir)/externs.h
+set.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+set.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+set.o: $(BASHINCDIR)/maxpath.h $(topdir)/error.h
+set.o: $(topdir)/arrayfunc.h ../pathnames.h
+setattr.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+setattr.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(BASHINCDIR)/maxpath.h
+setattr.o: $(topdir)/quit.h $(srcdir)/common.h $(srcdir)/bashgetopt.h
+setattr.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
+setattr.o: $(topdir)/externs.h 
+setattr.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h 
+setattr.o: $(topdir)/arrayfunc.h ../pathnames.h
+shift.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+shift.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+shift.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+shift.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+shift.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+shift.o: ../pathnames.h
+shopt.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+shopt.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h 
+shopt.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+shopt.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+shopt.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+shopt.o: $(srcdir)/common.h $(srcdir)/bashgetopt.h ../pathnames.h
+shopt.o: $(topdir)/bashhist.h $(topdir)/bashline.h
+source.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+source.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/findcmd.h
+source.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+source.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+source.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+source.o: $(srcdir)/bashgetopt.h $(topdir)/flags.h $(topdir)/trap.h
+source.o: ../pathnames.h
+suspend.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+suspend.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+suspend.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+suspend.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+suspend.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+suspend.o: $(topdir)/jobs.h ../pathnames.h
+test.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+test.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+test.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+test.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+test.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+test.o: $(topdir)/test.h ../pathnames.h
+times.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+times.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+times.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+times.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+times.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+times.o: $(BASHINCDIR)/posixtime.h ../pathnames.h
+trap.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+trap.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/externs.h
+trap.o: $(topdir)/quit.h $(srcdir)/common.h $(BASHINCDIR)/maxpath.h
+trap.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
+trap.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+trap.o: $(topdir)/findcmd.h ../pathnames.h
+type.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+type.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+type.o: $(topdir)/quit.h $(srcdir)/common.h $(BASHINCDIR)/maxpath.h
+type.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
+type.o: $(topdir)/externs.h $(topdir)/hashcmd.h ../pathnames.h
+type.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h 
+ulimit.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+ulimit.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+ulimit.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+ulimit.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+ulimit.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+ulimit.o: ../pathnames.h
+umask.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+umask.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+umask.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+umask.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+umask.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+umask.o: $(BASHINCDIR)/chartypes.h ../pathnames.h
+wait.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+wait.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+wait.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+wait.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+wait.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+wait.o: $(topdir)/jobs.h
+wait.o: $(BASHINCDIR)/chartypes.h ../pathnames.h
+
+complete.o: ../config.h ../pathnames.h
+complete.o: ${topdir}/shell.h $(topdir)/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h ${topdir}/sig.h  
+complete.o: ${topdir}/unwind_prot.h ${topdir}/variables.h
+complete.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+complete.o: ${topdir}/builtins.h
+complete.o: ${topdir}/pcomplete.h
+complete.o: ${srcdir}/common.h ${srcdir}/bashgetopt.h
+mapfile.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
+mapfile.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
+mapfile.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
+mapfile.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+mapfile.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/variables.h $(topdir)/conftypes.h
+mapfile.o: $(topdir)/arrayfunc.h ../pathnames.h
+
+#bind.o: $(RL_LIBSRC)chardefs.h $(RL_LIBSRC)readline.h $(RL_LIBSRC)keymaps.h
+
+# libintl dependencies
+bind.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+break.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+caller.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+cd.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+common.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+complete.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+declare.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+enable.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+evalfile.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+exec.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+exit.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+fc.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+fg_bg.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+getopt.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+hash.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+help.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+history.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+inlib.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+jobs.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+kill.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+let.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+mapfile.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+mkbuiltins.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+printf.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+pushd.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+read.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+return.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+set.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+setattr.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+shift.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+shopt.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+source.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+suspend.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+type.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+ulimit.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+umask.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
index a634e7ce82f6390578a6f1946c4313fa182716ff..f69daf8ae87951e25e302621e371b0f537951f23 100644 (file)
@@ -83,6 +83,7 @@ $END
 #include "../bashintl.h"
 
 #include "../shell.h"
+#include "../flags.h"
 #include "common.h"
 #include "builtext.h"
 #include "bashgetopt.h"
@@ -483,13 +484,13 @@ declare_internal (list, local_var)
              if (flags_on & att_assoc)
                {
                  var = make_new_assoc_variable (name);
-                 if (offset == 0)
+                 if (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)
+                 if (offset == 0 && no_invisible_vars == 0)
                    VSETATTR (var, att_invisible);
                }
              else
@@ -500,7 +501,8 @@ declare_internal (list, local_var)
              else
                {
                  var = mkglobal ? bind_global_variable (name, (char *)NULL, 0) : bind_variable (name, (char *)NULL, 0);
-                 VSETATTR (var, att_invisible);
+                 if (no_invisible_vars == 0)
+                   VSETATTR (var, att_invisible);
                }
            }
          /* Can't take an existing array variable and make it a nameref */
diff --git a/builtins/declare.def~ b/builtins/declare.def~
new file mode 100644 (file)
index 0000000..62dac08
--- /dev/null
@@ -0,0 +1,697 @@
+This file is declare.def, from which is created declare.c.
+It implements the builtins "declare" and "local" in Bash.
+
+Copyright (C) 1987-2012 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Bash is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+
+$PRODUCES declare.c
+
+$BUILTIN declare
+$FUNCTION declare_builtin
+$SHORT_DOC declare [-aAfFgilnrtux] [-p] [name[=value] ...]
+Set variable values and attributes.
+
+Declare variables and give them attributes.  If no NAMEs are given,
+display the attributes and values of all variables.
+
+Options:
+  -f   restrict action or display to function names and definitions
+  -F   restrict display to function names only (plus line number and
+       source file when debugging)
+  -g   create global variables when used in a shell function; otherwise
+       ignored
+  -p   display the attributes and value of each NAME
+
+Options which set attributes:
+  -a   to make NAMEs indexed arrays (if supported)
+  -A   to make NAMEs associative arrays (if supported)
+  -i   to make NAMEs have the `integer' attribute
+  -l   to convert NAMEs to lower case on assignment
+  -n   make NAME a reference to the variable named by its value
+  -r   to make NAMEs readonly
+  -t   to make NAMEs have the `trace' attribute
+  -u   to convert NAMEs to upper case on assignment
+  -x   to make NAMEs export
+
+Using `+' instead of `-' turns off the given attribute.
+
+Variables with the integer attribute have arithmetic evaluation (see
+the `let' command) performed when the variable is assigned a value.
+
+When used in a function, `declare' makes NAMEs local, as with the `local'
+command.  The `-g' option suppresses this behavior.
+
+Exit Status:
+Returns success unless an invalid option is supplied or a variable
+assignment error occurs.
+$END
+
+$BUILTIN typeset
+$FUNCTION declare_builtin
+$SHORT_DOC typeset [-aAfFgilrtux] [-p] name[=value] ...
+Set variable values and attributes.
+
+Obsolete.  See `help declare'.
+$END
+
+#include <config.h>
+
+#if defined (HAVE_UNISTD_H)
+#  ifdef _MINIX
+#    include <sys/types.h>
+#  endif
+#  include <unistd.h>
+#endif
+
+#include <stdio.h>
+
+#include "../bashansi.h"
+#include "../bashintl.h"
+
+#include "../shell.h"
+#include "common.h"
+#include "builtext.h"
+#include "bashgetopt.h"
+
+extern int array_needs_making;
+extern int posixly_correct;
+
+static int declare_internal __P((register WORD_LIST *, int));
+
+/* Declare or change variable attributes. */
+int
+declare_builtin (list)
+     register WORD_LIST *list;
+{
+  return (declare_internal (list, 0));
+}
+
+$BUILTIN local
+$FUNCTION local_builtin
+$SHORT_DOC local [option] name[=value] ...
+Define local variables.
+
+Create a local variable called NAME, and give it VALUE.  OPTION can
+be any option accepted by `declare'.
+
+Local variables can only be used within a function; they are visible
+only to the function where they are defined and its children.
+
+Exit Status:
+Returns success unless an invalid option is supplied, a variable
+assignment error occurs, or the shell is not executing a function.
+$END
+int
+local_builtin (list)
+     register WORD_LIST *list;
+{
+  if (variable_context)
+    return (declare_internal (list, 1));
+  else
+    {
+      builtin_error (_("can only be used in a function"));
+      return (EXECUTION_FAILURE);
+    }
+}
+
+#if defined (ARRAY_VARS)
+#  define DECLARE_OPTS "+acfgilnprtuxAF"
+#else
+#  define DECLARE_OPTS "+cfgilnprtuxF"
+#endif
+
+/* The workhorse function. */
+static int
+declare_internal (list, local_var)
+     register WORD_LIST *list;
+     int local_var;
+{
+  int flags_on, flags_off, *flags;
+  int any_failed, assign_error, pflag, nodefs, opt, mkglobal, onref, offref;
+  char *t, *subscript_start;
+  SHELL_VAR *var, *refvar, *v;
+  FUNCTION_DEF *shell_fn;
+
+  flags_on = flags_off = any_failed = assign_error = pflag = nodefs = mkglobal = 0;
+  refvar = (SHELL_VAR *)NULL;
+  reset_internal_getopt ();
+  while ((opt = internal_getopt (list, DECLARE_OPTS)) != EOF)
+    {
+      flags = list_opttype == '+' ? &flags_off : &flags_on;
+
+      switch (opt)
+       {
+       case 'a':
+#if defined (ARRAY_VARS)
+         *flags |= att_array;
+         break;
+#else
+         builtin_usage ();
+         return (EX_USAGE);
+#endif
+       case 'A':
+#if defined (ARRAY_VARS)
+         *flags |= att_assoc;
+         break;
+#else
+         builtin_usage ();
+         return (EX_USAGE);
+#endif
+       case 'p':
+         if (local_var == 0)
+           pflag++;
+         break;
+        case 'F':
+         nodefs++;
+         *flags |= att_function;
+         break;
+       case 'f':
+         *flags |= att_function;
+         break;
+       case 'g':
+         if (flags == &flags_on)
+           mkglobal = 1;
+         break;
+       case 'i':
+         *flags |= att_integer;
+         break;
+       case 'n':
+         *flags |= att_nameref;
+         break;
+       case 'r':
+         *flags |= att_readonly;
+         break;
+       case 't':
+         *flags |= att_trace;
+         break;
+       case 'x':
+         *flags |= att_exported;
+         array_needs_making = 1;
+         break;
+#if defined (CASEMOD_ATTRS)
+#  if defined (CASEMOD_CAPCASE)
+        case 'c':
+         *flags |= att_capcase;
+         if (flags == &flags_on)
+           flags_off |= att_uppercase|att_lowercase;
+         break;
+#  endif
+       case 'l':
+         *flags |= att_lowercase;
+         if (flags == &flags_on)
+           flags_off |= att_capcase|att_uppercase;
+         break;
+       case 'u':
+         *flags |= att_uppercase;
+         if (flags == &flags_on)
+           flags_off |= att_capcase|att_lowercase;
+         break;
+#endif /* CASEMOD_ATTRS */
+       default:
+         builtin_usage ();
+         return (EX_USAGE);
+       }
+    }
+
+  list = loptend;
+
+  /* If there are no more arguments left, then we just want to show
+     some variables. */
+  if (list == 0)       /* declare -[aAfFirtx] */
+    {
+      /* Show local variables defined at this context level if this is
+        the `local' builtin. */
+      if (local_var)
+       {
+         register SHELL_VAR **vlist;
+         register int i;
+
+         vlist = all_local_variables ();
+
+         if (vlist)
+           {
+             for (i = 0; vlist[i]; i++)
+               print_assignment (vlist[i]);
+
+             free (vlist);
+           }
+       }
+      else if (pflag && (flags_on == 0 || flags_on == att_function))
+       show_all_var_attributes (flags_on == 0, nodefs);
+      else if (flags_on == 0)
+       return (set_builtin ((WORD_LIST *)NULL));
+      else
+       set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
+
+      return (sh_chkwrite (EXECUTION_SUCCESS));
+    }
+
+  if (pflag)   /* declare -p [-aAfFirtx] name [name...] */
+    {
+      for (any_failed = 0; list; list = list->next)
+       {
+         if (flags_on & att_function)
+           pflag = show_func_attributes (list->word->word, nodefs);
+         else
+           pflag = show_name_attributes (list->word->word, nodefs);
+         if (pflag)
+           {
+             sh_notfound (list->word->word);
+             any_failed++;
+           }
+       }
+      return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
+    }
+
+#define NEXT_VARIABLE() free (name); list = list->next; continue
+
+  /* There are arguments left, so we are making variables. */
+  while (list)         /* declare [-aAfFirx] name [name ...] */
+    {
+      char *value, *name;
+      int offset, aflags;
+#if defined (ARRAY_VARS)
+      int making_array_special, compound_array_assign, simple_array_assign;
+#endif
+
+      name = savestring (list->word->word);
+      offset = assignment (name, 0);
+      aflags = 0;
+
+      if (offset)      /* declare [-aAfFirx] name=value */
+       {
+         name[offset] = '\0';
+         value = name + offset + 1;
+         if (name[offset - 1] == '+')
+           {
+             aflags |= ASS_APPEND;
+             name[offset - 1] = '\0';
+           }
+       }
+      else
+       value = "";
+
+      /* Do some lexical error checking on the LHS and RHS of the assignment
+        that is specific to nameref variables. */
+      if (flags_on & att_nameref)
+       {
+#if defined (ARRAY_VARIABLES)
+         if (valid_array_reference (name))
+           {
+             builtin_error (_("%s: reference variable cannot be an array"), name);
+             assign_error++;
+             NEXT_VARIABLE ();
+           }
+         else
+#endif
+         /* disallow self references at global scope */
+         if (STREQ (name, value) && variable_context == 0)
+           {
+             builtin_error (_("%s: nameref variable self references not allowed"), name);
+             assign_error++;
+             NEXT_VARIABLE ();
+           }
+       }
+
+#if defined (ARRAY_VARS)
+      compound_array_assign = simple_array_assign = 0;
+      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;
+       }
+      else
+       making_array_special = 0;
+#endif
+
+      /* If we're in posix mode or not looking for a shell function (since
+        shell function names don't have to be valid identifiers when the
+        shell's not in posix mode), check whether or not the argument is a
+        valid, well-formed shell identifier. */
+      if ((posixly_correct || (flags_on & att_function) == 0) && legal_identifier (name) == 0)
+       {
+         sh_invalidid (name);
+         assign_error++;
+         NEXT_VARIABLE ();
+       }
+
+      /* If VARIABLE_CONTEXT has a non-zero value, then we are executing
+        inside of a function.  This means we should make local variables,
+        not global ones. */
+
+      /* XXX - this has consequences when we're making a local copy of a
+              variable that was in the temporary environment.  Watch out
+              for this. */
+      refvar = (SHELL_VAR *)NULL;
+      if (variable_context && mkglobal == 0 && ((flags_on & att_function) == 0))
+       {
+#if defined (ARRAY_VARS)
+         if (flags_on & att_assoc)
+           var = make_local_assoc_variable (name);
+         else if ((flags_on & att_array) || making_array_special)
+           var = make_local_array_variable (name, making_array_special);
+         else
+#endif
+           var = make_local_variable (name);   /* sets att_invisible for new vars */
+         if (var == 0)
+           {
+             any_failed++;
+             NEXT_VARIABLE ();
+           }
+       }
+      else
+       var = (SHELL_VAR *)NULL;
+
+      /* If we are declaring a function, then complain about it in some way.
+        We don't let people make functions by saying `typeset -f foo=bar'. */
+
+      /* There should be a way, however, to let people look at a particular
+        function definition by saying `typeset -f foo'. */
+
+      if (flags_on & att_function)
+       {
+         if (offset)   /* declare -f [-rix] foo=bar */
+           {
+             builtin_error (_("cannot use `-f' to make functions"));
+             free (name);
+             return (EXECUTION_FAILURE);
+           }
+         else          /* declare -f [-rx] name [name...] */
+           {
+             var = find_function (name);
+
+             if (var)
+               {
+                 if (readonly_p (var) && (flags_off & att_readonly))
+                   {
+                     builtin_error (_("%s: readonly function"), name);
+                     any_failed++;
+                     NEXT_VARIABLE ();
+                   }
+
+                 /* declare -[Ff] name [name...] */
+                 if (flags_on == att_function && flags_off == 0)
+                   {
+#if defined (DEBUGGER)
+                     if (nodefs && debugging_mode)
+                       {
+                         shell_fn = find_function_def (var->name);
+                         if (shell_fn)
+                           printf ("%s %d %s\n", var->name, shell_fn->line, shell_fn->source_file);
+                         else
+                           printf ("%s\n", var->name);
+                       }
+                     else
+#endif /* DEBUGGER */
+                       {       
+                         t = nodefs ? var->name
+                                    : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
+                         printf ("%s\n", t);
+                         any_failed = sh_chkwrite (any_failed);
+                       }
+                   }
+                 else          /* declare -[fF] -[rx] name [name...] */
+                   {
+                     VSETATTR (var, flags_on);
+                     VUNSETATTR (var, flags_off);
+                   }
+               }
+             else
+               any_failed++;
+             NEXT_VARIABLE ();
+           }
+       }
+      else             /* declare -[aAirx] name [name...] */
+       {
+         /* Non-null if we just created or fetched a local variable. */
+         /* Here's what ksh93 seems to do.  If we are modifying an existing
+            nameref variable, we don't follow the nameref chain past the last
+            nameref, and we set the nameref variable's value so future
+            references to that variable will return the value of the variable
+            we're assigning right now. */
+         if (var == 0 && (flags_on & att_nameref))
+           {
+             /* See if we are trying to modify an existing nameref variable */
+             var = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
+             if (var && nameref_p (var) == 0)
+               var = 0;
+           }
+         /* However, if we're turning off the nameref attribute on an existing
+            nameref variable, we first follow the nameref chain to the end,
+            modify the value of the variable this nameref variable references,
+            *CHANGING ITS VALUE AS A SIDE EFFECT* then turn off the nameref
+            flag *LEAVING THE NAMEREF VARIABLE'S VALUE UNCHANGED* */
+         else if (var == 0 && (flags_off & att_nameref))
+           {
+             /* See if we are trying to modify an existing nameref variable */
+             refvar = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
+             if (refvar && nameref_p (refvar) == 0)
+               refvar = 0;
+             if (refvar)
+               var = mkglobal ? find_global_variable (nameref_cell (refvar)) : find_variable (nameref_cell (refvar));
+           }
+       
+         if (var == 0)
+           var = mkglobal ? find_global_variable (name) : find_variable (name);
+
+         if (var == 0)
+           {
+#if defined (ARRAY_VARS)
+             if (flags_on & att_assoc)
+               {
+                 var = make_new_assoc_variable (name);
+                 if (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)
+                   VSETATTR (var, att_invisible);
+               }
+             else
+#endif
+
+             if (offset)
+               var = mkglobal ? bind_global_variable (name, "", 0) : bind_variable (name, "", 0);
+             else
+               {
+                 var = mkglobal ? bind_global_variable (name, (char *)NULL, 0) : bind_variable (name, (char *)NULL, 0);
+                 if (no_invisible_vars == 0)
+                   VSETATTR (var, att_invisible);
+               }
+           }
+         /* Can't take an existing array variable and make it a nameref */
+         else if ((array_p (var) || assoc_p (var)) && (flags_on & att_nameref))
+           {
+             builtin_error (_("%s: reference variable cannot be an array"), name);
+             assign_error++;
+             NEXT_VARIABLE ();
+           }
+         else if (flags_on & att_nameref)
+           {
+             /* ksh93 compat: turning on nameref attribute turns off -ilu */
+             VUNSETATTR (var, att_integer|att_uppercase|att_lowercase|att_capcase);
+           }
+
+         /* Cannot use declare +r to turn off readonly attribute. */ 
+         if (readonly_p (var) && (flags_off & att_readonly))
+           {
+             sh_readonly (name);
+             any_failed++;
+             NEXT_VARIABLE ();
+           }
+
+         /* Cannot use declare to assign value to readonly or noassign
+            variable. */
+         if ((readonly_p (var) || noassign_p (var)) && offset)
+           {
+             if (readonly_p (var))
+               sh_readonly (name);
+             assign_error++;
+             NEXT_VARIABLE ();
+           }
+
+#if defined (ARRAY_VARS)
+         if ((making_array_special || (flags_on & (att_array|att_assoc)) || array_p (var) || assoc_p (var)) && offset)
+           {
+             int vlen;
+             vlen = STRLEN (value);
+
+             if (value[0] == '(' && value[vlen-1] == ')')
+               compound_array_assign = 1;
+             else
+               simple_array_assign = 1;
+           }
+
+         /* Cannot use declare +a name or declare +A name to remove an
+            array variable. */
+         if (((flags_off & att_array) && array_p (var)) || ((flags_off & att_assoc) && assoc_p (var)))
+           {
+             builtin_error (_("%s: cannot destroy array variables in this way"), name);
+             any_failed++;
+             NEXT_VARIABLE ();
+           }
+
+         if ((flags_on & att_array) && assoc_p (var))
+           {
+             builtin_error (_("%s: cannot convert associative to indexed array"), name);
+             any_failed++;
+             NEXT_VARIABLE ();
+           }
+         if ((flags_on & att_assoc) && array_p (var))
+           {
+             builtin_error (_("%s: cannot convert indexed to associative array"), name);
+             any_failed++;
+             NEXT_VARIABLE ();
+           }
+
+         /* declare -A name[[n]] makes name an associative array variable. */
+         if (flags_on & att_assoc)
+           {
+             if (assoc_p (var) == 0)
+               var = convert_var_to_assoc (var);
+           }
+         /* 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 && assoc_p (var) == 0)
+           var = convert_var_to_array (var);
+#endif /* ARRAY_VARS */
+
+         /* XXX - we note that we are turning on nameref attribute and defer
+            setting it until the assignment has been made so we don't do an
+            inadvertent nameref lookup.  Might have to do the same thing for
+            flags_off&att_nameref. */
+         /* XXX - ksh93 makes it an error to set a readonly nameref variable
+            using a single typeset command. */
+         onref = (flags_on & att_nameref);
+         flags_on &= ~att_nameref;
+#if defined (ARRAY_VARS)
+         if (array_p (var) || assoc_p (var)
+               || (offset && compound_array_assign)
+               || simple_array_assign)
+           onref = 0;          /* array variables may not be namerefs */
+#endif
+
+         /* ksh93 seems to do this */
+         offref = (flags_off & att_nameref);
+         flags_off &= ~att_nameref;
+
+         VSETATTR (var, flags_on);
+         VUNSETATTR (var, flags_off);
+
+#if defined (ARRAY_VARS)
+         if (offset && compound_array_assign)
+           assign_array_var_from_string (var, value, aflags);
+         else if (simple_array_assign && subscript_start)
+           {
+             /* declare [-aA] name[N]=value */
+             *subscript_start = '[';   /* ] */
+             var = assign_array_element (name, value, 0);      /* XXX - not aflags */
+             *subscript_start = '\0';
+             if (var == 0)     /* some kind of assignment error */
+               {
+                 assign_error++;
+                 flags_on |= onref;
+                 flags_off |= offref;
+                 NEXT_VARIABLE ();
+               }
+           }
+         else if (simple_array_assign)
+           {
+             /* let bind_{array,assoc}_variable take care of this. */
+             if (assoc_p (var))
+               bind_assoc_variable (var, name, savestring ("0"), value, aflags);
+             else
+               bind_array_variable (name, 0, value, aflags);
+           }
+         else
+#endif
+         /* bind_variable_value duplicates the essential internals of
+            bind_variable() */
+         if (offset)
+           {
+             if (onref)
+               aflags |= ASS_NAMEREF;
+             v = bind_variable_value (var, value, aflags);
+             if (v == 0 && onref)
+               {
+                 sh_invalidid (value);
+                 assign_error++;
+                 /* XXX - unset this variable? or leave it as normal var? */
+                 delete_var (var->name, mkglobal ? global_variables : shell_variables);
+                 NEXT_VARIABLE ();
+               }
+           }
+
+         /* If we found this variable in the temporary environment, as with
+            `var=value declare -x var', make sure it is treated identically
+            to `var=value export var'.  Do the same for `declare -r' and
+            `readonly'.  Preserve the attributes, except for att_tempvar. */
+         /* XXX -- should this create a variable in the global scope, or
+            modify the local variable flags?  ksh93 has it modify the
+            global scope.
+            Need to handle case like in set_var_attribute where a temporary
+            variable is in the same table as the function local vars. */
+         if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
+           {
+             SHELL_VAR *tv;
+             char *tvalue;
+
+             tv = find_tempenv_variable (var->name);
+             if (tv)
+               {
+                 tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
+                 tv = bind_variable (var->name, tvalue, 0);
+                 tv->attributes |= var->attributes & ~att_tempvar;
+                 if (tv->context > 0)
+                   VSETATTR (tv, att_propagate);
+                 free (tvalue);
+               }
+             VSETATTR (var, att_propagate);
+           }
+       }
+
+      /* Turn on nameref attribute we deferred above. */
+      /* XXX - should we turn on the noassign attribute for consistency with
+        ksh93 when we turn on the nameref attribute? */
+      VSETATTR (var, onref);
+      flags_on |= onref;
+      VUNSETATTR (var, offref);
+      flags_off |= offref;
+      /* Yuck.  ksh93 compatibility */
+      if (refvar)
+       VUNSETATTR (refvar, flags_off);
+
+      stupidly_hack_special_variables (name);
+
+      NEXT_VARIABLE ();
+    }
+
+  return (assign_error ? EX_BADASSIGN
+                      : ((any_failed == 0) ? EXECUTION_SUCCESS
+                                           : EXECUTION_FAILURE));
+}
index 3be31896ef272f8e4fbac76acaa4bfc0b68a164e..ba23ac4d2dfe35e8265cbce882aa1de5923345c2 100644 (file)
@@ -34,6 +34,7 @@ $PRODUCES setattr.c
 #include "../bashintl.h"
 
 #include "../shell.h"
+#include "../flags.h"
 #include "common.h"
 #include "bashgetopt.h"
 
@@ -536,7 +537,8 @@ set_var_attribute (name, attribute, undo)
          if (var == 0)
            {
              var = bind_variable (name, (char *)NULL, 0);
-             VSETATTR (var, att_invisible);
+             if (no_invisible_vars == 0)
+               VSETATTR (var, att_invisible);
            }
          else if (var->context != 0)
            VSETATTR (var, att_propagate);
diff --git a/builtins/setattr.def~ b/builtins/setattr.def~
new file mode 100644 (file)
index 0000000..0fd3c01
--- /dev/null
@@ -0,0 +1,552 @@
+This file is setattr.def, from which is created setattr.c.
+It implements the builtins "export" and "readonly", in Bash.
+
+Copyright (C) 1987-2012 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Bash is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+
+$PRODUCES setattr.c
+
+#include <config.h>
+
+#if defined (HAVE_UNISTD_H)
+#  ifdef _MINIX
+#    include <sys/types.h>
+#  endif
+#  include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include "../bashansi.h"
+#include "../bashintl.h"
+
+#include "../shell.h"
+#include "common.h"
+#include "bashgetopt.h"
+
+extern int posixly_correct;
+extern int array_needs_making;
+extern char *this_command_name;
+extern sh_builtin_func_t *this_shell_builtin;
+
+#ifdef ARRAY_VARS
+extern int declare_builtin __P((WORD_LIST *));
+#endif
+
+#define READONLY_OR_EXPORT \
+  (this_shell_builtin == readonly_builtin || this_shell_builtin == export_builtin)
+
+$BUILTIN export
+$FUNCTION export_builtin
+$SHORT_DOC export [-fn] [name[=value] ...] or export -p
+Set export attribute for shell variables.
+
+Marks each NAME for automatic export to the environment of subsequently
+executed commands.  If VALUE is supplied, assign VALUE before exporting.
+
+Options:
+  -f   refer to shell functions
+  -n   remove the export property from each NAME
+  -p   display a list of all exported variables and functions
+
+An argument of `--' disables further option processing.
+
+Exit Status:
+Returns success unless an invalid option is given or NAME is invalid.
+$END
+
+/* For each variable name in LIST, make that variable appear in the
+   environment passed to simple commands.  If there is no LIST, then
+   print all such variables.  An argument of `-n' says to remove the
+   exported attribute from variables named in LIST.  An argument of
+  -f indicates that the names present in LIST refer to functions. */
+int
+export_builtin (list)
+     register WORD_LIST *list;
+{
+  return (set_or_show_attributes (list, att_exported, 0));
+}
+
+$BUILTIN readonly
+$FUNCTION readonly_builtin
+$SHORT_DOC readonly [-aAf] [name[=value] ...] or readonly -p
+Mark shell variables as unchangeable.
+
+Mark each NAME as read-only; the values of these NAMEs may not be
+changed by subsequent assignment.  If VALUE is supplied, assign VALUE
+before marking as read-only.
+
+Options:
+  -a   refer to indexed array variables
+  -A   refer to associative array variables
+  -f   refer to shell functions
+  -p   display a list of all readonly variables or functions, depending on
+        whether or not the -f option is given
+
+An argument of `--' disables further option processing.
+
+Exit Status:
+Returns success unless an invalid option is given or NAME is invalid.
+$END
+
+/* For each variable name in LIST, make that variable readonly.  Given an
+   empty LIST, print out all existing readonly variables. */
+int
+readonly_builtin (list)
+     register WORD_LIST *list;
+{
+  return (set_or_show_attributes (list, att_readonly, 0));
+}
+
+#if defined (ARRAY_VARS)
+#  define ATTROPTS     "aAfnp"
+#else
+#  define ATTROPTS     "fnp"
+#endif
+
+/* For each variable name in LIST, make that variable have the specified
+   ATTRIBUTE.  An arg of `-n' says to remove the attribute from the the
+   remaining names in LIST (doesn't work for readonly). */
+int
+set_or_show_attributes (list, attribute, nodefs)
+     register WORD_LIST *list;
+     int attribute, nodefs;
+{
+  register SHELL_VAR *var;
+  int assign, undo, any_failed, assign_error, opt;
+  int functions_only, arrays_only, assoc_only;
+  int aflags;
+  char *name;
+#if defined (ARRAY_VARS)
+  WORD_LIST *nlist, *tlist;
+  WORD_DESC *w;
+#endif
+
+  functions_only = arrays_only = assoc_only = 0;
+  undo = any_failed = assign_error = 0;
+  /* Read arguments from the front of the list. */
+  reset_internal_getopt ();
+  while ((opt = internal_getopt (list, ATTROPTS)) != -1)
+    {
+      switch (opt)
+       {
+         case 'n':
+           undo = 1;
+           break;
+         case 'f':
+           functions_only = 1;
+           break;
+#if defined (ARRAY_VARS)
+         case 'a':
+           arrays_only = 1;
+           break;
+         case 'A':
+           assoc_only = 1;
+           break;
+#endif
+         case 'p':
+           break;
+         default:
+           builtin_usage ();
+           return (EX_USAGE);
+       }
+    }
+  list = loptend;
+
+  if (list)
+    {
+      if (attribute & att_exported)
+       array_needs_making = 1;
+
+      /* Cannot undo readonly status, silently disallowed. */
+      if (undo && (attribute & att_readonly))
+       attribute &= ~att_readonly;
+
+      while (list)
+       {
+         name = list->word->word;
+
+         if (functions_only)           /* xxx -f name */
+           {
+             var = find_function (name);
+             if (var == 0)
+               {
+                 builtin_error (_("%s: not a function"), name);
+                 any_failed++;
+               }
+             else
+               SETVARATTR (var, attribute, undo);
+
+             list = list->next;
+             continue;
+           }
+
+         /* xxx [-np] name[=value] */
+         assign = assignment (name, 0);
+
+         aflags = 0;
+         if (assign)
+           {
+             name[assign] = '\0';
+             if (name[assign - 1] == '+')
+               {
+                 aflags |= ASS_APPEND;
+                 name[assign - 1] = '\0';
+               }
+           }
+
+         if (legal_identifier (name) == 0)
+           {
+             sh_invalidid (name);
+             if (assign)
+               assign_error++;
+             else
+               any_failed++;
+             list = list->next;
+             continue;
+           }
+
+         if (assign)   /* xxx [-np] name=value */
+           {
+             name[assign] = '=';
+             if (aflags & ASS_APPEND)
+               name[assign - 1] = '+';
+#if defined (ARRAY_VARS)
+             /* Let's try something here.  Turn readonly -a xxx=yyy into
+                declare -ra xxx=yyy and see what that gets us. */
+             if (arrays_only || assoc_only)
+               {
+                 tlist = list->next;
+                 list->next = (WORD_LIST *)NULL;
+                 w = arrays_only ? make_word ("-ra") : make_word ("-rA");
+                 nlist = make_word_list (w, list);
+                 opt = declare_builtin (nlist);
+                 if (opt != EXECUTION_SUCCESS)
+                   assign_error++;
+                 list->next = tlist;
+                 dispose_word (w);
+                 free (nlist);
+               }
+             else
+#endif
+             /* This word has already been expanded once with command
+                and parameter expansion.  Call do_assignment_no_expand (),
+                which does not do command or parameter substitution.  If
+                the assignment is not performed correctly, flag an error. */
+             if (do_assignment_no_expand (name) == 0)
+               assign_error++;
+             name[assign] = '\0';
+             if (aflags & ASS_APPEND)
+               name[assign - 1] = '\0';
+           }
+
+         set_var_attribute (name, attribute, undo);
+         list = list->next;
+       }
+    }
+  else
+    {
+      SHELL_VAR **variable_list;
+      register int i;
+
+      if ((attribute & att_function) || functions_only)
+       {
+         variable_list = all_shell_functions ();
+         if (attribute != att_function)
+           attribute &= ~att_function; /* so declare -xf works, for example */
+       }
+      else
+       variable_list = all_shell_variables ();
+
+#if defined (ARRAY_VARS)
+      if (attribute & att_array)
+       {
+         arrays_only++;
+         if (attribute != att_array)
+           attribute &= ~att_array;
+       }
+      else if (attribute & att_assoc)
+       {
+         assoc_only++;
+         if (attribute != att_assoc)
+           attribute &= ~att_assoc;
+       }
+#endif
+
+      if (variable_list)
+       {
+         for (i = 0; var = variable_list[i]; i++)
+           {
+#if defined (ARRAY_VARS)
+             if (arrays_only && array_p (var) == 0)
+               continue;
+             else if (assoc_only && assoc_p (var) == 0)
+               continue;
+#endif
+             if ((var->attributes & attribute))
+               {
+                 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
+                 if (any_failed = sh_chkwrite (any_failed))
+                   break;
+               }
+           }
+         free (variable_list);
+       }
+    }
+
+  return (assign_error ? EX_BADASSIGN
+                      : ((any_failed == 0) ? EXECUTION_SUCCESS
+                                           : EXECUTION_FAILURE));
+}
+
+/* Show all variable variables (v == 1) or functions (v == 0) with
+   attributes. */
+int
+show_all_var_attributes (v, nodefs)
+     int v, nodefs;
+{
+  SHELL_VAR **variable_list, *var;
+  int any_failed;
+  register int i;
+
+  variable_list = v ? all_shell_variables () : all_shell_functions ();
+  if (variable_list == 0)  
+    return (EXECUTION_SUCCESS);
+
+  for (i = any_failed = 0; var = variable_list[i]; i++)
+    {
+      show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
+      if (any_failed = sh_chkwrite (any_failed))
+        break;
+    }
+  free (variable_list);
+  return (any_failed == 0 ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
+}
+
+/* Show the attributes for shell variable VAR.  If NODEFS is non-zero,
+   don't show function definitions along with the name.  If PATTR is
+   non-zero, it indicates we're being called from `export' or `readonly'.
+   In POSIX mode, this prints the name of the calling builtin (`export'
+   or `readonly') instead of `declare', and doesn't print function defs
+   when called by `export' or `readonly'. */
+int
+show_var_attributes (var, pattr, nodefs)
+     SHELL_VAR *var;
+     int pattr, nodefs;
+{
+  char flags[16], *x;
+  int i;
+
+  i = 0;
+
+  /* pattr == 0 means we are called from `declare'. */
+  if (pattr == 0 || posixly_correct == 0)
+    {
+#if defined (ARRAY_VARS)
+      if (array_p (var))
+       flags[i++] = 'a';
+
+      if (assoc_p (var))
+       flags[i++] = 'A';
+#endif
+
+      if (function_p (var))
+       flags[i++] = 'f';
+
+      if (integer_p (var))
+       flags[i++] = 'i';
+
+      if (nameref_p (var))
+       flags[i++] = 'n';
+
+      if (readonly_p (var))
+       flags[i++] = 'r';
+
+      if (trace_p (var))
+       flags[i++] = 't';
+
+      if (exported_p (var))
+       flags[i++] = 'x';
+
+      if (capcase_p (var))
+       flags[i++] = 'c';
+
+      if (lowercase_p (var))
+       flags[i++] = 'l';
+
+      if (uppercase_p (var))
+       flags[i++] = 'u';
+    }
+  else
+    {
+#if defined (ARRAY_VARS)
+      if (array_p (var))
+       flags[i++] = 'a';
+
+      if (assoc_p (var))
+       flags[i++] = 'A';
+#endif
+
+      if (function_p (var))
+       flags[i++] = 'f';
+    }
+
+  flags[i] = '\0';
+
+  /* If we're printing functions with definitions, print the function def
+     first, then the attributes, instead of printing output that can't be
+     reused as input to recreate the current state. */
+  if (function_p (var) && nodefs == 0 && (pattr == 0 || posixly_correct == 0))
+    {
+      printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
+      nodefs++;
+      if (pattr == 0 && i == 1 && flags[0] == 'f')
+       return 0;               /* don't print `declare -f name' */
+    }
+
+  if (pattr == 0 || posixly_correct == 0)
+    printf ("declare -%s ", i ? flags : "-");
+  else if (i)
+    printf ("%s -%s ", this_command_name, flags);
+  else
+    printf ("%s ", this_command_name);
+
+#if defined (ARRAY_VARS)
+  if (array_p (var))
+    print_array_assignment (var, 1);
+  else if (assoc_p (var))
+    print_assoc_assignment (var, 1);
+  else
+#endif
+  /* force `readonly' and `export' to not print out function definitions
+     when in POSIX mode. */
+  if (nodefs || (function_p (var) && pattr != 0 && posixly_correct))
+    printf ("%s\n", var->name);
+  else if (function_p (var))
+    printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
+  else if (invisible_p (var) || var_isset (var) == 0)
+    printf ("%s\n", var->name);
+  else
+    {
+      x = sh_double_quote (value_cell (var));
+      printf ("%s=%s\n", var->name, x);
+      free (x);
+    }
+  return (0);
+}
+
+int
+show_name_attributes (name, nodefs)
+     char *name;
+     int nodefs;
+{
+  SHELL_VAR *var;
+
+#if 0
+  var = find_variable_tempenv (name);
+#else
+  var = find_variable_noref (name);
+#endif
+
+  if (var && invisible_p (var) == 0)
+    {
+      show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
+      return (0);
+    }
+  else
+    return (1);
+}
+
+int
+show_func_attributes (name, nodefs)
+     char *name;
+     int nodefs;
+{
+  SHELL_VAR *var;
+
+  var = find_function (name);
+
+  if (var)
+    {
+      show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
+      return (0);
+    }
+  else
+    return (1);
+}
+
+void
+set_var_attribute (name, attribute, undo)
+     char *name;
+     int attribute, undo;
+{
+  SHELL_VAR *var, *tv, *v;
+  char *tvalue;
+
+  if (undo)
+    var = find_variable (name);
+  else
+    {
+      tv = find_tempenv_variable (name);
+      /* XXX -- need to handle case where tv is a temp variable in a
+        function-scope context, since function_env has been merged into
+        the local variables table. */
+      if (tv && tempvar_p (tv))
+       {
+         tvalue = var_isset (tv) ? savestring (value_cell (tv)) : savestring ("");
+
+         var = bind_variable (tv->name, tvalue, 0);
+         var->attributes |= tv->attributes & ~att_tempvar;
+         /* This avoids an error message when propagating a read-only var
+            later on. */
+         if (var->context == 0 && (attribute & att_readonly))
+           {
+             /* Don't bother to set the `propagate to the global variables
+                table' flag if we've just bound the variable in that table */
+             v = find_global_variable (tv->name);
+             if (v != var)
+               VSETATTR (tv, att_propagate);
+           }
+         else
+           VSETATTR (tv, att_propagate);
+         if (var->context != 0)
+           VSETATTR (var, att_propagate);
+         SETVARATTR (tv, attribute, undo);     /* XXX */
+
+         stupidly_hack_special_variables (tv->name);
+
+         free (tvalue);
+       }
+      else
+       {
+         var = find_variable_notempenv (name);
+         if (var == 0)
+           {
+             var = bind_variable (name, (char *)NULL, 0);
+             if (no_invisible_vars == 0)
+               VSETATTR (var, att_invisible);
+           }
+         else if (var->context != 0)
+           VSETATTR (var, att_propagate);
+       }
+    }
+
+  if (var)
+    SETVARATTR (var, attribute, undo);
+
+  if (var && (exported_p (var) || (attribute & att_exported)))
+    array_needs_making++;      /* XXX */
+}
index c3b29b563cac3c7b4a280e8290c93a8e134bfa2a..93ec99f00a46e2f049a8a89f2eb631e90db33918 100644 (file)
@@ -532,7 +532,9 @@ S\bSH\bHE\bEL\bLL\bL G\bGR\bRA\bAM\bMM\bMA\bAR\bR
               parentheses are optional.  The _\bb_\bo_\bd_\by of the function is the  com-
               pound  command  _\bc_\bo_\bm_\bp_\bo_\bu_\bn_\bd_\b-_\bc_\bo_\bm_\bm_\ba_\bn_\bd  (see C\bCo\bom\bmp\bpo\bou\bun\bnd\bd C\bCo\bom\bmm\bma\ban\bnd\bds\bs above).
               That command is usually a _\bl_\bi_\bs_\bt of commands between { and },  but
-              may  be  any command listed under C\bCo\bom\bmp\bpo\bou\bun\bnd\bd C\bCo\bom\bmm\bma\ban\bnd\bds\bs above.  _\bc_\bo_\bm_\b-
+              may  be  any  command listed under C\bCo\bom\bmp\bpo\bou\bun\bnd\bd C\bCo\bom\bmm\bma\ban\bnd\bds\bs above, with
+              one exception: If the f\bfu\bun\bnc\bct\bti\bio\bon\bn reserved word is  used,  but  the
+              parentheses  are  not  supplied,  the braces are required.  _\bc_\bo_\bm_\b-
               _\bp_\bo_\bu_\bn_\bd_\b-_\bc_\bo_\bm_\bm_\ba_\bn_\bd is executed whenever _\bn_\ba_\bm_\be is specified as the name
               of  a  simple  command.  When in _\bp_\bo_\bs_\bi_\bx _\bm_\bo_\bd_\be, _\bn_\ba_\bm_\be may not be the
               name of one of the POSIX  _\bs_\bp_\be_\bc_\bi_\ba_\bl  _\bb_\bu_\bi_\bl_\bt_\bi_\bn_\bs.   Any  redirections
@@ -2150,10 +2152,10 @@ A\bAL\bLI\bIA\bAS\bSE\bES\bS
        alias.  This behavior is also an issue  when  functions  are  executed.
        Aliases  are  expanded when a function definition is read, not when the
        function is executed, because a function definition is  itself  a  com-
-       pound command.  As a consequence, aliases defined in a function are not
-       available until after that function is executed.  To  be  safe,  always
-       put  alias definitions on a separate line, and do not use a\bal\bli\bia\bas\bs in com-
-       pound commands.
+       mand.   As  a consequence, aliases defined in a function are not avail-
+       able until after that function is executed.  To  be  safe,  always  put
+       alias  definitions on a separate line, and do not use a\bal\bli\bia\bas\bs in compound
+       commands.
 
        For almost every purpose, aliases are superseded by shell functions.
 
@@ -2583,138 +2585,139 @@ E\bEX\bXI\bIT\bT S\bST\bTA\bAT\bTU\bUS\bS
 
        Shell builtin commands return a status of 0 (_\bt_\br_\bu_\be) if  successful,  and
        non-zero  (_\bf_\ba_\bl_\bs_\be)  if an error occurs while they execute.  All builtins
-       return an exit status of 2 to indicate incorrect usage.
+       return an exit status of  2  to  indicate  incorrect  usage,  generally
+       invalid options or missing arguments.
 
-       B\bBa\bas\bsh\bitself returns the exit  status  of  the  last  command  executed,
-       unless  a  syntax  error occurs, in which case it exits with a non-zero
+       B\bBa\bas\bsh\b itself  returns  the  exit  status  of the last command executed,
+       unless a syntax error occurs, in which case it exits  with  a  non-zero
        value.  See also the e\bex\bxi\bit\bt builtin command below.
 
 S\bSI\bIG\bGN\bNA\bAL\bLS\bS
-       When b\bba\bas\bsh\bh is interactive, in the  absence  of  any  traps,  it  ignores
+       When  b\bba\bas\bsh\bh  is  interactive,  in  the  absence of any traps, it ignores
        S\bSI\bIG\bGT\bTE\bER\bRM\bM (so that k\bki\bil\bll\bl 0\b0 does not kill an interactive shell), and S\bSI\bIG\bGI\bIN\bNT\bT
-       is caught and handled (so that the w\bwa\bai\bit\bt builtin is interruptible).   In
-       all  cases,  b\bba\bas\bsh\bh  ignores  S\bSI\bIG\bGQ\bQU\bUI\bIT\bT.  If job control is in effect, b\bba\bas\bsh\bh
+       is  caught and handled (so that the w\bwa\bai\bit\bt builtin is interruptible).  In
+       all cases, b\bba\bas\bsh\bh ignores S\bSI\bIG\bGQ\bQU\bUI\bIT\bT.  If job control  is  in  effect,  b\bba\bas\bsh\bh
        ignores S\bSI\bIG\bGT\bTT\bTI\bIN\bN, S\bSI\bIG\bGT\bTT\bTO\bOU\bU, and S\bSI\bIG\bGT\bTS\bST\bTP\bP.
 
        Non-builtin commands run by b\bba\bas\bsh\bh have signal handlers set to the values
-       inherited  by  the  shell  from its parent.  When job control is not in
-       effect, asynchronous commands ignore S\bSI\bIG\bGI\bIN\bNT\bT and S\bSI\bIG\bGQ\bQU\bUI\bIT\bT in addition  to
-       these  inherited handlers.  Commands run as a result of command substi-
+       inherited by the shell from its parent.  When job  control  is  not  in
+       effect,  asynchronous commands ignore S\bSI\bIG\bGI\bIN\bNT\bT and S\bSI\bIG\bGQ\bQU\bUI\bIT\bT in addition to
+       these inherited handlers.  Commands run as a result of command  substi-
        tution ignore the keyboard-generated job control signals S\bSI\bIG\bGT\bTT\bTI\bIN\bN, S\bSI\bIG\bGT\bT-\b-
        T\bTO\bOU\bU, and S\bSI\bIG\bGT\bTS\bST\bTP\bP.
 
-       The  shell  exits by default upon receipt of a S\bSI\bIG\bGH\bHU\bUP\bP.  Before exiting,
-       an interactive shell  resends  the  S\bSI\bIG\bGH\bHU\bUP\bP  to  all  jobs,  running  or
+       The shell exits by default upon receipt of a S\bSI\bIG\bGH\bHU\bUP\bP.   Before  exiting,
+       an  interactive  shell  resends  the  S\bSI\bIG\bGH\bHU\bUP\bP  to  all  jobs, running or
        stopped.  Stopped jobs are sent S\bSI\bIG\bGC\bCO\bON\bNT\bT to ensure that they receive the
-       S\bSI\bIG\bGH\bHU\bUP\bP.  To prevent the shell from sending the signal to  a  particular
-       job,  it  should be removed from the jobs table with the d\bdi\bis\bso\bow\bwn\bn builtin
-       (see S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS below) or  marked  to  not  receive  S\bSI\bIG\bGH\bHU\bUP\bP
+       S\bSI\bIG\bGH\bHU\bUP\bP.   To  prevent the shell from sending the signal to a particular
+       job, it should be removed from the jobs table with the  d\bdi\bis\bso\bow\bwn\b builtin
+       (see  S\bSH\bHE\bEL\bLL\bL  B\bBU\bUI\bIL\bLT\bTI\bIN\bN  C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS  below)  or marked to not receive S\bSI\bIG\bGH\bHU\bUP\bP
        using d\bdi\bis\bso\bow\bwn\bn -\b-h\bh.
 
-       If  the  h\bhu\bup\bpo\bon\bne\bex\bxi\bit\bt  shell  option has been set with s\bsh\bho\bop\bpt\bt, b\bba\bas\bsh\bh sends a
+       If the h\bhu\bup\bpo\bon\bne\bex\bxi\bit\bt shell option has been set with  s\bsh\bho\bop\bpt\bt,  b\bba\bas\bsh\bh  sends  a
        S\bSI\bIG\bGH\bHU\bUP\bP to all jobs when an interactive login shell exits.
 
-       If b\bba\bas\bsh\bh is waiting for a command to complete and receives a signal  for
+       If  b\bba\bas\bsh\bh is waiting for a command to complete and receives a signal for
        which a trap has been set, the trap will not be executed until the com-
-       mand completes.  When b\bba\bas\bsh\bh is waiting for an asynchronous  command  via
-       the  w\bwa\bai\bit\bt  builtin, the reception of a signal for which a trap has been
+       mand  completes.   When b\bba\bas\bsh\bh is waiting for an asynchronous command via
+       the w\bwa\bai\bit\bt builtin, the reception of a signal for which a trap  has  been
        set will cause the w\bwa\bai\bit\bt builtin to return immediately with an exit sta-
        tus greater than 128, immediately after which the trap is executed.
 
 J\bJO\bOB\bB C\bCO\bON\bNT\bTR\bRO\bOL\bL
-       _\bJ_\bo_\b _\bc_\bo_\bn_\bt_\br_\bo_\bl  refers  to  the ability to selectively stop (_\bs_\bu_\bs_\bp_\be_\bn_\bd) the
+       _\bJ_\bo_\b_\bc_\bo_\bn_\bt_\br_\bo_\bl refers to the ability to  selectively  stop  (_\bs_\bu_\bs_\bp_\be_\bn_\bd)  the
        execution of processes and continue (_\br_\be_\bs_\bu_\bm_\be) their execution at a later
-       point.   A  user  typically  employs  this  facility via an interactive
-       interface supplied jointly by the operating  system  kernel's  terminal
+       point.  A user typically  employs  this  facility  via  an  interactive
+       interface  supplied  jointly  by the operating system kernel's terminal
        driver and b\bba\bas\bsh\bh.
 
-       The  shell  associates  a  _\bj_\bo_\bb with each pipeline.  It keeps a table of
-       currently executing jobs, which may be listed with  the  j\bjo\bob\bbs\b command.
-       When  b\bba\bas\bsh\bh starts a job asynchronously (in the _\bb_\ba_\bc_\bk_\bg_\br_\bo_\bu_\bn_\bd), it prints a
+       The shell associates a _\bj_\bo_\bb with each pipeline.  It  keeps  a  table  of
+       currently  executing  jobs,  which may be listed with the j\bjo\bob\bbs\bs command.
+       When b\bba\bas\bsh\bh starts a job asynchronously (in the _\bb_\ba_\bc_\bk_\bg_\br_\bo_\bu_\bn_\bd), it prints  a
        line that looks like:
 
               [1] 25647
 
        indicating that this job is job number 1 and that the process ID of the
        last process in the pipeline associated with this job is 25647.  All of
-       the processes in a single pipeline are members of the same  job.   B\bBa\bas\bsh\bh
+       the  processes  in a single pipeline are members of the same job.  B\bBa\bas\bsh\bh
        uses the _\bj_\bo_\bb abstraction as the basis for job control.
 
-       To  facilitate the implementation of the user interface to job control,
+       To facilitate the implementation of the user interface to job  control,
        the operating system maintains the notion of a _\bc_\bu_\br_\br_\be_\bn_\bt _\bt_\be_\br_\bm_\bi_\bn_\ba_\bl _\bp_\br_\bo_\bc_\be_\bs_\bs
        _\bg_\br_\bo_\bu_\bp _\bI_\bD.  Members of this process group (processes whose process group
        ID is equal to the current terminal process group ID) receive keyboard-
-       generated  signals  such  as S\bSI\bIG\bGI\bIN\bNT\bT.  These processes are said to be in
-       the _\bf_\bo_\br_\be_\bg_\br_\bo_\bu_\bn_\bd.  _\bB_\ba_\bc_\bk_\bg_\br_\bo_\bu_\bn_\bd processes are those whose process group  ID
+       generated signals such as S\bSI\bIG\bGI\bIN\bNT\bT.  These processes are said  to  be  in
+       the  _\bf_\bo_\br_\be_\bg_\br_\bo_\bu_\bn_\bd.  _\bB_\ba_\bc_\bk_\bg_\br_\bo_\bu_\bn_\bd processes are those whose process group ID
        differs from the terminal's; such processes are immune to keyboard-gen-
        erated signals.  Only foreground processes are allowed to read from or,
-       if  the  user  so  specifies  with  stty tostop, write to the terminal.
-       Background processes which attempt to read from  (write  to  when  stty
-       tostop  is  in effect) the terminal are sent a S\bSI\bIG\bGT\bTT\bTI\bIN\bN (\b(S\bSI\bIG\bGT\bTT\bTO\bOU\bU)\b) signal
-       by the kernel's terminal driver, which,  unless  caught,  suspends  the
+       if the user so specifies with  stty  tostop,  write  to  the  terminal.
+       Background  processes  which  attempt  to read from (write to when stty
+       tostop is in effect) the terminal are sent a S\bSI\bIG\bGT\bTT\bTI\bIN\bN  (\b(S\bSI\bIG\bGT\bTT\bTO\bOU\bU)\b signal
+       by  the  kernel's  terminal  driver, which, unless caught, suspends the
        process.
 
-       If  the operating system on which b\bba\bas\bsh\bh is running supports job control,
+       If the operating system on which b\bba\bas\bsh\bh is running supports job  control,
        b\bba\bas\bsh\bh contains facilities to use it.  Typing the _\bs_\bu_\bs_\bp_\be_\bn_\bd character (typ-
        ically ^\b^Z\bZ, Control-Z) while a process is running causes that process to
-       be stopped and returns control to b\bba\bas\bsh\bh.   Typing  the  _\bd_\be_\bl_\ba_\by_\be_\b _\bs_\bu_\bs_\bp_\be_\bn_\bd
-       character  (typically  ^\b^Y\bY,  Control-Y) causes the process to be stopped
-       when it attempts to read input from the terminal,  and  control  to  be
-       returned  to b\bba\bas\bsh\bh.  The user may then manipulate the state of this job,
-       using the b\bbg\bg command to continue it in the background, the  f\bfg\b command
+       be  stopped  and  returns  control to b\bba\bas\bsh\bh.  Typing the _\bd_\be_\bl_\ba_\by_\be_\bd _\bs_\bu_\bs_\bp_\be_\bn_\bd
+       character (typically ^\b^Y\bY, Control-Y) causes the process  to  be  stopped
+       when  it  attempts  to  read input from the terminal, and control to be
+       returned to b\bba\bas\bsh\bh.  The user may then manipulate the state of this  job,
+       using  the  b\bbg\bg command to continue it in the background, the f\bfg\bg command
        to continue it in the foreground, or the k\bki\bil\bll\bl command to kill it.  A ^\b^Z\bZ
        takes effect immediately, and has the additional side effect of causing
        pending output and typeahead to be discarded.
 
        There are a number of ways to refer to a job in the shell.  The charac-
-       ter %\b% introduces a job specification (_\bj_\bo_\bb_\bs_\bp_\be_\bc).  Job number  _\bn  may  be
+       ter  %\b%  introduces  a job specification (_\bj_\bo_\bb_\bs_\bp_\be_\bc).  Job number _\bn may be
        referred to as %\b%n\bn.  A job may also be referred to using a prefix of the
        name used to start it, or using a substring that appears in its command
-       line.   For  example,  %\b%c\bce\be  refers  to  a  stopped c\bce\be job.  If a prefix
-       matches more than one job, b\bba\bas\bsh\bh reports an error.  Using %\b%?\b?c\bce\be,  on  the
-       other  hand,  refers to any job containing the string c\bce\be in its command
-       line.  If the substring matches more than  one  job,  b\bba\bas\bsh\bh  reports  an
-       error.   The  symbols %\b%%\b% and %\b%+\b+ refer to the shell's notion of the _\bc_\bu_\br_\b-
-       _\br_\be_\bn_\b_\bj_\bo_\bb, which is the last job stopped while it was in the  foreground
+       line.  For example, %\b%c\bce\be refers to  a  stopped  c\bce\be  job.   If  a  prefix
+       matches  more  than one job, b\bba\bas\bsh\bh reports an error.  Using %\b%?\b?c\bce\be, on the
+       other hand, refers to any job containing the string c\bce\be in  its  command
+       line.   If  the  substring  matches  more than one job, b\bba\bas\bsh\bh reports an
+       error.  The symbols %\b%%\b% and %\b%+\b+ refer to the shell's notion of  the  _\bc_\bu_\br_\b-
+       _\br_\be_\bn_\b _\bj_\bo_\bb, which is the last job stopped while it was in the foreground
        or started in the background.  The _\bp_\br_\be_\bv_\bi_\bo_\bu_\bs _\bj_\bo_\bb may be referenced using
        %\b%-\b-.  If there is only a single job, %\b%+\b+ and %\b%-\b- can both be used to refer
-       to  that  job.   In  output pertaining to jobs (e.g., the output of the
+       to that job.  In output pertaining to jobs (e.g.,  the  output  of  the
        j\bjo\bob\bbs\bs command), the current job is always flagged with a +\b+, and the pre-
-       vious  job  with  a -\b-.  A single % (with no accompanying job specifica-
+       vious job with a -\b-.  A single % (with no  accompanying  job  specifica-
        tion) also refers to the current job.
 
-       Simply naming a job can be used to bring it into the foreground: %\b%1\b is
-       a  synonym  for  `\b``\b`f\bfg\bg %\b%1\b1'\b''\b', bringing job 1 from the background into the
-       foreground.  Similarly, `\b``\b`%\b%1\b1 &\b&'\b''\b'  resumes  job  1  in  the  background,
+       Simply  naming a job can be used to bring it into the foreground: %\b%1\b1 is
+       a synonym for `\b``\b`f\bfg\bg %\b%1\b1'\b''\b', bringing job 1 from the  background  into  the
+       foreground.   Similarly,  `\b``\b`%\b%1\b1  &\b&'\b''\b'  resumes  job  1 in the background,
        equivalent to `\b``\b`b\bbg\bg %\b%1\b1'\b''\b'.
 
-       The  shell  learns immediately whenever a job changes state.  Normally,
+       The shell learns immediately whenever a job changes  state.   Normally,
        b\bba\bas\bsh\bh waits until it is about to print a prompt before reporting changes
-       in  a  job's status so as to not interrupt any other output.  If the -\b-b\bb
+       in a job's status so as to not interrupt any other output.  If  the  -\b-b\bb
        option to the s\bse\bet\bt builtin command is enabled, b\bba\bas\bsh\bh reports such changes
-       immediately.   Any  trap  on  S\bSI\bIG\bGC\bCH\bHL\bLD\bD  is  executed for each child that
+       immediately.  Any trap on S\bSI\bIG\bGC\bCH\bHL\bLD\bD  is  executed  for  each  child  that
        exits.
 
-       If an attempt to exit b\bba\bas\bsh\bh is made while jobs are stopped (or,  if  the
-       c\bch\bhe\bec\bck\bkj\bjo\bob\bbs\b shell  option has been enabled using the s\bsh\bho\bop\bpt\bt builtin, run-
+       If  an  attempt to exit b\bba\bas\bsh\bh is made while jobs are stopped (or, if the
+       c\bch\bhe\bec\bck\bkj\bjo\bob\bbs\bshell option has been enabled using the s\bsh\bho\bop\bpt\bt  builtin,  run-
        ning), the shell prints a warning message, and, if the c\bch\bhe\bec\bck\bkj\bjo\bob\bbs\bs option
-       is  enabled,  lists  the jobs and their statuses.  The j\bjo\bob\bbs\bs command may
-       then be used to inspect their status.  If a second attempt to  exit  is
-       made  without  an intervening command, the shell does not print another
+       is enabled, lists the jobs and their statuses.  The  j\bjo\bob\bbs\bs  command  may
+       then  be  used to inspect their status.  If a second attempt to exit is
+       made without an intervening command, the shell does not  print  another
        warning, and any stopped jobs are terminated.
 
 P\bPR\bRO\bOM\bMP\bPT\bTI\bIN\bNG\bG
        When executing interactively, b\bba\bas\bsh\bh displays the primary prompt P\bPS\bS1\b1 when
-       it  is  ready  to  read a command, and the secondary prompt P\bPS\bS2\b2 when it
-       needs more input to complete  a  command.   B\bBa\bas\bsh\bh  allows  these  prompt
-       strings  to  be  customized  by inserting a number of backslash-escaped
+       it is ready to read a command, and the secondary  prompt  P\bPS\bS2\b2  when  it
+       needs  more  input  to  complete  a  command.  B\bBa\bas\bsh\bh allows these prompt
+       strings to be customized by inserting  a  number  of  backslash-escaped
        special characters that are decoded as follows:
               \\b\a\ba     an ASCII bell character (07)
-              \\b\d\bd     the date in "Weekday Month Date" format (e.g.,  "Tue  May
+              \\b\d\bd     the  date  in "Weekday Month Date" format (e.g., "Tue May
                      26")
               \\b\D\bD{\b{_\bf_\bo_\br_\bm_\ba_\bt}\b}
-                     the  _\bf_\bo_\br_\bm_\ba_\bt  is  passed  to _\bs_\bt_\br_\bf_\bt_\bi_\bm_\be(3) and the result is
-                     inserted into the prompt string; an empty _\bf_\bo_\br_\bm_\ba_\b results
+                     the _\bf_\bo_\br_\bm_\ba_\bt is passed to _\bs_\bt_\br_\bf_\bt_\bi_\bm_\be(3)  and  the  result  is
+                     inserted  into the prompt string; an empty _\bf_\bo_\br_\bm_\ba_\bt results
                      in a locale-specific time representation.  The braces are
                      required
               \\b\e\be     an ASCII escape character (033)
@@ -2724,7 +2727,7 @@ P\bPR\bRO\bOM\bMP\bPT\bTI\bIN\bNG\bG
               \\b\l\bl     the basename of the shell's terminal device name
               \\b\n\bn     newline
               \\b\r\br     carriage return
-              \\b\s\bs     the name of the shell, the basename of  $\b$0\b0  (the  portion
+              \\b\s\bs     the  name  of  the shell, the basename of $\b$0\b0 (the portion
                      following the final slash)
               \\b\t\bt     the current time in 24-hour HH:MM:SS format
               \\b\T\bT     the current time in 12-hour HH:MM:SS format
@@ -2733,8 +2736,8 @@ P\bPR\bRO\bOM\bMP\bPT\bTI\bIN\bNG\bG
               \\b\u\bu     the username of the current user
               \\b\v\bv     the version of b\bba\bas\bsh\bh (e.g., 2.00)
               \\b\V\bV     the release of b\bba\bas\bsh\bh, version + patch level (e.g., 2.00.0)
-              \\b\w\bw     the current working  directory,  with  $\b$H\bHO\bOM\bME\b abbreviated
-                     with  a tilde (uses the value of the P\bPR\bRO\bOM\bMP\bPT\bT_\b_D\bDI\bIR\bRT\bTR\bRI\bIM\bM vari-
+              \\b\w\bw     the  current  working  directory,  with $\b$H\bHO\bOM\bME\bE abbreviated
+                     with a tilde (uses the value of the P\bPR\bRO\bOM\bMP\bPT\bT_\b_D\bDI\bIR\bRT\bTR\bRI\bIM\b vari-
                      able)
               \\b\W\bW     the basename of the current working directory, with $\b$H\bHO\bOM\bME\bE
                      abbreviated with a tilde
@@ -2743,66 +2746,66 @@ P\bPR\bRO\bOM\bMP\bPT\bTI\bIN\bNG\bG
               \\b\$\b$     if the effective UID is 0, a #\b#, otherwise a $\b$
               \\b\_\bn_\bn_\bn   the character corresponding to the octal number _\bn_\bn_\bn
               \\b\\\b\     a backslash
-              \\b\[\b[     begin  a sequence of non-printing characters, which could
-                     be used to embed a terminal  control  sequence  into  the
+              \\b\[\b[     begin a sequence of non-printing characters, which  could
+                     be  used  to  embed  a terminal control sequence into the
                      prompt
               \\b\]\b]     end a sequence of non-printing characters
 
-       The  command  number  and the history number are usually different: the
-       history number of a command is its position in the history list,  which
-       may  include  commands  restored  from  the  history  file (see H\bHI\bIS\bST\bTO\bOR\bRY\bY
-       below), while the command number is the position  in  the  sequence  of
-       commands  executed  during the current shell session.  After the string
-       is decoded, it is expanded via parameter expansion,  command  substitu-
-       tion,  arithmetic expansion, and quote removal, subject to the value of
-       the p\bpr\bro\bom\bmp\bpt\btv\bva\bar\brs\bs shell option (see the description of the  s\bsh\bho\bop\bpt\b command
+       The command number and the history number are  usually  different:  the
+       history  number of a command is its position in the history list, which
+       may include commands  restored  from  the  history  file  (see  H\bHI\bIS\bST\bTO\bOR\bRY\bY
+       below),  while  the  command  number is the position in the sequence of
+       commands executed during the current shell session.  After  the  string
+       is  decoded,  it is expanded via parameter expansion, command substitu-
+       tion, arithmetic expansion, and quote removal, subject to the value  of
+       the  p\bpr\bro\bom\bmp\bpt\btv\bva\bar\brs\bs  shell option (see the description of the s\bsh\bho\bop\bpt\bt command
        under S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS below).
 
 R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE
-       This  is  the library that handles reading input when using an interac-
+       This is the library that handles reading input when using  an  interac-
        tive shell, unless the -\b--\b-n\bno\boe\bed\bdi\bit\bti\bin\bng\bg option is given at shell invocation.
        Line editing is also used when using the -\b-e\be option to the r\bre\bea\bad\bd builtin.
        By default, the line editing commands are similar to those of Emacs.  A
        vi-style line editing interface is also available.  Line editing can be
-       enabled at any time using the -\b-o\bo e\bem\bma\bac\bcs\bs or -\b-o\bo  v\bvi\bi  options  to  the  s\bse\bet\bt
-       builtin  (see  S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS below).  To turn off line editing
-       after the shell is running, use the +\b+o\bo e\bem\bma\bac\bcs\bs or +\b+o\bo v\bvi\bi  options  to  the
+       enabled  at  any  time  using  the -\b-o\bo e\bem\bma\bac\bcs\bs or -\b-o\bo v\bvi\bi options to the s\bse\bet\bt
+       builtin (see S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS below).  To turn off  line  editing
+       after  the  shell  is running, use the +\b+o\bo e\bem\bma\bac\bcs\bs or +\b+o\bo v\bvi\bi options to the
        s\bse\bet\bt builtin.
 
    R\bRe\bea\bad\bdl\bli\bin\bne\be N\bNo\bot\bta\bat\bti\bio\bon\bn
        In this section, the Emacs-style notation is used to denote keystrokes.
-       Control keys are denoted by C-_\bk_\be_\by, e.g., C-n  means  Control-N.   Simi-
-       larly,  _\bm_\be_\bt_\ba  keys are denoted by M-_\bk_\be_\by, so M-x means Meta-X.  (On key-
-       boards without a _\bm_\be_\bt_\ba key, M-_\bx means ESC _\bx, i.e., press the Escape  key
+       Control  keys  are  denoted by C-_\bk_\be_\by, e.g., C-n means Control-N.  Simi-
+       larly, _\bm_\be_\bt_\ba keys are denoted by M-_\bk_\be_\by, so M-x means Meta-X.   (On  key-
+       boards  without a _\bm_\be_\bt_\ba key, M-_\bx means ESC _\bx, i.e., press the Escape key
        then the _\bx key.  This makes ESC the _\bm_\be_\bt_\ba _\bp_\br_\be_\bf_\bi_\bx.  The combination M-C-_\bx
-       means ESC-Control-_\bx, or press the Escape key then hold the Control  key
+       means  ESC-Control-_\bx, or press the Escape key then hold the Control key
        while pressing the _\bx key.)
 
        Readline commands may be given numeric _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs, which normally act as
-       a repeat count.  Sometimes, however, it is the  sign  of  the  argument
-       that  is  significant.   Passing  a negative argument to a command that
-       acts in the forward direction (e.g., k\bki\bil\bll\bl-\b-l\bli\bin\bne\be) causes that command  to
-       act  in  a  backward direction.  Commands whose behavior with arguments
+       a  repeat  count.   Sometimes,  however, it is the sign of the argument
+       that is significant.  Passing a negative argument  to  a  command  that
+       acts  in the forward direction (e.g., k\bki\bil\bll\bl-\b-l\bli\bin\bne\be) causes that command to
+       act in a backward direction.  Commands whose  behavior  with  arguments
        deviates from this are noted below.
 
-       When a command is described as _\bk_\bi_\bl_\bl_\bi_\bn_\bg text, the text deleted is  saved
+       When  a command is described as _\bk_\bi_\bl_\bl_\bi_\bn_\bg text, the text deleted is saved
        for possible future retrieval (_\by_\ba_\bn_\bk_\bi_\bn_\bg).  The killed text is saved in a
        _\bk_\bi_\bl_\bl _\br_\bi_\bn_\bg.  Consecutive kills cause the text to be accumulated into one
        unit, which can be yanked all at once.  Commands which do not kill text
        separate the chunks of text on the kill ring.
 
    R\bRe\bea\bad\bdl\bli\bin\bne\be I\bIn\bni\bit\bti\bia\bal\bli\biz\bza\bat\bti\bio\bon\bn
-       Readline is customized by putting commands in  an  initialization  file
-       (the  _\bi_\bn_\bp_\bu_\bt_\br_\bc  file).  The name of this file is taken from the value of
-       the I\bIN\bNP\bPU\bUT\bTR\bRC\bC variable.  If  that  variable  is  unset,  the  default  is
-       _\b~_\b/_\b._\bi_\bn_\bp_\bu_\bt_\br_\bc.   When a program which uses the readline library starts up,
+       Readline  is  customized  by putting commands in an initialization file
+       (the _\bi_\bn_\bp_\bu_\bt_\br_\bc file).  The name of this file is taken from the  value  of
+       the  I\bIN\bNP\bPU\bUT\bTR\bRC\bC  variable.   If  that  variable  is  unset, the default is
+       _\b~_\b/_\b._\bi_\bn_\bp_\bu_\bt_\br_\bc.  When a program which uses the readline library starts  up,
        the initialization file is read, and the key bindings and variables are
-       set.   There  are  only  a few basic constructs allowed in the readline
-       initialization file.  Blank lines are ignored.  Lines beginning with  a
-       #\b are  comments.   Lines  beginning with a $\b$ indicate conditional con-
+       set.  There are only a few basic constructs  allowed  in  the  readline
+       initialization  file.  Blank lines are ignored.  Lines beginning with a
+       #\bare comments.  Lines beginning with a  $\b$  indicate  conditional  con-
        structs.  Other lines denote key bindings and variable settings.
 
-       The default key-bindings may be changed with an  _\bi_\bn_\bp_\bu_\bt_\br_\bc  file.   Other
+       The  default  key-bindings  may be changed with an _\bi_\bn_\bp_\bu_\bt_\br_\bc file.  Other
        programs that use this library may add their own commands and bindings.
 
        For example, placing
@@ -2810,19 +2813,19 @@ R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE
               M-Control-u: universal-argument
        or
               C-Meta-u: universal-argument
-       into the _\bi_\bn_\bp_\bu_\bt_\br_\bc would make M-C-u execute the readline command  _\bu_\bn_\bi_\bv_\be_\br_\b-
+       into  the _\bi_\bn_\bp_\bu_\bt_\br_\bc would make M-C-u execute the readline command _\bu_\bn_\bi_\bv_\be_\br_\b-
        _\bs_\ba_\bl_\b-_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt.
 
-       The  following  symbolic  character  names are recognized: _\bR_\bU_\bB_\bO_\bU_\bT, _\bD_\bE_\bL,
+       The following symbolic character names  are  recognized:  _\bR_\bU_\bB_\bO_\bU_\bT,  _\bD_\bE_\bL,
        _\bE_\bS_\bC, _\bL_\bF_\bD, _\bN_\bE_\bW_\bL_\bI_\bN_\bE, _\bR_\bE_\bT, _\bR_\bE_\bT_\bU_\bR_\bN, _\bS_\bP_\bC, _\bS_\bP_\bA_\bC_\bE, and _\bT_\bA_\bB.
 
-       In addition to command names, readline allows keys to  be  bound  to  a
+       In  addition  to  command  names, readline allows keys to be bound to a
        string that is inserted when the key is pressed (a _\bm_\ba_\bc_\br_\bo).
 
    R\bRe\bea\bad\bdl\bli\bin\bne\be K\bKe\bey\by B\bBi\bin\bnd\bdi\bin\bng\bgs\bs
-       The  syntax for controlling key bindings in the _\bi_\bn_\bp_\bu_\bt_\br_\bc file is simple.
-       All that is required is the name of the command or the text of a  macro
-       and  a key sequence to which it should be bound. The name may be speci-
+       The syntax for controlling key bindings in the _\bi_\bn_\bp_\bu_\bt_\br_\bc file is  simple.
+       All  that is required is the name of the command or the text of a macro
+       and a key sequence to which it should be bound. The name may be  speci-
        fied in one of two ways: as a symbolic key name, possibly with _\bM_\be_\bt_\ba_\b- or
        _\bC_\bo_\bn_\bt_\br_\bo_\bl_\b- prefixes, or as a key sequence.
 
@@ -2833,15 +2836,15 @@ R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE
               Meta-Rubout: backward-kill-word
               Control-o: "> output"
 
-       In the above example, _\bC_\b-_\bu is bound to the function  u\bun\bni\biv\bve\ber\brs\bsa\bal\bl-\b-a\bar\brg\bgu\bum\bme\ben\bnt\bt,
-       _\bM_\b-_\bD_\bE_\b is bound to the function b\bba\bac\bck\bkw\bwa\bar\brd\bd-\b-k\bki\bil\bll\bl-\b-w\bwo\bor\brd\bd, and _\bC_\b-_\bo is bound to
-       run the macro expressed on the right hand side (that is, to insert  the
+       In  the above example, _\bC_\b-_\bu is bound to the function u\bun\bni\biv\bve\ber\brs\bsa\bal\bl-\b-a\bar\brg\bgu\bum\bme\ben\bnt\bt,
+       _\bM_\b-_\bD_\bE_\bis bound to the function b\bba\bac\bck\bkw\bwa\bar\brd\bd-\b-k\bki\bil\bll\bl-\b-w\bwo\bor\brd\bd, and _\bC_\b-_\bo is bound  to
+       run  the macro expressed on the right hand side (that is, to insert the
        text ``> output'' into the line).
 
-       In  the  second  form,  "\b"k\bke\bey\bys\bse\beq\bq"\b":_\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn_\b-_\bn_\ba_\bm_\be or _\bm_\ba_\bc_\br_\bo, k\bke\bey\bys\bse\beq\bq differs
-       from k\bke\bey\byn\bna\bam\bme\be above in that strings denoting an entire key sequence  may
-       be  specified  by  placing the sequence within double quotes.  Some GNU
-       Emacs style key escapes can be used, as in the following  example,  but
+       In the second form, "\b"k\bke\bey\bys\bse\beq\bq"\b":_\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn_\b-_\bn_\ba_\bm_\be  or  _\bm_\ba_\bc_\br_\bo,  k\bke\bey\bys\bse\beq\b differs
+       from  k\bke\bey\byn\bna\bam\bme\be above in that strings denoting an entire key sequence may
+       be specified by placing the sequence within double  quotes.   Some  GNU
+       Emacs  style  key escapes can be used, as in the following example, but
        the symbolic character names are not recognized.
 
               "\C-u": universal-argument
@@ -2849,7 +2852,7 @@ R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE
               "\e[11~": "Function Key 1"
 
        In this example, _\bC_\b-_\bu is again bound to the function u\bun\bni\biv\bve\ber\brs\bsa\bal\bl-\b-a\bar\brg\bgu\bum\bme\ben\bnt\bt.
-       _\bC_\b-_\b_\bC_\b-_\br is bound to the function r\bre\be-\b-r\bre\bea\bad\bd-\b-i\bin\bni\bit\bt-\b-f\bfi\bil\ble\be, and _\bE_\bS_\bC _\b[ _\b1 _\b1 _\b is
+       _\bC_\b-_\b _\bC_\b-_\br is bound to the function r\bre\be-\b-r\bre\bea\bad\bd-\b-i\bin\bni\bit\bt-\b-f\bfi\bil\ble\be, and _\bE_\bS_\bC _\b[ _\b1 _\b1 _\b~ is
        bound to insert the text ``Function Key 1''.
 
        The full set of GNU Emacs style escape sequences is
@@ -2860,7 +2863,7 @@ R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE
               \\b\"\b"     literal "
               \\b\'\b'     literal '
 
-       In  addition  to  the GNU Emacs style escape sequences, a second set of
+       In addition to the GNU Emacs style escape sequences, a  second  set  of
        backslash escapes is available:
               \\b\a\ba     alert (bell)
               \\b\b\bb     backspace
@@ -2870,20 +2873,20 @@ R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE
               \\b\r\br     carriage return
               \\b\t\bt     horizontal tab
               \\b\v\bv     vertical tab
-              \\b\_\bn_\bn_\bn   the eight-bit character whose value is  the  octal  value
+              \\b\_\bn_\bn_\bn   the  eight-bit  character  whose value is the octal value
                      _\bn_\bn_\bn (one to three digits)
-              \\b\x\bx_\bH_\bH   the  eight-bit  character  whose value is the hexadecimal
+              \\b\x\bx_\bH_\bH   the eight-bit character whose value  is  the  hexadecimal
                      value _\bH_\bH (one or two hex digits)
 
        When entering the text of a macro, single or double quotes must be used
        to indicate a macro definition.  Unquoted text is assumed to be a func-
-       tion name.  In the macro body, the backslash  escapes  described  above
-       are  expanded.   Backslash  will quote any other character in the macro
+       tion  name.   In  the macro body, the backslash escapes described above
+       are expanded.  Backslash will quote any other character  in  the  macro
        text, including " and '.
 
-       B\bBa\bas\bsh\ballows the current readline key bindings to be displayed or  modi-
-       fied  with  the b\bbi\bin\bnd\bd builtin command.  The editing mode may be switched
-       during interactive use by using the -\b-o\bo option to the s\bse\bet\bt  builtin  com-
+       B\bBa\bas\bsh\b allows the current readline key bindings to be displayed or modi-
+       fied with the b\bbi\bin\bnd\bd builtin command.  The editing mode may  be  switched
+       during  interactive  use by using the -\b-o\bo option to the s\bse\bet\bt builtin com-
        mand (see S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS below).
 
    R\bRe\bea\bad\bdl\bli\bin\bne\be V\bVa\bar\bri\bia\bab\bbl\ble\bes\bs
@@ -2893,213 +2896,213 @@ R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE
 
               s\bse\bet\bt _\bv_\ba_\br_\bi_\ba_\bb_\bl_\be_\b-_\bn_\ba_\bm_\be _\bv_\ba_\bl_\bu_\be
 
-       Except  where  noted,  readline variables can take the values O\bOn\bn or O\bOf\bff\bf
-       (without regard to case).  Unrecognized  variable  names  are  ignored.
-       When  a variable value is read, empty or null values, "on" (case-insen-
+       Except where noted, readline variables can take the values  O\bOn\bn  or  O\bOf\bff\bf
+       (without  regard  to  case).   Unrecognized variable names are ignored.
+       When a variable value is read, empty or null values, "on"  (case-insen-
        sitive), and "1" are equivalent to O\bOn\bn.  All other values are equivalent
        to O\bOf\bff\bf.  The variables and their default values are:
 
        b\bbe\bel\bll\bl-\b-s\bst\bty\byl\ble\be (\b(a\bau\bud\bdi\bib\bbl\ble\be)\b)
-              Controls  what  happens when readline wants to ring the terminal
+              Controls what happens when readline wants to ring  the  terminal
               bell.  If set to n\bno\bon\bne\be, readline never rings the bell.  If set to
-              v\bvi\bis\bsi\bib\bbl\ble\be,  readline  uses a visible bell if one is available.  If
+              v\bvi\bis\bsi\bib\bbl\ble\be, readline uses a visible bell if one is  available.   If
               set to a\bau\bud\bdi\bib\bbl\ble\be, readline attempts to ring the terminal's bell.
        b\bbi\bin\bnd\bd-\b-t\btt\bty\by-\b-s\bsp\bpe\bec\bci\bia\bal\bl-\b-c\bch\bha\bar\brs\bs (\b(O\bOn\bn)\b)
-              If set to O\bOn\bn, readline attempts to bind the  control  characters
+              If  set  to O\bOn\bn, readline attempts to bind the control characters
               treated specially by the kernel's terminal driver to their read-
               line equivalents.
        c\bco\bol\blo\bor\bre\bed\bd-\b-s\bst\bta\bat\bts\bs (\b(O\bOf\bff\bf)\b)
-              If set to O\bOn\bn, readline displays possible completions using  dif-
-              ferent  colors  to  indicate their file type.  The color defini-
-              tions are taken from the  value  of  the  L\bLS\bS_\b_C\bCO\bOL\bLO\bOR\bRS\b environment
+              If  set to O\bOn\bn, readline displays possible completions using dif-
+              ferent colors to indicate their file type.   The  color  defini-
+              tions  are  taken  from  the  value of the L\bLS\bS_\b_C\bCO\bOL\bLO\bOR\bRS\bS environment
               variable.
        c\bco\bom\bmm\bme\ben\bnt\bt-\b-b\bbe\beg\bgi\bin\bn (\b(`\b``\b`#\b#'\b''\b')\b)
-              The  string  that  is  inserted when the readline i\bin\bns\bse\ber\brt\bt-\b-c\bco\bom\bmm\bme\ben\bnt\bt
+              The string that is inserted  when  the  readline  i\bin\bns\bse\ber\brt\bt-\b-c\bco\bom\bmm\bme\ben\bnt\bt
               command is executed.  This command is bound to M\bM-\b-#\b# in emacs mode
               and to #\b# in vi command mode.
        c\bco\bom\bmp\bpl\ble\bet\bti\bio\bon\bn-\b-i\big\bgn\bno\bor\bre\be-\b-c\bca\bas\bse\be (\b(O\bOf\bff\bf)\b)
               If set to O\bOn\bn, readline performs filename matching and completion
               in a case-insensitive fashion.
        c\bco\bom\bmp\bpl\ble\bet\bti\bio\bon\bn-\b-p\bpr\bre\bef\bfi\bix\bx-\b-d\bdi\bis\bsp\bpl\bla\bay\by-\b-l\ble\ben\bng\bgt\bth\bh (\b(0\b0)\b)
-              The length in characters of the common prefix of a list of  pos-
-              sible  completions that is displayed without modification.  When
-              set to a value greater than zero, common  prefixes  longer  than
-              this  value are replaced with an ellipsis when displaying possi-
+              The  length in characters of the common prefix of a list of pos-
+              sible completions that is displayed without modification.   When
+              set  to  a  value greater than zero, common prefixes longer than
+              this value are replaced with an ellipsis when displaying  possi-
               ble completions.
        c\bco\bom\bmp\bpl\ble\bet\bti\bio\bon\bn-\b-q\bqu\bue\ber\bry\by-\b-i\bit\bte\bem\bms\bs (\b(1\b10\b00\b0)\b)
-              This determines when the user is queried about viewing the  num-
-              ber  of  possible  completions generated by the p\bpo\bos\bss\bsi\bib\bbl\ble\be-\b-c\bco\bom\bmp\bpl\ble\be-\b-
-              t\bti\bio\bon\bns\bcommand.  It may be set to any integer value greater  than
-              or  equal  to  zero.   If  the number of possible completions is
+              This  determines when the user is queried about viewing the num-
+              ber of possible completions generated  by  the  p\bpo\bos\bss\bsi\bib\bbl\ble\be-\b-c\bco\bom\bmp\bpl\ble\be-\b-
+              t\bti\bio\bon\bns\b command.  It may be set to any integer value greater than
+              or equal to zero.  If the  number  of  possible  completions  is
               greater than or equal to the value of this variable, the user is
-              asked  whether or not he wishes to view them; otherwise they are
+              asked whether or not he wishes to view them; otherwise they  are
               simply listed on the terminal.
        c\bco\bon\bnv\bve\ber\brt\bt-\b-m\bme\bet\bta\ba (\b(O\bOn\bn)\b)
-              If set to O\bOn\bn, readline will convert characters with  the  eighth
+              If  set  to O\bOn\bn, readline will convert characters with the eighth
               bit set to an ASCII key sequence by stripping the eighth bit and
-              prefixing an escape character (in effect, using  escape  as  the
+              prefixing  an  escape  character (in effect, using escape as the
               _\bm_\be_\bt_\ba _\bp_\br_\be_\bf_\bi_\bx).
        d\bdi\bis\bsa\bab\bbl\ble\be-\b-c\bco\bom\bmp\bpl\ble\bet\bti\bio\bon\bn (\b(O\bOf\bff\bf)\b)
               If set to O\bOn\bn, readline will inhibit word completion.  Completion
-              characters will be inserted into the line as if  they  had  been
+              characters  will  be  inserted into the line as if they had been
               mapped to s\bse\bel\blf\bf-\b-i\bin\bns\bse\ber\brt\bt.
        e\bed\bdi\bit\bti\bin\bng\bg-\b-m\bmo\bod\bde\be (\b(e\bem\bma\bac\bcs\bs)\b)
               Controls whether readline begins with a set of key bindings sim-
               ilar to _\bE_\bm_\ba_\bc_\bs or _\bv_\bi.  e\bed\bdi\bit\bti\bin\bng\bg-\b-m\bmo\bod\bde\be can be set to either e\bem\bma\bac\bcs\bs or
               v\bvi\bi.
        e\bec\bch\bho\bo-\b-c\bco\bon\bnt\btr\bro\bol\bl-\b-c\bch\bha\bar\bra\bac\bct\bte\ber\brs\bs (\b(O\bOn\bn)\b)
-              When  set to O\bOn\bn, on operating systems that indicate they support
+              When set to O\bOn\bn, on operating systems that indicate they  support
               it, readline echoes a character corresponding to a signal gener-
               ated from the keyboard.
        e\ben\bna\bab\bbl\ble\be-\b-k\bke\bey\byp\bpa\bad\bd (\b(O\bOf\bff\bf)\b)
               When set to O\bOn\bn, readline will try to enable the application key-
-              pad when it is called.  Some systems need  this  to  enable  the
+              pad  when  it  is  called.  Some systems need this to enable the
               arrow keys.
        e\ben\bna\bab\bbl\ble\be-\b-m\bme\bet\bta\ba-\b-k\bke\bey\by (\b(O\bOn\bn)\b)
-              When  set  to  O\bOn\bn, readline will try to enable any meta modifier
-              key the terminal claims to support when it is called.   On  many
+              When set to O\bOn\bn, readline will try to enable  any  meta  modifier
+              key  the  terminal claims to support when it is called.  On many
               terminals, the meta key is used to send eight-bit characters.
        e\bex\bxp\bpa\ban\bnd\bd-\b-t\bti\bil\bld\bde\be (\b(O\bOf\bff\bf)\b)
-              If  set  to  O\bOn\bn,  tilde  expansion  is  performed  when readline
+              If set  to  O\bOn\bn,  tilde  expansion  is  performed  when  readline
               attempts word completion.
        h\bhi\bis\bst\bto\bor\bry\by-\b-p\bpr\bre\bes\bse\ber\brv\bve\be-\b-p\bpo\boi\bin\bnt\bt (\b(O\bOf\bff\bf)\b)
-              If set to O\bOn\bn, the history code attempts to place  point  at  the
-              same  location on each history line retrieved with p\bpr\bre\bev\bvi\bio\bou\bus\bs-\b-h\bhi\bis\bs-\b-
+              If  set  to  O\bOn\bn, the history code attempts to place point at the
+              same location on each history line retrieved with  p\bpr\bre\bev\bvi\bio\bou\bus\bs-\b-h\bhi\bis\bs-\b-
               t\bto\bor\bry\by or n\bne\bex\bxt\bt-\b-h\bhi\bis\bst\bto\bor\bry\by.
        h\bhi\bis\bst\bto\bor\bry\by-\b-s\bsi\biz\bze\be (\b(0\b0)\b)
-              Set the maximum number of history entries saved in  the  history
-              list.   If set to zero, any existing history entries are deleted
+              Set  the  maximum number of history entries saved in the history
+              list.  If set to zero, any existing history entries are  deleted
               and no new entries are saved.  If set to a value less than zero,
-              the  number  of history entries is not limited.  By default, the
+              the number of history entries is not limited.  By  default,  the
               number of history entries is not limited.
        h\bho\bor\bri\biz\bzo\bon\bnt\bta\bal\bl-\b-s\bsc\bcr\bro\bol\bll\bl-\b-m\bmo\bod\bde\be (\b(O\bOf\bff\bf)\b)
-              When set to O\bOn\bn, makes readline use a single  line  for  display,
+              When  set  to  O\bOn\bn, makes readline use a single line for display,
               scrolling the input horizontally on a single screen line when it
-              becomes longer than the screen width rather than wrapping  to  a
+              becomes  longer  than the screen width rather than wrapping to a
               new line.
        i\bin\bnp\bpu\but\bt-\b-m\bme\bet\bta\ba (\b(O\bOf\bff\bf)\b)
-              If  set to O\bOn\bn, readline will enable eight-bit input (that is, it
-              will not strip the high  bit  from  the  characters  it  reads),
+              If set to O\bOn\bn, readline will enable eight-bit input (that is,  it
+              will  not  strip  the  high  bit  from the characters it reads),
               regardless of what the terminal claims it can support.  The name
               m\bme\bet\bta\ba-\b-f\bfl\bla\bag\bg is a synonym for this variable.
        i\bis\bse\bea\bar\brc\bch\bh-\b-t\bte\ber\brm\bmi\bin\bna\bat\bto\bor\brs\bs (\b(`\b``\b`C\bC-\b-[\b[C\bC-\b-J\bJ'\b''\b')\b)
-              The string of characters that should  terminate  an  incremental
-              search  without  subsequently  executing the character as a com-
-              mand.  If this variable has not been given a value, the  charac-
+              The  string  of  characters that should terminate an incremental
+              search without subsequently executing the character  as  a  com-
+              mand.   If this variable has not been given a value, the charac-
               ters _\bE_\bS_\bC and _\bC_\b-_\bJ will terminate an incremental search.
        k\bke\bey\bym\bma\bap\bp (\b(e\bem\bma\bac\bcs\bs)\b)
-              Set  the current readline keymap.  The set of valid keymap names
-              is _\be_\bm_\ba_\bc_\bs_\b, _\be_\bm_\ba_\bc_\bs_\b-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\bd_\b, _\be_\bm_\ba_\bc_\bs_\b-_\bm_\be_\bt_\ba_\b,  _\be_\bm_\ba_\bc_\bs_\b-_\bc_\bt_\bl_\bx_\b,  _\bv_\bi_\b _\bv_\bi_\b-_\bc_\bo_\bm_\b-
-              _\bm_\ba_\bn_\bd,  and  _\bv_\bi_\b-_\bi_\bn_\bs_\be_\br_\bt.  _\bv_\bi is equivalent to _\bv_\bi_\b-_\bc_\bo_\bm_\bm_\ba_\bn_\bd; _\be_\bm_\ba_\bc_\bs is
-              equivalent to _\be_\bm_\ba_\bc_\bs_\b-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\bd.  The default value is  _\be_\bm_\ba_\bc_\bs;  the
+              Set the current readline keymap.  The set of valid keymap  names
+              is  _\be_\bm_\ba_\bc_\bs_\b,  _\be_\bm_\ba_\bc_\bs_\b-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\bd_\b,  _\be_\bm_\ba_\bc_\bs_\b-_\bm_\be_\bt_\ba_\b, _\be_\bm_\ba_\bc_\bs_\b-_\bc_\bt_\bl_\bx_\b, _\bv_\bi_\b, _\bv_\bi_\b-_\bc_\bo_\bm_\b-
+              _\bm_\ba_\bn_\bd, and _\bv_\bi_\b-_\bi_\bn_\bs_\be_\br_\bt.  _\bv_\bi is equivalent to _\bv_\bi_\b-_\bc_\bo_\bm_\bm_\ba_\bn_\bd;  _\be_\bm_\ba_\bc_\b is
+              equivalent  to  _\be_\bm_\ba_\bc_\bs_\b-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\bd.  The default value is _\be_\bm_\ba_\bc_\bs; the
               value of e\bed\bdi\bit\bti\bin\bng\bg-\b-m\bmo\bod\bde\be also affects the default keymap.
        k\bke\bey\bys\bse\beq\bq-\b-t\bti\bim\bme\beo\bou\but\bt (\b(5\b50\b00\b0)\b)
-              Specifies  the  duration _\br_\be_\ba_\bd_\bl_\bi_\bn_\be will wait for a character when
-              reading an ambiguous key sequence (one that can form a  complete
+              Specifies the duration _\br_\be_\ba_\bd_\bl_\bi_\bn_\be will wait for a  character  when
+              reading  an ambiguous key sequence (one that can form a complete
               key sequence using the input read so far, or can take additional
-              input to complete a  longer  key  sequence).   If  no  input  is
-              received  within  the timeout, _\br_\be_\ba_\bd_\bl_\bi_\bn_\be will use the shorter but
-              complete key sequence.  The value is specified in  milliseconds,
-              so  a value of 1000 means that _\br_\be_\ba_\bd_\bl_\bi_\bn_\be will wait one second for
-              additional input.  If this variable is set to a value less  than
-              or  equal to zero, or to a non-numeric value, _\br_\be_\ba_\bd_\bl_\bi_\bn_\be will wait
-              until another key is pressed to decide  which  key  sequence  to
+              input  to  complete  a  longer  key  sequence).   If no input is
+              received within the timeout, _\br_\be_\ba_\bd_\bl_\bi_\bn_\be will use the  shorter  but
+              complete  key sequence.  The value is specified in milliseconds,
+              so a value of 1000 means that _\br_\be_\ba_\bd_\bl_\bi_\bn_\be will wait one second  for
+              additional  input.  If this variable is set to a value less than
+              or equal to zero, or to a non-numeric value, _\br_\be_\ba_\bd_\bl_\bi_\bn_\be will  wait
+              until  another  key  is  pressed to decide which key sequence to
               complete.
        m\bma\bar\brk\bk-\b-d\bdi\bir\bre\bec\bct\bto\bor\bri\bie\bes\bs (\b(O\bOn\bn)\b)
               If set to O\bOn\bn, completed directory names have a slash appended.
        m\bma\bar\brk\bk-\b-m\bmo\bod\bdi\bif\bfi\bie\bed\bd-\b-l\bli\bin\bne\bes\bs (\b(O\bOf\bff\bf)\b)
-              If  set  to  O\bOn\bn,  history lines that have been modified are dis-
+              If set to O\bOn\bn, history lines that have  been  modified  are  dis-
               played with a preceding asterisk (*\b*).
        m\bma\bar\brk\bk-\b-s\bsy\bym\bml\bli\bin\bnk\bke\bed\bd-\b-d\bdi\bir\bre\bec\bct\bto\bor\bri\bie\bes\bs (\b(O\bOf\bff\bf)\b)
               If set to O\bOn\bn, completed names which are symbolic links to direc-
-              tories   have   a  slash  appended  (subject  to  the  value  of
+              tories  have  a  slash  appended  (subject  to  the   value   of
               m\bma\bar\brk\bk-\b-d\bdi\bir\bre\bec\bct\bto\bor\bri\bie\bes\bs).
        m\bma\bat\btc\bch\bh-\b-h\bhi\bid\bdd\bde\ben\bn-\b-f\bfi\bil\ble\bes\bs (\b(O\bOn\bn)\b)
-              This variable, when set to O\bOn\bn, causes readline  to  match  files
-              whose  names  begin  with  a  `.' (hidden files) when performing
-              filename completion.  If set to O\bOf\bff\bf, the  leading  `.'  must  be
+              This  variable,  when  set to O\bOn\bn, causes readline to match files
+              whose names begin with a  `.'  (hidden  files)  when  performing
+              filename  completion.   If  set  to O\bOf\bff\bf, the leading `.' must be
               supplied by the user in the filename to be completed.
        m\bme\ben\bnu\bu-\b-c\bco\bom\bmp\bpl\ble\bet\bte\be-\b-d\bdi\bis\bsp\bpl\bla\bay\by-\b-p\bpr\bre\bef\bfi\bix\bx (\b(O\bOf\bff\bf)\b)
-              If  set to O\bOn\bn, menu completion displays the common prefix of the
+              If set to O\bOn\bn, menu completion displays the common prefix of  the
               list of possible completions (which may be empty) before cycling
               through the list.
        o\bou\but\btp\bpu\but\bt-\b-m\bme\bet\bta\ba (\b(O\bOf\bff\bf)\b)
-              If  set  to O\bOn\bn, readline will display characters with the eighth
+              If set to O\bOn\bn, readline will display characters with  the  eighth
               bit set directly rather than as a meta-prefixed escape sequence.
        p\bpa\bag\bge\be-\b-c\bco\bom\bmp\bpl\ble\bet\bti\bio\bon\bns\bs (\b(O\bOn\bn)\b)
-              If  set to O\bOn\bn, readline uses an internal _\bm_\bo_\br_\be-like pager to dis-
+              If set to O\bOn\bn, readline uses an internal _\bm_\bo_\br_\be-like pager to  dis-
               play a screenful of possible completions at a time.
        p\bpr\bri\bin\bnt\bt-\b-c\bco\bom\bmp\bpl\ble\bet\bti\bio\bon\bns\bs-\b-h\bho\bor\bri\biz\bzo\bon\bnt\bta\bal\bll\bly\by (\b(O\bOf\bff\bf)\b)
-              If set to O\bOn\bn, readline will  display  completions  with  matches
-              sorted  horizontally in alphabetical order, rather than down the
+              If  set  to  O\bOn\bn,  readline will display completions with matches
+              sorted horizontally in alphabetical order, rather than down  the
               screen.
        r\bre\bev\bve\ber\brt\bt-\b-a\bal\bll\bl-\b-a\bat\bt-\b-n\bne\bew\bwl\bli\bin\bne\be (\b(O\bOf\bff\bf)\b)
-              If set to O\bOn\bn, readline will undo all changes  to  history  lines
+              If  set  to  O\bOn\bn, readline will undo all changes to history lines
               before returning when a\bac\bcc\bce\bep\bpt\bt-\b-l\bli\bin\bne\be is executed.  By default, his-
-              tory lines may be modified  and  retain  individual  undo  lists
+              tory  lines  may  be  modified  and retain individual undo lists
               across calls to r\bre\bea\bad\bdl\bli\bin\bne\be.
        s\bsh\bho\bow\bw-\b-a\bal\bll\bl-\b-i\bif\bf-\b-a\bam\bmb\bbi\big\bgu\buo\bou\bus\bs (\b(O\bOf\bff\bf)\b)
-              This  alters  the  default behavior of the completion functions.
+              This alters the default behavior of  the  completion  functions.
               If set to O\bOn\bn, words which have more than one possible completion
-              cause  the  matches  to be listed immediately instead of ringing
+              cause the matches to be listed immediately  instead  of  ringing
               the bell.
        s\bsh\bho\bow\bw-\b-a\bal\bll\bl-\b-i\bif\bf-\b-u\bun\bnm\bmo\bod\bdi\bif\bfi\bie\bed\bd (\b(O\bOf\bff\bf)\b)
-              This alters the default behavior of the completion functions  in
+              This  alters the default behavior of the completion functions in
               a fashion similar to s\bsh\bho\bow\bw-\b-a\bal\bll\bl-\b-i\bif\bf-\b-a\bam\bmb\bbi\big\bgu\buo\bou\bus\bs.  If set to O\bOn\bn, words
-              which have more than one possible completion without any  possi-
-              ble  partial  completion (the possible completions don't share a
-              common prefix)  cause  the  matches  to  be  listed  immediately
+              which  have more than one possible completion without any possi-
+              ble partial completion (the possible completions don't  share  a
+              common  prefix)  cause  the  matches  to  be  listed immediately
               instead of ringing the bell.
        s\bsh\bho\bow\bw-\b-m\bmo\bod\bde\be-\b-i\bin\bn-\b-p\bpr\bro\bom\bmp\bpt\bt (\b(O\bOf\bff\bf)\b)
-              If  set  to  O\bOn\bn,  add a character to the beginning of the prompt
-              indicating the editing mode: emacs (@), vi  command  (:)  or  vi
+              If set to O\bOn\bn, add a character to the  beginning  of  the  prompt
+              indicating  the  editing  mode:  emacs (@), vi command (:) or vi
               insertion (+).
        s\bsk\bki\bip\bp-\b-c\bco\bom\bmp\bpl\ble\bet\bte\bed\bd-\b-t\bte\bex\bxt\bt (\b(O\bOf\bff\bf)\b)
-              If  set  to O\bOn\bn, this alters the default completion behavior when
-              inserting a single match into the line.  It's only  active  when
-              performing  completion  in  the  middle  of a word.  If enabled,
-              readline does not insert characters  from  the  completion  that
-              match  characters  after  point  in the word being completed, so
+              If set to O\bOn\bn, this alters the default completion  behavior  when
+              inserting  a  single match into the line.  It's only active when
+              performing completion in the middle  of  a  word.   If  enabled,
+              readline  does  not  insert  characters from the completion that
+              match characters after point in the  word  being  completed,  so
               portions of the word following the cursor are not duplicated.
        v\bvi\bis\bsi\bib\bbl\ble\be-\b-s\bst\bta\bat\bts\bs (\b(O\bOf\bff\bf)\b)
-              If set to O\bOn\bn, a character denoting a file's type as reported  by
-              _\bs_\bt_\ba_\bt(2)  is  appended to the filename when listing possible com-
+              If  set to O\bOn\bn, a character denoting a file's type as reported by
+              _\bs_\bt_\ba_\bt(2) is appended to the filename when listing  possible  com-
               pletions.
 
    R\bRe\bea\bad\bdl\bli\bin\bne\be C\bCo\bon\bnd\bdi\bit\bti\bio\bon\bna\bal\bl C\bCo\bon\bns\bst\btr\bru\buc\bct\bts\bs
-       Readline implements a facility similar in  spirit  to  the  conditional
-       compilation  features  of  the C preprocessor which allows key bindings
-       and variable settings to be performed as the result  of  tests.   There
+       Readline  implements  a  facility  similar in spirit to the conditional
+       compilation features of the C preprocessor which  allows  key  bindings
+       and  variable  settings  to be performed as the result of tests.  There
        are four parser directives used.
 
-       $\b$i\bif\bf    The  $\b$i\bif\bf construct allows bindings to be made based on the edit-
-              ing mode, the terminal being  used,  or  the  application  using
-              readline.   The text of the test extends to the end of the line;
+       $\b$i\bif\bf    The $\b$i\bif\bf construct allows bindings to be made based on the  edit-
+              ing  mode,  the  terminal  being  used, or the application using
+              readline.  The text of the test extends to the end of the  line;
               no characters are required to isolate it.
 
-              m\bmo\bod\bde\be   The m\bmo\bod\bde\be=\b= form of the  $\b$i\bif\bf  directive  is  used  to  test
-                     whether  readline  is  in  emacs or vi mode.  This may be
-                     used in conjunction with  the  s\bse\bet\bt  k\bke\bey\bym\bma\bap\bp  command,  for
-                     instance,  to  set  bindings  in  the  _\be_\bm_\ba_\bc_\bs_\b-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\bd and
-                     _\be_\bm_\ba_\bc_\bs_\b-_\bc_\bt_\bl_\bkeymaps only if readline is  starting  out  in
+              m\bmo\bod\bde\be   The  m\bmo\bod\bde\be=\b=  form  of  the  $\b$i\bif\bf  directive is used to test
+                     whether readline is in emacs or vi  mode.   This  may  be
+                     used  in  conjunction  with  the  s\bse\bet\bt k\bke\bey\bym\bma\bap\bp command, for
+                     instance, to  set  bindings  in  the  _\be_\bm_\ba_\bc_\bs_\b-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\b and
+                     _\be_\bm_\ba_\bc_\bs_\b-_\bc_\bt_\bl_\b keymaps  only  if readline is starting out in
                      emacs mode.
 
-              t\bte\ber\brm\bm   The  t\bte\ber\brm\bm=\b=  form may be used to include terminal-specific
+              t\bte\ber\brm\bm   The t\bte\ber\brm\bm=\b= form may be used to  include  terminal-specific
                      key bindings, perhaps to bind the key sequences output by
                      the terminal's function keys.  The word on the right side
                      of the =\b= is tested against the both full name of the ter-
-                     minal  and  the  portion  of the terminal name before the
-                     first -\b-.  This allows _\bs_\bu_\bn to match both _\bs_\bu_\bn and  _\bs_\bu_\bn_\b-_\bc_\bm_\bd,
+                     minal and the portion of the  terminal  name  before  the
+                     first  -\b-.  This allows _\bs_\bu_\bn to match both _\bs_\bu_\bn and _\bs_\bu_\bn_\b-_\bc_\bm_\bd,
                      for instance.
 
               a\bap\bpp\bpl\bli\bic\bca\bat\bti\bio\bon\bn
                      The a\bap\bpp\bpl\bli\bic\bca\bat\bti\bio\bon\bn construct is used to include application-
                      specific  settings.   Each  program  using  the  readline
-                     library  sets the _\ba_\bp_\bp_\bl_\bi_\bc_\ba_\bt_\bi_\bo_\bn _\bn_\ba_\bm_\be, and an initialization
+                     library sets the _\ba_\bp_\bp_\bl_\bi_\bc_\ba_\bt_\bi_\bo_\bn _\bn_\ba_\bm_\be, and an  initialization
                      file can test for a particular value.  This could be used
-                     to  bind key sequences to functions useful for a specific
-                     program.  For instance, the following command adds a  key
-                     sequence  that  quotes  the  current  or previous word in
+                     to bind key sequences to functions useful for a  specific
+                     program.   For instance, the following command adds a key
+                     sequence that quotes the  current  or  previous  word  in
                      b\bba\bas\bsh\bh:
 
                      $\b$i\bif\bf Bash
@@ -3114,51 +3117,51 @@ R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE
               test fails.
 
        $\b$i\bin\bnc\bcl\blu\bud\bde\be
-              This directive takes a single filename as an argument and  reads
-              commands  and bindings from that file.  For example, the follow-
+              This  directive takes a single filename as an argument and reads
+              commands and bindings from that file.  For example, the  follow-
               ing directive would read _\b/_\be_\bt_\bc_\b/_\bi_\bn_\bp_\bu_\bt_\br_\bc:
 
               $\b$i\bin\bnc\bcl\blu\bud\bde\be  _\b/_\be_\bt_\bc_\b/_\bi_\bn_\bp_\bu_\bt_\br_\bc
 
    S\bSe\bea\bar\brc\bch\bhi\bin\bng\bg
-       Readline provides commands for searching through  the  command  history
+       Readline  provides  commands  for searching through the command history
        (see H\bHI\bIS\bST\bTO\bOR\bRY\bY below) for lines containing a specified string.  There are
        two search modes: _\bi_\bn_\bc_\br_\be_\bm_\be_\bn_\bt_\ba_\bl and _\bn_\bo_\bn_\b-_\bi_\bn_\bc_\br_\be_\bm_\be_\bn_\bt_\ba_\bl.
 
-       Incremental searches begin before the  user  has  finished  typing  the
-       search  string.  As each character of the search string is typed, read-
+       Incremental  searches  begin  before  the  user has finished typing the
+       search string.  As each character of the search string is typed,  read-
        line displays the next entry from the history matching the string typed
-       so  far.   An  incremental  search  requires only as many characters as
-       needed to find the desired history entry.  The  characters  present  in
-       the  value of the i\bis\bse\bea\bar\brc\bch\bh-\b-t\bte\ber\brm\bmi\bin\bna\bat\bto\bor\brs\bs variable are used to terminate an
+       so far.  An incremental search requires  only  as  many  characters  as
+       needed  to  find  the desired history entry.  The characters present in
+       the value of the i\bis\bse\bea\bar\brc\bch\bh-\b-t\bte\ber\brm\bmi\bin\bna\bat\bto\bor\brs\bs variable are used to terminate  an
        incremental search.  If that variable has not been assigned a value the
-       Escape  and  Control-J characters will terminate an incremental search.
-       Control-G will abort an incremental search  and  restore  the  original
-       line.   When the search is terminated, the history entry containing the
+       Escape and Control-J characters will terminate an  incremental  search.
+       Control-G  will  abort  an  incremental search and restore the original
+       line.  When the search is terminated, the history entry containing  the
        search string becomes the current line.
 
-       To find other matching entries in the history list, type  Control-S  or
-       Control-R  as appropriate.  This will search backward or forward in the
-       history for the next entry matching the search  string  typed  so  far.
-       Any  other  key sequence bound to a readline command will terminate the
-       search and execute that command.  For instance, a _\bn_\be_\bw_\bl_\bi_\bn_\be  will  termi-
+       To  find  other matching entries in the history list, type Control-S or
+       Control-R as appropriate.  This will search backward or forward in  the
+       history  for  the  next  entry matching the search string typed so far.
+       Any other key sequence bound to a readline command will  terminate  the
+       search  and  execute that command.  For instance, a _\bn_\be_\bw_\bl_\bi_\bn_\be will termi-
        nate the search and accept the line, thereby executing the command from
        the history list.
 
        Readline remembers the last incremental search string.  If two Control-
-       Rs  are  typed without any intervening characters defining a new search
+       Rs are typed without any intervening characters defining a  new  search
        string, any remembered search string is used.
 
-       Non-incremental searches read the entire search string before  starting
-       to  search  for matching history lines.  The search string may be typed
+       Non-incremental  searches read the entire search string before starting
+       to search for matching history lines.  The search string may  be  typed
        by the user or be part of the contents of the current line.
 
    R\bRe\bea\bad\bdl\bli\bin\bne\be C\bCo\bom\bmm\bma\ban\bnd\bd N\bNa\bam\bme\bes\bs
-       The following is a list of the names of the commands  and  the  default
+       The  following  is  a list of the names of the commands and the default
        key sequences to which they are bound.  Command names without an accom-
        panying key sequence are unbound by default.  In the following descrip-
-       tions,  _\bp_\bo_\bi_\bn_\bt refers to the current cursor position, and _\bm_\ba_\br_\bk refers to
-       a cursor position saved by the s\bse\bet\bt-\b-m\bma\bar\brk\bk command.  The text between  the
+       tions, _\bp_\bo_\bi_\bn_\bt refers to the current cursor position, and _\bm_\ba_\br_\bk refers  to
+       a  cursor position saved by the s\bse\bet\bt-\b-m\bma\bar\brk\bk command.  The text between the
        point and mark is referred to as the _\br_\be_\bg_\bi_\bo_\bn.
 
    C\bCo\bom\bmm\bma\ban\bnd\bds\bs f\bfo\bor\br M\bMo\bov\bvi\bin\bng\bg
@@ -3174,17 +3177,17 @@ R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE
               Move forward to the end of the next word.  Words are composed of
               alphanumeric characters (letters and digits).
        b\bba\bac\bck\bkw\bwa\bar\brd\bd-\b-w\bwo\bor\brd\bd (\b(M\bM-\b-b\bb)\b)
-              Move back to the start of the current or previous  word.   Words
+              Move  back  to the start of the current or previous word.  Words
               are composed of alphanumeric characters (letters and digits).
        s\bsh\bhe\bel\bll\bl-\b-f\bfo\bor\brw\bwa\bar\brd\bd-\b-w\bwo\bor\brd\bd
-              Move  forward  to the end of the next word.  Words are delimited
+              Move forward to the end of the next word.  Words  are  delimited
               by non-quoted shell metacharacters.
        s\bsh\bhe\bel\bll\bl-\b-b\bba\bac\bck\bkw\bwa\bar\brd\bd-\b-w\bwo\bor\brd\bd
-              Move back to the start of the current or previous  word.   Words
+              Move  back  to the start of the current or previous word.  Words
               are delimited by non-quoted shell metacharacters.
        c\bcl\ble\bea\bar\br-\b-s\bsc\bcr\bre\bee\ben\bn (\b(C\bC-\b-l\bl)\b)
-              Clear  the  screen  leaving  the  current line at the top of the
-              screen.  With an argument,  refresh  the  current  line  without
+              Clear the screen leaving the current line  at  the  top  of  the
+              screen.   With  an  argument,  refresh  the current line without
               clearing the screen.
        r\bre\bed\bdr\bra\baw\bw-\b-c\bcu\bur\brr\bre\ben\bnt\bt-\b-l\bli\bin\bne\be
               Refresh the current line.
@@ -3192,141 +3195,141 @@ R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE
    C\bCo\bom\bmm\bma\ban\bnd\bds\bs f\bfo\bor\br M\bMa\ban\bni\bip\bpu\bul\bla\bat\bti\bin\bng\bg t\bth\bhe\be H\bHi\bis\bst\bto\bor\bry\by
        a\bac\bcc\bce\bep\bpt\bt-\b-l\bli\bin\bne\be (\b(N\bNe\bew\bwl\bli\bin\bne\be,\b, R\bRe\bet\btu\bur\brn\bn)\b)
               Accept the line regardless of where the cursor is.  If this line
-              is non-empty, add it to the history list according to the  state
-              of  the H\bHI\bIS\bST\bTC\bCO\bON\bNT\bTR\bRO\bOL\bL variable.  If the line is a modified history
+              is  non-empty, add it to the history list according to the state
+              of the H\bHI\bIS\bST\bTC\bCO\bON\bNT\bTR\bRO\bOL\bL variable.  If the line is a modified  history
               line, then restore the history line to its original state.
        p\bpr\bre\bev\bvi\bio\bou\bus\bs-\b-h\bhi\bis\bst\bto\bor\bry\by (\b(C\bC-\b-p\bp)\b)
               Fetch the previous command from the history list, moving back in
               the list.
        n\bne\bex\bxt\bt-\b-h\bhi\bis\bst\bto\bor\bry\by (\b(C\bC-\b-n\bn)\b)
-              Fetch  the next command from the history list, moving forward in
+              Fetch the next command from the history list, moving forward  in
               the list.
        b\bbe\beg\bgi\bin\bnn\bni\bin\bng\bg-\b-o\bof\bf-\b-h\bhi\bis\bst\bto\bor\bry\by (\b(M\bM-\b-<\b<)\b)
               Move to the first line in the history.
        e\ben\bnd\bd-\b-o\bof\bf-\b-h\bhi\bis\bst\bto\bor\bry\by (\b(M\bM-\b->\b>)\b)
-              Move to the end of the input history, i.e., the  line  currently
+              Move  to  the end of the input history, i.e., the line currently
               being entered.
        r\bre\bev\bve\ber\brs\bse\be-\b-s\bse\bea\bar\brc\bch\bh-\b-h\bhi\bis\bst\bto\bor\bry\by (\b(C\bC-\b-r\br)\b)
-              Search  backward  starting  at  the current line and moving `up'
-              through the  history  as  necessary.   This  is  an  incremental
+              Search backward starting at the current  line  and  moving  `up'
+              through  the  history  as  necessary.   This  is  an incremental
               search.
        f\bfo\bor\brw\bwa\bar\brd\bd-\b-s\bse\bea\bar\brc\bch\bh-\b-h\bhi\bis\bst\bto\bor\bry\by (\b(C\bC-\b-s\bs)\b)
-              Search  forward  starting  at the current line and moving `down'
-              through the  history  as  necessary.   This  is  an  incremental
+              Search forward starting at the current line  and  moving  `down'
+              through  the  history  as  necessary.   This  is  an incremental
               search.
        n\bno\bon\bn-\b-i\bin\bnc\bcr\bre\bem\bme\ben\bnt\bta\bal\bl-\b-r\bre\bev\bve\ber\brs\bse\be-\b-s\bse\bea\bar\brc\bch\bh-\b-h\bhi\bis\bst\bto\bor\bry\by (\b(M\bM-\b-p\bp)\b)
               Search backward through the history starting at the current line
-              using a non-incremental search for  a  string  supplied  by  the
+              using  a  non-incremental  search  for  a string supplied by the
               user.
        n\bno\bon\bn-\b-i\bin\bnc\bcr\bre\bem\bme\ben\bnt\bta\bal\bl-\b-f\bfo\bor\brw\bwa\bar\brd\bd-\b-s\bse\bea\bar\brc\bch\bh-\b-h\bhi\bis\bst\bto\bor\bry\by (\b(M\bM-\b-n\bn)\b)
-              Search  forward  through  the  history  using  a non-incremental
+              Search forward  through  the  history  using  a  non-incremental
               search for a string supplied by the user.
        h\bhi\bis\bst\bto\bor\bry\by-\b-s\bse\bea\bar\brc\bch\bh-\b-f\bfo\bor\brw\bwa\bar\brd\bd
-              Search forward through the history for the string of  characters
-              between  the start of the current line and the point.  This is a
+              Search  forward through the history for the string of characters
+              between the start of the current line and the point.  This is  a
               non-incremental search.
        h\bhi\bis\bst\bto\bor\bry\by-\b-s\bse\bea\bar\brc\bch\bh-\b-b\bba\bac\bck\bkw\bwa\bar\brd\bd
               Search backward through the history for the string of characters
-              between  the start of the current line and the point.  This is a
+              between the start of the current line and the point.  This is  a
               non-incremental search.
        y\bya\ban\bnk\bk-\b-n\bnt\bth\bh-\b-a\bar\brg\bg (\b(M\bM-\b-C\bC-\b-y\by)\b)
-              Insert the first argument to the previous command  (usually  the
+              Insert  the  first argument to the previous command (usually the
               second word on the previous line) at point.  With an argument _\bn,
-              insert the _\bnth word from the previous command (the words in  the
-              previous  command  begin  with  word  0).   A  negative argument
+              insert  the _\bnth word from the previous command (the words in the
+              previous command  begin  with  word  0).   A  negative  argument
               inserts the _\bnth word from the end of the previous command.  Once
-              the  argument _\bn is computed, the argument is extracted as if the
+              the argument _\bn is computed, the argument is extracted as if  the
               "!_\bn" history expansion had been specified.
        y\bya\ban\bnk\bk-\b-l\bla\bas\bst\bt-\b-a\bar\brg\bg (\b(M\bM-\b-.\b.,\b, M\bM-\b-_\b_)\b)
-              Insert the last argument to the previous command (the last  word
+              Insert  the last argument to the previous command (the last word
               of the previous history entry).  With a numeric argument, behave
-              exactly like y\bya\ban\bnk\bk-\b-n\bnt\bth\bh-\b-a\bar\brg\bg.  Successive  calls  to  y\bya\ban\bnk\bk-\b-l\bla\bas\bst\bt-\b-a\bar\brg\bg
-              move  back through the history list, inserting the last word (or
-              the word specified by the argument to the first  call)  of  each
+              exactly  like  y\bya\ban\bnk\bk-\b-n\bnt\bth\bh-\b-a\bar\brg\bg.   Successive calls to y\bya\ban\bnk\bk-\b-l\bla\bas\bst\bt-\b-a\bar\brg\bg
+              move back through the history list, inserting the last word  (or
+              the  word  specified  by the argument to the first call) of each
               line in turn.  Any numeric argument supplied to these successive
-              calls determines the direction to move through the  history.   A
-              negative  argument  switches  the  direction through the history
+              calls  determines  the direction to move through the history.  A
+              negative argument switches the  direction  through  the  history
               (back or forward).  The history expansion facilities are used to
               extract the last word, as if the "!$" history expansion had been
               specified.
        s\bsh\bhe\bel\bll\bl-\b-e\bex\bxp\bpa\ban\bnd\bd-\b-l\bli\bin\bne\be (\b(M\bM-\b-C\bC-\b-e\be)\b)
               Expand the line as the shell does.  This performs alias and his-
               tory expansion as well as all of the shell word expansions.  See
-              H\bHI\bIS\bST\bTO\bOR\bRY\bE\bEX\bXP\bPA\bAN\bNS\bSI\bIO\bON\bN below for a description of history  expansion.
+              H\bHI\bIS\bST\bTO\bOR\bRY\b E\bEX\bXP\bPA\bAN\bNS\bSI\bIO\bON\bN below for a description of history expansion.
        h\bhi\bis\bst\bto\bor\bry\by-\b-e\bex\bxp\bpa\ban\bnd\bd-\b-l\bli\bin\bne\be (\b(M\bM-\b-^\b^)\b)
-              Perform  history  expansion  on  the  current line.  See H\bHI\bIS\bST\bTO\bOR\bRY\bY
+              Perform history expansion on  the  current  line.   See  H\bHI\bIS\bST\bTO\bOR\bRY\bY
               E\bEX\bXP\bPA\bAN\bNS\bSI\bIO\bON\bN below for a description of history expansion.
        m\bma\bag\bgi\bic\bc-\b-s\bsp\bpa\bac\bce\be
-              Perform history expansion on  the  current  line  and  insert  a
+              Perform  history  expansion  on  the  current  line and insert a
               space.  See H\bHI\bIS\bST\bTO\bOR\bRY\bY E\bEX\bXP\bPA\bAN\bNS\bSI\bIO\bON\bN below for a description of history
               expansion.
        a\bal\bli\bia\bas\bs-\b-e\bex\bxp\bpa\ban\bnd\bd-\b-l\bli\bin\bne\be
-              Perform alias expansion on the current line.  See A\bAL\bLI\bIA\bAS\bSE\bES\b above
+              Perform  alias expansion on the current line.  See A\bAL\bLI\bIA\bAS\bSE\bES\bS above
               for a description of alias expansion.
        h\bhi\bis\bst\bto\bor\bry\by-\b-a\ban\bnd\bd-\b-a\bal\bli\bia\bas\bs-\b-e\bex\bxp\bpa\ban\bnd\bd-\b-l\bli\bin\bne\be
               Perform history and alias expansion on the current line.
        i\bin\bns\bse\ber\brt\bt-\b-l\bla\bas\bst\bt-\b-a\bar\brg\bgu\bum\bme\ben\bnt\bt (\b(M\bM-\b-.\b.,\b, M\bM-\b-_\b_)\b)
               A synonym for y\bya\ban\bnk\bk-\b-l\bla\bas\bst\bt-\b-a\bar\brg\bg.
        o\bop\bpe\ber\bra\bat\bte\be-\b-a\ban\bnd\bd-\b-g\bge\bet\bt-\b-n\bne\bex\bxt\bt (\b(C\bC-\b-o\bo)\b)
-              Accept  the  current  line for execution and fetch the next line
-              relative to the current line from the history for editing.   Any
+              Accept the current line for execution and fetch  the  next  line
+              relative  to the current line from the history for editing.  Any
               argument is ignored.
        e\bed\bdi\bit\bt-\b-a\ban\bnd\bd-\b-e\bex\bxe\bec\bcu\but\bte\be-\b-c\bco\bom\bmm\bma\ban\bnd\bd (\b(C\bC-\b-x\bxC\bC-\b-e\be)\b)
-              Invoke  an  editor  on the current command line, and execute the
-              result as shell commands.   B\bBa\bas\bsh\bh  attempts  to  invoke  $\b$V\bVI\bIS\bSU\bUA\bAL\bL,
+              Invoke an editor on the current command line,  and  execute  the
+              result  as  shell  commands.   B\bBa\bas\bsh\bh  attempts to invoke $\b$V\bVI\bIS\bSU\bUA\bAL\bL,
               $\b$E\bED\bDI\bIT\bTO\bOR\bR, and _\be_\bm_\ba_\bc_\bs as the editor, in that order.
 
    C\bCo\bom\bmm\bma\ban\bnd\bds\bs f\bfo\bor\br C\bCh\bha\ban\bng\bgi\bin\bng\bg T\bTe\bex\bxt\bt
        _\be_\bn_\bd_\b-_\bo_\bf_\b-_\bf_\bi_\bl_\be (\b(u\bus\bsu\bua\bal\bll\bly\by C\bC-\b-d\bd)\b)
-              The  character  indicating  end-of-file  as set, for example, by
-              ``stty''.  If this character is read when there are  no  charac-
-              ters  on  the  line,  and point is at the beginning of the line,
+              The character indicating end-of-file as  set,  for  example,  by
+              ``stty''.   If  this character is read when there are no charac-
+              ters on the line, and point is at the  beginning  of  the  line,
               Readline interprets it as the end of input and returns E\bEO\bOF\bF.
        d\bde\bel\ble\bet\bte\be-\b-c\bch\bha\bar\br (\b(C\bC-\b-d\bd)\b)
               Delete the character at point.  If this function is bound to the
               same character as the tty E\bEO\bOF\bF character, as C\bC-\b-d\bd commonly is, see
               above for the effects.
        b\bba\bac\bck\bkw\bwa\bar\brd\bd-\b-d\bde\bel\ble\bet\bte\be-\b-c\bch\bha\bar\br (\b(R\bRu\bub\bbo\bou\but\bt)\b)
-              Delete the character behind the cursor.  When  given  a  numeric
+              Delete  the  character  behind the cursor.  When given a numeric
               argument, save the deleted text on the kill ring.
        f\bfo\bor\brw\bwa\bar\brd\bd-\b-b\bba\bac\bck\bkw\bwa\bar\brd\bd-\b-d\bde\bel\ble\bet\bte\be-\b-c\bch\bha\bar\br
-              Delete  the  character under the cursor, unless the cursor is at
+              Delete the character under the cursor, unless the cursor  is  at
               the end of the line, in which case the character behind the cur-
               sor is deleted.
        q\bqu\buo\bot\bte\bed\bd-\b-i\bin\bns\bse\ber\brt\bt (\b(C\bC-\b-q\bq,\b, C\bC-\b-v\bv)\b)
-              Add  the next character typed to the line verbatim.  This is how
+              Add the next character typed to the line verbatim.  This is  how
               to insert characters like C\bC-\b-q\bq, for example.
        t\bta\bab\bb-\b-i\bin\bns\bse\ber\brt\bt (\b(C\bC-\b-v\bv T\bTA\bAB\bB)\b)
               Insert a tab character.
        s\bse\bel\blf\bf-\b-i\bin\bns\bse\ber\brt\bt (\b(a\ba,\b, b\bb,\b, A\bA,\b, 1\b1,\b, !\b!,\b, .\b..\b..\b.)\b)
               Insert the character typed.
        t\btr\bra\ban\bns\bsp\bpo\bos\bse\be-\b-c\bch\bha\bar\brs\bs (\b(C\bC-\b-t\bt)\b)
-              Drag the character before point forward over  the  character  at
-              point,  moving point forward as well.  If point is at the end of
-              the line, then this transposes the two characters before  point.
+              Drag  the  character  before point forward over the character at
+              point, moving point forward as well.  If point is at the end  of
+              the  line, then this transposes the two characters before point.
               Negative arguments have no effect.
        t\btr\bra\ban\bns\bsp\bpo\bos\bse\be-\b-w\bwo\bor\brd\bds\bs (\b(M\bM-\b-t\bt)\b)
-              Drag  the  word  before  point past the word after point, moving
-              point over that word as well.  If point is at  the  end  of  the
+              Drag the word before point past the  word  after  point,  moving
+              point  over  that  word  as well.  If point is at the end of the
               line, this transposes the last two words on the line.
        u\bup\bpc\bca\bas\bse\be-\b-w\bwo\bor\brd\bd (\b(M\bM-\b-u\bu)\b)
-              Uppercase  the  current  (or  following)  word.  With a negative
+              Uppercase the current (or  following)  word.   With  a  negative
               argument, uppercase the previous word, but do not move point.
        d\bdo\bow\bwn\bnc\bca\bas\bse\be-\b-w\bwo\bor\brd\bd (\b(M\bM-\b-l\bl)\b)
-              Lowercase the current (or  following)  word.   With  a  negative
+              Lowercase  the  current  (or  following)  word.  With a negative
               argument, lowercase the previous word, but do not move point.
        c\bca\bap\bpi\bit\bta\bal\bli\biz\bze\be-\b-w\bwo\bor\brd\bd (\b(M\bM-\b-c\bc)\b)
-              Capitalize  the  current  (or  following) word.  With a negative
+              Capitalize the current (or following)  word.   With  a  negative
               argument, capitalize the previous word, but do not move point.
        o\bov\bve\ber\brw\bwr\bri\bit\bte\be-\b-m\bmo\bod\bde\be
-              Toggle overwrite mode.  With an explicit positive numeric  argu-
+              Toggle  overwrite mode.  With an explicit positive numeric argu-
               ment, switches to overwrite mode.  With an explicit non-positive
               numeric argument, switches to insert mode.  This command affects
-              only  e\bem\bma\bac\bcs\bs mode; v\bvi\bi mode does overwrite differently.  Each call
+              only e\bem\bma\bac\bcs\bs mode; v\bvi\bi mode does overwrite differently.  Each  call
               to _\br_\be_\ba_\bd_\bl_\bi_\bn_\be_\b(_\b) starts in insert mode.  In overwrite mode, charac-
-              ters  bound to s\bse\bel\blf\bf-\b-i\bin\bns\bse\ber\brt\bt replace the text at point rather than
-              pushing the text  to  the  right.   Characters  bound  to  b\bba\bac\bck\bk-\b-
-              w\bwa\bar\brd\bd-\b-d\bde\bel\ble\bet\bte\be-\b-c\bch\bha\bar\b replace  the  character  before  point  with a
+              ters bound to s\bse\bel\blf\bf-\b-i\bin\bns\bse\ber\brt\bt replace the text at point rather  than
+              pushing  the  text  to  the  right.   Characters  bound to b\bba\bac\bck\bk-\b-
+              w\bwa\bar\brd\bd-\b-d\bde\bel\ble\bet\bte\be-\b-c\bch\bha\bar\breplace  the  character  before  point  with  a
               space.  By default, this command is unbound.
 
    K\bKi\bil\bll\bli\bin\bng\bg a\ban\bnd\bd Y\bYa\ban\bnk\bki\bin\bng\bg
@@ -3335,31 +3338,31 @@ R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE
        b\bba\bac\bck\bkw\bwa\bar\brd\bd-\b-k\bki\bil\bll\bl-\b-l\bli\bin\bne\be (\b(C\bC-\b-x\bx R\bRu\bub\bbo\bou\but\bt)\b)
               Kill backward to the beginning of the line.
        u\bun\bni\bix\bx-\b-l\bli\bin\bne\be-\b-d\bdi\bis\bsc\bca\bar\brd\bd (\b(C\bC-\b-u\bu)\b)
-              Kill backward from point to the  beginning  of  the  line.   The
+              Kill  backward  from  point  to  the beginning of the line.  The
               killed text is saved on the kill-ring.
        k\bki\bil\bll\bl-\b-w\bwh\bho\bol\ble\be-\b-l\bli\bin\bne\be
-              Kill  all  characters on the current line, no matter where point
+              Kill all characters on the current line, no matter  where  point
               is.
        k\bki\bil\bll\bl-\b-w\bwo\bor\brd\bd (\b(M\bM-\b-d\bd)\b)
-              Kill from point to the end of the current word,  or  if  between
-              words,  to  the  end  of the next word.  Word boundaries are the
+              Kill  from  point  to the end of the current word, or if between
+              words, to the end of the next word.   Word  boundaries  are  the
               same as those used by f\bfo\bor\brw\bwa\bar\brd\bd-\b-w\bwo\bor\brd\bd.
        b\bba\bac\bck\bkw\bwa\bar\brd\bd-\b-k\bki\bil\bll\bl-\b-w\bwo\bor\brd\bd (\b(M\bM-\b-R\bRu\bub\bbo\bou\but\bt)\b)
-              Kill the word behind point.  Word boundaries  are  the  same  as
+              Kill  the  word  behind  point.  Word boundaries are the same as
               those used by b\bba\bac\bck\bkw\bwa\bar\brd\bd-\b-w\bwo\bor\brd\bd.
-       s\bsh\bhe\bel\bll\bl-\b-k\bki\bil\bll\bl-\b-w\bwo\bor\brd\bd (\b(M\bM-\b-d\bd)\b)
-              Kill  from  point  to the end of the current word, or if between
-              words, to the end of the next word.   Word  boundaries  are  the
+       s\bsh\bhe\bel\bll\bl-\b-k\bki\bil\bll\bl-\b-w\bwo\bor\brd\bd
+              Kill from point to the end of the current word,  or  if  between
+              words,  to  the  end  of the next word.  Word boundaries are the
               same as those used by s\bsh\bhe\bel\bll\bl-\b-f\bfo\bor\brw\bwa\bar\brd\bd-\b-w\bwo\bor\brd\bd.
-       s\bsh\bhe\bel\bll\bl-\b-b\bba\bac\bck\bkw\bwa\bar\brd\bd-\b-k\bki\bil\bll\bl-\b-w\bwo\bor\brd\bd (\b(M\bM-\b-R\bRu\bub\bbo\bou\but\bt)\b)
-              Kill  the  word  behind  point.  Word boundaries are the same as
+       s\bsh\bhe\bel\bll\bl-\b-b\bba\bac\bck\bkw\bwa\bar\brd\bd-\b-k\bki\bil\bll\bl-\b-w\bwo\bor\brd\bd
+              Kill the word behind point.  Word boundaries  are  the  same  as
               those used by s\bsh\bhe\bel\bll\bl-\b-b\bba\bac\bck\bkw\bwa\bar\brd\bd-\b-w\bwo\bor\brd\bd.
        u\bun\bni\bix\bx-\b-w\bwo\bor\brd\bd-\b-r\bru\bub\bbo\bou\but\bt (\b(C\bC-\b-w\bw)\b)
-              Kill the word behind point, using white space as a  word  bound-
+              Kill  the  word behind point, using white space as a word bound-
               ary.  The killed text is saved on the kill-ring.
        u\bun\bni\bix\bx-\b-f\bfi\bil\ble\ben\bna\bam\bme\be-\b-r\bru\bub\bbo\bou\but\bt
-              Kill  the  word  behind  point,  using white space and the slash
-              character as the word boundaries.  The killed text is  saved  on
+              Kill the word behind point, using  white  space  and  the  slash
+              character  as  the word boundaries.  The killed text is saved on
               the kill-ring.
        d\bde\bel\ble\bet\bte\be-\b-h\bho\bor\bri\biz\bzo\bon\bnt\bta\bal\bl-\b-s\bsp\bpa\bac\bce\be (\b(M\bM-\b-\\b\)\b)
               Delete all spaces and tabs around point.
@@ -3368,65 +3371,65 @@ R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE
        c\bco\bop\bpy\by-\b-r\bre\beg\bgi\bio\bon\bn-\b-a\bas\bs-\b-k\bki\bil\bll\bl
               Copy the text in the region to the kill buffer.
        c\bco\bop\bpy\by-\b-b\bba\bac\bck\bkw\bwa\bar\brd\bd-\b-w\bwo\bor\brd\bd
-              Copy  the word before point to the kill buffer.  The word bound-
+              Copy the word before point to the kill buffer.  The word  bound-
               aries are the same as b\bba\bac\bck\bkw\bwa\bar\brd\bd-\b-w\bwo\bor\brd\bd.
        c\bco\bop\bpy\by-\b-f\bfo\bor\brw\bwa\bar\brd\bd-\b-w\bwo\bor\brd\bd
-              Copy the word following point to  the  kill  buffer.   The  word
+              Copy  the  word  following  point  to the kill buffer.  The word
               boundaries are the same as f\bfo\bor\brw\bwa\bar\brd\bd-\b-w\bwo\bor\brd\bd.
        y\bya\ban\bnk\bk (\b(C\bC-\b-y\by)\b)
               Yank the top of the kill ring into the buffer at point.
        y\bya\ban\bnk\bk-\b-p\bpo\bop\bp (\b(M\bM-\b-y\by)\b)
-              Rotate  the kill ring, and yank the new top.  Only works follow-
+              Rotate the kill ring, and yank the new top.  Only works  follow-
               ing y\bya\ban\bnk\bk or y\bya\ban\bnk\bk-\b-p\bpo\bop\bp.
 
    N\bNu\bum\bme\ber\bri\bic\bc A\bAr\brg\bgu\bum\bme\ben\bnt\bts\bs
        d\bdi\big\bgi\bit\bt-\b-a\bar\brg\bgu\bum\bme\ben\bnt\bt (\b(M\bM-\b-0\b0,\b, M\bM-\b-1\b1,\b, .\b..\b..\b.,\b, M\bM-\b--\b-)\b)
-              Add this digit to the argument already accumulating, or start  a
+              Add  this digit to the argument already accumulating, or start a
               new argument.  M-- starts a negative argument.
        u\bun\bni\biv\bve\ber\brs\bsa\bal\bl-\b-a\bar\brg\bgu\bum\bme\ben\bnt\bt
-              This  is another way to specify an argument.  If this command is
-              followed by one or more digits, optionally with a leading  minus
-              sign,  those digits define the argument.  If the command is fol-
-              lowed by digits, executing  u\bun\bni\biv\bve\ber\brs\bsa\bal\bl-\b-a\bar\brg\bgu\bum\bme\ben\bnt\bt  again  ends  the
-              numeric  argument, but is otherwise ignored.  As a special case,
-              if this command is immediately followed by a character  that  is
-              neither  a  digit or minus sign, the argument count for the next
-              command is multiplied by four.  The argument count is  initially
-              one,  so  executing this function the first time makes the argu-
+              This is another way to specify an argument.  If this command  is
+              followed  by one or more digits, optionally with a leading minus
+              sign, those digits define the argument.  If the command is  fol-
+              lowed  by  digits,  executing  u\bun\bni\biv\bve\ber\brs\bsa\bal\bl-\b-a\bar\brg\bgu\bum\bme\ben\bnt\bt again ends the
+              numeric argument, but is otherwise ignored.  As a special  case,
+              if  this  command is immediately followed by a character that is
+              neither a digit or minus sign, the argument count for  the  next
+              command  is multiplied by four.  The argument count is initially
+              one, so executing this function the first time makes  the  argu-
               ment count four, a second time makes the argument count sixteen,
               and so on.
 
    C\bCo\bom\bmp\bpl\ble\bet\bti\bin\bng\bg
        c\bco\bom\bmp\bpl\ble\bet\bte\be (\b(T\bTA\bAB\bB)\b)
-              Attempt  to  perform  completion on the text before point.  B\bBa\bas\bsh\bh
+              Attempt to perform completion on the text  before  point.   B\bBa\bas\bsh\bh
               attempts completion treating the text as a variable (if the text
-              begins  with  $\b$), username (if the text begins with ~\b~), hostname
-              (if the text begins with @\b@), or command (including  aliases  and
+              begins with $\b$), username (if the text begins with  ~\b~),  hostname
+              (if  the  text begins with @\b@), or command (including aliases and
               functions) in turn.  If none of these produces a match, filename
               completion is attempted.
        p\bpo\bos\bss\bsi\bib\bbl\ble\be-\b-c\bco\bom\bmp\bpl\ble\bet\bti\bio\bon\bns\bs (\b(M\bM-\b-?\b?)\b)
               List the possible completions of the text before point.
        i\bin\bns\bse\ber\brt\bt-\b-c\bco\bom\bmp\bpl\ble\bet\bti\bio\bon\bns\bs (\b(M\bM-\b-*\b*)\b)
-              Insert all completions of the text before point that would  have
+              Insert  all completions of the text before point that would have
               been generated by p\bpo\bos\bss\bsi\bib\bbl\ble\be-\b-c\bco\bom\bmp\bpl\ble\bet\bti\bio\bon\bns\bs.
        m\bme\ben\bnu\bu-\b-c\bco\bom\bmp\bpl\ble\bet\bte\be
-              Similar  to c\bco\bom\bmp\bpl\ble\bet\bte\be, but replaces the word to be completed with
-              a single match from the list of possible completions.   Repeated
-              execution  of  m\bme\ben\bnu\bu-\b-c\bco\bom\bmp\bpl\ble\bet\bte\be  steps through the list of possible
-              completions, inserting each match in turn.  At the  end  of  the
+              Similar to c\bco\bom\bmp\bpl\ble\bet\bte\be, but replaces the word to be completed  with
+              a  single match from the list of possible completions.  Repeated
+              execution of m\bme\ben\bnu\bu-\b-c\bco\bom\bmp\bpl\ble\bet\bte\be steps through the  list  of  possible
+              completions,  inserting  each  match in turn.  At the end of the
               list of completions, the bell is rung (subject to the setting of
               b\bbe\bel\bll\bl-\b-s\bst\bty\byl\ble\be) and the original text is restored.  An argument of _\bn
-              moves  _\bn  positions  forward  in the list of matches; a negative
-              argument may be used to move backward through  the  list.   This
-              command  is  intended  to  be  bound  to  T\bTA\bAB\bB, but is unbound by
+              moves _\bn positions forward in the list  of  matches;  a  negative
+              argument  may  be  used to move backward through the list.  This
+              command is intended to be  bound  to  T\bTA\bAB\bB,  but  is  unbound  by
               default.
        m\bme\ben\bnu\bu-\b-c\bco\bom\bmp\bpl\ble\bet\bte\be-\b-b\bba\bac\bck\bkw\bwa\bar\brd\bd
-              Identical to m\bme\ben\bnu\bu-\b-c\bco\bom\bmp\bpl\ble\bet\bte\be, but moves backward through the  list
-              of  possible  completions,  as if m\bme\ben\bnu\bu-\b-c\bco\bom\bmp\bpl\ble\bet\bte\be had been given a
+              Identical  to m\bme\ben\bnu\bu-\b-c\bco\bom\bmp\bpl\ble\bet\bte\be, but moves backward through the list
+              of possible completions, as if m\bme\ben\bnu\bu-\b-c\bco\bom\bmp\bpl\ble\bet\bte\be had  been  given  a
               negative argument.  This command is unbound by default.
        d\bde\bel\ble\bet\bte\be-\b-c\bch\bha\bar\br-\b-o\bor\br-\b-l\bli\bis\bst\bt
-              Deletes the character under the cursor if not at  the  beginning
-              or  end  of  the  line (like d\bde\bel\ble\bet\bte\be-\b-c\bch\bha\bar\br).  If at the end of the
+              Deletes  the  character under the cursor if not at the beginning
+              or end of the line (like d\bde\bel\ble\bet\bte\be-\b-c\bch\bha\bar\br).  If at  the  end  of  the
               line, behaves identically to p\bpo\bos\bss\bsi\bib\bbl\ble\be-\b-c\bco\bom\bmp\bpl\ble\bet\bti\bio\bon\bns\bs.  This command
               is unbound by default.
        c\bco\bom\bmp\bpl\ble\bet\bte\be-\b-f\bfi\bil\ble\ben\bna\bam\bme\be (\b(M\bM-\b-/\b/)\b)
@@ -3435,216 +3438,216 @@ R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE
               List the possible completions of the text before point, treating
               it as a filename.
        c\bco\bom\bmp\bpl\ble\bet\bte\be-\b-u\bus\bse\ber\brn\bna\bam\bme\be (\b(M\bM-\b-~\b~)\b)
-              Attempt completion on the text before point, treating  it  as  a
+              Attempt  completion  on  the text before point, treating it as a
               username.
        p\bpo\bos\bss\bsi\bib\bbl\ble\be-\b-u\bus\bse\ber\brn\bna\bam\bme\be-\b-c\bco\bom\bmp\bpl\ble\bet\bti\bio\bon\bns\bs (\b(C\bC-\b-x\bx ~\b~)\b)
               List the possible completions of the text before point, treating
               it as a username.
        c\bco\bom\bmp\bpl\ble\bet\bte\be-\b-v\bva\bar\bri\bia\bab\bbl\ble\be (\b(M\bM-\b-$\b$)\b)
-              Attempt completion on the text before point, treating  it  as  a
+              Attempt  completion  on  the text before point, treating it as a
               shell variable.
        p\bpo\bos\bss\bsi\bib\bbl\ble\be-\b-v\bva\bar\bri\bia\bab\bbl\ble\be-\b-c\bco\bom\bmp\bpl\ble\bet\bti\bio\bon\bns\bs (\b(C\bC-\b-x\bx $\b$)\b)
               List the possible completions of the text before point, treating
               it as a shell variable.
        c\bco\bom\bmp\bpl\ble\bet\bte\be-\b-h\bho\bos\bst\btn\bna\bam\bme\be (\b(M\bM-\b-@\b@)\b)
-              Attempt completion on the text before point, treating  it  as  a
+              Attempt  completion  on  the text before point, treating it as a
               hostname.
        p\bpo\bos\bss\bsi\bib\bbl\ble\be-\b-h\bho\bos\bst\btn\bna\bam\bme\be-\b-c\bco\bom\bmp\bpl\ble\bet\bti\bio\bon\bns\bs (\b(C\bC-\b-x\bx @\b@)\b)
               List the possible completions of the text before point, treating
               it as a hostname.
        c\bco\bom\bmp\bpl\ble\bet\bte\be-\b-c\bco\bom\bmm\bma\ban\bnd\bd (\b(M\bM-\b-!\b!)\b)
-              Attempt completion on the text before point, treating  it  as  a
-              command  name.   Command  completion  attempts to match the text
-              against  aliases,  reserved  words,   shell   functions,   shell
+              Attempt  completion  on  the text before point, treating it as a
+              command name.  Command completion attempts  to  match  the  text
+              against   aliases,   reserved   words,  shell  functions,  shell
               builtins, and finally executable filenames, in that order.
        p\bpo\bos\bss\bsi\bib\bbl\ble\be-\b-c\bco\bom\bmm\bma\ban\bnd\bd-\b-c\bco\bom\bmp\bpl\ble\bet\bti\bio\bon\bns\bs (\b(C\bC-\b-x\bx !\b!)\b)
               List the possible completions of the text before point, treating
               it as a command name.
        d\bdy\byn\bna\bam\bmi\bic\bc-\b-c\bco\bom\bmp\bpl\ble\bet\bte\be-\b-h\bhi\bis\bst\bto\bor\bry\by (\b(M\bM-\b-T\bTA\bAB\bB)\b)
-              Attempt completion on the text before point, comparing the  text
-              against  lines  from  the  history  list for possible completion
+              Attempt  completion on the text before point, comparing the text
+              against lines from the  history  list  for  possible  completion
               matches.
        d\bda\bab\bbb\bbr\bre\bev\bv-\b-e\bex\bxp\bpa\ban\bnd\bd
-              Attempt menu completion on the text before point, comparing  the
+              Attempt  menu completion on the text before point, comparing the
               text against lines from the history list for possible completion
               matches.
        c\bco\bom\bmp\bpl\ble\bet\bte\be-\b-i\bin\bnt\bto\bo-\b-b\bbr\bra\bac\bce\bes\bs (\b(M\bM-\b-{\b{)\b)
               Perform filename completion and insert the list of possible com-
-              pletions  enclosed within braces so the list is available to the
+              pletions enclosed within braces so the list is available to  the
               shell (see B\bBr\bra\bac\bce\be E\bEx\bxp\bpa\ban\bns\bsi\bio\bon\bn above).
 
    K\bKe\bey\byb\bbo\boa\bar\brd\bd M\bMa\bac\bcr\bro\bos\bs
        s\bst\bta\bar\brt\bt-\b-k\bkb\bbd\bd-\b-m\bma\bac\bcr\bro\bo (\b(C\bC-\b-x\bx (\b()\b)
-              Begin saving the characters  typed  into  the  current  keyboard
+              Begin  saving  the  characters  typed  into the current keyboard
               macro.
        e\ben\bnd\bd-\b-k\bkb\bbd\bd-\b-m\bma\bac\bcr\bro\bo (\b(C\bC-\b-x\bx )\b))\b)
               Stop saving the characters typed into the current keyboard macro
               and store the definition.
        c\bca\bal\bll\bl-\b-l\bla\bas\bst\bt-\b-k\bkb\bbd\bd-\b-m\bma\bac\bcr\bro\bo (\b(C\bC-\b-x\bx e\be)\b)
-              Re-execute the last keyboard macro defined, by making the  char-
+              Re-execute  the last keyboard macro defined, by making the char-
               acters in the macro appear as if typed at the keyboard.
        p\bpr\bri\bin\bnt\bt-\b-l\bla\bas\bst\bt-\b-k\bkb\bbd\bd-\b-m\bma\bac\bcr\bro\bo (\b()\b)
-              Print  the  last keyboard macro defined in a format suitable for
+              Print the last keyboard macro defined in a format  suitable  for
               the _\bi_\bn_\bp_\bu_\bt_\br_\bc file.
 
    M\bMi\bis\bsc\bce\bel\bll\bla\ban\bne\beo\bou\bus\bs
        r\bre\be-\b-r\bre\bea\bad\bd-\b-i\bin\bni\bit\bt-\b-f\bfi\bil\ble\be (\b(C\bC-\b-x\bx C\bC-\b-r\br)\b)
-              Read in the contents of the _\bi_\bn_\bp_\bu_\bt_\br_\bc file,  and  incorporate  any
+              Read  in  the  contents of the _\bi_\bn_\bp_\bu_\bt_\br_\bc file, and incorporate any
               bindings or variable assignments found there.
        a\bab\bbo\bor\brt\bt (\b(C\bC-\b-g\bg)\b)
-              Abort  the  current editing command and ring the terminal's bell
+              Abort the current editing command and ring the  terminal's  bell
               (subject to the setting of b\bbe\bel\bll\bl-\b-s\bst\bty\byl\ble\be).
        d\bdo\bo-\b-u\bup\bpp\bpe\ber\brc\bca\bas\bse\be-\b-v\bve\ber\brs\bsi\bio\bon\bn (\b(M\bM-\b-a\ba,\b, M\bM-\b-b\bb,\b, M\bM-\b-_\bx,\b, .\b..\b..\b.)\b)
-              If the metafied character _\bx is lowercase, run the  command  that
+              If  the  metafied character _\bx is lowercase, run the command that
               is bound to the corresponding uppercase character.
        p\bpr\bre\bef\bfi\bix\bx-\b-m\bme\bet\bta\ba (\b(E\bES\bSC\bC)\b)
               Metafy the next character typed.  E\bES\bSC\bC f\bf is equivalent to M\bMe\bet\bta\ba-\b-f\bf.
        u\bun\bnd\bdo\bo (\b(C\bC-\b-_\b_,\b, C\bC-\b-x\bx C\bC-\b-u\bu)\b)
               Incremental undo, separately remembered for each line.
        r\bre\bev\bve\ber\brt\bt-\b-l\bli\bin\bne\be (\b(M\bM-\b-r\br)\b)
-              Undo all changes made to this line.  This is like executing  the
-              u\bun\bnd\bdo\b command  enough  times  to  return the line to its initial
+              Undo  all changes made to this line.  This is like executing the
+              u\bun\bnd\bdo\bcommand enough times to return  the  line  to  its  initial
               state.
        t\bti\bil\bld\bde\be-\b-e\bex\bxp\bpa\ban\bnd\bd (\b(M\bM-\b-&\b&)\b)
               Perform tilde expansion on the current word.
        s\bse\bet\bt-\b-m\bma\bar\brk\bk (\b(C\bC-\b-@\b@,\b, M\bM-\b-<\b<s\bsp\bpa\bac\bce\be>\b>)\b)
-              Set the mark to the point.  If a numeric argument  is  supplied,
+              Set  the  mark to the point.  If a numeric argument is supplied,
               the mark is set to that position.
        e\bex\bxc\bch\bha\ban\bng\bge\be-\b-p\bpo\boi\bin\bnt\bt-\b-a\ban\bnd\bd-\b-m\bma\bar\brk\bk (\b(C\bC-\b-x\bx C\bC-\b-x\bx)\b)
-              Swap  the  point  with the mark.  The current cursor position is
-              set to the saved position, and the old cursor position is  saved
+              Swap the point with the mark.  The current  cursor  position  is
+              set  to the saved position, and the old cursor position is saved
               as the mark.
        c\bch\bha\bar\bra\bac\bct\bte\ber\br-\b-s\bse\bea\bar\brc\bch\bh (\b(C\bC-\b-]\b])\b)
               A character is read and point is moved to the next occurrence of
-              that character.  A negative count searches for  previous  occur-
+              that  character.   A negative count searches for previous occur-
               rences.
        c\bch\bha\bar\bra\bac\bct\bte\ber\br-\b-s\bse\bea\bar\brc\bch\bh-\b-b\bba\bac\bck\bkw\bwa\bar\brd\bd (\b(M\bM-\b-C\bC-\b-]\b])\b)
-              A  character  is  read and point is moved to the previous occur-
-              rence of that character.  A negative count searches  for  subse-
+              A character is read and point is moved to  the  previous  occur-
+              rence  of  that character.  A negative count searches for subse-
               quent occurrences.
        s\bsk\bki\bip\bp-\b-c\bcs\bsi\bi-\b-s\bse\beq\bqu\bue\ben\bnc\bce\be
-              Read  enough  characters to consume a multi-key sequence such as
-              those defined for keys like Home and End.  Such sequences  begin
+              Read enough characters to consume a multi-key sequence  such  as
+              those  defined for keys like Home and End.  Such sequences begin
               with a Control Sequence Indicator (CSI), usually ESC-[.  If this
-              sequence is bound to "\[", keys producing  such  sequences  will
-              have  no  effect  unless explicitly bound to a readline command,
-              instead of inserting stray characters into the  editing  buffer.
+              sequence  is  bound  to "\[", keys producing such sequences will
+              have no effect unless explicitly bound to  a  readline  command,
+              instead  of  inserting stray characters into the editing buffer.
               This is unbound by default, but usually bound to ESC-[.
        i\bin\bns\bse\ber\brt\bt-\b-c\bco\bom\bmm\bme\ben\bnt\bt (\b(M\bM-\b-#\b#)\b)
-              Without  a  numeric  argument,  the  value  of the readline c\bco\bom\bm-\b-
-              m\bme\ben\bnt\bt-\b-b\bbe\beg\bgi\bin\bvariable is inserted at the beginning of the  current
+              Without a numeric argument,  the  value  of  the  readline  c\bco\bom\bm-\b-
+              m\bme\ben\bnt\bt-\b-b\bbe\beg\bgi\bin\b variable is inserted at the beginning of the current
               line.  If a numeric argument is supplied, this command acts as a
-              toggle:  if the characters at the beginning of the line  do  not
-              match  the value of c\bco\bom\bmm\bme\ben\bnt\bt-\b-b\bbe\beg\bgi\bin\bn, the value is inserted, other-
+              toggle:   if  the characters at the beginning of the line do not
+              match the value of c\bco\bom\bmm\bme\ben\bnt\bt-\b-b\bbe\beg\bgi\bin\bn, the value is inserted,  other-
               wise the characters in c\bco\bom\bmm\bme\ben\bnt\bt-\b-b\bbe\beg\bgi\bin\bn are deleted from the begin-
-              ning  of the line.  In either case, the line is accepted as if a
-              newline had been typed.   The  default  value  of  c\bco\bom\bmm\bme\ben\bnt\bt-\b-b\bbe\beg\bgi\bin\bn
-              causes  this  command  to make the current line a shell comment.
-              If a  numeric  argument  causes  the  comment  character  to  be
+              ning of the line.  In either case, the line is accepted as if  a
+              newline  had  been  typed.   The  default value of c\bco\bom\bmm\bme\ben\bnt\bt-\b-b\bbe\beg\bgi\bin\bn
+              causes this command to make the current line  a  shell  comment.
+              If  a  numeric  argument  causes  the  comment  character  to be
               removed, the line will be executed by the shell.
        g\bgl\blo\bob\bb-\b-c\bco\bom\bmp\bpl\ble\bet\bte\be-\b-w\bwo\bor\brd\bd (\b(M\bM-\b-g\bg)\b)
-              The  word  before  point  is  treated  as a pattern for pathname
-              expansion, with an asterisk implicitly appended.   This  pattern
-              is  used  to  generate a list of matching filenames for possible
+              The word before point is  treated  as  a  pattern  for  pathname
+              expansion,  with  an asterisk implicitly appended.  This pattern
+              is used to generate a list of matching  filenames  for  possible
               completions.
        g\bgl\blo\bob\bb-\b-e\bex\bxp\bpa\ban\bnd\bd-\b-w\bwo\bor\brd\bd (\b(C\bC-\b-x\bx *\b*)\b)
-              The word before point is  treated  as  a  pattern  for  pathname
-              expansion,  and  the  list  of  matching  filenames is inserted,
-              replacing the word.  If  a  numeric  argument  is  supplied,  an
+              The  word  before  point  is  treated  as a pattern for pathname
+              expansion, and the  list  of  matching  filenames  is  inserted,
+              replacing  the  word.   If  a  numeric  argument is supplied, an
               asterisk is appended before pathname expansion.
        g\bgl\blo\bob\bb-\b-l\bli\bis\bst\bt-\b-e\bex\bxp\bpa\ban\bns\bsi\bio\bon\bns\bs (\b(C\bC-\b-x\bx g\bg)\b)
-              The  list  of  expansions  that  would  have  been  generated by
-              g\bgl\blo\bob\bb-\b-e\bex\bxp\bpa\ban\bnd\bd-\b-w\bwo\bor\brd\bis displayed, and the line is  redrawn.   If  a
-              numeric  argument  is  supplied,  an asterisk is appended before
+              The list  of  expansions  that  would  have  been  generated  by
+              g\bgl\blo\bob\bb-\b-e\bex\bxp\bpa\ban\bnd\bd-\b-w\bwo\bor\brd\b is  displayed,  and the line is redrawn.  If a
+              numeric argument is supplied, an  asterisk  is  appended  before
               pathname expansion.
        d\bdu\bum\bmp\bp-\b-f\bfu\bun\bnc\bct\bti\bio\bon\bns\bs
-              Print all of the functions and their key bindings to  the  read-
+              Print  all  of the functions and their key bindings to the read-
               line output stream.  If a numeric argument is supplied, the out-
-              put is formatted in such a way that it can be made  part  of  an
+              put  is  formatted  in such a way that it can be made part of an
               _\bi_\bn_\bp_\bu_\bt_\br_\bc file.
        d\bdu\bum\bmp\bp-\b-v\bva\bar\bri\bia\bab\bbl\ble\bes\bs
               Print all of the settable readline variables and their values to
-              the readline output stream.  If a numeric argument is  supplied,
-              the  output  is formatted in such a way that it can be made part
+              the  readline output stream.  If a numeric argument is supplied,
+              the output is formatted in such a way that it can be  made  part
               of an _\bi_\bn_\bp_\bu_\bt_\br_\bc file.
        d\bdu\bum\bmp\bp-\b-m\bma\bac\bcr\bro\bos\bs
-              Print all of the readline key sequences bound to macros and  the
-              strings  they  output.   If  a numeric argument is supplied, the
+              Print  all of the readline key sequences bound to macros and the
+              strings they output.  If a numeric  argument  is  supplied,  the
               output is formatted in such a way that it can be made part of an
               _\bi_\bn_\bp_\bu_\bt_\br_\bc file.
        d\bdi\bis\bsp\bpl\bla\bay\by-\b-s\bsh\bhe\bel\bll\bl-\b-v\bve\ber\brs\bsi\bio\bon\bn (\b(C\bC-\b-x\bx C\bC-\b-v\bv)\b)
-              Display  version information about the current instance of b\bba\bas\bsh\bh.
+              Display version information about the current instance of  b\bba\bas\bsh\bh.
 
    P\bPr\bro\bog\bgr\bra\bam\bmm\bma\bab\bbl\ble\be C\bCo\bom\bmp\bpl\ble\bet\bti\bio\bon\bn
-       When word completion is attempted for an  argument  to  a  command  for
-       which  a  completion  specification (a _\bc_\bo_\bm_\bp_\bs_\bp_\be_\bc) has been defined using
-       the c\bco\bom\bmp\bpl\ble\bet\bte\be builtin (see  S\bSH\bHE\bEL\bLL\bL  B\bBU\bUI\bIL\bLT\bTI\bIN\bN  C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS  below),  the  pro-
+       When  word  completion  is  attempted  for an argument to a command for
+       which a completion specification (a _\bc_\bo_\bm_\bp_\bs_\bp_\be_\bc) has  been  defined  using
+       the  c\bco\bom\bmp\bpl\ble\bet\bte\be  builtin  (see  S\bSH\bHE\bEL\bLL\bL  B\bBU\bUI\bIL\bLT\bTI\bIN\bN  C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS below), the pro-
        grammable completion facilities are invoked.
 
-       First,  the  command  name  is  identified.  If the command word is the
-       empty string (completion attempted at the beginning of an empty  line),
-       any  compspec  defined  with  the  -\b-E\bE option to c\bco\bom\bmp\bpl\ble\bet\bte\be is used.  If a
-       compspec has been defined for that command, the  compspec  is  used  to
+       First, the command name is identified.  If  the  command  word  is  the
+       empty  string (completion attempted at the beginning of an empty line),
+       any compspec defined with the -\b-E\bE option to  c\bco\bom\bmp\bpl\ble\bet\bte\be  is  used.   If  a
+       compspec  has  been  defined  for that command, the compspec is used to
        generate the list of possible completions for the word.  If the command
-       word is a full pathname, a compspec for the full pathname  is  searched
-       for  first.   If no compspec is found for the full pathname, an attempt
-       is made to find a compspec for the portion following the  final  slash.
-       If  those  searches  do  not result in a compspec, any compspec defined
+       word  is  a full pathname, a compspec for the full pathname is searched
+       for first.  If no compspec is found for the full pathname,  an  attempt
+       is  made  to find a compspec for the portion following the final slash.
+       If those searches do not result in a  compspec,  any  compspec  defined
        with the -\b-D\bD option to c\bco\bom\bmp\bpl\ble\bet\bte\be is used as the default.
 
-       Once a compspec has been found, it is used  to  generate  the  list  of
-       matching  words.   If a compspec is not found, the default b\bba\bas\bsh\bh comple-
+       Once  a  compspec  has  been  found, it is used to generate the list of
+       matching words.  If a compspec is not found, the default  b\bba\bas\bsh\b comple-
        tion as described above under C\bCo\bom\bmp\bpl\ble\bet\bti\bin\bng\bg is performed.
 
-       First, the actions specified by the compspec are  used.   Only  matches
-       which  are prefixed by the word being completed are returned.  When the
-       -\b-f\bor -\b-d\bd option is used for filename or directory name completion,  the
+       First,  the  actions  specified by the compspec are used.  Only matches
+       which are prefixed by the word being completed are returned.  When  the
+       -\b-f\b or -\b-d\bd option is used for filename or directory name completion, the
        shell variable F\bFI\bIG\bGN\bNO\bOR\bRE\bE is used to filter the matches.
 
-       Any  completions  specified  by  a pathname expansion pattern to the -\b-G\bG
+       Any completions specified by a pathname expansion  pattern  to  the  -\b-G\bG
        option are generated next.  The words generated by the pattern need not
-       match  the  word being completed.  The G\bGL\bLO\bOB\bBI\bIG\bGN\bNO\bOR\bRE\bE shell variable is not
+       match the word being completed.  The G\bGL\bLO\bOB\bBI\bIG\bGN\bNO\bOR\bRE\bE shell variable  is  not
        used to filter the matches, but the F\bFI\bIG\bGN\bNO\bOR\bRE\bE variable is used.
 
-       Next, the string specified as the argument to the -\b-W\bW option is  consid-
-       ered.   The  string is first split using the characters in the I\bIF\bFS\bS spe-
-       cial variable as delimiters.  Shell quoting is honored.  Each  word  is
-       then  expanded  using  brace  expansion, tilde expansion, parameter and
-       variable expansion, command substitution, and arithmetic expansion,  as
+       Next,  the string specified as the argument to the -\b-W\bW option is consid-
+       ered.  The string is first split using the characters in the  I\bIF\bFS\b spe-
+       cial  variable  as delimiters.  Shell quoting is honored.  Each word is
+       then expanded using brace expansion,  tilde  expansion,  parameter  and
+       variable  expansion, command substitution, and arithmetic expansion, as
        described above under E\bEX\bXP\bPA\bAN\bNS\bSI\bIO\bON\bN.  The results are split using the rules
        described above under W\bWo\bor\brd\bd S\bSp\bpl\bli\bit\btt\bti\bin\bng\bg.  The results of the expansion are
        prefix-matched against the word being completed, and the matching words
        become the possible completions.
 
-       After these matches have been generated, any shell function or  command
-       specified  with  the -\b-F\bF and -\b-C\bC options is invoked.  When the command or
+       After  these matches have been generated, any shell function or command
+       specified with the -\b-F\bF and -\b-C\bC options is invoked.  When the  command  or
        function is invoked, the C\bCO\bOM\bMP\bP_\b_L\bLI\bIN\bNE\bE, C\bCO\bOM\bMP\bP_\b_P\bPO\bOI\bIN\bNT\bT, C\bCO\bOM\bMP\bP_\b_K\bKE\bEY\bY, and C\bCO\bOM\bMP\bP_\b_T\bTY\bYP\bPE\bE
        variables are assigned values as described above under S\bSh\bhe\bel\bll\bl V\bVa\bar\bri\bia\bab\bbl\ble\bes\bs.
-       If a shell function is being invoked,  the  C\bCO\bOM\bMP\bP_\b_W\bWO\bOR\bRD\bDS\bS  and  C\bCO\bOM\bMP\bP_\b_C\bCW\bWO\bOR\bRD\bD
-       variables  are  also set.  When the function or command is invoked, the
-       first argument ($\b$1\b1) is the name of  the  command  whose  arguments  are
-       being  completed, the second argument ($\b$2\b2) is the word being completed,
-       and the third argument ($\b$3\b3) is the word preceding the word  being  com-
+       If  a  shell  function  is being invoked, the C\bCO\bOM\bMP\bP_\b_W\bWO\bOR\bRD\bDS\bS and C\bCO\bOM\bMP\bP_\b_C\bCW\bWO\bOR\bRD\bD
+       variables are also set.  When the function or command is  invoked,  the
+       first  argument  ($\b$1\b1)  is  the  name of the command whose arguments are
+       being completed, the second argument ($\b$2\b2) is the word being  completed,
+       and  the  third argument ($\b$3\b3) is the word preceding the word being com-
        pleted on the current command line.  No filtering of the generated com-
        pletions against the word being completed is performed; the function or
        command has complete freedom in generating the matches.
 
-       Any  function specified with -\b-F\bF is invoked first.  The function may use
-       any of the shell facilities, including the  c\bco\bom\bmp\bpg\bge\ben\bn  builtin  described
-       below,  to  generate the matches.  It must put the possible completions
+       Any function specified with -\b-F\bF is invoked first.  The function may  use
+       any  of  the  shell facilities, including the c\bco\bom\bmp\bpg\bge\ben\bn builtin described
+       below, to generate the matches.  It must put the  possible  completions
        in the C\bCO\bOM\bMP\bPR\bRE\bEP\bPL\bLY\bY array variable, one per array element.
 
-       Next, any command specified with the -\b-C\bC option is invoked in  an  envi-
-       ronment  equivalent to command substitution.  It should print a list of
-       completions, one per line, to the standard output.   Backslash  may  be
+       Next,  any  command specified with the -\b-C\bC option is invoked in an envi-
+       ronment equivalent to command substitution.  It should print a list  of
+       completions,  one  per  line, to the standard output.  Backslash may be
        used to escape a newline, if necessary.
 
-       After  all of the possible completions are generated, any filter speci-
-       fied with the -\b-X\bX option is applied to the list.  The filter is  a  pat-
-       tern  as  used  for  pathname expansion; a &\b& in the pattern is replaced
-       with the text of the word being completed.  A literal &\b& may be  escaped
-       with  a  backslash; the backslash is removed before attempting a match.
-       Any completion that matches the pattern will be removed from the  list.
+       After all of the possible completions are generated, any filter  speci-
+       fied  with  the -\b-X\bX option is applied to the list.  The filter is a pat-
+       tern as used for pathname expansion; a &\b& in  the  pattern  is  replaced
+       with  the text of the word being completed.  A literal &\b& may be escaped
+       with a backslash; the backslash is removed before attempting  a  match.
+       Any  completion that matches the pattern will be removed from the list.
        A leading !\b! negates the pattern; in this case any completion not match-
        ing the pattern will be removed.
 
@@ -3652,44 +3655,44 @@ R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE
        added to each member of the completion list, and the result is returned
        to the readline completion code as the list of possible completions.
 
-       If the previously-applied actions do not generate any matches, and  the
-       -\b-o\b d\bdi\bir\brn\bna\bam\bme\bes\bs  option  was  supplied  to  c\bco\bom\bmp\bpl\ble\bet\bte\be when the compspec was
+       If  the previously-applied actions do not generate any matches, and the
+       -\b-o\bd\bdi\bir\brn\bna\bam\bme\bes\bs option was supplied  to  c\bco\bom\bmp\bpl\ble\bet\bte\be  when  the  compspec  was
        defined, directory name completion is attempted.
 
-       If the -\b-o\bo p\bpl\blu\bus\bsd\bdi\bir\brs\bs option was supplied to c\bco\bom\bmp\bpl\ble\bet\bte\be  when  the  compspec
+       If  the  -\b-o\bo  p\bpl\blu\bus\bsd\bdi\bir\brs\bs option was supplied to c\bco\bom\bmp\bpl\ble\bet\bte\be when the compspec
        was defined, directory name completion is attempted and any matches are
        added to the results of the other actions.
 
-       By default, if a compspec is found, whatever it generates  is  returned
-       to  the  completion  code as the full set of possible completions.  The
+       By  default,  if a compspec is found, whatever it generates is returned
+       to the completion code as the full set of  possible  completions.   The
        default b\bba\bas\bsh\bh completions are not attempted, and the readline default of
        filename completion is disabled.  If the -\b-o\bo b\bba\bas\bsh\bhd\bde\bef\bfa\bau\bul\blt\bt option was sup-
-       plied to c\bco\bom\bmp\bpl\ble\bet\bte\be when the compspec was defined, the b\bba\bas\bsh\bh default  com-
+       plied  to c\bco\bom\bmp\bpl\ble\bet\bte\be when the compspec was defined, the b\bba\bas\bsh\bh default com-
        pletions are attempted if the compspec generates no matches.  If the -\b-o\bo
-       d\bde\bef\bfa\bau\bul\blt\boption was supplied to c\bco\bom\bmp\bpl\ble\bet\bte\be when the compspec was  defined,
-       readline's  default  completion will be performed if the compspec (and,
+       d\bde\bef\bfa\bau\bul\blt\b option was supplied to c\bco\bom\bmp\bpl\ble\bet\bte\be when the compspec was defined,
+       readline's default completion will be performed if the  compspec  (and,
        if attempted, the default b\bba\bas\bsh\bh completions) generate no matches.
 
-       When a compspec indicates that directory name  completion  is  desired,
-       the  programmable completion functions force readline to append a slash
-       to completed names which are symbolic links to directories, subject  to
-       the  value of the m\bma\bar\brk\bk-\b-d\bdi\bir\bre\bec\bct\bto\bor\bri\bie\bes\bs readline variable, regardless of the
+       When  a  compspec  indicates that directory name completion is desired,
+       the programmable completion functions force readline to append a  slash
+       to  completed names which are symbolic links to directories, subject to
+       the value of the m\bma\bar\brk\bk-\b-d\bdi\bir\bre\bec\bct\bto\bor\bri\bie\bes\bs readline variable, regardless of  the
        setting of the m\bma\bar\brk\bk-\b-s\bsy\bym\bml\bli\bin\bnk\bke\bed\bd-\b-d\bdi\bir\bre\bec\bct\bto\bor\bri\bie\bes\bs readline variable.
 
-       There is some support for dynamically modifying completions.   This  is
-       most  useful  when used in combination with a default completion speci-
-       fied with c\bco\bom\bmp\bpl\ble\bet\bte\be -\b-D\bD.  It's possible for shell functions  executed  as
-       completion  handlers  to  indicate that completion should be retried by
-       returning an exit status of 124.  If a shell function returns 124,  and
+       There  is  some support for dynamically modifying completions.  This is
+       most useful when used in combination with a default  completion  speci-
+       fied  with  c\bco\bom\bmp\bpl\ble\bet\bte\be -\b-D\bD.  It's possible for shell functions executed as
+       completion handlers to indicate that completion should  be  retried  by
+       returning  an exit status of 124.  If a shell function returns 124, and
        changes the compspec associated with the command on which completion is
-       being attempted (supplied as the first argument when  the  function  is
+       being  attempted  (supplied  as the first argument when the function is
        executed), programmable completion restarts from the beginning, with an
-       attempt to find a new compspec for that command.  This allows a set  of
-       completions  to be built dynamically as completion is attempted, rather
+       attempt  to find a new compspec for that command.  This allows a set of
+       completions to be built dynamically as completion is attempted,  rather
        than being loaded all at once.
 
-       For instance, assuming that there is a library of compspecs, each  kept
-       in  a  file  corresponding  to  the  name of the command, the following
+       For  instance, assuming that there is a library of compspecs, each kept
+       in a file corresponding to the  name  of  the  command,  the  following
        default completion function would load completions dynamically:
 
        _completion_loader()
@@ -3700,159 +3703,159 @@ R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE
 
 
 H\bHI\bIS\bST\bTO\bOR\bRY\bY
-       When the -\b-o\bo h\bhi\bis\bst\bto\bor\bry\by option to the s\bse\bet\bt builtin  is  enabled,  the  shell
+       When  the  -\b-o\bo  h\bhi\bis\bst\bto\bor\bry\by  option to the s\bse\bet\bt builtin is enabled, the shell
        provides access to the _\bc_\bo_\bm_\bm_\ba_\bn_\bd _\bh_\bi_\bs_\bt_\bo_\br_\by, the list of commands previously
-       typed.  The value of the H\bHI\bIS\bST\bTS\bSI\bIZ\bZE\bE variable is used  as  the  number  of
+       typed.   The  value  of  the H\bHI\bIS\bST\bTS\bSI\bIZ\bZE\bE variable is used as the number of
        commands to save in a history list.  The text of the last H\bHI\bIS\bST\bTS\bSI\bIZ\bZE\bE com-
-       mands (default 500) is saved.  The shell stores  each  command  in  the
-       history  list  prior to parameter and variable expansion (see E\bEX\bXP\bPA\bAN\bNS\bSI\bIO\bON\bN
-       above) but after history expansion is performed, subject to the  values
+       mands  (default  500)  is  saved.  The shell stores each command in the
+       history list prior to parameter and variable expansion  (see  E\bEX\bXP\bPA\bAN\bNS\bSI\bIO\bON\bN
+       above)  but after history expansion is performed, subject to the values
        of the shell variables H\bHI\bIS\bST\bTI\bIG\bGN\bNO\bOR\bRE\bE and H\bHI\bIS\bST\bTC\bCO\bON\bNT\bTR\bRO\bOL\bL.
 
        On startup, the history is initialized from the file named by the vari-
-       able H\bHI\bIS\bST\bTF\bFI\bIL\bLE\bE (default _\b~_\b/_\b._\bb_\ba_\bs_\bh_\b__\bh_\bi_\bs_\bt_\bo_\br_\by).  The file named by  the  value
-       of  H\bHI\bIS\bST\bTF\bFI\bIL\bLE\bE  is  truncated,  if necessary, to contain no more than the
-       number of lines specified by the value of H\bHI\bIS\bST\bTF\bFI\bIL\bLE\bES\bSI\bIZ\bZE\bE.   If  H\bHI\bIS\bST\bTF\bFI\bIL\bLE\bE-\b-
-       S\bSI\bIZ\bZE\b is unset, or set to null, a non-numeric value, or a numeric value
-       less than zero, the history file is not truncated.   When  the  history
-       file  is  read, lines beginning with the history comment character fol-
+       able  H\bHI\bIS\bST\bTF\bFI\bIL\bLE\bE  (default _\b~_\b/_\b._\bb_\ba_\bs_\bh_\b__\bh_\bi_\bs_\bt_\bo_\br_\by).  The file named by the value
+       of H\bHI\bIS\bST\bTF\bFI\bIL\bLE\bE is truncated, if necessary, to contain  no  more  than  the
+       number  of  lines specified by the value of H\bHI\bIS\bST\bTF\bFI\bIL\bLE\bES\bSI\bIZ\bZE\bE.  If H\bHI\bIS\bST\bTF\bFI\bIL\bLE\bE-\b-
+       S\bSI\bIZ\bZE\bis unset, or set to null, a non-numeric value, or a numeric  value
+       less  than  zero,  the history file is not truncated.  When the history
+       file is read, lines beginning with the history comment  character  fol-
        lowed immediately by a digit are interpreted as timestamps for the pre-
        ceding history line.  These timestamps are optionally displayed depend-
-       ing on the value of the H\bHI\bIS\bST\bTT\bTI\bIM\bME\bEF\bFO\bOR\bRM\bMA\bAT\bT variable.   When  a  shell  with
-       history  enabled  exits,  the  last $\b$H\bHI\bIS\bST\bTS\bSI\bIZ\bZE\bE lines are copied from the
-       history list to $\b$H\bHI\bIS\bST\bTF\bFI\bIL\bLE\bE.  If the h\bhi\bis\bst\bta\bap\bpp\bpe\ben\bnd\bd shell option  is  enabled
-       (see  the description of s\bsh\bho\bop\bpt\bt under S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS below), the
-       lines are appended to the history file, otherwise the history  file  is
+       ing  on  the  value  of the H\bHI\bIS\bST\bTT\bTI\bIM\bME\bEF\bFO\bOR\bRM\bMA\bAT\bT variable.  When a shell with
+       history enabled exits, the last $\b$H\bHI\bIS\bST\bTS\bSI\bIZ\bZE\bE lines  are  copied  from  the
+       history  list  to $\b$H\bHI\bIS\bST\bTF\bFI\bIL\bLE\bE.  If the h\bhi\bis\bst\bta\bap\bpp\bpe\ben\bnd\bd shell option is enabled
+       (see the description of s\bsh\bho\bop\bpt\bt under S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS below),  the
+       lines  are  appended to the history file, otherwise the history file is
        overwritten.   If  H\bHI\bIS\bST\bTF\bFI\bIL\bLE\bE  is  unset,  or  if  the  history  file  is
-       unwritable, the history is not saved.  If the  H\bHI\bIS\bST\bTT\bTI\bIM\bME\bEF\bFO\bOR\bRM\bMA\bAT\b variable
-       is  set,  time  stamps are written to the history file, marked with the
-       history comment character, so they may be preserved across  shell  ses-
-       sions.   This  uses  the history comment character to distinguish time-
+       unwritable,  the  history is not saved.  If the H\bHI\bIS\bST\bTT\bTI\bIM\bME\bEF\bFO\bOR\bRM\bMA\bAT\bT variable
+       is set, time stamps are written to the history file,  marked  with  the
+       history  comment  character, so they may be preserved across shell ses-
+       sions.  This uses the history comment character  to  distinguish  time-
        stamps from other history lines.  After saving the history, the history
        file is truncated to contain no more than H\bHI\bIS\bST\bTF\bFI\bIL\bLE\bES\bSI\bIZ\bZE\bE lines.  If H\bHI\bIS\bST\bT-\b-
-       F\bFI\bIL\bLE\bES\bSI\bIZ\bZE\bis unset, or set to null, a non-numeric value,  or  a  numeric
+       F\bFI\bIL\bLE\bES\bSI\bIZ\bZE\b is  unset,  or set to null, a non-numeric value, or a numeric
        value less than zero, the history file is not truncated.
 
-       The  builtin  command f\bfc\bc (see S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS below) may be used
+       The builtin command f\bfc\bc (see S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS below) may  be  used
        to list or edit and re-execute a portion of the history list.  The h\bhi\bis\bs-\b-
-       t\bto\bor\bry\b builtin  may  be  used  to display or modify the history list and
-       manipulate the history file.  When using command-line  editing,  search
-       commands  are available in each editing mode that provide access to the
+       t\bto\bor\bry\bbuiltin may be used to display or  modify  the  history  list  and
+       manipulate  the  history file.  When using command-line editing, search
+       commands are available in each editing mode that provide access to  the
        history list.
 
-       The shell allows control over which commands are saved on  the  history
+       The  shell  allows control over which commands are saved on the history
        list.  The H\bHI\bIS\bST\bTC\bCO\bON\bNT\bTR\bRO\bOL\bL and H\bHI\bIS\bST\bTI\bIG\bGN\bNO\bOR\bRE\bE variables may be set to cause the
        shell to save only a subset of the commands entered.  The c\bcm\bmd\bdh\bhi\bis\bst\bt shell
-       option,  if enabled, causes the shell to attempt to save each line of a
-       multi-line command in the same history entry, adding  semicolons  where
-       necessary  to preserve syntactic correctness.  The l\bli\bit\bth\bhi\bis\bst\bt shell option
-       causes the shell to save the command with embedded newlines instead  of
+       option, if enabled, causes the shell to attempt to save each line of  a
+       multi-line  command  in the same history entry, adding semicolons where
+       necessary to preserve syntactic correctness.  The l\bli\bit\bth\bhi\bis\bst\bt shell  option
+       causes  the shell to save the command with embedded newlines instead of
        semicolons.  See the description of the s\bsh\bho\bop\bpt\bt builtin below under S\bSH\bHE\bEL\bLL\bL
        B\bBU\bUI\bIL\bLT\bTI\bIN\bN  C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS  for  information  on  setting  and  unsetting  shell
        options.
 
 H\bHI\bIS\bST\bTO\bOR\bRY\bY E\bEX\bXP\bPA\bAN\bNS\bSI\bIO\bON\bN
-       The  shell  supports a history expansion feature that is similar to the
-       history expansion in c\bcs\bsh\bh.\b.  This section describes what syntax  features
-       are  available.   This  feature  is  enabled by default for interactive
+       The shell supports a history expansion feature that is similar  to  the
+       history  expansion in c\bcs\bsh\bh.\b.  This section describes what syntax features
+       are available.  This feature is  enabled  by  default  for  interactive
        shells, and can be disabled using the +\b+H\bH option to the s\bse\bet\bt builtin com-
        mand (see S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS below).  Non-interactive shells do not
        perform history expansion by default.
 
        History expansions introduce words from the history list into the input
-       stream,  making  it  easy to repeat commands, insert the arguments to a
+       stream, making it easy to repeat commands, insert the  arguments  to  a
        previous command into the current input line, or fix errors in previous
        commands quickly.
 
-       History  expansion  is  performed  immediately after a complete line is
-       read, before the shell breaks it into words.  It  takes  place  in  two
-       parts.   The  first is to determine which line from the history list to
+       History expansion is performed immediately after  a  complete  line  is
+       read,  before  the  shell  breaks it into words.  It takes place in two
+       parts.  The first is to determine which line from the history  list  to
        use during substitution.  The second is to select portions of that line
        for inclusion into the current one.  The line selected from the history
-       is the _\be_\bv_\be_\bn_\bt, and the portions of that line that  are  acted  upon  are
-       _\bw_\bo_\br_\bd_\bs.   Various  _\bm_\bo_\bd_\bi_\bf_\bi_\be_\br_\bs  are  available  to manipulate the selected
+       is  the  _\be_\bv_\be_\bn_\bt,  and  the portions of that line that are acted upon are
+       _\bw_\bo_\br_\bd_\bs.  Various _\bm_\bo_\bd_\bi_\bf_\bi_\be_\br_\bs are  available  to  manipulate  the  selected
        words.  The line is broken into words in the same fashion as when read-
-       ing  input, so that several _\bm_\be_\bt_\ba_\bc_\bh_\ba_\br_\ba_\bc_\bt_\be_\br-separated words surrounded by
-       quotes are considered one word.  History expansions are  introduced  by
-       the  appearance  of  the  history  expansion  character,  which is !\b! by
-       default.  Only backslash (\\b\) and single quotes can  quote  the  history
+       ing input, so that several _\bm_\be_\bt_\ba_\bc_\bh_\ba_\br_\ba_\bc_\bt_\be_\br-separated words surrounded  by
+       quotes  are  considered one word.  History expansions are introduced by
+       the appearance of the  history  expansion  character,  which  is  !\b by
+       default.   Only  backslash  (\\b\) and single quotes can quote the history
        expansion character.
 
-       Several  characters inhibit history expansion if found immediately fol-
-       lowing the history expansion character, even if it is unquoted:  space,
-       tab,  newline,  carriage return, and =\b=.  If the e\bex\bxt\btg\bgl\blo\bob\bb shell option is
+       Several characters inhibit history expansion if found immediately  fol-
+       lowing  the history expansion character, even if it is unquoted: space,
+       tab, newline, carriage return, and =\b=.  If the e\bex\bxt\btg\bgl\blo\bob\bb shell  option  is
        enabled, (\b( will also inhibit expansion.
 
-       Several shell options settable with the s\bsh\bho\bop\bpt\bt builtin may  be  used  to
-       tailor  the  behavior  of  history  expansion.  If the h\bhi\bis\bst\btv\bve\ber\bri\bif\bfy\by shell
+       Several  shell  options  settable with the s\bsh\bho\bop\bpt\bt builtin may be used to
+       tailor the behavior of history  expansion.   If  the  h\bhi\bis\bst\btv\bve\ber\bri\bif\bfy\b shell
        option is enabled (see the description of the s\bsh\bho\bop\bpt\bt builtin below), and
-       r\bre\bea\bad\bdl\bli\bin\bne\b is  being  used,  history  substitutions  are not immediately
-       passed to the shell parser.  Instead, the  expanded  line  is  reloaded
+       r\bre\bea\bad\bdl\bli\bin\bne\bis being  used,  history  substitutions  are  not  immediately
+       passed  to  the  shell  parser.  Instead, the expanded line is reloaded
        into the r\bre\bea\bad\bdl\bli\bin\bne\be editing buffer for further modification.  If r\bre\bea\bad\bdl\bli\bin\bne\be
-       is being used, and the h\bhi\bis\bst\btr\bre\bee\bed\bdi\bit\bt shell option  is  enabled,  a  failed
-       history  substitution will be reloaded into the r\bre\bea\bad\bdl\bli\bin\bne\be editing buffer
-       for correction.  The -\b-p\bp option to the h\bhi\bis\bst\bto\bor\bry\by builtin  command  may  be
-       used  to  see what a history expansion will do before using it.  The -\b-s\bs
+       is  being  used,  and  the h\bhi\bis\bst\btr\bre\bee\bed\bdi\bit\bt shell option is enabled, a failed
+       history substitution will be reloaded into the r\bre\bea\bad\bdl\bli\bin\bne\be editing  buffer
+       for  correction.   The  -\b-p\bp option to the h\bhi\bis\bst\bto\bor\bry\by builtin command may be
+       used to see what a history expansion will do before using it.   The  -\b-s\bs
        option to the h\bhi\bis\bst\bto\bor\bry\by builtin may be used to add commands to the end of
-       the  history  list  without  actually  executing them, so that they are
+       the history list without actually executing  them,  so  that  they  are
        available for subsequent recall.
 
-       The shell allows control of the various characters used by the  history
+       The  shell allows control of the various characters used by the history
        expansion mechanism (see the description of h\bhi\bis\bst\btc\bch\bha\bar\brs\bs above under S\bSh\bhe\bel\bll\bl
-       V\bVa\bar\bri\bia\bab\bbl\ble\bes\bs).  The shell uses the history comment character to mark  his-
+       V\bVa\bar\bri\bia\bab\bbl\ble\bes\bs).   The shell uses the history comment character to mark his-
        tory timestamps when writing the history file.
 
    E\bEv\bve\ben\bnt\bt D\bDe\bes\bsi\big\bgn\bna\bat\bto\bor\brs\bs
-       An  event designator is a reference to a command line entry in the his-
-       tory list.  Unless the reference is absolute, events  are  relative  to
+       An event designator is a reference to a command line entry in the  his-
+       tory  list.   Unless  the reference is absolute, events are relative to
        the current position in the history list.
 
-       !\b!      Start  a  history substitution, except when followed by a b\bbl\bla\ban\bnk\bk,
-              newline, carriage return, = or ( (when the e\bex\bxt\btg\bgl\blo\bob\bb shell  option
+       !\b!      Start a history substitution, except when followed by  a  b\bbl\bla\ban\bnk\bk,
+              newline,  carriage return, = or ( (when the e\bex\bxt\btg\bgl\blo\bob\bb shell option
               is enabled using the s\bsh\bho\bop\bpt\bt builtin).
        !\b!_\bn     Refer to command line _\bn.
        !\b!-\b-_\bn    Refer to the current command minus _\bn.
        !\b!!\b!     Refer to the previous command.  This is a synonym for `!-1'.
        !\b!_\bs_\bt_\br_\bi_\bn_\bg
-              Refer  to the most recent command preceding the current position
+              Refer to the most recent command preceding the current  position
               in the history list starting with _\bs_\bt_\br_\bi_\bn_\bg.
        !\b!?\b?_\bs_\bt_\br_\bi_\bn_\bg[\b[?\b?]\b]
-              Refer to the most recent command preceding the current  position
-              in  the  history  list containing _\bs_\bt_\br_\bi_\bn_\bg.  The trailing ?\b? may be
+              Refer  to the most recent command preceding the current position
+              in the history list containing _\bs_\bt_\br_\bi_\bn_\bg.  The trailing  ?\b?  may  be
               omitted if _\bs_\bt_\br_\bi_\bn_\bg is followed immediately by a newline.
        ^\b^_\bs_\bt_\br_\bi_\bn_\bg_\b1^\b^_\bs_\bt_\br_\bi_\bn_\bg_\b2^\b^
-              Quick substitution.   Repeat  the  previous  command,  replacing
-              _\bs_\bt_\br_\bi_\bn_\bg_\b with  _\bs_\bt_\br_\bi_\bn_\bg_\b2.  Equivalent to ``!!:s/_\bs_\bt_\br_\bi_\bn_\bg_\b1/_\bs_\bt_\br_\bi_\bn_\bg_\b2/''
+              Quick  substitution.   Repeat  the  previous  command, replacing
+              _\bs_\bt_\br_\bi_\bn_\bg_\bwith _\bs_\bt_\br_\bi_\bn_\bg_\b2.  Equivalent  to  ``!!:s/_\bs_\bt_\br_\bi_\bn_\bg_\b1/_\bs_\bt_\br_\bi_\bn_\bg_\b2/''
               (see M\bMo\bod\bdi\bif\bfi\bie\ber\brs\bs below).
        !\b!#\b#     The entire command line typed so far.
 
    W\bWo\bor\brd\bd D\bDe\bes\bsi\big\bgn\bna\bat\bto\bor\brs\bs
-       Word designators are used to select desired words from the event.  A  :\b:
-       separates  the event specification from the word designator.  It may be
-       omitted if the word designator begins with a ^\b^, $\b$, *\b*, -\b-, or  %\b%.   Words
-       are  numbered from the beginning of the line, with the first word being
-       denoted by 0 (zero).  Words are inserted into the  current  line  sepa-
+       Word  designators are used to select desired words from the event.  A :\b:
+       separates the event specification from the word designator.  It may  be
+       omitted  if  the word designator begins with a ^\b^, $\b$, *\b*, -\b-, or %\b%.  Words
+       are numbered from the beginning of the line, with the first word  being
+       denoted  by  0  (zero).  Words are inserted into the current line sepa-
        rated by single spaces.
 
        0\b0 (\b(z\bze\ber\bro\bo)\b)
               The zeroth word.  For the shell, this is the command word.
        _\bn      The _\bnth word.
        ^\b^      The first argument.  That is, word 1.
-       $\b$      The  last  word.   This  is  usually the last argument, but will
+       $\b$      The last word.  This is usually  the  last  argument,  but  will
               expand to the zeroth word if there is only one word in the line.
        %\b%      The word matched by the most recent `?_\bs_\bt_\br_\bi_\bn_\bg?' search.
        _\bx-\b-_\by    A range of words; `-_\by' abbreviates `0-_\by'.
-       *\b*      All  of  the words but the zeroth.  This is a synonym for `_\b1_\b-_\b$'.
-              It is not an error to use *\b* if there is just  one  word  in  the
+       *\b*      All of the words but the zeroth.  This is a synonym  for  `_\b1_\b-_\b$'.
+              It  is  not  an  error to use *\b* if there is just one word in the
               event; the empty string is returned in that case.
        x\bx*\b*     Abbreviates _\bx_\b-_\b$.
        x\bx-\b-     Abbreviates _\bx_\b-_\b$ like x\bx*\b*, but omits the last word.
 
-       If  a  word  designator is supplied without an event specification, the
+       If a word designator is supplied without an  event  specification,  the
        previous command is used as the event.
 
    M\bMo\bod\bdi\bif\bfi\bie\ber\brs\bs
-       After the optional word designator, there may appear a sequence of  one
+       After  the optional word designator, there may appear a sequence of one
        or more of the following modifiers, each preceded by a `:'.
 
        h\bh      Remove a trailing filename component, leaving only the head.
@@ -3861,74 +3864,74 @@ H\bHI\bIS\bST\bTO\bOR\bRY\bY E\bEX\bXP\bPA\bAN\bNS\bSI\bIO\bON\bN
        e\be      Remove all but the trailing suffix.
        p\bp      Print the new command but do not execute it.
        q\bq      Quote the substituted words, escaping further substitutions.
-       x\bx      Quote the substituted words as with q\bq, but break into  words  at
+       x\bx      Quote  the  substituted words as with q\bq, but break into words at
               b\bbl\bla\ban\bnk\bks\bs and newlines.
        s\bs/\b/_\bo_\bl_\bd/\b/_\bn_\be_\bw/\b/
-              Substitute  _\bn_\be_\bw  for  the  first  occurrence of _\bo_\bl_\bd in the event
-              line.  Any delimiter can be used  in  place  of  /.   The  final
-              delimiter  is  optional if it is the last character of the event
-              line.  The delimiter may be quoted in _\bo_\bl_\bd and _\bn_\be_\bw with a  single
-              backslash.   If & appears in _\bn_\be_\bw, it is replaced by _\bo_\bl_\bd.  A sin-
-              gle backslash will quote the &.  If _\bo_\bl_\bd is null, it  is  set  to
-              the  last  _\bo_\bl_\bd substituted, or, if no previous history substitu-
+              Substitute _\bn_\be_\bw for the first occurrence  of  _\bo_\bl_\bd  in  the  event
+              line.   Any  delimiter  can  be  used  in place of /.  The final
+              delimiter is optional if it is the last character of  the  event
+              line.   The delimiter may be quoted in _\bo_\bl_\bd and _\bn_\be_\bw with a single
+              backslash.  If & appears in _\bn_\be_\bw, it is replaced by _\bo_\bl_\bd.  A  sin-
+              gle  backslash  will  quote the &.  If _\bo_\bl_\bd is null, it is set to
+              the last _\bo_\bl_\bd substituted, or, if no previous  history  substitu-
               tions took place, the last _\bs_\bt_\br_\bi_\bn_\bg in a !\b!?\b?_\bs_\bt_\br_\bi_\bn_\bg[\b[?\b?]\b]  search.
        &\b&      Repeat the previous substitution.
        g\bg      Cause changes to be applied over the entire event line.  This is
-              used  in  conjunction  with `:\b:s\bs' (e.g., `:\b:g\bgs\bs/\b/_\bo_\bl_\bd/\b/_\bn_\be_\bw/\b/') or `:\b:&\b&'.
-              If used with `:\b:s\bs', any delimiter can be used in place of /,  and
-              the  final  delimiter is optional if it is the last character of
+              used in conjunction with `:\b:s\bs' (e.g.,  `:\b:g\bgs\bs/\b/_\bo_\bl_\bd/\b/_\bn_\be_\bw/\b/')  or  `:\b:&\b&'.
+              If  used with `:\b:s\bs', any delimiter can be used in place of /, and
+              the final delimiter is optional if it is the last  character  of
               the event line.  An a\ba may be used as a synonym for g\bg.
-       G\bG      Apply the following `s\bs' modifier once to each word in the  event
+       G\bG      Apply  the following `s\bs' modifier once to each word in the event
               line.
 
 S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS
        Unless otherwise noted, each builtin command documented in this section
        as accepting options preceded by -\b- accepts -\b--\b- to signify the end of the
-       options.   The  :\b:, t\btr\bru\bue\be, f\bfa\bal\bls\bse\be, and t\bte\bes\bst\bt builtins do not accept options
+       options.  The :\b:, t\btr\bru\bue\be, f\bfa\bal\bls\bse\be, and t\bte\bes\bst\bt builtins do not  accept  options
        and do not treat -\b--\b- specially.  The e\bex\bxi\bit\bt, l\blo\bog\bgo\bou\but\bt, b\bbr\bre\bea\bak\bk, c\bco\bon\bnt\bti\bin\bnu\bue\be, l\ble\bet\bt,
-       and  s\bsh\bhi\bif\bft\bt builtins accept and process arguments beginning with -\b- with-
-       out requiring -\b--\b-.  Other builtins that accept  arguments  but  are  not
-       specified  as accepting options interpret arguments beginning with -\b- as
+       and s\bsh\bhi\bif\bft\bt builtins accept and process arguments beginning with -\b with-
+       out  requiring  -\b--\b-.   Other  builtins that accept arguments but are not
+       specified as accepting options interpret arguments beginning with -\b as
        invalid options and require -\b--\b- to prevent this interpretation.
        :\b: [_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs]
-              No effect; the command does nothing beyond  expanding  _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs
-              and  performing any specified redirections.  A zero exit code is
+              No  effect;  the command does nothing beyond expanding _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs
+              and performing any specified redirections.  A zero exit code  is
               returned.
 
         .\b.  _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be [_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs]
        s\bso\bou\bur\brc\bce\be _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be [_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs]
-              Read and execute commands from _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be  in  the  current  shell
-              environment  and return the exit status of the last command exe-
-              cuted from _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be.  If _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be  does  not  contain  a  slash,
-              filenames  in  P\bPA\bAT\bTH\bH  are  used  to find the directory containing
+              Read  and  execute  commands  from _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be in the current shell
+              environment and return the exit status of the last command  exe-
+              cuted  from  _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be.   If  _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be  does not contain a slash,
+              filenames in P\bPA\bAT\bTH\bH are used  to  find  the  directory  containing
               _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be.  The file searched for in P\bPA\bAT\bTH\bH need not be executable.
-              When  b\bba\bas\bsh\bh  is  not  in  _\bp_\bo_\bs_\bi_\bx  _\bm_\bo_\bd_\be,  the  current directory is
-              searched if no file is found in P\bPA\bAT\bTH\bH.  If the s\bso\bou\bur\brc\bce\bep\bpa\bat\bth\b option
-              to  the  s\bsh\bho\bop\bpt\bt  builtin  command  is turned off, the P\bPA\bAT\bTH\bH is not
-              searched.  If any _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs are supplied, they become the  posi-
-              tional  parameters  when  _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be  is  executed.  Otherwise the
-              positional parameters are unchanged.  The return status  is  the
-              status  of  the  last  command exited within the script (0 if no
-              commands are executed), and false if _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be is  not  found  or
+              When b\bba\bas\bsh\bh is  not  in  _\bp_\bo_\bs_\bi_\bx  _\bm_\bo_\bd_\be,  the  current  directory  is
+              searched  if no file is found in P\bPA\bAT\bTH\bH.  If the s\bso\bou\bur\brc\bce\bep\bpa\bat\bth\bh option
+              to the s\bsh\bho\bop\bpt\bt builtin command is turned  off,  the  P\bPA\bAT\bTH\bH  is  not
+              searched.   If any _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs are supplied, they become the posi-
+              tional parameters when  _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be  is  executed.   Otherwise  the
+              positional  parameters  are unchanged.  The return status is the
+              status of the last command exited within the  script  (0  if  no
+              commands  are  executed),  and false if _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be is not found or
               cannot be read.
 
        a\bal\bli\bia\bas\bs [-\b-p\bp] [_\bn_\ba_\bm_\be[=_\bv_\ba_\bl_\bu_\be] ...]
               A\bAl\bli\bia\bas\bs with no arguments or with the -\b-p\bp option prints the list of
-              aliases in the form a\bal\bli\bia\bas\bs _\bn_\ba_\bm_\be=_\bv_\ba_\bl_\bu_\be on standard  output.   When
-              arguments  are supplied, an alias is defined for each _\bn_\ba_\bm_\be whose
+              aliases  in  the form a\bal\bli\bia\bas\bs _\bn_\ba_\bm_\be=_\bv_\ba_\bl_\bu_\be on standard output.  When
+              arguments are supplied, an alias is defined for each _\bn_\ba_\bm_\b whose
               _\bv_\ba_\bl_\bu_\be is given.  A trailing space in  _\bv_\ba_\bl_\bu_\be causes the next word
               to be checked for alias substitution when the alias is expanded.
-              For each _\bn_\ba_\bm_\be in the argument list for which no  _\bv_\ba_\bl_\bu_\be  is  sup-
-              plied,  the  name  and  value  of  the  alias is printed.  A\bAl\bli\bia\bas\bs
-              returns true unless a _\bn_\ba_\bm_\be is given for which no alias has  been
+              For  each  _\bn_\ba_\bm_\be  in the argument list for which no _\bv_\ba_\bl_\bu_\be is sup-
+              plied, the name and  value  of  the  alias  is  printed.   A\bAl\bli\bia\bas\bs
+              returns  true unless a _\bn_\ba_\bm_\be is given for which no alias has been
               defined.
 
        b\bbg\bg [_\bj_\bo_\bb_\bs_\bp_\be_\bc ...]
-              Resume  each  suspended  job _\bj_\bo_\bb_\bs_\bp_\be_\bc in the background, as if it
+              Resume each suspended job _\bj_\bo_\bb_\bs_\bp_\be_\bc in the background,  as  if  it
               had been started with &\b&.  If _\bj_\bo_\bb_\bs_\bp_\be_\bc is not present, the shell's
-              notion  of the _\bc_\bu_\br_\br_\be_\bn_\bt _\bj_\bo_\bb is used.  b\bbg\bg _\bj_\bo_\bb_\bs_\bp_\be_\bc returns 0 unless
-              run when job control is disabled or, when run with  job  control
-              enabled,  any  specified  _\bj_\bo_\bb_\bs_\bp_\be_\bc  was  not found or was started
+              notion of the _\bc_\bu_\br_\br_\be_\bn_\bt _\bj_\bo_\bb is used.  b\bbg\bg _\bj_\bo_\bb_\bs_\bp_\be_\bc returns 0  unless
+              run  when  job control is disabled or, when run with job control
+              enabled, any specified _\bj_\bo_\bb_\bs_\bp_\be_\bc was  not  found  or  was  started
               without job control.
 
        b\bbi\bin\bnd\bd [-\b-m\bm _\bk_\be_\by_\bm_\ba_\bp] [-\b-l\blp\bps\bsv\bvP\bPS\bSV\bVX\bX]
@@ -3937,28 +3940,28 @@ S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS
        b\bbi\bin\bnd\bd [-\b-m\bm _\bk_\be_\by_\bm_\ba_\bp] -\b-x\bx _\bk_\be_\by_\bs_\be_\bq:_\bs_\bh_\be_\bl_\bl_\b-_\bc_\bo_\bm_\bm_\ba_\bn_\bd
        b\bbi\bin\bnd\bd [-\b-m\bm _\bk_\be_\by_\bm_\ba_\bp] _\bk_\be_\by_\bs_\be_\bq:_\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn_\b-_\bn_\ba_\bm_\be
        b\bbi\bin\bnd\bd _\br_\be_\ba_\bd_\bl_\bi_\bn_\be_\b-_\bc_\bo_\bm_\bm_\ba_\bn_\bd
-              Display current r\bre\bea\bad\bdl\bli\bin\bne\be key and function bindings, bind  a  key
-              sequence  to  a  r\bre\bea\bad\bdl\bli\bin\bne\be  function  or macro, or set a r\bre\bea\bad\bdl\bli\bin\bne\be
-              variable.  Each non-option argument is a  command  as  it  would
-              appear  in  _\b._\bi_\bn_\bp_\bu_\bt_\br_\bc, but each binding or command must be passed
-              as a separate argument; e.g.,  '"\C-x\C-r":  re-read-init-file'.
+              Display  current  r\bre\bea\bad\bdl\bli\bin\bne\be key and function bindings, bind a key
+              sequence to a r\bre\bea\bad\bdl\bli\bin\bne\be function or  macro,  or  set  a  r\bre\bea\bad\bdl\bli\bin\bne\be
+              variable.   Each  non-option  argument  is a command as it would
+              appear in _\b._\bi_\bn_\bp_\bu_\bt_\br_\bc, but each binding or command must  be  passed
+              as  a  separate argument; e.g., '"\C-x\C-r": re-read-init-file'.
               Options, if supplied, have the following meanings:
               -\b-m\bm _\bk_\be_\by_\bm_\ba_\bp
                      Use _\bk_\be_\by_\bm_\ba_\bp as the keymap to be affected by the subsequent
                      bindings.  Acceptable _\bk_\be_\by_\bm_\ba_\bp names are _\be_\bm_\ba_\bc_\bs_\b, _\be_\bm_\ba_\bc_\bs_\b-_\bs_\bt_\ba_\bn_\b-
-                     _\bd_\ba_\br_\bd_\b _\be_\bm_\ba_\bc_\bs_\b-_\bm_\be_\bt_\ba_\b,  _\be_\bm_\ba_\bc_\bs_\b-_\bc_\bt_\bl_\bx_\b,  _\bv_\bi_\b, _\bv_\bi_\b-_\bm_\bo_\bv_\be_\b, _\bv_\bi_\b-_\bc_\bo_\bm_\bm_\ba_\bn_\bd,
-                     and _\bv_\bi_\b-_\bi_\bn_\bs_\be_\br_\bt.  _\bv_\bi is equivalent to _\bv_\bi_\b-_\bc_\bo_\bm_\bm_\ba_\bn_\bd; _\be_\bm_\ba_\bc_\b is
+                     _\bd_\ba_\br_\bd_\b_\be_\bm_\ba_\bc_\bs_\b-_\bm_\be_\bt_\ba_\b, _\be_\bm_\ba_\bc_\bs_\b-_\bc_\bt_\bl_\bx_\b,  _\bv_\bi_\b,  _\bv_\bi_\b-_\bm_\bo_\bv_\be_\b _\bv_\bi_\b-_\bc_\bo_\bm_\bm_\ba_\bn_\bd,
+                     and  _\bv_\bi_\b-_\bi_\bn_\bs_\be_\br_\bt.  _\bv_\bi is equivalent to _\bv_\bi_\b-_\bc_\bo_\bm_\bm_\ba_\bn_\bd; _\be_\bm_\ba_\bc_\bs is
                      equivalent to _\be_\bm_\ba_\bc_\bs_\b-_\bs_\bt_\ba_\bn_\bd_\ba_\br_\bd.
               -\b-l\bl     List the names of all r\bre\bea\bad\bdl\bli\bin\bne\be functions.
-              -\b-p\bp     Display  r\bre\bea\bad\bdl\bli\bin\bne\be  function  names and bindings in such a
+              -\b-p\bp     Display r\bre\bea\bad\bdl\bli\bin\bne\be function names and bindings  in  such  a
                      way that they can be re-read.
               -\b-P\bP     List current r\bre\bea\bad\bdl\bli\bin\bne\be function names and bindings.
-              -\b-s\bs     Display r\bre\bea\bad\bdl\bli\bin\bne\be key sequences bound to  macros  and  the
-                     strings  they  output  in such a way that they can be re-
+              -\b-s\bs     Display  r\bre\bea\bad\bdl\bli\bin\bne\be  key  sequences bound to macros and the
+                     strings they output in such a way that they  can  be  re-
                      read.
-              -\b-S\bS     Display r\bre\bea\bad\bdl\bli\bin\bne\be key sequences bound to  macros  and  the
+              -\b-S\bS     Display  r\bre\bea\bad\bdl\bli\bin\bne\be  key  sequences bound to macros and the
                      strings they output.
-              -\b-v\bv     Display  r\bre\bea\bad\bdl\bli\bin\bne\be variable names and values in such a way
+              -\b-v\bv     Display r\bre\bea\bad\bdl\bli\bin\bne\be variable names and values in such a  way
                      that they can be re-read.
               -\b-V\bV     List current r\bre\bea\bad\bdl\bli\bin\bne\be variable names and values.
               -\b-f\bf _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be
@@ -3970,172 +3973,172 @@ S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS
               -\b-r\br _\bk_\be_\by_\bs_\be_\bq
                      Remove any current binding for _\bk_\be_\by_\bs_\be_\bq.
               -\b-x\bx _\bk_\be_\by_\bs_\be_\bq:\b:_\bs_\bh_\be_\bl_\bl_\b-_\bc_\bo_\bm_\bm_\ba_\bn_\bd
-                     Cause _\bs_\bh_\be_\bl_\bl_\b-_\bc_\bo_\bm_\bm_\ba_\bn_\bd to be  executed  whenever  _\bk_\be_\by_\bs_\be_\b is
-                     entered.   When _\bs_\bh_\be_\bl_\bl_\b-_\bc_\bo_\bm_\bm_\ba_\bn_\bd is executed, the shell sets
-                     the R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE_\b_L\bLI\bIN\bNE\bE variable to the contents of  the  r\bre\bea\bad\bd-\b-
-                     l\bli\bin\bne\b line  buffer and the R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE_\b_P\bPO\bOI\bIN\bNT\bT variable to the
+                     Cause  _\bs_\bh_\be_\bl_\bl_\b-_\bc_\bo_\bm_\bm_\ba_\bn_\bd  to  be  executed whenever _\bk_\be_\by_\bs_\be_\bq is
+                     entered.  When _\bs_\bh_\be_\bl_\bl_\b-_\bc_\bo_\bm_\bm_\ba_\bn_\bd is executed, the shell  sets
+                     the  R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE_\b_L\bLI\bIN\bNE\bE  variable to the contents of the r\bre\bea\bad\bd-\b-
+                     l\bli\bin\bne\bline buffer and the R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE_\b_P\bPO\bOI\bIN\bNT\bT variable  to  the
                      current location of the insertion point.  If the executed
-                     command  changes  the  value  of  R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE_\b_L\bLI\bIN\bNE\bE  or R\bRE\bEA\bAD\bD-\b-
-                     L\bLI\bIN\bNE\bE_\b_P\bPO\bOI\bIN\bNT\bT, those new values will  be  reflected  in  the
+                     command changes  the  value  of  R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE_\b_L\bLI\bIN\bNE\bE  or  R\bRE\bEA\bAD\bD-\b-
+                     L\bLI\bIN\bNE\bE_\b_P\bPO\bOI\bIN\bNT\bT,  those  new  values  will be reflected in the
                      editing state.
-              -\b-X\bX     List  all  key  sequences bound to shell commands and the
-                     associated commands in a format that  can  be  reused  as
+              -\b-X\bX     List all key sequences bound to shell  commands  and  the
+                     associated  commands  in  a  format that can be reused as
                      input.
 
-              The  return value is 0 unless an unrecognized option is given or
+              The return value is 0 unless an unrecognized option is given  or
               an error occurred.
 
        b\bbr\bre\bea\bak\bk [_\bn]
-              Exit from within a f\bfo\bor\br, w\bwh\bhi\bil\ble\be, u\bun\bnt\bti\bil\bl, or s\bse\bel\ble\bec\bct\bt loop.  If  _\b is
-              specified,  break  _\bn  levels.   _\bn must be >= 1.  If _\bn is greater
-              than the number of enclosing  loops,  all  enclosing  loops  are
-              exited.   The  return value is 0 unless _\bn is not greater than or
+              Exit  from  within a f\bfo\bor\br, w\bwh\bhi\bil\ble\be, u\bun\bnt\bti\bil\bl, or s\bse\bel\ble\bec\bct\bt loop.  If _\bn is
+              specified, break _\bn levels.  _\bn must be >= 1.   If  _\bn  is  greater
+              than  the  number  of  enclosing  loops, all enclosing loops are
+              exited.  The return value is 0 unless _\bn is not greater  than  or
               equal to 1.
 
        b\bbu\bui\bil\blt\bti\bin\bn _\bs_\bh_\be_\bl_\bl_\b-_\bb_\bu_\bi_\bl_\bt_\bi_\bn [_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs]
-              Execute the specified shell builtin, passing it  _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs,  and
+              Execute  the  specified shell builtin, passing it _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs, and
               return its exit status.  This is useful when defining a function
-              whose name is the same as a shell builtin, retaining  the  func-
+              whose  name  is the same as a shell builtin, retaining the func-
               tionality of the builtin within the function.  The c\bcd\bd builtin is
-              commonly redefined this way.  The  return  status  is  false  if
+              commonly  redefined  this  way.   The  return status is false if
               _\bs_\bh_\be_\bl_\bl_\b-_\bb_\bu_\bi_\bl_\bt_\bi_\bn is not a shell builtin command.
 
        c\bca\bal\bll\ble\ber\br [_\be_\bx_\bp_\br]
               Returns the context of any active subroutine call (a shell func-
               tion or a script executed with the .\b. or s\bso\bou\bur\brc\bce\be builtins).  With-
               out _\be_\bx_\bp_\br, c\bca\bal\bll\ble\ber\br displays the line number and source filename of
-              the current subroutine call.  If a non-negative integer is  sup-
+              the  current subroutine call.  If a non-negative integer is sup-
               plied as _\be_\bx_\bp_\br, c\bca\bal\bll\ble\ber\br displays the line number, subroutine name,
-              and source file corresponding to that position  in  the  current
-              execution  call  stack.  This extra information may be used, for
-              example, to print a stack trace.  The current frame is frame  0.
-              The  return  value is 0 unless the shell is not executing a sub-
-              routine call or _\be_\bx_\bp_\br does not correspond to a valid position  in
+              and  source  file  corresponding to that position in the current
+              execution call stack.  This extra information may be  used,  for
+              example,  to print a stack trace.  The current frame is frame 0.
+              The return value is 0 unless the shell is not executing  a  sub-
+              routine  call or _\be_\bx_\bp_\br does not correspond to a valid position in
               the call stack.
 
        c\bcd\bd [-\b-L\bL|[-\b-P\bP [-\b-e\be]] [-@]] [_\bd_\bi_\br]
-              Change  the  current  directory to _\bd_\bi_\br.  if _\bd_\bi_\br is not supplied,
-              the value of the H\bHO\bOM\bME\bE shell variable is the default.  Any  addi-
+              Change the current directory to _\bd_\bi_\br.  if _\bd_\bi_\br  is  not  supplied,
+              the  value of the H\bHO\bOM\bME\bE shell variable is the default.  Any addi-
               tional arguments following _\bd_\bi_\br are ignored.  The variable C\bCD\bDP\bPA\bAT\bTH\bH
-              defines the search path for the directory containing  _\bd_\bi_\br:  each
-              directory  name  in  C\bCD\bDP\bPA\bAT\bTH\bH  is  searched  for _\bd_\bi_\br.  Alternative
-              directory names in C\bCD\bDP\bPA\bAT\bTH\bH are separated by a colon (:).  A  null
-              directory  name  in C\bCD\bDP\bPA\bAT\bTH\bH is the same as the current directory,
+              defines  the  search path for the directory containing _\bd_\bi_\br: each
+              directory name in  C\bCD\bDP\bPA\bAT\bTH\bH  is  searched  for  _\bd_\bi_\br.   Alternative
+              directory  names in C\bCD\bDP\bPA\bAT\bTH\bH are separated by a colon (:).  A null
+              directory name in C\bCD\bDP\bPA\bAT\bTH\bH is the same as the  current  directory,
               i.e., ``.\b.''.  If _\bd_\bi_\br begins with a slash (/), then C\bCD\bDP\bPA\bAT\bTH\bH is not
-              used.  The  -\b-P\bP  option  causes  c\bcd\bd to use the physical directory
-              structure by resolving symbolic links while traversing  _\bd_\bi_\b and
+              used. The -\b-P\bP option causes c\bcd\bd  to  use  the  physical  directory
+              structure  by  resolving symbolic links while traversing _\bd_\bi_\br and
               before processing instances of _\b._\b. in _\bd_\bi_\br (see also the -\b-P\bP option
               to the s\bse\bet\bt builtin command); the -\b-L\bL option forces symbolic links
-              to  be followed by resolving the link after processing instances
+              to be followed by resolving the link after processing  instances
               of _\b._\b. in _\bd_\bi_\br.  If _\b._\b. appears in _\bd_\bi_\br, it is processed by removing
-              the  immediately previous pathname component from _\bd_\bi_\br, back to a
-              slash or the beginning of _\bd_\bi_\br.  If the  -\b-e\be  option  is  supplied
-              with  -\b-P\bP,  and  the current working directory cannot be success-
-              fully determined after a successful directory  change,  c\bcd\b will
-              return  an unsuccessful status.  On systems that support it, the
-              -\b-@\boption presents the extended  attributes  associated  with  a
-              file  as  a directory.  An argument of -\b- is converted to $\b$O\bOL\bLD\bDP\bPW\bWD\bD
+              the immediately previous pathname component from _\bd_\bi_\br, back to  a
+              slash  or  the  beginning  of _\bd_\bi_\br.  If the -\b-e\be option is supplied
+              with -\b-P\bP, and the current working directory  cannot  be  success-
+              fully  determined  after  a successful directory change, c\bcd\bd will
+              return an unsuccessful status.  On systems that support it,  the
+              -\b-@\b option  presents  the  extended attributes associated with a
+              file as a directory.  An argument of -\b- is converted  to  $\b$O\bOL\bLD\bDP\bPW\bWD\bD
               before the directory change is attempted.  If a non-empty direc-
-              tory  name  from  C\bCD\bDP\bPA\bAT\bTH\bH is used, or if -\b- is the first argument,
+              tory name from C\bCD\bDP\bPA\bAT\bTH\bH is used, or if -\b- is  the  first  argument,
               and the directory change is successful, the absolute pathname of
-              the  new  working  directory  is written to the standard output.
-              The return value is  true  if  the  directory  was  successfully
+              the new working directory is written  to  the  standard  output.
+              The  return  value  is  true  if  the directory was successfully
               changed; false otherwise.
 
        c\bco\bom\bmm\bma\ban\bnd\bd [-\b-p\bpV\bVv\bv] _\bc_\bo_\bm_\bm_\ba_\bn_\bd [_\ba_\br_\bg ...]
-              Run  _\bc_\bo_\bm_\bm_\ba_\bn_\bd  with  _\ba_\br_\bg_\bs  suppressing  the normal shell function
-              lookup. Only builtin commands or commands found in the P\bPA\bAT\bTH\b are
-              executed.   If the -\b-p\bp option is given, the search for _\bc_\bo_\bm_\bm_\ba_\bn_\bd is
-              performed using a default value for P\bPA\bAT\bTH\bH that is  guaranteed  to
-              find  all  of  the  standard  utilities.  If either the -\b-V\bV or -\b-v\bv
+              Run _\bc_\bo_\bm_\bm_\ba_\bn_\bd with _\ba_\br_\bg_\bs  suppressing  the  normal  shell  function
+              lookup.  Only builtin commands or commands found in the P\bPA\bAT\bTH\bH are
+              executed.  If the -\b-p\bp option is given, the search for _\bc_\bo_\bm_\bm_\ba_\bn_\b is
+              performed  using  a default value for P\bPA\bAT\bTH\bH that is guaranteed to
+              find all of the standard utilities.  If  either  the  -\b-V\bV  or  -\b-v\bv
               option is supplied, a description of _\bc_\bo_\bm_\bm_\ba_\bn_\bd is printed.  The -\b-v\bv
-              option  causes  a single word indicating the command or filename
+              option causes a single word indicating the command  or  filename
               used to invoke _\bc_\bo_\bm_\bm_\ba_\bn_\bd to be displayed; the -\b-V\bV option produces a
-              more  verbose  description.  If the -\b-V\bV or -\b-v\bv option is supplied,
-              the exit status is 0 if _\bc_\bo_\bm_\bm_\ba_\bn_\bd was found, and  1  if  not.   If
+              more verbose description.  If the -\b-V\bV or -\b-v\bv option  is  supplied,
+              the  exit  status  is  0 if _\bc_\bo_\bm_\bm_\ba_\bn_\bd was found, and 1 if not.  If
               neither option is supplied and an error occurred or _\bc_\bo_\bm_\bm_\ba_\bn_\bd can-
-              not be found, the exit status is 127.  Otherwise, the exit  sta-
+              not  be found, the exit status is 127.  Otherwise, the exit sta-
               tus of the c\bco\bom\bmm\bma\ban\bnd\bd builtin is the exit status of _\bc_\bo_\bm_\bm_\ba_\bn_\bd.
 
        c\bco\bom\bmp\bpg\bge\ben\bn [_\bo_\bp_\bt_\bi_\bo_\bn] [_\bw_\bo_\br_\bd]
-              Generate  possible  completion matches for _\bw_\bo_\br_\bd according to the
-              _\bo_\bp_\bt_\bi_\bo_\bns, which may  be  any  option  accepted  by  the  c\bco\bom\bmp\bpl\ble\bet\bte\be
-              builtin  with  the exception of -\b-p\bp and -\b-r\br, and write the matches
-              to the standard output.  When using the -\b-F\bF or  -\b-C\bC  options,  the
-              various  shell  variables  set  by  the  programmable completion
+              Generate possible completion matches for _\bw_\bo_\br_\bd according  to  the
+              _\bo_\bp_\bt_\bi_\bo_\bns,  which  may  be  any  option  accepted  by the c\bco\bom\bmp\bpl\ble\bet\bte\be
+              builtin with the exception of -\b-p\bp and -\b-r\br, and write  the  matches
+              to  the  standard  output.  When using the -\b-F\bF or -\b-C\bC options, the
+              various shell  variables  set  by  the  programmable  completion
               facilities, while available, will not have useful values.
 
-              The matches will be generated in the same way  as  if  the  pro-
-              grammable  completion  code  had  generated them directly from a
+              The  matches  will  be  generated in the same way as if the pro-
+              grammable completion code had generated  them  directly  from  a
               completion specification with the same flags.  If _\bw_\bo_\br_\bd is speci-
               fied, only those completions matching _\bw_\bo_\br_\bd will be displayed.
 
-              The  return  value is true unless an invalid option is supplied,
+              The return value is true unless an invalid option  is  supplied,
               or no matches were generated.
 
-       c\bco\bom\bmp\bpl\ble\bet\bte\b[-\b-a\bab\bbc\bcd\bde\bef\bfg\bgj\bjk\bks\bsu\buv\bv] [-\b-o\bo _\bc_\bo_\bm_\bp_\b-_\bo_\bp_\bt_\bi_\bo_\bn] [-\b-D\bDE\bE] [-\b-A\bA _\ba_\bc_\bt_\bi_\bo_\bn]  [-\b-G\b _\bg_\bl_\bo_\bb_\b-
+       c\bco\bom\bmp\bpl\ble\bet\bte\b [-\b-a\bab\bbc\bcd\bde\bef\bfg\bgj\bjk\bks\bsu\buv\bv]  [-\b-o\bo _\bc_\bo_\bm_\bp_\b-_\bo_\bp_\bt_\bi_\bo_\bn] [-\b-D\bDE\bE] [-\b-A\bA _\ba_\bc_\bt_\bi_\bo_\bn] [-\b-G\bG _\bg_\bl_\bo_\bb_\b-
        _\bp_\ba_\bt] [-\b-W\bW _\bw_\bo_\br_\bd_\bl_\bi_\bs_\bt] [-\b-F\bF _\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn] [-\b-C\bC _\bc_\bo_\bm_\bm_\ba_\bn_\bd]
               [-\b-X\bX _\bf_\bi_\bl_\bt_\be_\br_\bp_\ba_\bt] [-\b-P\bP _\bp_\br_\be_\bf_\bi_\bx] [-\b-S\bS _\bs_\bu_\bf_\bf_\bi_\bx] _\bn_\ba_\bm_\be [_\bn_\ba_\bm_\be _\b._\b._\b.]
        c\bco\bom\bmp\bpl\ble\bet\bte\be -\b-p\bpr\br [-\b-D\bDE\bE] [_\bn_\ba_\bm_\be ...]
-              Specify how arguments to each _\bn_\ba_\bm_\be should be completed.  If  the
-              -\b-p\b option  is supplied, or if no options are supplied, existing
-              completion specifications are printed in a way that allows  them
+              Specify  how arguments to each _\bn_\ba_\bm_\be should be completed.  If the
+              -\b-p\boption is supplied, or if no options are  supplied,  existing
+              completion  specifications are printed in a way that allows them
               to be reused as input.  The -\b-r\br option removes a completion spec-
-              ification for each _\bn_\ba_\bm_\be, or, if no _\bn_\ba_\bm_\bes are supplied, all  com-
+              ification  for each _\bn_\ba_\bm_\be, or, if no _\bn_\ba_\bm_\bes are supplied, all com-
               pletion  specifications.   The  -\b-D\bD  option  indicates  that  the
-              remaining options and actions should apply  to  the  ``default''
-              command  completion;  that is, completion attempted on a command
-              for which no completion has previously  been  defined.   The  -\b-E\bE
-              option  indicates  that the remaining options and actions should
-              apply to  ``empty''  command  completion;  that  is,  completion
+              remaining  options  and  actions should apply to the ``default''
+              command completion; that is, completion attempted on  a  command
+              for  which  no  completion  has previously been defined.  The -\b-E\bE
+              option indicates that the remaining options and  actions  should
+              apply  to  ``empty''  command  completion;  that  is, completion
               attempted on a blank line.
 
-              The  process  of  applying  these completion specifications when
-              word completion is  attempted  is  described  above  under  P\bPr\bro\bo-\b-
+              The process of applying  these  completion  specifications  when
+              word  completion  is  attempted  is  described  above under P\bPr\bro\bo-\b-
               g\bgr\bra\bam\bmm\bma\bab\bbl\ble\be C\bCo\bom\bmp\bpl\ble\bet\bti\bio\bon\bn.
 
-              Other  options,  if specified, have the following meanings.  The
-              arguments to the -\b-G\bG, -\b-W\bW, and -\b-X\bX options (and, if necessary,  the
-              -\b-P\b and -\b-S\bS options) should be quoted to protect them from expan-
+              Other options, if specified, have the following  meanings.   The
+              arguments  to the -\b-G\bG, -\b-W\bW, and -\b-X\bX options (and, if necessary, the
+              -\b-P\band -\b-S\bS options) should be quoted to protect them from  expan-
               sion before the c\bco\bom\bmp\bpl\ble\bet\bte\be builtin is invoked.
               -\b-o\bo _\bc_\bo_\bm_\bp_\b-_\bo_\bp_\bt_\bi_\bo_\bn
-                      The _\bc_\bo_\bm_\bp_\b-_\bo_\bp_\bt_\bi_\bo_\bn controls several aspects  of  the  comp-
-                      spec's  behavior beyond the simple generation of comple-
+                      The  _\bc_\bo_\bm_\bp_\b-_\bo_\bp_\bt_\bi_\bo_\bn  controls  several aspects of the comp-
+                      spec's behavior beyond the simple generation of  comple-
                       tions.  _\bc_\bo_\bm_\bp_\b-_\bo_\bp_\bt_\bi_\bo_\bn may be one of:
                       b\bba\bas\bsh\bhd\bde\bef\bfa\bau\bul\blt\bt
                               Perform the rest of the default b\bba\bas\bsh\bh completions
                               if the compspec generates no matches.
-                      d\bde\bef\bfa\bau\bul\blt\bt Use  readline's  default  filename completion if
+                      d\bde\bef\bfa\bau\bul\blt\bt Use readline's default  filename  completion  if
                               the compspec generates no matches.
                       d\bdi\bir\brn\bna\bam\bme\bes\bs
-                              Perform directory name completion if  the  comp-
+                              Perform  directory  name completion if the comp-
                               spec generates no matches.
                       f\bfi\bil\ble\ben\bna\bam\bme\bes\bs
-                              Tell  readline that the compspec generates file-
-                              names, so it can perform  any  filename-specific
-                              processing  (like  adding  a  slash to directory
-                              names, quoting special characters, or  suppress-
-                              ing  trailing spaces).  Intended to be used with
+                              Tell readline that the compspec generates  file-
+                              names,  so  it can perform any filename-specific
+                              processing (like adding  a  slash  to  directory
+                              names,  quoting special characters, or suppress-
+                              ing trailing spaces).  Intended to be used  with
                               shell functions.
-                      n\bno\boq\bqu\buo\bot\bte\be Tell readline not to quote the  completed  words
-                              if  they are filenames (quoting filenames is the
+                      n\bno\boq\bqu\buo\bot\bte\be Tell  readline  not to quote the completed words
+                              if they are filenames (quoting filenames is  the
                               default).
-                      n\bno\bos\bsp\bpa\bac\bce\be Tell  readline  not  to  append  a  space   (the
-                              default)  to  words  completed at the end of the
+                      n\bno\bos\bsp\bpa\bac\bce\be Tell   readline  not  to  append  a  space  (the
+                              default) to words completed at the  end  of  the
                               line.
                       p\bpl\blu\bus\bsd\bdi\bir\brs\bs
-                              After any matches defined by  the  compspec  are
-                              generated,    directory   name   completion   is
-                              attempted and  any  matches  are  added  to  the
+                              After  any  matches  defined by the compspec are
+                              generated,   directory   name   completion    is
+                              attempted  and  any  matches  are  added  to the
                               results of the other actions.
               -\b-A\bA _\ba_\bc_\bt_\bi_\bo_\bn
-                      The  _\ba_\bc_\bt_\bi_\bo_\bn  may  be  one of the following to generate a
+                      The _\ba_\bc_\bt_\bi_\bo_\bn may be one of the  following  to  generate  a
                       list of possible completions:
                       a\bal\bli\bia\bas\bs   Alias names.  May also be specified as -\b-a\ba.
                       a\bar\brr\bra\bay\byv\bva\bar\br
                               Array variable names.
                       b\bbi\bin\bnd\bdi\bin\bng\bg R\bRe\bea\bad\bdl\bli\bin\bne\be key binding names.
-                      b\bbu\bui\bil\blt\bti\bin\bn Names of shell builtin commands.   May  also  be
+                      b\bbu\bui\bil\blt\bti\bin\bn Names  of  shell  builtin commands.  May also be
                               specified as -\b-b\bb.
                       c\bco\bom\bmm\bma\ban\bnd\bd Command names.  May also be specified as -\b-c\bc.
                       d\bdi\bir\bre\bec\bct\bto\bor\bry\by
@@ -4143,7 +4146,7 @@ S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS
                       d\bdi\bis\bsa\bab\bbl\ble\bed\bd
                               Names of disabled shell builtins.
                       e\ben\bna\bab\bbl\ble\bed\bd Names of enabled shell builtins.
-                      e\bex\bxp\bpo\bor\brt\bt  Names  of exported shell variables.  May also be
+                      e\bex\bxp\bpo\bor\brt\bt  Names of exported shell variables.  May also  be
                               specified as -\b-e\be.
                       f\bfi\bil\ble\be    File names.  May also be specified as -\b-f\bf.
                       f\bfu\bun\bnc\bct\bti\bio\bon\bn
@@ -4152,17 +4155,17 @@ S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS
                       h\bhe\bel\blp\bpt\bto\bop\bpi\bic\bc
                               Help topics as accepted by the h\bhe\bel\blp\bp builtin.
                       h\bho\bos\bst\btn\bna\bam\bme\be
-                              Hostnames, as taken from the file  specified  by
+                              Hostnames,  as  taken from the file specified by
                               the H\bHO\bOS\bST\bTF\bFI\bIL\bLE\bE shell variable.
-                      j\bjo\bob\bb     Job  names,  if job control is active.  May also
+                      j\bjo\bob\bb     Job names, if job control is active.   May  also
                               be specified as -\b-j\bj.
-                      k\bke\bey\byw\bwo\bor\brd\bd Shell reserved words.  May also be specified  as
+                      k\bke\bey\byw\bwo\bor\brd\bd Shell  reserved words.  May also be specified as
                               -\b-k\bk.
                       r\bru\bun\bnn\bni\bin\bng\bg Names of running jobs, if job control is active.
                       s\bse\ber\brv\bvi\bic\bce\be Service names.  May also be specified as -\b-s\bs.
-                      s\bse\bet\bto\bop\bpt\bt  Valid arguments for the -\b-o\bo  option  to  the  s\bse\bet\bt
+                      s\bse\bet\bto\bop\bpt\bt  Valid  arguments  for  the  -\b-o\bo option to the s\bse\bet\bt
                               builtin.
-                      s\bsh\bho\bop\bpt\bt   Shell  option  names  as  accepted  by the s\bsh\bho\bop\bpt\bt
+                      s\bsh\bho\bop\bpt\bt   Shell option names  as  accepted  by  the  s\bsh\bho\bop\bpt\bt
                               builtin.
                       s\bsi\big\bgn\bna\bal\bl  Signal names.
                       s\bst\bto\bop\bpp\bpe\bed\bd Names of stopped jobs, if job control is active.
@@ -4171,187 +4174,187 @@ S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS
                               Names of all shell variables.  May also be spec-
                               ified as -\b-v\bv.
               -\b-C\bC _\bc_\bo_\bm_\bm_\ba_\bn_\bd
-                      _\bc_\bo_\bm_\bm_\ba_\bn_\bis executed in a subshell environment,  and  its
+                      _\bc_\bo_\bm_\bm_\ba_\bn_\b is  executed in a subshell environment, and its
                       output is used as the possible completions.
               -\b-F\bF _\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn
-                      The  shell  function _\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn is executed in the current
-                      shell environment.  When the function is  executed,  the
-                      first  argument  ($\b$1\b1)  is  the name of the command whose
-                      arguments are being completed, the second argument  ($\b$2\b2)
+                      The shell function _\bf_\bu_\bn_\bc_\bt_\bi_\bo_\bn is executed in  the  current
+                      shell  environment.   When the function is executed, the
+                      first argument ($\b$1\b1) is the name  of  the  command  whose
+                      arguments  are being completed, the second argument ($\b$2\b2)
                       is the word being completed, and the third argument ($\b$3\b3)
-                      is the word preceding the word being  completed  on  the
-                      current  command  line.   When it finishes, the possible
-                      completions are retrieved from the value of the  C\bCO\bOM\bMP\bPR\bRE\bE-\b-
+                      is  the  word  preceding the word being completed on the
+                      current command line.  When it  finishes,  the  possible
+                      completions  are retrieved from the value of the C\bCO\bOM\bMP\bPR\bRE\bE-\b-
                       P\bPL\bLY\bY array variable.
               -\b-G\bG _\bg_\bl_\bo_\bb_\bp_\ba_\bt
-                      The  pathname  expansion  pattern _\bg_\bl_\bo_\bb_\bp_\ba_\bt is expanded to
+                      The pathname expansion pattern _\bg_\bl_\bo_\bb_\bp_\ba_\bt  is  expanded  to
                       generate the possible completions.
               -\b-P\bP _\bp_\br_\be_\bf_\bi_\bx
-                      _\bp_\br_\be_\bf_\bi_\bis added at the beginning of each  possible  com-
+                      _\bp_\br_\be_\bf_\bi_\b is  added at the beginning of each possible com-
                       pletion after all other options have been applied.
               -\b-S\bS _\bs_\bu_\bf_\bf_\bi_\bx
                       _\bs_\bu_\bf_\bf_\bi_\bx is appended to each possible completion after all
                       other options have been applied.
               -\b-W\bW _\bw_\bo_\br_\bd_\bl_\bi_\bs_\bt
-                      The _\bw_\bo_\br_\bd_\bl_\bi_\bs_\bt is split using the characters  in  the  I\bIF\bFS\bS
-                      special  variable as delimiters, and each resultant word
-                      is expanded.  The possible completions are  the  members
-                      of  the  resultant  list which match the word being com-
+                      The  _\bw_\bo_\br_\bd_\bl_\bi_\bs_\bt  is  split using the characters in the I\bIF\bFS\bS
+                      special variable as delimiters, and each resultant  word
+                      is  expanded.   The possible completions are the members
+                      of the resultant list which match the  word  being  com-
                       pleted.
               -\b-X\bX _\bf_\bi_\bl_\bt_\be_\br_\bp_\ba_\bt
-                      _\bf_\bi_\bl_\bt_\be_\br_\bp_\ba_\bis a pattern as used for  pathname  expansion.
+                      _\bf_\bi_\bl_\bt_\be_\br_\bp_\ba_\b is  a pattern as used for pathname expansion.
                       It is applied to the list of possible completions gener-
-                      ated by the preceding options and  arguments,  and  each
-                      completion  matching _\bf_\bi_\bl_\bt_\be_\br_\bp_\ba_\bt is removed from the list.
-                      A leading !\b! in _\bf_\bi_\bl_\bt_\be_\br_\bp_\ba_\bt negates the  pattern;  in  this
-                      case,  any completion not matching _\bf_\bi_\bl_\bt_\be_\br_\bp_\ba_\bt is removed.
+                      ated  by  the  preceding options and arguments, and each
+                      completion matching _\bf_\bi_\bl_\bt_\be_\br_\bp_\ba_\bt is removed from the  list.
+                      A  leading  !\b!  in _\bf_\bi_\bl_\bt_\be_\br_\bp_\ba_\bt negates the pattern; in this
+                      case, any completion not matching _\bf_\bi_\bl_\bt_\be_\br_\bp_\ba_\bt is  removed.
 
-              The return value is true unless an invalid option  is  supplied,
-              an  option  other than -\b-p\bp or -\b-r\br is supplied without a _\bn_\ba_\bm_\be argu-
-              ment, an attempt is made to remove  a  completion  specification
+              The  return  value is true unless an invalid option is supplied,
+              an option other than -\b-p\bp or -\b-r\br is supplied without a  _\bn_\ba_\bm_\b argu-
+              ment,  an  attempt  is made to remove a completion specification
               for a _\bn_\ba_\bm_\be for which no specification exists, or an error occurs
               adding a completion specification.
 
        c\bco\bom\bmp\bpo\bop\bpt\bt [-\b-o\bo _\bo_\bp_\bt_\bi_\bo_\bn] [-\b-D\bDE\bE] [+\b+o\bo _\bo_\bp_\bt_\bi_\bo_\bn] [_\bn_\ba_\bm_\be]
               Modify  completion  options  for  each  _\bn_\ba_\bm_\be  according  to  the
-              _\bo_\bp_\bt_\bi_\bo_\bns,  or  for the currently-executing completion if no _\bn_\ba_\bm_\bes
-              are supplied.  If no _\bo_\bp_\bt_\bi_\bo_\bns are given, display  the  completion
-              options  for  each _\bn_\ba_\bm_\be or the current completion.  The possible
-              values of _\bo_\bp_\bt_\bi_\bo_\bn  are  those  valid  for  the  c\bco\bom\bmp\bpl\ble\bet\bte\b builtin
-              described  above.   The  -\b-D\bD  option indicates that the remaining
+              _\bo_\bp_\bt_\bi_\bo_\bns, or for the currently-executing completion if  no  _\bn_\ba_\bm_\bes
+              are  supplied.   If no _\bo_\bp_\bt_\bi_\bo_\bns are given, display the completion
+              options for each _\bn_\ba_\bm_\be or the current completion.   The  possible
+              values  of  _\bo_\bp_\bt_\bi_\bo_\bn  are  those  valid  for  the c\bco\bom\bmp\bpl\ble\bet\bte\be builtin
+              described above.  The -\b-D\bD option  indicates  that  the  remaining
               options should apply to the ``default'' command completion; that
-              is,  completion  attempted  on a command for which no completion
-              has previously been defined.  The -\b-E\bE option indicates  that  the
-              remaining  options should apply to ``empty'' command completion;
+              is, completion attempted on a command for  which  no  completion
+              has  previously  been defined.  The -\b-E\bE option indicates that the
+              remaining options should apply to ``empty'' command  completion;
               that is, completion attempted on a blank line.
 
-              The return value is true unless an invalid option  is  supplied,
+              The  return  value is true unless an invalid option is supplied,
               an attempt is made to modify the options for a _\bn_\ba_\bm_\be for which no
               completion specification exists, or an output error occurs.
 
        c\bco\bon\bnt\bti\bin\bnu\bue\be [_\bn]
               Resume the next iteration of the enclosing f\bfo\bor\br, w\bwh\bhi\bil\ble\be, u\bun\bnt\bti\bil\bl, or
-              s\bse\bel\ble\bec\bct\b loop.   If  _\bn  is specified, resume at the _\bnth enclosing
-              loop.  _\bn must be >= 1.  If _\bn  is  greater  than  the  number  of
-              enclosing  loops,  the  last  enclosing  loop (the ``top-level''
+              s\bse\bel\ble\bec\bct\bloop.  If _\bn is specified, resume  at  the  _\bnth  enclosing
+              loop.   _\bn  must  be  >=  1.   If _\bn is greater than the number of
+              enclosing loops, the  last  enclosing  loop  (the  ``top-level''
               loop) is resumed.  The return value is 0 unless _\bn is not greater
               than or equal to 1.
 
        d\bde\bec\bcl\bla\bar\bre\be [-\b-a\baA\bAf\bfF\bFg\bgi\bil\bln\bnr\brt\btu\bux\bx] [-\b-p\bp] [_\bn_\ba_\bm_\be[=_\bv_\ba_\bl_\bu_\be] ...]
        t\bty\byp\bpe\bes\bse\bet\bt [-\b-a\baA\bAf\bfF\bFg\bgi\bil\bln\bnr\brt\btu\bux\bx] [-\b-p\bp] [_\bn_\ba_\bm_\be[=_\bv_\ba_\bl_\bu_\be] ...]
-              Declare  variables and/or give them attributes.  If no _\bn_\ba_\bm_\bes are
-              given then display the values of variables.  The -\b-p\bp option  will
+              Declare variables and/or give them attributes.  If no _\bn_\ba_\bm_\bes  are
+              given  then display the values of variables.  The -\b-p\bp option will
               display the attributes and values of each _\bn_\ba_\bm_\be.  When -\b-p\bp is used
-              with _\bn_\ba_\bm_\be arguments, additional options, other than -\b-f\bf  and  -\b-F\bF,
-              are  ignored.   When  -\b-p\bp  is supplied without _\bn_\ba_\bm_\be arguments, it
-              will display the attributes and values of all  variables  having
+              with  _\bn_\ba_\bm_\be  arguments, additional options, other than -\b-f\bf and -\b-F\bF,
+              are ignored.  When -\b-p\bp is supplied  without  _\bn_\ba_\bm_\be  arguments,  it
+              will  display  the attributes and values of all variables having
               the attributes specified by the additional options.  If no other
-              options  are  supplied  with  -\b-p\bp,  d\bde\bec\bcl\bla\bar\bre\be  will   display   the
-              attributes  and  values  of  all shell variables.  The -\b-f\bf option
-              will restrict the display to shell  functions.   The  -\b-F\b option
-              inhibits  the display of function definitions; only the function
-              name and attributes are printed.  If the e\bex\bxt\btd\bde\beb\bbu\bug\bg  shell  option
-              is  enabled  using  s\bsh\bho\bop\bpt\bt,  the source file name and line number
-              where the function is defined are displayed  as  well.   The  -\b-F\bF
+              options   are   supplied  with  -\b-p\bp,  d\bde\bec\bcl\bla\bar\bre\be  will  display  the
+              attributes and values of all shell  variables.   The  -\b-f\b option
+              will  restrict  the  display  to shell functions.  The -\b-F\bF option
+              inhibits the display of function definitions; only the  function
+              name  and  attributes are printed.  If the e\bex\bxt\btd\bde\beb\bbu\bug\bg shell option
+              is enabled using s\bsh\bho\bop\bpt\bt, the source file  name  and  line  number
+              where  the  function  is  defined are displayed as well.  The -\b-F\bF
               option implies -\b-f\bf.  The -\b-g\bg option forces variables to be created
-              or modified at the global scope, even when d\bde\bec\bcl\bla\bar\bre\be  is  executed
-              in  a  shell  function.   It is ignored in all other cases.  The
-              following options can be used to restrict  output  to  variables
+              or  modified  at the global scope, even when d\bde\bec\bcl\bla\bar\bre\be is executed
+              in a shell function.  It is ignored in  all  other  cases.   The
+              following  options  can  be used to restrict output to variables
               with the specified attribute or to give variables attributes:
-              -\b-a\ba     Each  _\bn_\ba_\bm_\be  is  an  indexed  array  variable  (see A\bAr\brr\bra\bay\bys\bs
+              -\b-a\ba     Each _\bn_\ba_\bm_\be  is  an  indexed  array  variable  (see  A\bAr\brr\bra\bay\bys\bs
                      above).
-              -\b-A\bA     Each _\bn_\ba_\bm_\be is an associative array  variable  (see  A\bAr\brr\bra\bay\bys\bs
+              -\b-A\bA     Each  _\bn_\ba_\bm_\be  is  an associative array variable (see A\bAr\brr\bra\bay\bys\bs
                      above).
               -\b-f\bf     Use function names only.
               -\b-i\bi     The variable is treated as an integer; arithmetic evalua-
-                     tion (see A\bAR\bRI\bIT\bTH\bHM\bME\bET\bTI\bIC\bC E\bEV\bVA\bAL\bLU\bUA\bAT\bTI\bIO\bON\bN above) is performed  when
+                     tion  (see A\bAR\bRI\bIT\bTH\bHM\bME\bET\bTI\bIC\bC E\bEV\bVA\bAL\bLU\bUA\bAT\bTI\bIO\bON\bN above) is performed when
                      the variable is assigned a value.
-              -\b-l\bl     When  the  variable  is  assigned a value, all upper-case
-                     characters are converted to lower-case.   The  upper-case
+              -\b-l\bl     When the variable is assigned  a  value,  all  upper-case
+                     characters  are  converted to lower-case.  The upper-case
                      attribute is disabled.
-              -\b-n\bn     Give  each  _\bn_\ba_\bm_\be  the _\bn_\ba_\bm_\be_\br_\be_\bf attribute, making it a name
-                     reference to another variable.  That  other  variable  is
+              -\b-n\bn     Give each _\bn_\ba_\bm_\be the _\bn_\ba_\bm_\be_\br_\be_\bf attribute, making  it  a  name
+                     reference  to  another  variable.  That other variable is
                      defined by the value of _\bn_\ba_\bm_\be.  All references and assign-
-                     ments to _\bn_\ba_\bm_\be,  except  for  changing  the  -\b-n\b attribute
-                     itself,  are  performed  on  the  variable  referenced by
-                     _\bn_\ba_\bm_\be's value.  The -\b-n\bn  attribute  cannot  be  applied  to
+                     ments  to  _\bn_\ba_\bm_\be,  except  for  changing  the -\b-n\bn attribute
+                     itself, are  performed  on  the  variable  referenced  by
+                     _\bn_\ba_\bm_\be's  value.   The  -\b-n\bn  attribute  cannot be applied to
                      array variables.
               -\b-r\br     Make _\bn_\ba_\bm_\bes readonly.  These names cannot then be assigned
                      values by subsequent assignment statements or unset.
-              -\b-t\bt     Give each _\bn_\ba_\bm_\be the  _\bt_\br_\ba_\bc_\be  attribute.   Traced  functions
-                     inherit  the  D\bDE\bEB\bBU\bUG\bG  and  R\bRE\bET\bTU\bUR\bRN\bN  traps  from the calling
-                     shell.  The trace attribute has no  special  meaning  for
+              -\b-t\bt     Give  each  _\bn_\ba_\bm_\be  the  _\bt_\br_\ba_\bc_\be attribute.  Traced functions
+                     inherit the D\bDE\bEB\bBU\bUG\bG  and  R\bRE\bET\bTU\bUR\bRN\bN  traps  from  the  calling
+                     shell.   The  trace  attribute has no special meaning for
                      variables.
-              -\b-u\bu     When  the  variable  is  assigned a value, all lower-case
-                     characters are converted to upper-case.   The  lower-case
+              -\b-u\bu     When the variable is assigned  a  value,  all  lower-case
+                     characters  are  converted to upper-case.  The lower-case
                      attribute is disabled.
-              -\b-x\bx     Mark  _\bn_\ba_\bm_\bes  for  export  to  subsequent commands via the
+              -\b-x\bx     Mark _\bn_\ba_\bm_\bes for export  to  subsequent  commands  via  the
                      environment.
 
-              Using `+' instead of `-' turns off the attribute  instead,  with
+              Using  `+'  instead of `-' turns off the attribute instead, with
               the exceptions that +\b+a\ba may not be used to destroy an array vari-
-              able and +\b+r\br will not remove the readonly attribute.   When  used
+              able  and  +\b+r\br will not remove the readonly attribute.  When used
               in a function, d\bde\bec\bcl\bla\bar\bre\be and t\bty\byp\bpe\bes\bse\bet\bt make each _\bn_\ba_\bm_\be local, as with
               the l\blo\boc\bca\bal\bl command, unless the -\b-g\bg option is supplied.  If a vari-
-              able  name  is  followed by =_\bv_\ba_\bl_\bu_\be, the value of the variable is
-              set to _\bv_\ba_\bl_\bu_\be.  When using -\b-a\ba or -\b-A\bA and the  compound  assignment
-              syntax  to  create array variables, additional attributes do not
+              able name is followed by =_\bv_\ba_\bl_\bu_\be, the value of  the  variable  is
+              set  to  _\bv_\ba_\bl_\bu_\be.  When using -\b-a\ba or -\b-A\bA and the compound assignment
+              syntax to create array variables, additional attributes  do  not
               take effect until subsequent assignments.  The return value is 0
-              unless  an  invalid option is encountered, an attempt is made to
-              define a function using ``-f foo=bar'', an attempt  is  made  to
-              assign  a  value  to  a readonly variable, an attempt is made to
-              assign a value to an array variable without using  the  compound
-              assignment  syntax (see A\bAr\brr\bra\bay\bys\bs above), one of the _\bn_\ba_\bm_\be_\bs is not a
-              valid shell variable name, an attempt is made to turn off  read-
-              only  status for a readonly variable, an attempt is made to turn
+              unless an invalid option is encountered, an attempt is  made  to
+              define  a  function  using ``-f foo=bar'', an attempt is made to
+              assign a value to a readonly variable, an  attempt  is  made  to
+              assign  a  value to an array variable without using the compound
+              assignment syntax (see A\bAr\brr\bra\bay\bys\bs above), one of the _\bn_\ba_\bm_\be_\bs is not  a
+              valid  shell variable name, an attempt is made to turn off read-
+              only status for a readonly variable, an attempt is made to  turn
               off array status for an array variable, or an attempt is made to
               display a non-existent function with -\b-f\bf.
 
        d\bdi\bir\brs\bs [\b[-\b-c\bcl\blp\bpv\bv]\b] [\b[+\b+_\bn]\b] [\b[-\b-_\bn]\b]
-              Without  options,  displays  the  list  of  currently remembered
-              directories.  The default display  is  on  a  single  line  with
-              directory  names  separated by spaces.  Directories are added to
-              the list with  the  p\bpu\bus\bsh\bhd\bd  command;  the  p\bpo\bop\bpd\bd  command  removes
+              Without options,  displays  the  list  of  currently  remembered
+              directories.   The  default  display  is  on  a single line with
+              directory names separated by spaces.  Directories are  added  to
+              the  list  with  the  p\bpu\bus\bsh\bhd\bd  command;  the  p\bpo\bop\bpd\bd command removes
               entries from the list.
               -\b-c\bc     Clears  the  directory  stack  by  deleting  all  of  the
                      entries.
-              -\b-l\bl     Produces a listing  using  full  pathnames;  the  default
+              -\b-l\bl     Produces  a  listing  using  full  pathnames; the default
                      listing format uses a tilde to denote the home directory.
               -\b-p\bp     Print the directory stack with one entry per line.
-              -\b-v\bv     Print the directory stack with one entry per  line,  pre-
+              -\b-v\bv     Print  the  directory stack with one entry per line, pre-
                      fixing each entry with its index in the stack.
               +\b+_\bn     Displays the _\bnth entry counting from the left of the list
                      shown by d\bdi\bir\brs\bs when invoked without options, starting with
                      zero.
-              -\b-_\bn     Displays  the  _\bnth  entry  counting from the right of the
+              -\b-_\bn     Displays the _\bnth entry counting from  the  right  of  the
                      list shown by d\bdi\bir\brs\bs when invoked without options, starting
                      with zero.
 
-              The  return value is 0 unless an invalid option is supplied or _\bn
+              The return value is 0 unless an invalid option is supplied or  _\bn
               indexes beyond the end of the directory stack.
 
        d\bdi\bis\bso\bow\bwn\bn [-\b-a\bar\br] [-\b-h\bh] [_\bj_\bo_\bb_\bs_\bp_\be_\bc ...]
-              Without options, remove each _\bj_\bo_\bb_\bs_\bp_\be_\bc from the  table  of  active
-              jobs.   If _\bj_\bo_\bb_\bs_\bp_\be_\bc is not present, and neither the -\b-a\ba nor the -\b-r\br
-              option is supplied, the _\bc_\bu_\br_\br_\be_\bn_\bt _\bj_\bo_\bb is used.  If the  -\b-h\b option
-              is  given,  each  _\bj_\bo_\bb_\bs_\bp_\be_\bc  is not removed from the table, but is
-              marked so that S\bSI\bIG\bGH\bHU\bUP\bP is not  sent  to  the  job  if  the  shell
-              receives  a  S\bSI\bIG\bGH\bHU\bUP\bP.   If  no _\bj_\bo_\bb_\bs_\bp_\be_\bc is supplied, the -\b-a\ba option
-              means to remove or mark all jobs; the -\b-r\br option without  a  _\bj_\bo_\bb_\b-
-              _\bs_\bp_\be_\b argument  restricts operation to running jobs.  The return
+              Without  options,  remove  each _\bj_\bo_\bb_\bs_\bp_\be_\bc from the table of active
+              jobs.  If _\bj_\bo_\bb_\bs_\bp_\be_\bc is not present, and neither the -\b-a\ba nor the  -\b-r\br
+              option  is  supplied, the _\bc_\bu_\br_\br_\be_\bn_\bt _\bj_\bo_\bb is used.  If the -\b-h\bh option
+              is given, each _\bj_\bo_\bb_\bs_\bp_\be_\bc is not removed from  the  table,  but  is
+              marked  so  that  S\bSI\bIG\bGH\bHU\bUP\bP  is  not  sent  to the job if the shell
+              receives a S\bSI\bIG\bGH\bHU\bUP\bP.  If no _\bj_\bo_\bb_\bs_\bp_\be_\bc is  supplied,  the  -\b-a\b option
+              means  to  remove or mark all jobs; the -\b-r\br option without a _\bj_\bo_\bb_\b-
+              _\bs_\bp_\be_\bargument restricts operation to running jobs.   The  return
               value is 0 unless a _\bj_\bo_\bb_\bs_\bp_\be_\bc does not specify a valid job.
 
        e\bec\bch\bho\bo [-\b-n\bne\beE\bE] [_\ba_\br_\bg ...]
-              Output the _\ba_\br_\bgs, separated by spaces,  followed  by  a  newline.
-              The  return  status  is 0 unless a write error occurs.  If -\b-n\bn is
+              Output  the  _\ba_\br_\bgs,  separated  by spaces, followed by a newline.
+              The return status is 0 unless a write error occurs.   If  -\b-n\b is
               specified, the trailing newline is suppressed.  If the -\b-e\be option
-              is  given,  interpretation  of  the  following backslash-escaped
-              characters is enabled.  The -\b-E\bE option disables  the  interpreta-
-              tion  of these escape characters, even on systems where they are
-              interpreted by default.  The x\bxp\bpg\bg_\b_e\bec\bch\bho\bo shell option may  be  used
-              to  dynamically  determine  whether  or  not  e\bec\bch\bho\bo expands these
-              escape characters by default.  e\bec\bch\bho\bo does  not  interpret  -\b--\b to
-              mean  the  end of options.  e\bec\bch\bho\bo interprets the following escape
+              is given,  interpretation  of  the  following  backslash-escaped
+              characters  is  enabled.  The -\b-E\bE option disables the interpreta-
+              tion of these escape characters, even on systems where they  are
+              interpreted  by  default.  The x\bxp\bpg\bg_\b_e\bec\bch\bho\bo shell option may be used
+              to dynamically determine  whether  or  not  e\bec\bch\bho\bo  expands  these
+              escape  characters  by  default.   e\bec\bch\bho\bo does not interpret -\b--\b- to
+              mean the end of options.  e\bec\bch\bho\bo interprets the  following  escape
               sequences:
               \\b\a\ba     alert (bell)
               \\b\b\bb     backspace
@@ -4364,189 +4367,189 @@ S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS
               \\b\t\bt     horizontal tab
               \\b\v\bv     vertical tab
               \\b\\\b\     backslash
-              \\b\0\b0_\bn_\bn_\bn  the eight-bit character whose value is  the  octal  value
+              \\b\0\b0_\bn_\bn_\bn  the  eight-bit  character  whose value is the octal value
                      _\bn_\bn_\bn (zero to three octal digits)
-              \\b\x\bx_\bH_\bH   the  eight-bit  character  whose value is the hexadecimal
+              \\b\x\bx_\bH_\bH   the eight-bit character whose value  is  the  hexadecimal
                      value _\bH_\bH (one or two hex digits)
-              \\b\u\bu_\bH_\bH_\bH_\bH the Unicode (ISO/IEC 10646) character whose value is  the
+              \\b\u\bu_\bH_\bH_\bH_\bH the  Unicode (ISO/IEC 10646) character whose value is the
                      hexadecimal value _\bH_\bH_\bH_\bH (one to four hex digits)
               \\b\U\bU_\bH_\bH_\bH_\bH_\bH_\bH_\bH_\bH
-                     the  Unicode (ISO/IEC 10646) character whose value is the
+                     the Unicode (ISO/IEC 10646) character whose value is  the
                      hexadecimal value _\bH_\bH_\bH_\bH_\bH_\bH_\bH_\bH (one to eight hex digits)
 
        e\ben\bna\bab\bbl\ble\be [-\b-a\ba] [-\b-d\bdn\bnp\bps\bs] [-\b-f\bf _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be] [_\bn_\ba_\bm_\be ...]
-              Enable and disable builtin shell commands.  Disabling a  builtin
+              Enable  and disable builtin shell commands.  Disabling a builtin
               allows a disk command which has the same name as a shell builtin
-              to be executed without specifying a full pathname,  even  though
-              the  shell  normally searches for builtins before disk commands.
-              If -\b-n\bn is used, each  _\bn_\ba_\bm_\be  is  disabled;  otherwise,  _\bn_\ba_\bm_\be_\b are
+              to  be  executed without specifying a full pathname, even though
+              the shell normally searches for builtins before  disk  commands.
+              If  -\b-n\bn  is  used,  each  _\bn_\ba_\bm_\be  is disabled; otherwise, _\bn_\ba_\bm_\be_\bs are
               enabled.  For example, to use the t\bte\bes\bst\bt binary found via the P\bPA\bAT\bTH\bH
-              instead of the shell builtin version, run  ``enable  -n  test''.
-              The  -\b-f\bf  option  means to load the new builtin command _\bn_\ba_\bm_\be from
+              instead  of  the  shell builtin version, run ``enable -n test''.
+              The -\b-f\bf option means to load the new builtin  command  _\bn_\ba_\bm_\b from
               shared object _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be, on systems that support dynamic loading.
-              The  -\b-d\bd  option will delete a builtin previously loaded with -\b-f\bf.
+              The -\b-d\bd option will delete a builtin previously loaded  with  -\b-f\bf.
               If no _\bn_\ba_\bm_\be arguments are given, or if the -\b-p\bp option is supplied,
               a list of shell builtins is printed.  With no other option argu-
-              ments, the list consists of all enabled shell builtins.   If  -\b-n\bn
-              is  supplied, only disabled builtins are printed.  If -\b-a\ba is sup-
-              plied, the list printed includes all builtins, with  an  indica-
-              tion  of whether or not each is enabled.  If -\b-s\bs is supplied, the
-              output is restricted to the POSIX _\bs_\bp_\be_\bc_\bi_\ba_\bl builtins.  The  return
-              value  is  0 unless a _\bn_\ba_\bm_\be is not a shell builtin or there is an
+              ments,  the  list consists of all enabled shell builtins.  If -\b-n\bn
+              is supplied, only disabled builtins are printed.  If -\b-a\ba is  sup-
+              plied,  the  list printed includes all builtins, with an indica-
+              tion of whether or not each is enabled.  If -\b-s\bs is supplied,  the
+              output  is restricted to the POSIX _\bs_\bp_\be_\bc_\bi_\ba_\bl builtins.  The return
+              value is 0 unless a _\bn_\ba_\bm_\be is not a shell builtin or there  is  an
               error loading a new builtin from a shared object.
 
        e\bev\bva\bal\bl [_\ba_\br_\bg ...]
-              The _\ba_\br_\bgs are read and concatenated together into a  single  com-
-              mand.   This command is then read and executed by the shell, and
-              its exit status is returned as the value of e\bev\bva\bal\bl.  If there  are
+              The  _\ba_\br_\bgs  are read and concatenated together into a single com-
+              mand.  This command is then read and executed by the shell,  and
+              its  exit status is returned as the value of e\bev\bva\bal\bl.  If there are
               no _\ba_\br_\bg_\bs, or only null arguments, e\bev\bva\bal\bl returns 0.
 
        e\bex\bxe\bec\bc [-\b-c\bcl\bl] [-\b-a\ba _\bn_\ba_\bm_\be] [_\bc_\bo_\bm_\bm_\ba_\bn_\bd [_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs]]
-              If  _\bc_\bo_\bm_\bm_\ba_\bn_\bd is specified, it replaces the shell.  No new process
-              is created.  The _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs become the arguments to _\bc_\bo_\bm_\bm_\ba_\bn_\bd.   If
+              If _\bc_\bo_\bm_\bm_\ba_\bn_\bd is specified, it replaces the shell.  No new  process
+              is  created.  The _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs become the arguments to _\bc_\bo_\bm_\bm_\ba_\bn_\bd.  If
               the -\b-l\bl option is supplied, the shell places a dash at the begin-
-              ning of the zeroth argument passed to  _\bc_\bo_\bm_\bm_\ba_\bn_\bd.   This  is  what
+              ning  of  the  zeroth  argument passed to _\bc_\bo_\bm_\bm_\ba_\bn_\bd.  This is what
               _\bl_\bo_\bg_\bi_\bn(1) does.  The -\b-c\bc option causes _\bc_\bo_\bm_\bm_\ba_\bn_\bd to be executed with
-              an empty environment.  If -\b-a\ba is supplied, the shell passes  _\bn_\ba_\bm_\be
+              an  empty environment.  If -\b-a\ba is supplied, the shell passes _\bn_\ba_\bm_\be
               as the zeroth argument to the executed command.  If _\bc_\bo_\bm_\bm_\ba_\bn_\bd can-
-              not be executed for some reason, a non-interactive shell  exits,
-              unless  the  e\bex\bxe\bec\bcf\bfa\bai\bil\bl shell option is enabled.  In that case, it
-              returns failure.  An interactive shell returns  failure  if  the
+              not  be executed for some reason, a non-interactive shell exits,
+              unless the e\bex\bxe\bec\bcf\bfa\bai\bil\bl shell option is enabled.  In that  case,  it
+              returns  failure.   An  interactive shell returns failure if the
               file cannot be executed.  If _\bc_\bo_\bm_\bm_\ba_\bn_\bd is not specified, any redi-
               rections take effect in the current shell, and the return status
-              is  0.  If there is a redirection error, the return status is 1.
+              is 0.  If there is a redirection error, the return status is  1.
 
        e\bex\bxi\bit\bt [_\bn]
-              Cause the shell to exit with a status of _\bn.  If  _\bn  is  omitted,
+              Cause  the  shell  to exit with a status of _\bn.  If _\bn is omitted,
               the exit status is that of the last command executed.  A trap on
               E\bEX\bXI\bIT\bT is executed before the shell terminates.
 
        e\bex\bxp\bpo\bor\brt\bt [-\b-f\bfn\bn] [_\bn_\ba_\bm_\be[=_\bw_\bo_\br_\bd]] ...
        e\bex\bxp\bpo\bor\brt\bt -\b-p\bp
-              The supplied _\bn_\ba_\bm_\be_\bs are marked for automatic export to the  envi-
-              ronment  of subsequently executed commands.  If the -\b-f\bf option is
-              given, the _\bn_\ba_\bm_\be_\bs refer to functions.  If no _\bn_\ba_\bm_\be_\bs are given,  or
-              if  the  -\b-p\bp  option is supplied, a list of names of all exported
-              variables is printed.  The -\b-n\bn option causes the export  property
+              The  supplied _\bn_\ba_\bm_\be_\bs are marked for automatic export to the envi-
+              ronment of subsequently executed commands.  If the -\b-f\bf option  is
+              given,  the _\bn_\ba_\bm_\be_\bs refer to functions.  If no _\bn_\ba_\bm_\be_\bs are given, or
+              if the -\b-p\bp option is supplied, a list of names  of  all  exported
+              variables  is printed.  The -\b-n\bn option causes the export property
               to be removed from each _\bn_\ba_\bm_\be.  If a variable name is followed by
               =_\bw_\bo_\br_\bd, the value of the variable is set to _\bw_\bo_\br_\bd.  e\bex\bxp\bpo\bor\brt\bt returns
               an exit status of 0 unless an invalid option is encountered, one
-              of the _\bn_\ba_\bm_\be_\bs is not a valid shell variable name, or -\b-f\bf  is  sup-
+              of  the  _\bn_\ba_\bm_\be_\bs is not a valid shell variable name, or -\b-f\bf is sup-
               plied with a _\bn_\ba_\bm_\be that is not a function.
 
        f\bfc\bc [-\b-e\be _\be_\bn_\ba_\bm_\be] [-\b-l\bln\bnr\br] [_\bf_\bi_\br_\bs_\bt] [_\bl_\ba_\bs_\bt]
        f\bfc\bc -\b-s\bs [_\bp_\ba_\bt=_\br_\be_\bp] [_\bc_\bm_\bd]
-              The  first  form  selects a range of commands from _\bf_\bi_\br_\bs_\bt to _\bl_\ba_\bs_\bt
-              from the history list and  displays  or  edits  and  re-executes
-              them.   _\bF_\bi_\br_\bs_\bt  and  _\bl_\ba_\bs_\bt may be specified as a string (to locate
-              the last command beginning with that string) or as a number  (an
-              index  into the history list, where a negative number is used as
-              an offset from the current command  number).   If  _\bl_\ba_\bs_\bt  is  not
-              specified  it is set to the current command for listing (so that
-              ``fc -l -10'' prints the last 10 commands) and to  _\bf_\bi_\br_\bs_\b other-
-              wise.   If _\bf_\bi_\br_\bs_\bt is not specified it is set to the previous com-
+              The first form selects a range of commands from  _\bf_\bi_\br_\bs_\bt  to  _\bl_\ba_\bs_\bt
+              from  the  history  list  and  displays or edits and re-executes
+              them.  _\bF_\bi_\br_\bs_\bt and _\bl_\ba_\bs_\bt may be specified as a  string  (to  locate
+              the  last command beginning with that string) or as a number (an
+              index into the history list, where a negative number is used  as
+              an  offset  from  the  current  command number).  If _\bl_\ba_\bs_\bt is not
+              specified it is set to the current command for listing (so  that
+              ``fc  -l  -10'' prints the last 10 commands) and to _\bf_\bi_\br_\bs_\bt other-
+              wise.  If _\bf_\bi_\br_\bs_\bt is not specified it is set to the previous  com-
               mand for editing and -16 for listing.
 
-              The -\b-n\bn option suppresses the command numbers when listing.   The
-              -\b-r\b option reverses the order of the commands.  If the -\b-l\bl option
-              is given, the commands are listed on  standard  output.   Other-
-              wise,  the editor given by _\be_\bn_\ba_\bm_\be is invoked on a file containing
-              those commands.  If _\be_\bn_\ba_\bm_\be is not given, the value of the  F\bFC\bCE\bED\bDI\bIT\bT
-              variable  is used, and the value of E\bED\bDI\bIT\bTO\bOR\bR if F\bFC\bCE\bED\bDI\bIT\bT is not set.
-              If neither variable is set, _\bv_\bi is used.  When  editing  is  com-
+              The  -\b-n\bn option suppresses the command numbers when listing.  The
+              -\b-r\boption reverses the order of the commands.  If the -\b-l\b option
+              is  given,  the  commands are listed on standard output.  Other-
+              wise, the editor given by _\be_\bn_\ba_\bm_\be is invoked on a file  containing
+              those  commands.  If _\be_\bn_\ba_\bm_\be is not given, the value of the F\bFC\bCE\bED\bDI\bIT\bT
+              variable is used, and the value of E\bED\bDI\bIT\bTO\bOR\bR if F\bFC\bCE\bED\bDI\bIT\bT is not  set.
+              If  neither  variable  is set, _\bv_\bi is used.  When editing is com-
               plete, the edited commands are echoed and executed.
 
-              In  the  second form, _\bc_\bo_\bm_\bm_\ba_\bn_\bd is re-executed after each instance
-              of _\bp_\ba_\bt is replaced by _\br_\be_\bp.  _\bC_\bo_\bm_\bm_\ba_\bn_\bd is intepreted  the  same  as
-              _\bf_\bi_\br_\bs_\b above.  A useful alias to use with this is ``r="fc -s"'',
-              so that typing ``r cc'' runs the  last  command  beginning  with
+              In the second form, _\bc_\bo_\bm_\bm_\ba_\bn_\bd is re-executed after  each  instance
+              of  _\bp_\ba_\bt  is  replaced by _\br_\be_\bp.  _\bC_\bo_\bm_\bm_\ba_\bn_\bd is intepreted the same as
+              _\bf_\bi_\br_\bs_\babove.  A useful alias to use with this is ``r="fc  -s"'',
+              so  that  typing  ``r  cc'' runs the last command beginning with
               ``cc'' and typing ``r'' re-executes the last command.
 
-              If  the  first  form  is  used,  the return value is 0 unless an
-              invalid option is encountered or _\bf_\bi_\br_\bs_\bt or _\bl_\ba_\bs_\bt  specify  history
-              lines  out  of  range.  If the -\b-e\be option is supplied, the return
+              If the first form is used, the  return  value  is  0  unless  an
+              invalid  option  is encountered or _\bf_\bi_\br_\bs_\bt or _\bl_\ba_\bs_\bt specify history
+              lines out of range.  If the -\b-e\be option is  supplied,  the  return
               value is the value of the last command executed or failure if an
               error occurs with the temporary file of commands.  If the second
-              form is used, the return status is that of the  command  re-exe-
-              cuted,  unless  _\bc_\bm_\bd  does  not  specify a valid history line, in
+              form  is  used, the return status is that of the command re-exe-
+              cuted, unless _\bc_\bm_\bd does not specify  a  valid  history  line,  in
               which case f\bfc\bc returns failure.
 
        f\bfg\bg [_\bj_\bo_\bb_\bs_\bp_\be_\bc]
-              Resume _\bj_\bo_\bb_\bs_\bp_\be_\bc in the foreground, and make it the  current  job.
+              Resume  _\bj_\bo_\bb_\bs_\bp_\be_\bc  in the foreground, and make it the current job.
               If _\bj_\bo_\bb_\bs_\bp_\be_\bc is not present, the shell's notion of the _\bc_\bu_\br_\br_\be_\bn_\bt _\bj_\bo_\bb
-              is used.  The return value is that of the  command  placed  into
-              the  foreground,  or failure if run when job control is disabled
+              is  used.   The  return value is that of the command placed into
+              the foreground, or failure if run when job control  is  disabled
               or, when run with job control enabled, if _\bj_\bo_\bb_\bs_\bp_\be_\bc does not spec-
-              ify  a  valid  job  or  _\bj_\bo_\bb_\bs_\bp_\be_\bc specifies a job that was started
+              ify a valid job or _\bj_\bo_\bb_\bs_\bp_\be_\bc specifies  a  job  that  was  started
               without job control.
 
        g\bge\bet\bto\bop\bpt\bts\bs _\bo_\bp_\bt_\bs_\bt_\br_\bi_\bn_\bg _\bn_\ba_\bm_\be [_\ba_\br_\bg_\bs]
-              g\bge\bet\bto\bop\bpt\bts\bis used by shell procedures to parse positional  parame-
-              ters.   _\bo_\bp_\bt_\bs_\bt_\br_\bi_\bn_\bg  contains  the  option characters to be recog-
-              nized; if a character is followed by  a  colon,  the  option  is
-              expected  to have an argument, which should be separated from it
-              by white space.  The colon and question mark characters may  not
-              be  used as option characters.  Each time it is invoked, g\bge\bet\bto\bop\bpt\bts\bs
-              places the next option in the shell variable _\bn_\ba_\bm_\be,  initializing
+              g\bge\bet\bto\bop\bpt\bts\b is used by shell procedures to parse positional parame-
+              ters.  _\bo_\bp_\bt_\bs_\bt_\br_\bi_\bn_\bg contains the option  characters  to  be  recog-
+              nized;  if  a  character  is  followed by a colon, the option is
+              expected to have an argument, which should be separated from  it
+              by  white space.  The colon and question mark characters may not
+              be used as option characters.  Each time it is invoked,  g\bge\bet\bto\bop\bpt\bts\bs
+              places  the next option in the shell variable _\bn_\ba_\bm_\be, initializing
               _\bn_\ba_\bm_\be if it does not exist, and the index of the next argument to
               be processed into the variable O\bOP\bPT\bTI\bIN\bND\bD.  O\bOP\bPT\bTI\bIN\bND\bD is initialized to
-              1  each  time  the  shell or a shell script is invoked.  When an
-              option requires an argument, g\bge\bet\bto\bop\bpt\bts\bs places that  argument  into
-              the  variable O\bOP\bPT\bTA\bAR\bRG\bG.  The shell does not reset O\bOP\bPT\bTI\bIN\bND\bD automati-
-              cally; it must be  manually  reset  between  multiple  calls  to
+              1 each time the shell or a shell script  is  invoked.   When  an
+              option  requires  an argument, g\bge\bet\bto\bop\bpt\bts\bs places that argument into
+              the variable O\bOP\bPT\bTA\bAR\bRG\bG.  The shell does not reset O\bOP\bPT\bTI\bIN\bND\b automati-
+              cally;  it  must  be  manually  reset  between multiple calls to
               g\bge\bet\bto\bop\bpt\bts\bs within the same shell invocation if a new set of parame-
               ters is to be used.
 
-              When the end of options is encountered,  g\bge\bet\bto\bop\bpt\bts\bs  exits  with  a
-              return  value  greater than zero.  O\bOP\bPT\bTI\bIN\bND\bD is set to the index of
+              When  the  end  of  options is encountered, g\bge\bet\bto\bop\bpt\bts\bs exits with a
+              return value greater than zero.  O\bOP\bPT\bTI\bIN\bND\bD is set to the  index  of
               the first non-option argument, and _\bn_\ba_\bm_\be is set to ?.
 
-              g\bge\bet\bto\bop\bpt\bts\bnormally parses the positional parameters, but  if  more
+              g\bge\bet\bto\bop\bpt\bts\b normally  parses the positional parameters, but if more
               arguments are given in _\ba_\br_\bg_\bs, g\bge\bet\bto\bop\bpt\bts\bs parses those instead.
 
-              g\bge\bet\bto\bop\bpt\bts\b can  report errors in two ways.  If the first character
-              of _\bo_\bp_\bt_\bs_\bt_\br_\bi_\bn_\bg is a colon, _\bs_\bi_\bl_\be_\bn_\bt error  reporting  is  used.   In
-              normal  operation,  diagnostic messages are printed when invalid
-              options or missing option arguments  are  encountered.   If  the
-              variable  O\bOP\bPT\bTE\bER\bRR\bR  is  set  to  0, no error messages will be dis-
+              g\bge\bet\bto\bop\bpt\bts\bcan report errors in two ways.  If the  first  character
+              of  _\bo_\bp_\bt_\bs_\bt_\br_\bi_\bn_\bg  is  a  colon, _\bs_\bi_\bl_\be_\bn_\bt error reporting is used.  In
+              normal operation, diagnostic messages are printed  when  invalid
+              options  or  missing  option  arguments are encountered.  If the
+              variable O\bOP\bPT\bTE\bER\bRR\bR is set to 0, no  error  messages  will  be  dis-
               played, even if the first character of _\bo_\bp_\bt_\bs_\bt_\br_\bi_\bn_\bg is not a colon.
 
               If an invalid option is seen, g\bge\bet\bto\bop\bpt\bts\bs places ? into _\bn_\ba_\bm_\be and, if
-              not silent, prints an  error  message  and  unsets  O\bOP\bPT\bTA\bAR\bRG\bG.   If
-              g\bge\bet\bto\bop\bpt\bts\b is  silent,  the  option  character  found is placed in
+              not  silent,  prints  an  error  message  and unsets O\bOP\bPT\bTA\bAR\bRG\bG.  If
+              g\bge\bet\bto\bop\bpt\bts\bis silent, the  option  character  found  is  placed  in
               O\bOP\bPT\bTA\bAR\bRG\bG and no diagnostic message is printed.
 
-              If a required argument is not found, and g\bge\bet\bto\bop\bpt\bts\bs is not  silent,
-              a  question  mark  (?\b?) is placed in _\bn_\ba_\bm_\be, O\bOP\bPT\bTA\bAR\bRG\bG is unset, and a
-              diagnostic message is printed.  If g\bge\bet\bto\bop\bpt\bts\bs  is  silent,  then  a
-              colon  (:\b:)  is  placed  in  _\bn_\ba_\bm_\be and O\bOP\bPT\bTA\bAR\bRG\bG is set to the option
+              If  a required argument is not found, and g\bge\bet\bto\bop\bpt\bts\bs is not silent,
+              a question mark (?\b?) is placed in _\bn_\ba_\bm_\be, O\bOP\bPT\bTA\bAR\bRG\bG is  unset,  and  a
+              diagnostic  message  is  printed.   If g\bge\bet\bto\bop\bpt\bts\bs is silent, then a
+              colon (:\b:) is placed in _\bn_\ba_\bm_\be and O\bOP\bPT\bTA\bAR\bRG\bG  is  set  to  the  option
               character found.
 
-              g\bge\bet\bto\bop\bpt\bts\breturns true if an option, specified or unspecified,  is
+              g\bge\bet\bto\bop\bpt\bts\b returns true if an option, specified or unspecified, is
               found.  It returns false if the end of options is encountered or
               an error occurs.
 
        h\bha\bas\bsh\bh [-\b-l\blr\br] [-\b-p\bp _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be] [-\b-d\bdt\bt] [_\bn_\ba_\bm_\be]
               Each time h\bha\bas\bsh\bh is invoked, the full pathname of the command _\bn_\ba_\bm_\be
-              is  determined  by searching the directories in $\b$P\bPA\bAT\bTH\bH and remem-
+              is determined by searching the directories in $\b$P\bPA\bAT\bTH\bH  and  remem-
               bered.  Any previously-remembered pathname is discarded.  If the
               -\b-p\bp option is supplied, no path search is performed, and _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be
-              is used as the full filename of  the  command.   The  -\b-r\b option
-              causes  the  shell  to  forget all remembered locations.  The -\b-d\bd
-              option causes the shell to forget  the  remembered  location  of
-              each  _\bn_\ba_\bm_\be.   If the -\b-t\bt option is supplied, the full pathname to
-              which each _\bn_\ba_\bm_\be corresponds is printed.  If multiple _\bn_\ba_\bm_\b argu-
-              ments  are  supplied  with  -\b-t\bt,  the  _\bn_\ba_\bm_\be is printed before the
-              hashed full pathname.  The -\b-l\bl option causes output  to  be  dis-
+              is  used  as  the  full  filename of the command.  The -\b-r\br option
+              causes the shell to forget all  remembered  locations.   The  -\b-d\bd
+              option  causes  the  shell  to forget the remembered location of
+              each _\bn_\ba_\bm_\be.  If the -\b-t\bt option is supplied, the full  pathname  to
+              which  each _\bn_\ba_\bm_\be corresponds is printed.  If multiple _\bn_\ba_\bm_\be argu-
+              ments are supplied with -\b-t\bt,  the  _\bn_\ba_\bm_\be  is  printed  before  the
+              hashed  full  pathname.   The -\b-l\bl option causes output to be dis-
               played in a format that may be reused as input.  If no arguments
-              are given, or if only -\b-l\bl is supplied, information  about  remem-
-              bered  commands  is printed.  The return status is true unless a
+              are  given,  or if only -\b-l\bl is supplied, information about remem-
+              bered commands is printed.  The return status is true  unless  a
               _\bn_\ba_\bm_\be is not found or an invalid option is supplied.
 
        h\bhe\bel\blp\bp [-\b-d\bdm\bms\bs] [_\bp_\ba_\bt_\bt_\be_\br_\bn]
-              Display helpful information about builtin commands.  If  _\bp_\ba_\bt_\bt_\be_\br_\bn
-              is  specified, h\bhe\bel\blp\bp gives detailed help on all commands matching
-              _\bp_\ba_\bt_\bt_\be_\br_\bn; otherwise help for all the builtins and  shell  control
+              Display  helpful information about builtin commands.  If _\bp_\ba_\bt_\bt_\be_\br_\bn
+              is specified, h\bhe\bel\blp\bp gives detailed help on all commands  matching
+              _\bp_\ba_\bt_\bt_\be_\br_\bn;  otherwise  help for all the builtins and shell control
               structures is printed.
               -\b-d\bd     Display a short description of each _\bp_\ba_\bt_\bt_\be_\br_\bn
               -\b-m\bm     Display the description of each _\bp_\ba_\bt_\bt_\be_\br_\bn in a manpage-like
@@ -4563,44 +4566,44 @@ S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS
        h\bhi\bis\bst\bto\bor\bry\by -\b-s\bs _\ba_\br_\bg [_\ba_\br_\bg _\b._\b._\b.]
               With no options, display the command history list with line num-
               bers.  Lines listed with a *\b* have been modified.  An argument of
-              _\blists only the last _\bn lines.  If the shell variable  H\bHI\bIS\bST\bTT\bTI\bIM\bME\bE-\b-
-              F\bFO\bOR\bRM\bMA\bAT\b is  set  and not null, it is used as a format string for
-              _\bs_\bt_\br_\bf_\bt_\bi_\bm_\be(3) to display the time stamp associated with each  dis-
-              played  history  entry.  No intervening blank is printed between
-              the formatted time stamp and the history line.  If  _\bf_\bi_\bl_\be_\bn_\ba_\bm_\b is
-              supplied,  it  is  used as the name of the history file; if not,
-              the value of H\bHI\bIS\bST\bTF\bFI\bIL\bLE\bE is used.  Options, if supplied,  have  the
+              _\b lists only the last _\bn lines.  If the shell variable H\bHI\bIS\bST\bTT\bTI\bIM\bME\bE-\b-
+              F\bFO\bOR\bRM\bMA\bAT\bis set and not null, it is used as a  format  string  for
+              _\bs_\bt_\br_\bf_\bt_\bi_\bm_\be(3)  to display the time stamp associated with each dis-
+              played history entry.  No intervening blank is  printed  between
+              the  formatted  time stamp and the history line.  If _\bf_\bi_\bl_\be_\bn_\ba_\bm_\be is
+              supplied, it is used as the name of the history  file;  if  not,
+              the  value  of H\bHI\bIS\bST\bTF\bFI\bIL\bLE\bE is used.  Options, if supplied, have the
               following meanings:
               -\b-c\bc     Clear the history list by deleting all the entries.
               -\b-d\bd _\bo_\bf_\bf_\bs_\be_\bt
                      Delete the history entry at position _\bo_\bf_\bf_\bs_\be_\bt.
-              -\b-a\ba     Append  the  ``new'' history lines (history lines entered
-                     since the beginning of the current b\bba\bas\bsh\bh session)  to  the
+              -\b-a\ba     Append the ``new'' history lines (history  lines  entered
+                     since  the  beginning of the current b\bba\bas\bsh\bh session) to the
                      history file.
-              -\b-n\bn     Read  the history lines not already read from the history
-                     file into the current  history  list.   These  are  lines
-                     appended  to  the history file since the beginning of the
+              -\b-n\bn     Read the history lines not already read from the  history
+                     file  into  the  current  history  list.  These are lines
+                     appended to the history file since the beginning  of  the
                      current b\bba\bas\bsh\bh session.
-              -\b-r\br     Read the contents of the history file and append them  to
+              -\b-r\br     Read  the contents of the history file and append them to
                      the current history list.
               -\b-w\bw     Write the current history list to the history file, over-
                      writing the history file's contents.
-              -\b-p\bp     Perform history substitution on the  following  _\ba_\br_\bg_\b and
-                     display  the  result  on  the  standard output.  Does not
-                     store the results in the history list.  Each _\ba_\br_\bg must  be
+              -\b-p\bp     Perform  history  substitution  on the following _\ba_\br_\bg_\bs and
+                     display the result on  the  standard  output.   Does  not
+                     store  the results in the history list.  Each _\ba_\br_\bg must be
                      quoted to disable normal history expansion.
-              -\b-s\bs     Store  the  _\ba_\br_\bg_\bs  in  the history list as a single entry.
-                     The last command in the history list  is  removed  before
+              -\b-s\bs     Store the _\ba_\br_\bg_\bs in the history list  as  a  single  entry.
+                     The  last  command  in the history list is removed before
                      the _\ba_\br_\bg_\bs are added.
 
-              If  the  H\bHI\bIS\bST\bTT\bTI\bIM\bME\bEF\bFO\bOR\bRM\bMA\bAT\bT variable is set, the time stamp informa-
-              tion associated with each history entry is written to  the  his-
-              tory  file, marked with the history comment character.  When the
-              history file is read, lines beginning with the  history  comment
-              character  followed  immediately  by  a digit are interpreted as
+              If the H\bHI\bIS\bST\bTT\bTI\bIM\bME\bEF\bFO\bOR\bRM\bMA\bAT\bT variable is set, the time  stamp  informa-
+              tion  associated  with each history entry is written to the his-
+              tory file, marked with the history comment character.  When  the
+              history  file  is read, lines beginning with the history comment
+              character followed immediately by a  digit  are  interpreted  as
               timestamps for the previous history line.  The return value is 0
-              unless  an  invalid option is encountered, an error occurs while
-              reading or writing the history file, an invalid _\bo_\bf_\bf_\bs_\be_\bt  is  sup-
+              unless an invalid option is encountered, an error  occurs  while
+              reading  or  writing the history file, an invalid _\bo_\bf_\bf_\bs_\be_\bt is sup-
               plied as an argument to -\b-d\bd, or the history expansion supplied as
               an argument to -\b-p\bp fails.
 
@@ -4609,199 +4612,199 @@ S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS
               The first form lists the active jobs.  The options have the fol-
               lowing meanings:
               -\b-l\bl     List process IDs in addition to the normal information.
-              -\b-n\bn     Display  information  only  about  jobs that have changed
-                     status since the user was last notified of their  status.
-              -\b-p\bp     List  only  the  process  ID  of  the job's process group
+              -\b-n\bn     Display information only about  jobs  that  have  changed
+                     status  since the user was last notified of their status.
+              -\b-p\bp     List only the process  ID  of  the  job's  process  group
                      leader.
               -\b-r\br     Display only running jobs.
               -\b-s\bs     Display only stopped jobs.
 
-              If _\bj_\bo_\bb_\bs_\bp_\be_\bc is given, output is restricted to  information  about
-              that  job.   The  return status is 0 unless an invalid option is
+              If  _\bj_\bo_\bb_\bs_\bp_\be_\bc  is given, output is restricted to information about
+              that job.  The return status is 0 unless an  invalid  option  is
               encountered or an invalid _\bj_\bo_\bb_\bs_\bp_\be_\bc is supplied.
 
               If the -\b-x\bx option is supplied, j\bjo\bob\bbs\bs replaces any _\bj_\bo_\bb_\bs_\bp_\be_\bc found in
-              _\bc_\bo_\bm_\bm_\ba_\bn_\b or  _\ba_\br_\bg_\bs  with  the corresponding process group ID, and
+              _\bc_\bo_\bm_\bm_\ba_\bn_\bor _\ba_\br_\bg_\bs with the corresponding  process  group  ID,  and
               executes _\bc_\bo_\bm_\bm_\ba_\bn_\bd passing it _\ba_\br_\bg_\bs, returning its exit status.
 
        k\bki\bil\bll\bl [-\b-s\bs _\bs_\bi_\bg_\bs_\bp_\be_\bc | -\b-n\bn _\bs_\bi_\bg_\bn_\bu_\bm | -\b-_\bs_\bi_\bg_\bs_\bp_\be_\bc] [_\bp_\bi_\bd | _\bj_\bo_\bb_\bs_\bp_\be_\bc] ...
        k\bki\bil\bll\bl -\b-l\bl [_\bs_\bi_\bg_\bs_\bp_\be_\bc | _\be_\bx_\bi_\bt_\b__\bs_\bt_\ba_\bt_\bu_\bs]
-              Send the signal named by _\bs_\bi_\bg_\bs_\bp_\be_\bc  or  _\bs_\bi_\bg_\bn_\bu_\bm  to  the  processes
-              named  by  _\bp_\bi_\bd or _\bj_\bo_\bb_\bs_\bp_\be_\bc.  _\bs_\bi_\bg_\bs_\bp_\be_\bc is either a case-insensitive
-              signal name such as S\bSI\bIG\bGK\bKI\bIL\bLL\bL (with or without the S\bSI\bIG\bG prefix)  or
-              a  signal  number; _\bs_\bi_\bg_\bn_\bu_\bm is a signal number.  If _\bs_\bi_\bg_\bs_\bp_\be_\bc is not
-              present, then S\bSI\bIG\bGT\bTE\bER\bRM\bM is assumed.  An argument of -\b-l\bl  lists  the
-              signal  names.   If any arguments are supplied when -\b-l\bl is given,
-              the names of the signals  corresponding  to  the  arguments  are
+              Send  the  signal  named  by  _\bs_\bi_\bg_\bs_\bp_\be_\bc or _\bs_\bi_\bg_\bn_\bu_\bm to the processes
+              named by _\bp_\bi_\bd or _\bj_\bo_\bb_\bs_\bp_\be_\bc.  _\bs_\bi_\bg_\bs_\bp_\be_\bc is either  a  case-insensitive
+              signal  name such as S\bSI\bIG\bGK\bKI\bIL\bLL\bL (with or without the S\bSI\bIG\bG prefix) or
+              a signal number; _\bs_\bi_\bg_\bn_\bu_\bm is a signal number.  If _\bs_\bi_\bg_\bs_\bp_\be_\bc  is  not
+              present,  then  S\bSI\bIG\bGT\bTE\bER\bRM\bM is assumed.  An argument of -\b-l\bl lists the
+              signal names.  If any arguments are supplied when -\b-l\bl  is  given,
+              the  names  of  the  signals  corresponding to the arguments are
               listed, and the return status is 0.  The _\be_\bx_\bi_\bt_\b__\bs_\bt_\ba_\bt_\bu_\bs argument to
-              -\b-l\bis a number specifying either a signal  number  or  the  exit
-              status  of  a process terminated by a signal.  k\bki\bil\bll\bl returns true
-              if at least one signal was successfully sent,  or  false  if  an
+              -\b-l\b is  a  number  specifying either a signal number or the exit
+              status of a process terminated by a signal.  k\bki\bil\bll\bl  returns  true
+              if  at  least  one  signal was successfully sent, or false if an
               error occurs or an invalid option is encountered.
 
        l\ble\bet\bt _\ba_\br_\bg [_\ba_\br_\bg ...]
               Each _\ba_\br_\bg is an arithmetic expression to be evaluated (see A\bAR\bRI\bIT\bTH\bH-\b-
-              M\bME\bET\bTI\bIC\bE\bEV\bVA\bAL\bLU\bUA\bAT\bTI\bIO\bON\bN above).  If the last _\ba_\br_\bg evaluates  to  0,  l\ble\bet\bt
+              M\bME\bET\bTI\bIC\b E\bEV\bVA\bAL\bLU\bUA\bAT\bTI\bIO\bON\bN  above).   If the last _\ba_\br_\bg evaluates to 0, l\ble\bet\bt
               returns 1; 0 is returned otherwise.
 
        l\blo\boc\bca\bal\bl [_\bo_\bp_\bt_\bi_\bo_\bn] [_\bn_\ba_\bm_\be[=_\bv_\ba_\bl_\bu_\be] ...]
-              For  each  argument, a local variable named _\bn_\ba_\bm_\be is created, and
-              assigned _\bv_\ba_\bl_\bu_\be.  The _\bo_\bp_\bt_\bi_\bo_\bn can be any of the  options  accepted
+              For each argument, a local variable named _\bn_\ba_\bm_\be is  created,  and
+              assigned  _\bv_\ba_\bl_\bu_\be.   The _\bo_\bp_\bt_\bi_\bo_\bn can be any of the options accepted
               by d\bde\bec\bcl\bla\bar\bre\be.  When l\blo\boc\bca\bal\bl is used within a function, it causes the
-              variable _\bn_\ba_\bm_\be to have a visible scope restricted to  that  func-
+              variable  _\bn_\ba_\bm_\be  to have a visible scope restricted to that func-
               tion and its children.  With no operands, l\blo\boc\bca\bal\bl writes a list of
-              local variables to the standard output.  It is an error  to  use
+              local  variables  to the standard output.  It is an error to use
               l\blo\boc\bca\bal\bl when not within a function.  The return status is 0 unless
-              l\blo\boc\bca\bal\bis used outside a function, an invalid _\bn_\ba_\bm_\be  is  supplied,
+              l\blo\boc\bca\bal\b is  used outside a function, an invalid _\bn_\ba_\bm_\be is supplied,
               or _\bn_\ba_\bm_\be is a readonly variable.
 
        l\blo\bog\bgo\bou\but\bt Exit a login shell.
 
-       m\bma\bap\bpf\bfi\bil\ble\b [-\b-n\bn  _\bc_\bo_\bu_\bn_\bt]  [-\b-O\bO _\bo_\br_\bi_\bg_\bi_\bn] [-\b-s\bs _\bc_\bo_\bu_\bn_\bt] [-\b-t\bt] [-\b-u\bu _\bf_\bd] [-\b-C\bC _\bc_\ba_\bl_\bl_\bb_\ba_\bc_\bk]
+       m\bma\bap\bpf\bfi\bil\ble\b[-\b-n\bn _\bc_\bo_\bu_\bn_\bt] [-\b-O\bO _\bo_\br_\bi_\bg_\bi_\bn] [-\b-s\bs _\bc_\bo_\bu_\bn_\bt] [-\b-t\bt] [-\b-u\bu  _\bf_\bd]  [-\b-C\b _\bc_\ba_\bl_\bl_\bb_\ba_\bc_\bk]
        [-\b-c\bc _\bq_\bu_\ba_\bn_\bt_\bu_\bm] [_\ba_\br_\br_\ba_\by]
-       r\bre\bea\bad\bda\bar\brr\bra\bay\b [-\b-n\bn _\bc_\bo_\bu_\bn_\bt] [-\b-O\bO _\bo_\br_\bi_\bg_\bi_\bn] [-\b-s\bs _\bc_\bo_\bu_\bn_\bt] [-\b-t\bt] [-\b-u\bu _\bf_\bd] [-\b-C\bC _\bc_\ba_\bl_\bl_\bb_\ba_\bc_\bk]
+       r\bre\bea\bad\bda\bar\brr\bra\bay\b[-\b-n\bn _\bc_\bo_\bu_\bn_\bt] [-\b-O\bO _\bo_\br_\bi_\bg_\bi_\bn] [-\b-s\bs _\bc_\bo_\bu_\bn_\bt] [-\b-t\bt] [-\b-u\bu _\bf_\bd] [-\b-C\b _\bc_\ba_\bl_\bl_\bb_\ba_\bc_\bk]
        [-\b-c\bc _\bq_\bu_\ba_\bn_\bt_\bu_\bm] [_\ba_\br_\br_\ba_\by]
-              Read  lines from the standard input into the indexed array vari-
-              able _\ba_\br_\br_\ba_\by, or from file descriptor _\bf_\bd if the -\b-u\bu option is  sup-
-              plied.   The variable M\bMA\bAP\bPF\bFI\bIL\bLE\bE is the default _\ba_\br_\br_\ba_\by.  Options, if
+              Read lines from the standard input into the indexed array  vari-
+              able  _\ba_\br_\br_\ba_\by, or from file descriptor _\bf_\bd if the -\b-u\bu option is sup-
+              plied.  The variable M\bMA\bAP\bPF\bFI\bIL\bLE\bE is the default _\ba_\br_\br_\ba_\by.  Options,  if
               supplied, have the following meanings:
-              -\b-n\bn     Copy at most _\bc_\bo_\bu_\bn_\bt lines.  If _\bc_\bo_\bu_\bn_\bt is 0, all  lines  are
+              -\b-n\bn     Copy  at  most _\bc_\bo_\bu_\bn_\bt lines.  If _\bc_\bo_\bu_\bn_\bt is 0, all lines are
                      copied.
-              -\b-O\bO     Begin  assigning  to  _\ba_\br_\br_\ba_\by at index _\bo_\br_\bi_\bg_\bi_\bn.  The default
+              -\b-O\bO     Begin assigning to _\ba_\br_\br_\ba_\by at index  _\bo_\br_\bi_\bg_\bi_\bn.   The  default
                      index is 0.
               -\b-s\bs     Discard the first _\bc_\bo_\bu_\bn_\bt lines read.
               -\b-t\bt     Remove a trailing newline from each line read.
-              -\b-u\bu     Read lines from file descriptor _\bf_\bd instead of  the  stan-
+              -\b-u\bu     Read  lines  from file descriptor _\bf_\bd instead of the stan-
                      dard input.
-              -\b-C\bC     Evaluate  _\bc_\ba_\bl_\bl_\bb_\ba_\bc_\bk each time _\bq_\bu_\ba_\bn_\bt_\bu_\bm lines are read.  The
+              -\b-C\bC     Evaluate _\bc_\ba_\bl_\bl_\bb_\ba_\bc_\bk each time _\bq_\bu_\ba_\bn_\bt_\bu_\bm lines are read.   The
                      -\b-c\bc option specifies _\bq_\bu_\ba_\bn_\bt_\bu_\bm.
-              -\b-c\bc     Specify the number of lines read  between  each  call  to
+              -\b-c\bc     Specify  the  number  of  lines read between each call to
                      _\bc_\ba_\bl_\bl_\bb_\ba_\bc_\bk.
 
-              If  -\b-C\bC  is  specified  without  -\b-c\bc, the default quantum is 5000.
+              If -\b-C\bC is specified without -\b-c\bc,  the  default  quantum  is  5000.
               When _\bc_\ba_\bl_\bl_\bb_\ba_\bc_\bk is evaluated, it is supplied the index of the next
               array element to be assigned and the line to be assigned to that
-              element as additional arguments.  _\bc_\ba_\bl_\bl_\bb_\ba_\bc_\bk  is  evaluated  after
+              element  as  additional  arguments.  _\bc_\ba_\bl_\bl_\bb_\ba_\bc_\bk is evaluated after
               the line is read but before the array element is assigned.
 
-              If  not  supplied  with  an  explicit origin, m\bma\bap\bpf\bfi\bil\ble\be will clear
+              If not supplied with an  explicit  origin,  m\bma\bap\bpf\bfi\bil\ble\be  will  clear
               _\ba_\br_\br_\ba_\by before assigning to it.
 
-              m\bma\bap\bpf\bfi\bil\ble\breturns successfully unless an invalid option or  option
-              argument  is  supplied,  _\ba_\br_\br_\ba_\by is invalid or unassignable, or if
+              m\bma\bap\bpf\bfi\bil\ble\b returns successfully unless an invalid option or option
+              argument is supplied, _\ba_\br_\br_\ba_\by is invalid or  unassignable,  or  if
               _\ba_\br_\br_\ba_\by is not an indexed array.
 
        p\bpo\bop\bpd\bd [-n\bn] [+_\bn] [-_\bn]
-              Removes entries from the directory stack.   With  no  arguments,
-              removes  the  top directory from the stack, and performs a c\bcd\bd to
+              Removes  entries  from  the directory stack.  With no arguments,
+              removes the top directory from the stack, and performs a  c\bcd\b to
               the new top directory.  Arguments, if supplied, have the follow-
               ing meanings:
-              -\b-n\bn     Suppresses  the  normal change of directory when removing
-                     directories from the stack, so that  only  the  stack  is
+              -\b-n\bn     Suppresses the normal change of directory  when  removing
+                     directories  from  the  stack,  so that only the stack is
                      manipulated.
-              +\b+_\bn     Removes  the _\bnth entry counting from the left of the list
-                     shown by d\bdi\bir\brs\bs, starting with zero.  For  example:  ``popd
+              +\b+_\bn     Removes the _\bnth entry counting from the left of the  list
+                     shown  by  d\bdi\bir\brs\bs, starting with zero.  For example: ``popd
                      +0'' removes the first directory, ``popd +1'' the second.
               -\b-_\bn     Removes the _\bnth entry counting from the right of the list
-                     shown  by  d\bdi\bir\brs\bs, starting with zero.  For example: ``popd
-                     -0'' removes the last directory, ``popd -1'' the next  to
+                     shown by d\bdi\bir\brs\bs, starting with zero.  For  example:  ``popd
+                     -0''  removes the last directory, ``popd -1'' the next to
                      last.
 
-              If  the p\bpo\bop\bpd\bd command is successful, a d\bdi\bir\brs\bs is performed as well,
-              and the return status is 0.  p\bpo\bop\bpd\bd returns false  if  an  invalid
+              If the p\bpo\bop\bpd\bd command is successful, a d\bdi\bir\brs\bs is performed as  well,
+              and  the  return  status is 0.  p\bpo\bop\bpd\bd returns false if an invalid
               option is encountered, the directory stack is empty, a non-exis-
               tent directory stack entry is specified, or the directory change
               fails.
 
        p\bpr\bri\bin\bnt\btf\bf [-\b-v\bv _\bv_\ba_\br] _\bf_\bo_\br_\bm_\ba_\bt [_\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs]
-              Write  the  formatted _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs to the standard output under the
-              control of the _\bf_\bo_\br_\bm_\ba_\bt.  The -\b-v\bv option causes the  output  to  be
-              assigned  to  the  variable _\bv_\ba_\br rather than being printed to the
+              Write the formatted _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs to the standard output  under  the
+              control  of  the  _\bf_\bo_\br_\bm_\ba_\bt.  The -\b-v\bv option causes the output to be
+              assigned to the variable _\bv_\ba_\br rather than being  printed  to  the
               standard output.
 
-              The _\bf_\bo_\br_\bm_\ba_\bt is a character string which contains three  types  of
-              objects:  plain  characters, which are simply copied to standard
-              output, character escape  sequences,  which  are  converted  and
-              copied  to  the standard output, and format specifications, each
-              of which causes printing of the next  successive  _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt.   In
+              The  _\bf_\bo_\br_\bm_\ba_\bt  is a character string which contains three types of
+              objects: plain characters, which are simply copied  to  standard
+              output,  character  escape  sequences,  which  are converted and
+              copied to the standard output, and format  specifications,  each
+              of  which  causes  printing of the next successive _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt.  In
               addition to the standard _\bp_\br_\bi_\bn_\bt_\bf(1) format specifications, p\bpr\bri\bin\bnt\btf\bf
               interprets the following extensions:
               %\b%b\bb     causes p\bpr\bri\bin\bnt\btf\bf to expand backslash escape sequences in the
                      corresponding _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt (except that \\b\c\bc terminates output,
-                     backslashes in \\b\'\b', \\b\"\b", and \\b\?\b? are not removed, and  octal
+                     backslashes  in \\b\'\b', \\b\"\b", and \\b\?\b? are not removed, and octal
                      escapes beginning with \\b\0\b0 may contain up to four digits).
-              %\b%q\bq     causes p\bpr\bri\bin\bnt\btf\bf to output the corresponding _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt  in  a
+              %\b%q\bq     causes  p\bpr\bri\bin\bnt\btf\bf  to output the corresponding _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt in a
                      format that can be reused as shell input.
               %\b%(\b(_\bd_\ba_\bt_\be_\bf_\bm_\bt)\b)T\bT
-                     causes  p\bpr\bri\bin\bnt\btf\bf  to  output the date-time string resulting
-                     from using _\bd_\ba_\bt_\be_\bf_\bm_\bt as a format  string  for  _\bs_\bt_\br_\bf_\bt_\bi_\bm_\be(3).
+                     causes p\bpr\bri\bin\bnt\btf\bf to output the  date-time  string  resulting
+                     from  using  _\bd_\ba_\bt_\be_\bf_\bm_\bt  as a format string for _\bs_\bt_\br_\bf_\bt_\bi_\bm_\be(3).
                      The corresponding _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt is an integer representing the
-                     number of seconds since the epoch.  Two special  argument
-                     values  may  be used: -1 represents the current time, and
-                     -2 represents the time the  shell  was  invoked.   If  no
-                     argument  is  specified,  conversion behaves as if -1 had
-                     been given.  This is an exception  to  the  usual  p\bpr\bri\bin\bnt\btf\bf
+                     number  of seconds since the epoch.  Two special argument
+                     values may be used: -1 represents the current  time,  and
+                     -2  represents  the  time  the  shell was invoked.  If no
+                     argument is specified, conversion behaves as  if  -1  had
+                     been  given.   This  is  an exception to the usual p\bpr\bri\bin\bnt\btf\bf
                      behavior.
 
-              Arguments  to non-string format specifiers are treated as C con-
+              Arguments to non-string format specifiers are treated as C  con-
               stants, except that a leading plus or minus sign is allowed, and
-              if  the leading character is a single or double quote, the value
+              if the leading character is a single or double quote, the  value
               is the ASCII value of the following character.
 
-              The _\bf_\bo_\br_\bm_\ba_\bt is reused as necessary to consume all  of  the  _\ba_\br_\bg_\bu_\b-
+              The  _\bf_\bo_\br_\bm_\ba_\bt  is  reused as necessary to consume all of the _\ba_\br_\bg_\bu_\b-
               _\bm_\be_\bn_\bt_\bs.  If the _\bf_\bo_\br_\bm_\ba_\bt requires more _\ba_\br_\bg_\bu_\bm_\be_\bn_\bt_\bs than are supplied,
-              the extra format specifications behave as if  a  zero  value  or
-              null  string,  as  appropriate,  had  been supplied.  The return
+              the  extra  format  specifications  behave as if a zero value or
+              null string, as appropriate,  had  been  supplied.   The  return
               value is zero on success, non-zero on failure.
 
        p\bpu\bus\bsh\bhd\bd [-\b-n\bn] [+_\bn] [-_\bn]
        p\bpu\bus\bsh\bhd\bd [-\b-n\bn] [_\bd_\bi_\br]
-              Adds a directory to the top of the directory stack,  or  rotates
-              the  stack,  making the new top of the stack the current working
+              Adds  a  directory to the top of the directory stack, or rotates
+              the stack, making the new top of the stack the  current  working
               directory.  With no arguments, exchanges the top two directories
-              and  returns 0, unless the directory stack is empty.  Arguments,
+              and returns 0, unless the directory stack is empty.   Arguments,
               if supplied, have the following meanings:
-              -\b-n\bn     Suppresses the normal change  of  directory  when  adding
-                     directories  to  the  stack,  so  that  only the stack is
+              -\b-n\bn     Suppresses  the  normal  change  of directory when adding
+                     directories to the stack,  so  that  only  the  stack  is
                      manipulated.
-              +\b+_\bn     Rotates the stack so that  the  _\bnth  directory  (counting
-                     from  the  left  of the list shown by d\bdi\bir\brs\bs, starting with
+              +\b+_\bn     Rotates  the  stack  so  that the _\bnth directory (counting
+                     from the left of the list shown by  d\bdi\bir\brs\bs,  starting  with
                      zero) is at the top.
-              -\b-_\bn     Rotates the stack so that  the  _\bnth  directory  (counting
-                     from  the  right of the list shown by d\bdi\bir\brs\bs, starting with
+              -\b-_\bn     Rotates  the  stack  so  that the _\bnth directory (counting
+                     from the right of the list shown by d\bdi\bir\brs\bs,  starting  with
                      zero) is at the top.
               _\bd_\bi_\br    Adds _\bd_\bi_\br to the directory stack at the top, making it the
-                     new  current working directory as if it had been supplied
+                     new current working directory as if it had been  supplied
                      as the argument to the c\bcd\bd builtin.
 
               If the p\bpu\bus\bsh\bhd\bd command is successful, a d\bdi\bir\brs\bs is performed as well.
-              If  the first form is used, p\bpu\bus\bsh\bhd\bd returns 0 unless the cd to _\bd_\bi_\br
-              fails.  With the second form, p\bpu\bus\bsh\bhd\bd returns 0 unless the  direc-
-              tory  stack  is empty, a non-existent directory stack element is
-              specified, or the directory change to the specified new  current
+              If the first form is used, p\bpu\bus\bsh\bhd\bd returns 0 unless the cd to  _\bd_\bi_\br
+              fails.   With the second form, p\bpu\bus\bsh\bhd\bd returns 0 unless the direc-
+              tory stack is empty, a non-existent directory stack  element  is
+              specified,  or the directory change to the specified new current
               directory fails.
 
        p\bpw\bwd\bd [-\b-L\bLP\bP]
-              Print  the  absolute  pathname of the current working directory.
+              Print the absolute pathname of the  current  working  directory.
               The pathname printed contains no symbolic links if the -\b-P\bP option
               is supplied or the -\b-o\bo p\bph\bhy\bys\bsi\bic\bca\bal\bl option to the s\bse\bet\bt builtin command
-              is enabled.  If the -\b-L\bL option is used, the pathname printed  may
-              contain  symbolic links.  The return status is 0 unless an error
-              occurs while reading the name of the  current  directory  or  an
+              is  enabled.  If the -\b-L\bL option is used, the pathname printed may
+              contain symbolic links.  The return status is 0 unless an  error
+              occurs  while  reading  the  name of the current directory or an
               invalid option is supplied.
 
        r\bre\bea\bad\bd [-\b-e\ber\brs\bs] [-\b-a\ba _\ba_\bn_\ba_\bm_\be] [-\b-d\bd _\bd_\be_\bl_\bi_\bm] [-\b-i\bi _\bt_\be_\bx_\bt] [-\b-n\bn _\bn_\bc_\bh_\ba_\br_\bs] [-\b-N\bN _\bn_\bc_\bh_\ba_\br_\bs] [-\b-p\bp
        _\bp_\br_\bo_\bm_\bp_\bt] [-\b-t\bt _\bt_\bi_\bm_\be_\bo_\bu_\bt] [-\b-u\bu _\bf_\bd] [_\bn_\ba_\bm_\be ...]
-              One  line  is  read  from  the  standard input, or from the file
-              descriptor _\bf_\bd supplied as an argument to the -\b-u\bu option, and  the
+              One line is read from the  standard  input,  or  from  the  file
+              descriptor  _\bf_\bd supplied as an argument to the -\b-u\bu option, and the
               first word is assigned to the first _\bn_\ba_\bm_\be, the second word to the
-              second _\bn_\ba_\bm_\be, and so on, with leftover words and their  interven-
-              ing  separators  assigned  to the last _\bn_\ba_\bm_\be.  If there are fewer
+              second  _\bn_\ba_\bm_\be, and so on, with leftover words and their interven-
+              ing separators assigned to the last _\bn_\ba_\bm_\be.  If  there  are  fewer
               words read from the input stream than names, the remaining names
-              are  assigned  empty  values.  The characters in I\bIF\bFS\bS are used to
-              split the line into words using the same rules  the  shell  uses
+              are assigned empty values.  The characters in I\bIF\bFS\bS  are  used  to
+              split  the  line  into words using the same rules the shell uses
               for expansion (described above under W\bWo\bor\brd\bd S\bSp\bpl\bli\bit\btt\bti\bin\bng\bg).  The back-
-              slash character (\\b\) may be used to remove  any  special  meaning
+              slash  character  (\\b\)  may be used to remove any special meaning
               for the next character read and for line continuation.  Options,
               if supplied, have the following meanings:
               -\b-a\ba _\ba_\bn_\ba_\bm_\be
@@ -4810,81 +4813,86 @@ S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS
                      new  values  are  assigned.   Other  _\bn_\ba_\bm_\be  arguments  are
                      ignored.
               -\b-d\bd _\bd_\be_\bl_\bi_\bm
-                     The  first  character  of  _\bd_\be_\bl_\bi_\bm is used to terminate the
+                     The first character of _\bd_\be_\bl_\bi_\bm is  used  to  terminate  the
                      input line, rather than newline.
               -\b-e\be     If the standard input is coming from a terminal, r\bre\bea\bad\bdl\bli\bin\bne\be
-                     (see  R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE  above) is used to obtain the line.  Read-
-                     line uses the current (or default, if  line  editing  was
+                     (see R\bRE\bEA\bAD\bDL\bLI\bIN\bNE\bE above) is used to obtain the  line.   Read-
+                     line  uses  the  current (or default, if line editing was
                      not previously active) editing settings.
               -\b-i\bi _\bt_\be_\bx_\bt
-                     If  r\bre\bea\bad\bdl\bli\bin\bne\be  is  being  used  to  read the line, _\bt_\be_\bx_\bt is
+                     If r\bre\bea\bad\bdl\bli\bin\bne\be is being used  to  read  the  line,  _\bt_\be_\bx_\b is
                      placed into the editing buffer before editing begins.
               -\b-n\bn _\bn_\bc_\bh_\ba_\br_\bs
-                     r\bre\bea\bad\breturns after reading _\bn_\bc_\bh_\ba_\br_\bs characters rather  than
-                     waiting  for a complete line of input, but honor a delim-
-                     iter if fewer than _\bn_\bc_\bh_\ba_\br_\bs characters are read before  the
+                     r\bre\bea\bad\b returns after reading _\bn_\bc_\bh_\ba_\br_\bs characters rather than
+                     waiting for a complete line of input, but honor a  delim-
+                     iter  if fewer than _\bn_\bc_\bh_\ba_\br_\bs characters are read before the
                      delimiter.
               -\b-N\bN _\bn_\bc_\bh_\ba_\br_\bs
-                     r\bre\bea\bad\b returns  after  reading  exactly  _\bn_\bc_\bh_\ba_\br_\bs characters
-                     rather than waiting for a complete line of input,  unless
-                     EOF  is encountered or r\bre\bea\bad\bd times out.  Delimiter charac-
-                     ters encountered in the input are not  treated  specially
-                     and  do  not cause r\bre\bea\bad\bd to return until _\bn_\bc_\bh_\ba_\br_\bs characters
+                     r\bre\bea\bad\breturns  after  reading  exactly  _\bn_\bc_\bh_\ba_\br_\b characters
+                     rather  than waiting for a complete line of input, unless
+                     EOF is encountered or r\bre\bea\bad\bd times out.  Delimiter  charac-
+                     ters  encountered  in the input are not treated specially
+                     and do not cause r\bre\bea\bad\bd to return until  _\bn_\bc_\bh_\ba_\br_\b characters
                      are read.
               -\b-p\bp _\bp_\br_\bo_\bm_\bp_\bt
                      Display _\bp_\br_\bo_\bm_\bp_\bt on standard error, without a trailing new-
                      line, before attempting to read any input.  The prompt is
                      displayed only if input is coming from a terminal.
               -\b-r\br     Backslash does not act as an escape character.  The back-
-                     slash  is considered to be part of the line.  In particu-
-                     lar, a backslash-newline pair may not be used as  a  line
+                     slash is considered to be part of the line.  In  particu-
+                     lar,  a  backslash-newline pair may not be used as a line
                      continuation.
               -\b-s\bs     Silent mode.  If input is coming from a terminal, charac-
                      ters are not echoed.
               -\b-t\bt _\bt_\bi_\bm_\be_\bo_\bu_\bt
-                     Cause r\bre\bea\bad\bd to time out and return failure if  a  complete
-                     line  of  input  (or a specified number of characters) is
-                     not read within _\bt_\bi_\bm_\be_\bo_\bu_\bt seconds.  _\bt_\bi_\bm_\be_\bo_\bu_\bt may be a  deci-
-                     mal  number with a fractional portion following the deci-
-                     mal point.  This option is  only  effective  if  r\bre\bea\bad\b is
-                     reading  input  from  a  terminal, pipe, or other special
-                     file; it has no effect when reading from  regular  files.
+                     Cause  r\bre\bea\bad\bd  to time out and return failure if a complete
+                     line of input (or a specified number  of  characters)  is
+                     not  read within _\bt_\bi_\bm_\be_\bo_\bu_\bt seconds.  _\bt_\bi_\bm_\be_\bo_\bu_\bt may be a deci-
+                     mal number with a fractional portion following the  deci-
+                     mal  point.   This  option  is  only effective if r\bre\bea\bad\bd is
+                     reading input from a terminal,  pipe,  or  other  special
+                     file;  it  has no effect when reading from regular files.
                      If r\bre\bea\bad\bd times out, r\bre\bea\bad\bd saves any partial input read into
-                     the specified variable  _\bn_\ba_\bm_\be.   If  _\bt_\bi_\bm_\be_\bo_\bu_\bt  is  0,  r\bre\bea\bad\bd
-                     returns  immediately,  without  trying  to read any data.
-                     The exit status is 0 if input is available on the  speci-
-                     fied  file descriptor, non-zero otherwise.  The exit sta-
+                     the  specified  variable  _\bn_\ba_\bm_\be.   If  _\bt_\bi_\bm_\be_\bo_\bu_\bt  is 0, r\bre\bea\bad\bd
+                     returns immediately, without trying  to  read  any  data.
+                     The  exit status is 0 if input is available on the speci-
+                     fied file descriptor, non-zero otherwise.  The exit  sta-
                      tus is greater than 128 if the timeout is exceeded.
               -\b-u\bu _\bf_\bd  Read input from file descriptor _\bf_\bd.
 
               If no _\bn_\ba_\bm_\be_\bs are supplied, the line read is assigned to the vari-
-              able  R\bRE\bEP\bPL\bLY\bY.   The  return  code  is zero, unless end-of-file is
-              encountered, r\bre\bea\bad\bd times out (in which case the  return  code  is
-              greater  than 128), a variable assignment error (such as assign-
-              ing to a readonly variable) occurs, or an invalid file  descrip-
+              able R\bRE\bEP\bPL\bLY\bY.  The return code  is  zero,  unless  end-of-file  is
+              encountered,  r\bre\bea\bad\bd  times  out (in which case the return code is
+              greater than 128), a variable assignment error (such as  assign-
+              ing  to a readonly variable) occurs, or an invalid file descrip-
               tor is supplied as the argument to -\b-u\bu.
 
        r\bre\bea\bad\bdo\bon\bnl\bly\by [-\b-a\baA\bAf\bf] [-\b-p\bp] [_\bn_\ba_\bm_\be[=_\bw_\bo_\br_\bd] ...]
-              The  given  _\bn_\ba_\bm_\be_\bs are marked readonly; the values of these _\bn_\ba_\bm_\be_\bs
-              may not be changed by subsequent assignment.  If the  -\b-f\b option
-              is  supplied,  the  functions  corresponding to the _\bn_\ba_\bm_\be_\bs are so
-              marked.  The  -\b-a\ba  option  restricts  the  variables  to  indexed
-              arrays;  the  -\b-A\bA  option  restricts the variables to associative
-              arrays.  If both options are supplied, -\b-A\bA takes precedence.   If
-              no  _\bn_\ba_\bm_\be arguments are given, or if the -\b-p\bp option is supplied, a
+              The given _\bn_\ba_\bm_\be_\bs are marked readonly; the values of  these  _\bn_\ba_\bm_\be_\bs
+              may  not  be changed by subsequent assignment.  If the -\b-f\bf option
+              is supplied, the functions corresponding to  the  _\bn_\ba_\bm_\be_\bs  are  so
+              marked.   The  -\b-a\ba  option  restricts  the  variables  to indexed
+              arrays; the -\b-A\bA option restricts  the  variables  to  associative
+              arrays.   If both options are supplied, -\b-A\bA takes precedence.  If
+              no _\bn_\ba_\bm_\be arguments are given, or if the -\b-p\bp option is supplied,  a
               list of all readonly names is printed.  The other options may be
-              used  to  restrict the output to a subset of the set of readonly
-              names.  The -\b-p\bp option causes output to be displayed in a  format
-              that  may be reused as input.  If a variable name is followed by
-              =_\bw_\bo_\br_\bd, the value of the variable is set  to  _\bw_\bo_\br_\bd.   The  return
-              status  is 0 unless an invalid option is encountered, one of the
+              used to restrict the output to a subset of the set  of  readonly
+              names.   The -\b-p\bp option causes output to be displayed in a format
+              that may be reused as input.  If a variable name is followed  by
+              =_\bw_\bo_\br_\bd,  the  value  of  the variable is set to _\bw_\bo_\br_\bd.  The return
+              status is 0 unless an invalid option is encountered, one of  the
               _\bn_\ba_\bm_\be_\bs is not a valid shell variable name, or -\b-f\bf is supplied with
               a _\bn_\ba_\bm_\be that is not a function.
 
        r\bre\bet\btu\bur\brn\bn [_\bn]
-              Causes  a function to stop executing and return the value speci-
-              fied by _\bn to its caller.  If _\bn is omitted, the return status  is
-              that  of  the  last  command  executed in the function body.  If
+              Causes a function to stop executing and return the value  speci-
+              fied  by _\bn to its caller.  If _\bn is omitted, the return status is
+              that of the last command executed  in  the  function  body.   If
+              r\bre\bet\btu\bur\brn\bn  is  executed by a trap handler, the last command used to
+              determine the status is the last  command  executed  before  the
+              trap  handler.   if  r\bre\bet\btu\bur\brn\bn is executed during a D\bDE\bEB\bBU\bUG\bG trap, the
+              last command used to determine the status is  the  last  command
+              executed  by  the  trap  handler  before r\bre\bet\btu\bur\brn\bn was invoked.  If
               r\bre\bet\btu\bur\brn\bn is used outside a function, but  during  execution  of  a
               script  by  the .\b.  (s\bso\bou\bur\brc\bce\be) command, it causes the shell to stop
               executing that script and return either _\bn or the exit status  of
@@ -5234,8 +5242,8 @@ S\bSH\bHE\bEL\bLL\bL B\bBU\bUI\bIL\bLT\bTI\bIN\bN C\bCO\bOM\bMM\bMA\bAN\bND\bDS\bS
                       3\b3.\b.     If the command run by the D\bDE\bEB\bBU\bUG\bG  trap  returns  a
                              value  of 2, and the shell is executing in a sub-
                              routine (a shell function or a shell script  exe-
-                             cuted  by  the  .\b.  or s\bso\bou\bur\brc\bce\be builtins), a call to
-                             r\bre\bet\btu\bur\brn\bn is simulated.
+                             cuted  by  the  .\b.  or s\bso\bou\bur\brc\bce\be builtins), the shell
+                             simulates a call to r\bre\bet\btu\bur\brn\bn.
                       4\b4.\b.     B\bBA\bAS\bSH\bH_\b_A\bAR\bRG\bGC\bC and B\bBA\bAS\bSH\bH_\b_A\bAR\bRG\bGV\bV are updated as  described
                              in their descriptions above.
                       5\b5.\b.     Function  tracing  is enabled:  command substitu-
@@ -5726,4 +5734,4 @@ B\bBU\bUG\bGS\bS
 
 
 
-GNU Bash 4.3                    2014 February 2                        BASH(1)
+GNU Bash 4.3                     2014 March 18                         BASH(1)
index 059dd9de31bc8ba6904b8381ee23daaaeb7d2010..f701ba51bae3a68368a875c270516580a75ca3c2 100644 (file)
@@ -1083,6 +1083,19 @@ extern int timeval_to_cpu __P((struct timeval *, struct timeval *, struct timeva
 
 static const int precs[] = { 0, 100, 10, 1 };
 
+#if defined (HAVE_LOCALE_H) && defined (HAVE_LOCALECONV)
+static int
+decpoint ()
+{
+  struct lconv *lv;
+
+  lv = localeconv ();
+  return (lv && lv->decimal_point && lv->decimal_point[0]) ? lv->decimal_point[0] : '.';
+}
+#else
+#  define decpoint() '.'
+#endif
+
 /* Expand one `%'-prefixed escape sequence from a time format string. */
 static int
 mkfmt (buf, prec, lng, sec, sec_fraction)
@@ -1127,7 +1140,7 @@ mkfmt (buf, prec, lng, sec, sec_fraction)
      and 999. */
   if (prec != 0)
     {
-      buf[ind++] = '.';
+      buf[ind++] = decpoint ();
       for (aind = 1; aind <= prec; aind++)
        {
          buf[ind++] = (sec_fraction / precs[aind]) + '0';
diff --git a/execute_cmd.c~ b/execute_cmd.c~
new file mode 100644 (file)
index 0000000..6e79861
--- /dev/null
@@ -0,0 +1,5463 @@
+/* execute_cmd.c -- Execute a COMMAND structure. */
+
+/* Copyright (C) 1987-2013 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Bash is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
+  #pragma alloca
+#endif /* _AIX && RISC6000 && !__GNUC__ */
+
+#include <stdio.h>
+#include "chartypes.h"
+#include "bashtypes.h"
+#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
+#  include <sys/file.h>
+#endif
+#include "filecntl.h"
+#include "posixstat.h"
+#include <signal.h>
+#if defined (HAVE_SYS_PARAM_H)
+#  include <sys/param.h>
+#endif
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include "posixtime.h"
+
+#if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE)
+#  include <sys/resource.h>
+#endif
+
+#if defined (HAVE_SYS_TIMES_H) && defined (HAVE_TIMES)
+#  include <sys/times.h>
+#endif
+
+#include <errno.h>
+
+#if !defined (errno)
+extern int errno;
+#endif
+
+#define NEED_FPURGE_DECL
+
+#include "bashansi.h"
+#include "bashintl.h"
+
+#include "memalloc.h"
+#include "shell.h"
+#include <y.tab.h>     /* use <...> so we pick it up from the build directory */
+#include "flags.h"
+#include "builtins.h"
+#include "hashlib.h"
+#include "jobs.h"
+#include "execute_cmd.h"
+#include "findcmd.h"
+#include "redir.h"
+#include "trap.h"
+#include "pathexp.h"
+#include "hashcmd.h"
+
+#if defined (COND_COMMAND)
+#  include "test.h"
+#endif
+
+#include "builtins/common.h"
+#include "builtins/builtext.h" /* list of builtins */
+
+#include <glob/strmatch.h>
+#include <tilde/tilde.h>
+
+#if defined (BUFFERED_INPUT)
+#  include "input.h"
+#endif
+
+#if defined (ALIAS)
+#  include "alias.h"
+#endif
+
+#if defined (HISTORY)
+#  include "bashhist.h"
+#endif
+
+extern int dollar_dollar_pid;
+extern int posixly_correct;
+extern int expand_aliases;
+extern int autocd;
+extern int breaking, continuing, loop_level;
+extern int parse_and_execute_level, running_trap, sourcelevel;
+extern int command_string_index, line_number;
+extern int dot_found_in_search;
+extern int already_making_children;
+extern int tempenv_assign_error;
+extern char *the_printed_command, *shell_name;
+extern pid_t last_command_subst_pid;
+extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
+extern char **subshell_argv, **subshell_envp;
+extern int subshell_argc;
+extern time_t shell_start_time;
+#if 0
+extern char *glob_argv_flags;
+#endif
+
+extern int job_control;        /* XXX */
+
+extern int close __P((int));
+
+/* Static functions defined and used in this file. */
+static void close_pipes __P((int, int));
+static void do_piping __P((int, int));
+static void bind_lastarg __P((char *));
+static int shell_control_structure __P((enum command_type));
+static void cleanup_redirects __P((REDIRECT *));
+
+#if defined (JOB_CONTROL)
+static int restore_signal_mask __P((sigset_t *));
+#endif
+
+static void async_redirect_stdin __P((void));
+
+static int builtin_status __P((int));
+
+static int execute_for_command __P((FOR_COM *));
+#if defined (SELECT_COMMAND)
+static int displen __P((const char *));
+static int print_index_and_element __P((int, int, WORD_LIST *));
+static void indent __P((int, int));
+static void print_select_list __P((WORD_LIST *, int, int, int));
+static char *select_query __P((WORD_LIST *, int, char *, int));
+static int execute_select_command __P((SELECT_COM *));
+#endif
+#if defined (DPAREN_ARITHMETIC)
+static int execute_arith_command __P((ARITH_COM *));
+#endif
+#if defined (COND_COMMAND)
+static int execute_cond_node __P((COND_COM *));
+static int execute_cond_command __P((COND_COM *));
+#endif
+#if defined (COMMAND_TIMING)
+static int mkfmt __P((char *, int, int, time_t, int));
+static void print_formatted_time __P((FILE *, char *,
+                                     time_t, int, time_t, int,
+                                     time_t, int, int));
+static int time_command __P((COMMAND *, int, int, int, struct fd_bitmap *));
+#endif
+#if defined (ARITH_FOR_COMMAND)
+static intmax_t eval_arith_for_expr __P((WORD_LIST *, int *));
+static int execute_arith_for_command __P((ARITH_FOR_COM *));
+#endif
+static int execute_case_command __P((CASE_COM *));
+static int execute_while_command __P((WHILE_COM *));
+static int execute_until_command __P((WHILE_COM *));
+static int execute_while_or_until __P((WHILE_COM *, int));
+static int execute_if_command __P((IF_COM *));
+static int execute_null_command __P((REDIRECT *, int, int, int));
+static void fix_assignment_words __P((WORD_LIST *));
+static int execute_simple_command __P((SIMPLE_COM *, int, int, int, struct fd_bitmap *));
+static int execute_builtin __P((sh_builtin_func_t *, WORD_LIST *, int, int));
+static int execute_function __P((SHELL_VAR *, WORD_LIST *, int, struct fd_bitmap *, int, int));
+static int execute_builtin_or_function __P((WORD_LIST *, sh_builtin_func_t *,
+                                           SHELL_VAR *,
+                                           REDIRECT *, struct fd_bitmap *, int));
+static void execute_subshell_builtin_or_function __P((WORD_LIST *, REDIRECT *,
+                                                     sh_builtin_func_t *,
+                                                     SHELL_VAR *,
+                                                     int, int, int,
+                                                     struct fd_bitmap *,
+                                                     int));
+static int execute_disk_command __P((WORD_LIST *, REDIRECT *, char *,
+                                     int, int, int, struct fd_bitmap *, int));
+
+static char *getinterp __P((char *, int, int *));
+static void initialize_subshell __P((void));
+static int execute_in_subshell __P((COMMAND *, int, int, int, struct fd_bitmap *));
+#if defined (COPROCESS_SUPPORT)
+static int execute_coproc __P((COMMAND *, int, int, struct fd_bitmap *));
+#endif
+
+static int execute_pipeline __P((COMMAND *, int, int, int, struct fd_bitmap *));
+
+static int execute_connection __P((COMMAND *, int, int, int, struct fd_bitmap *));
+
+static int execute_intern_function __P((WORD_DESC *, FUNCTION_DEF *));
+
+/* Set to 1 if fd 0 was the subject of redirection to a subshell.  Global
+   so that reader_loop can set it to zero before executing a command. */
+int stdin_redir;
+
+/* The name of the command that is currently being executed.
+   `test' needs this, for example. */
+char *this_command_name;
+
+/* The printed representation of the currently-executing command (same as
+   the_printed_command), except when a trap is being executed.  Useful for
+   a debugger to know where exactly the program is currently executing. */
+char *the_printed_command_except_trap;
+
+/* For catching RETURN in a function. */
+int return_catch_flag;
+int return_catch_value;
+procenv_t return_catch;
+
+/* The value returned by the last synchronous command. */
+volatile int last_command_exit_value;
+
+/* Whether or not the last command (corresponding to last_command_exit_value)
+   was terminated by a signal, and, if so, which one. */
+int last_command_exit_signal;
+
+/* Are we currently ignoring the -e option for the duration of a builtin's
+   execution? */
+int builtin_ignoring_errexit = 0;
+
+/* The list of redirections to perform which will undo the redirections
+   that I made in the shell. */
+REDIRECT *redirection_undo_list = (REDIRECT *)NULL;
+
+/* The list of redirections to perform which will undo the internal
+   redirections performed by the `exec' builtin.  These are redirections
+   that must be undone even when exec discards redirection_undo_list. */
+REDIRECT *exec_redirection_undo_list = (REDIRECT *)NULL;
+
+/* When greater than zero, value is the `level' of builtins we are
+   currently executing (e.g. `eval echo a' would have it set to 2). */
+int executing_builtin = 0;
+
+/* Non-zero if we are executing a command list (a;b;c, etc.) */
+int executing_list = 0;
+
+/* Non-zero if failing commands in a command substitution should not exit the
+   shell even if -e is set.  Used to pass the CMD_IGNORE_RETURN flag down to
+   commands run in command substitutions by parse_and_execute. */
+int comsub_ignore_return = 0;
+
+/* Non-zero if we have just forked and are currently running in a subshell
+   environment. */
+int subshell_environment;
+
+/* Count of nested subshells, like SHLVL.  Available via $BASH_SUBSHELL */
+int subshell_level = 0;
+
+/* Currently-executing shell function. */
+SHELL_VAR *this_shell_function;
+
+/* If non-zero, matches in case and [[ ... ]] are case-insensitive */
+int match_ignore_case = 0;
+
+int executing_command_builtin = 0;
+
+struct stat SB;                /* used for debugging */
+
+static int special_builtin_failed;
+
+static COMMAND *currently_executing_command;
+
+/* The line number that the currently executing function starts on. */
+static int function_line_number;
+
+/* XXX - set to 1 if we're running the DEBUG trap and we want to show the line
+   number containing the function name.  Used by executing_line_number to
+   report the correct line number.  Kind of a hack. */
+static int showing_function_line;
+
+/* $LINENO ($BASH_LINENO) for use by an ERR trap.  Global so parse_and_execute
+   can save and restore it. */
+int line_number_for_err_trap;
+
+/* A sort of function nesting level counter */
+int funcnest = 0;
+int funcnest_max = 0;          /* bash-4.2 */
+
+volatile int from_return_trap = 0;
+
+int lastpipe_opt = 0;
+
+struct fd_bitmap *current_fds_to_close = (struct fd_bitmap *)NULL;
+
+#define FD_BITMAP_DEFAULT_SIZE 32
+
+/* Functions to allocate and deallocate the structures used to pass
+   information from the shell to its children about file descriptors
+   to close. */
+struct fd_bitmap *
+new_fd_bitmap (size)
+     int size;
+{
+  struct fd_bitmap *ret;
+
+  ret = (struct fd_bitmap *)xmalloc (sizeof (struct fd_bitmap));
+
+  ret->size = size;
+
+  if (size)
+    {
+      ret->bitmap = (char *)xmalloc (size);
+      memset (ret->bitmap, '\0', size);
+    }
+  else
+    ret->bitmap = (char *)NULL;
+  return (ret);
+}
+
+void
+dispose_fd_bitmap (fdbp)
+     struct fd_bitmap *fdbp;
+{
+  FREE (fdbp->bitmap);
+  free (fdbp);
+}
+
+void
+close_fd_bitmap (fdbp)
+     struct fd_bitmap *fdbp;
+{
+  register int i;
+
+  if (fdbp)
+    {
+      for (i = 0; i < fdbp->size; i++)
+       if (fdbp->bitmap[i])
+         {
+           close (i);
+           fdbp->bitmap[i] = 0;
+         }
+    }
+}
+
+/* Return the line number of the currently executing command. */
+int
+executing_line_number ()
+{
+  if (executing && showing_function_line == 0 &&
+      (variable_context == 0 || interactive_shell == 0) &&
+      currently_executing_command)
+    {
+#if defined (COND_COMMAND)
+      if (currently_executing_command->type == cm_cond)
+       return currently_executing_command->value.Cond->line;
+#endif
+#if defined (DPAREN_ARITHMETIC)
+      if (currently_executing_command->type == cm_arith)
+       return currently_executing_command->value.Arith->line;
+#endif
+#if defined (ARITH_FOR_COMMAND)
+      if (currently_executing_command->type == cm_arith_for)
+       return currently_executing_command->value.ArithFor->line;
+#endif
+
+       return line_number;
+    }
+  else
+    return line_number;
+}
+
+/* Execute the command passed in COMMAND.  COMMAND is exactly what
+   read_command () places into GLOBAL_COMMAND.  See "command.h" for the
+   details of the command structure.
+
+   EXECUTION_SUCCESS or EXECUTION_FAILURE are the only possible
+   return values.  Executing a command with nothing in it returns
+   EXECUTION_SUCCESS. */
+int
+execute_command (command)
+     COMMAND *command;
+{
+  struct fd_bitmap *bitmap;
+  int result;
+
+  current_fds_to_close = (struct fd_bitmap *)NULL;
+  bitmap = new_fd_bitmap (FD_BITMAP_DEFAULT_SIZE);
+  begin_unwind_frame ("execute-command");
+  add_unwind_protect (dispose_fd_bitmap, (char *)bitmap);
+
+  /* Just do the command, but not asynchronously. */
+  result = execute_command_internal (command, 0, NO_PIPE, NO_PIPE, bitmap);
+
+  dispose_fd_bitmap (bitmap);
+  discard_unwind_frame ("execute-command");
+
+#if defined (PROCESS_SUBSTITUTION)
+  /* don't unlink fifos if we're in a shell function; wait until the function
+     returns. */
+  if (variable_context == 0)
+    unlink_fifo_list ();
+#endif /* PROCESS_SUBSTITUTION */
+
+  QUIT;
+  return (result);
+}
+
+/* Return 1 if TYPE is a shell control structure type. */
+static int
+shell_control_structure (type)
+     enum command_type type;
+{
+  switch (type)
+    {
+#if defined (ARITH_FOR_COMMAND)
+    case cm_arith_for:
+#endif
+#if defined (SELECT_COMMAND)
+    case cm_select:
+#endif
+#if defined (DPAREN_ARITHMETIC)
+    case cm_arith:
+#endif
+#if defined (COND_COMMAND)
+    case cm_cond:
+#endif
+    case cm_case:
+    case cm_while:
+    case cm_until:
+    case cm_if:
+    case cm_for:
+    case cm_group:
+    case cm_function_def:
+      return (1);
+
+    default:
+      return (0);
+    }
+}
+
+/* A function to use to unwind_protect the redirection undo list
+   for loops. */
+static void
+cleanup_redirects (list)
+     REDIRECT *list;
+{
+  do_redirections (list, RX_ACTIVE);
+  dispose_redirects (list);
+}
+
+#if 0
+/* Function to unwind_protect the redirections for functions and builtins. */
+static void
+cleanup_func_redirects (list)
+     REDIRECT *list;
+{
+  do_redirections (list, RX_ACTIVE);
+}
+#endif
+
+void
+dispose_exec_redirects ()
+{
+  if (exec_redirection_undo_list)
+    {
+      dispose_redirects (exec_redirection_undo_list);
+      exec_redirection_undo_list = (REDIRECT *)NULL;
+    }
+}
+
+#if defined (JOB_CONTROL)
+/* A function to restore the signal mask to its proper value when the shell
+   is interrupted or errors occur while creating a pipeline. */
+static int
+restore_signal_mask (set)
+     sigset_t *set;
+{
+  return (sigprocmask (SIG_SETMASK, set, (sigset_t *)NULL));
+}
+#endif /* JOB_CONTROL */
+
+#ifdef DEBUG
+/* A debugging function that can be called from gdb, for instance. */
+void
+open_files ()
+{
+  register int i;
+  int f, fd_table_size;
+
+  fd_table_size = getdtablesize ();
+
+  fprintf (stderr, "pid %ld open files:", (long)getpid ());
+  for (i = 3; i < fd_table_size; i++)
+    {
+      if ((f = fcntl (i, F_GETFD, 0)) != -1)
+       fprintf (stderr, " %d (%s)", i, f ? "close" : "open");
+    }
+  fprintf (stderr, "\n");
+}
+#endif
+
+static void
+async_redirect_stdin ()
+{
+  int fd;
+
+  fd = open ("/dev/null", O_RDONLY);
+  if (fd > 0)
+    {
+      dup2 (fd, 0);
+      close (fd);
+    }
+  else if (fd < 0)
+    internal_error (_("cannot redirect standard input from /dev/null: %s"), strerror (errno));
+}
+
+#define DESCRIBE_PID(pid) do { if (interactive) describe_pid (pid); } while (0)
+
+/* Execute the command passed in COMMAND, perhaps doing it asynchronously.
+   COMMAND is exactly what read_command () places into GLOBAL_COMMAND.
+   ASYNCHROUNOUS, if non-zero, says to do this command in the background.
+   PIPE_IN and PIPE_OUT are file descriptors saying where input comes
+   from and where it goes.  They can have the value of NO_PIPE, which means
+   I/O is stdin/stdout.
+   FDS_TO_CLOSE is a list of file descriptors to close once the child has
+   been forked.  This list often contains the unusable sides of pipes, etc.
+
+   EXECUTION_SUCCESS or EXECUTION_FAILURE are the only possible
+   return values.  Executing a command with nothing in it returns
+   EXECUTION_SUCCESS. */
+int
+execute_command_internal (command, asynchronous, pipe_in, pipe_out,
+                         fds_to_close)
+     COMMAND *command;
+     int asynchronous;
+     int pipe_in, pipe_out;
+     struct fd_bitmap *fds_to_close;
+{
+  int exec_result, user_subshell, invert, ignore_return, was_error_trap;
+  REDIRECT *my_undo_list, *exec_undo_list;
+  char *tcmd;
+  volatile int last_pid;
+  volatile int save_line_number;
+#if defined (PROCESS_SUBSTITUTION)
+  volatile int ofifo, nfifo, osize, saved_fifo;
+  volatile char *ofifo_list;
+#endif
+
+  if (breaking || continuing)
+    return (last_command_exit_value);
+  if (command == 0 || read_but_dont_execute)
+    return (EXECUTION_SUCCESS);
+
+  QUIT;
+  run_pending_traps ();
+
+#if 0
+  if (running_trap == 0)
+#endif
+    currently_executing_command = command;
+
+  invert = (command->flags & CMD_INVERT_RETURN) != 0;
+
+  /* If we're inverting the return value and `set -e' has been executed,
+     we don't want a failing command to inadvertently cause the shell
+     to exit. */
+  if (exit_immediately_on_error && invert)     /* XXX */
+    command->flags |= CMD_IGNORE_RETURN;       /* XXX */
+
+  exec_result = EXECUTION_SUCCESS;
+
+  /* If a command was being explicitly run in a subshell, or if it is
+     a shell control-structure, and it has a pipe, then we do the command
+     in a subshell. */
+  if (command->type == cm_subshell && (command->flags & CMD_NO_FORK))
+    return (execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close));
+
+#if defined (COPROCESS_SUPPORT)
+  if (command->type == cm_coproc)
+    return (execute_coproc (command, pipe_in, pipe_out, fds_to_close));
+#endif
+
+  user_subshell = command->type == cm_subshell || ((command->flags & CMD_WANT_SUBSHELL) != 0);
+
+  if (command->type == cm_subshell ||
+      (command->flags & (CMD_WANT_SUBSHELL|CMD_FORCE_SUBSHELL)) ||
+      (shell_control_structure (command->type) &&
+       (pipe_out != NO_PIPE || pipe_in != NO_PIPE || asynchronous)))
+    {
+      pid_t paren_pid;
+      int s;
+
+      /* 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;
+      tcmd = make_command_string (command);
+      paren_pid = make_child (savestring (tcmd), asynchronous);
+
+      if (user_subshell && signal_is_trapped (ERROR_TRAP) && 
+         signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
+       {
+         FREE (the_printed_command_except_trap);
+         the_printed_command_except_trap = savestring (the_printed_command);
+       }
+
+      if (paren_pid == 0)
+        {
+         /* We want to run the exit trap for forced {} subshells, and we
+            want to note this before execute_in_subshell modifies the
+            COMMAND struct.  Need to keep in mind that execute_in_subshell
+            runs the exit trap for () subshells itself. */
+         /* This handles { command; } & */
+         s = user_subshell == 0 && command->type == cm_group && pipe_in == NO_PIPE && pipe_out == NO_PIPE && asynchronous;
+         /* run exit trap for : | { ...; } and { ...; } | : */
+         /* run exit trap for : | ( ...; ) and ( ...; ) | : */
+         s += user_subshell == 0 && command->type == cm_group && (pipe_in != NO_PIPE || pipe_out != NO_PIPE) && asynchronous == 0;
+
+         last_command_exit_value = execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close);
+         if (s)
+           subshell_exit (last_command_exit_value);
+         else
+           exit (last_command_exit_value);
+         /* NOTREACHED */
+        }
+      else
+       {
+         close_pipes (pipe_in, pipe_out);
+
+#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
+         if (variable_context == 0)    /* wait until shell function completes */
+           unlink_fifo_list ();
+#endif
+         /* If we are part of a pipeline, and not the end of the pipeline,
+            then we should simply return and let the last command in the
+            pipe be waited for.  If we are not in a pipeline, or are the
+            last command in the pipeline, then we wait for the subshell
+            and return its exit status as usual. */
+         if (pipe_out != NO_PIPE)
+           return (EXECUTION_SUCCESS);
+
+         stop_pipeline (asynchronous, (COMMAND *)NULL);
+
+         if (asynchronous == 0)
+           {
+             was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
+             invert = (command->flags & CMD_INVERT_RETURN) != 0;
+             ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
+
+             exec_result = wait_for (paren_pid);
+
+             /* If we have to, invert the return value. */
+             if (invert)
+               exec_result = ((exec_result == EXECUTION_SUCCESS)
+                               ? EXECUTION_FAILURE
+                               : EXECUTION_SUCCESS);
+
+             last_command_exit_value = exec_result;
+             if (user_subshell && was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
+               {
+                 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)
+               {
+                 run_pending_traps ();
+                 jump_to_top_level (ERREXIT);
+               }
+
+             return (last_command_exit_value);
+           }
+         else
+           {
+             DESCRIBE_PID (paren_pid);
+
+             run_pending_traps ();
+
+             /* Posix 2013 2.9.3.1: "the exit status of an asynchronous list
+                shall be zero." */
+             last_command_exit_value = 0;
+             return (EXECUTION_SUCCESS);
+           }
+       }
+    }
+
+#if defined (COMMAND_TIMING)
+  if (command->flags & CMD_TIME_PIPELINE)
+    {
+      if (asynchronous)
+       {
+         command->flags |= CMD_FORCE_SUBSHELL;
+         exec_result = execute_command_internal (command, 1, pipe_in, pipe_out, fds_to_close);
+       }
+      else
+       {
+         exec_result = time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close);
+#if 0
+         if (running_trap == 0)
+#endif
+           currently_executing_command = (COMMAND *)NULL;
+       }
+      return (exec_result);
+    }
+#endif /* COMMAND_TIMING */
+
+  if (shell_control_structure (command->type) && command->redirects)
+    stdin_redir = stdin_redirects (command->redirects);
+
+#if defined (PROCESS_SUBSTITUTION)
+  if (variable_context != 0)
+    {
+      ofifo = num_fifos ();
+      ofifo_list = copy_fifo_list ((int *)&osize);
+      saved_fifo = 1;
+    }
+  else
+    saved_fifo = 0;
+#endif
+
+  /* Handle WHILE FOR CASE etc. with redirections.  (Also '&' input
+     redirection.)  */
+  if (do_redirections (command->redirects, RX_ACTIVE|RX_UNDOABLE) != 0)
+    {
+      cleanup_redirects (redirection_undo_list);
+      redirection_undo_list = (REDIRECT *)NULL;
+      dispose_exec_redirects ();
+#if defined (PROCESS_SUBSTITUTION)
+      if (saved_fifo)
+       free ((void *)ofifo_list);
+#endif
+      return (last_command_exit_value = EXECUTION_FAILURE);
+    }
+
+  if (redirection_undo_list)
+    {
+      /* XXX - why copy here? */
+      my_undo_list = (REDIRECT *)copy_redirects (redirection_undo_list);
+      dispose_redirects (redirection_undo_list);
+      redirection_undo_list = (REDIRECT *)NULL;
+    }
+  else
+    my_undo_list = (REDIRECT *)NULL;
+
+  if (exec_redirection_undo_list)
+    {
+      /* XXX - why copy here? */
+      exec_undo_list = (REDIRECT *)copy_redirects (exec_redirection_undo_list);
+      dispose_redirects (exec_redirection_undo_list);
+      exec_redirection_undo_list = (REDIRECT *)NULL;
+    }
+  else
+    exec_undo_list = (REDIRECT *)NULL;
+
+  if (my_undo_list || exec_undo_list)
+    begin_unwind_frame ("loop_redirections");
+
+  if (my_undo_list)
+    add_unwind_protect ((Function *)cleanup_redirects, my_undo_list);
+
+  if (exec_undo_list)
+    add_unwind_protect ((Function *)dispose_redirects, exec_undo_list);
+
+  ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
+
+  QUIT;
+
+  switch (command->type)
+    {
+    case cm_simple:
+      {
+       save_line_number = line_number;
+       /* We can't rely on variables retaining their values across a
+          call to execute_simple_command if a longjmp occurs as the
+          result of a `return' builtin.  This is true for sure with gcc. */
+#if defined (RECYCLES_PIDS)
+       last_made_pid = NO_PID;
+#endif
+       last_pid = last_made_pid;
+       was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
+
+       if (ignore_return && command->value.Simple)
+         command->value.Simple->flags |= CMD_IGNORE_RETURN;
+       if (command->flags & CMD_STDIN_REDIR)
+         command->value.Simple->flags |= CMD_STDIN_REDIR;
+
+       line_number_for_err_trap = line_number = command->value.Simple->line;
+       exec_result =
+         execute_simple_command (command->value.Simple, pipe_in, pipe_out,
+                                 asynchronous, fds_to_close);
+       line_number = save_line_number;
+
+       /* The temporary environment should be used for only the simple
+          command immediately following its definition. */
+       dispose_used_env_vars ();
+
+#if (defined (ultrix) && defined (mips)) || defined (C_ALLOCA)
+       /* Reclaim memory allocated with alloca () on machines which
+          may be using the alloca emulation code. */
+       (void) alloca (0);
+#endif /* (ultrix && mips) || C_ALLOCA */
+
+       /* If we forked to do the command, then we must wait_for ()
+          the child. */
+
+       /* XXX - this is something to watch out for if there are problems
+          when the shell is compiled without job control.  Don't worry about
+          whether or not last_made_pid == last_pid; already_making_children
+          tells us whether or not there are unwaited-for children to wait
+          for and reap. */
+       if (already_making_children && pipe_out == NO_PIPE)
+         {
+           stop_pipeline (asynchronous, (COMMAND *)NULL);
+
+           if (asynchronous)
+             {
+               DESCRIBE_PID (last_made_pid);
+             }
+           else
+#if !defined (JOB_CONTROL)
+             /* Do not wait for asynchronous processes started from
+                startup files. */
+           if (last_made_pid != last_asynchronous_pid)
+#endif
+           /* When executing a shell function that executes other
+              commands, this causes the last simple command in
+              the function to be waited for twice.  This also causes
+              subshells forked to execute builtin commands (e.g., in
+              pipelines) to be waited for twice. */
+             exec_result = wait_for (last_made_pid);
+         }
+      }
+
+      /* 2009/02/13 -- pipeline failure is processed elsewhere.  This handles
+        only the failure of a simple command. */
+      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 &&
+         ((posixly_correct && interactive == 0 && special_builtin_failed) ||
+          (exit_immediately_on_error && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS)))
+       {
+         last_command_exit_value = exec_result;
+         run_pending_traps ();
+         jump_to_top_level (ERREXIT);
+       }
+
+      break;
+
+    case cm_for:
+      if (ignore_return)
+       command->value.For->flags |= CMD_IGNORE_RETURN;
+      exec_result = execute_for_command (command->value.For);
+      break;
+
+#if defined (ARITH_FOR_COMMAND)
+    case cm_arith_for:
+      if (ignore_return)
+       command->value.ArithFor->flags |= CMD_IGNORE_RETURN;
+      exec_result = execute_arith_for_command (command->value.ArithFor);
+      break;
+#endif
+
+#if defined (SELECT_COMMAND)
+    case cm_select:
+      if (ignore_return)
+       command->value.Select->flags |= CMD_IGNORE_RETURN;
+      exec_result = execute_select_command (command->value.Select);
+      break;
+#endif
+
+    case cm_case:
+      if (ignore_return)
+       command->value.Case->flags |= CMD_IGNORE_RETURN;
+      exec_result = execute_case_command (command->value.Case);
+      break;
+
+    case cm_while:
+      if (ignore_return)
+       command->value.While->flags |= CMD_IGNORE_RETURN;
+      exec_result = execute_while_command (command->value.While);
+      break;
+
+    case cm_until:
+      if (ignore_return)
+       command->value.While->flags |= CMD_IGNORE_RETURN;
+      exec_result = execute_until_command (command->value.While);
+      break;
+
+    case cm_if:
+      if (ignore_return)
+       command->value.If->flags |= CMD_IGNORE_RETURN;
+      exec_result = execute_if_command (command->value.If);
+      break;
+
+    case cm_group:
+
+      /* This code can be executed from either of two paths: an explicit
+        '{}' command, or via a function call.  If we are executed via a
+        function call, we have already taken care of the function being
+        executed in the background (down there in execute_simple_command ()),
+        and this command should *not* be marked as asynchronous.  If we
+        are executing a regular '{}' group command, and asynchronous == 1,
+        we must want to execute the whole command in the background, so we
+        need a subshell, and we want the stuff executed in that subshell
+        (this group command) to be executed in the foreground of that
+        subshell (i.e. there will not be *another* subshell forked).
+
+        What we do is to force a subshell if asynchronous, and then call
+        execute_command_internal again with asynchronous still set to 1,
+        but with the original group command, so the printed command will
+        look right.
+
+        The code above that handles forking off subshells will note that
+        both subshell and async are on, and turn off async in the child
+        after forking the subshell (but leave async set in the parent, so
+        the normal call to describe_pid is made).  This turning off
+        async is *crucial*; if it is not done, this will fall into an
+        infinite loop of executions through this spot in subshell after
+        subshell until the process limit is exhausted. */
+
+      if (asynchronous)
+       {
+         command->flags |= CMD_FORCE_SUBSHELL;
+         exec_result =
+           execute_command_internal (command, 1, pipe_in, pipe_out,
+                                     fds_to_close);
+       }
+      else
+       {
+         if (ignore_return && command->value.Group->command)
+           command->value.Group->command->flags |= CMD_IGNORE_RETURN;
+         exec_result =
+           execute_command_internal (command->value.Group->command,
+                                     asynchronous, pipe_in, pipe_out,
+                                     fds_to_close);
+       }
+      break;
+
+    case cm_connection:
+      exec_result = execute_connection (command, asynchronous,
+                                       pipe_in, pipe_out, fds_to_close);
+      break;
+
+#if defined (DPAREN_ARITHMETIC)
+    case cm_arith:
+      was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
+      if (ignore_return)
+       command->value.Arith->flags |= CMD_IGNORE_RETURN;
+      line_number_for_err_trap = save_line_number = line_number;
+      exec_result = execute_arith_command (command->value.Arith);
+      line_number = save_line_number;
+
+      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)
+       {
+         last_command_exit_value = exec_result;
+         run_pending_traps ();
+         jump_to_top_level (ERREXIT);
+       }
+
+      break;
+#endif
+
+#if defined (COND_COMMAND)
+    case cm_cond:
+      was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
+      if (ignore_return)
+       command->value.Cond->flags |= CMD_IGNORE_RETURN;
+
+      line_number_for_err_trap = save_line_number = line_number;
+      exec_result = execute_cond_command (command->value.Cond);
+      line_number = save_line_number;
+
+      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)
+       {
+         last_command_exit_value = exec_result;
+         run_pending_traps ();
+         jump_to_top_level (ERREXIT);
+       }
+
+      break;
+#endif
+    
+    case cm_function_def:
+      exec_result = execute_intern_function (command->value.Function_def->name,
+                                            command->value.Function_def);
+      break;
+
+    default:
+      command_error ("execute_command", CMDERR_BADTYPE, command->type, 0);
+    }
+
+  if (my_undo_list)
+    {
+      do_redirections (my_undo_list, RX_ACTIVE);
+      dispose_redirects (my_undo_list);
+    }
+
+  if (exec_undo_list)
+    dispose_redirects (exec_undo_list);
+
+  if (my_undo_list || exec_undo_list)
+    discard_unwind_frame ("loop_redirections");
+
+#if defined (PROCESS_SUBSTITUTION)
+  if (saved_fifo)
+    {
+      nfifo = num_fifos ();
+      if (nfifo > ofifo)
+       close_new_fifos ((char *)ofifo_list, osize);
+      free ((void *)ofifo_list);
+    }
+#endif
+
+  /* Invert the return value if we have to */
+  if (invert)
+    exec_result = (exec_result == EXECUTION_SUCCESS)
+                   ? EXECUTION_FAILURE
+                   : EXECUTION_SUCCESS;
+
+#if defined (DPAREN_ARITHMETIC) || defined (COND_COMMAND)
+  /* This is where we set PIPESTATUS from the exit status of the appropriate
+     compound commands (the ones that look enough like simple commands to
+     cause confusion).  We might be able to optimize by not doing this if
+     subshell_environment != 0. */
+  switch (command->type)
+    {
+#  if defined (DPAREN_ARITHMETIC)
+    case cm_arith:
+#  endif
+#  if defined (COND_COMMAND)
+    case cm_cond:
+#  endif
+      set_pipestatus_from_exit (exec_result);
+      break;
+    }
+#endif
+
+  last_command_exit_value = exec_result;
+  run_pending_traps ();
+#if 0
+  if (running_trap == 0)
+#endif
+    currently_executing_command = (COMMAND *)NULL;
+
+  return (last_command_exit_value);
+}
+
+#if defined (COMMAND_TIMING)
+
+#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
+extern struct timeval *difftimeval __P((struct timeval *, struct timeval *, struct timeval *));
+extern struct timeval *addtimeval __P((struct timeval *, struct timeval *, struct timeval *));
+extern int timeval_to_cpu __P((struct timeval *, struct timeval *, struct timeval *));
+#endif
+
+#define POSIX_TIMEFORMAT "real %2R\nuser %2U\nsys %2S"
+#define BASH_TIMEFORMAT  "\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS"
+
+static const int precs[] = { 0, 100, 10, 1 };
+
+#if defined (HAVE_LOCALE_H) && defined (HAVE_LOCALECONV)
+static int
+decpoint ()
+{
+  struct lconv lv;
+
+  lv = localeconv ();
+  return (lv && lv->decimal_point && lv->decimal_point[0]) ? lv->decimal_point[0] : '.';
+}
+#else
+#  define decpoint() '.'
+#endif
+
+/* Expand one `%'-prefixed escape sequence from a time format string. */
+static int
+mkfmt (buf, prec, lng, sec, sec_fraction)
+     char *buf;
+     int prec, lng;
+     time_t sec;
+     int sec_fraction;
+{
+  time_t min;
+  char abuf[INT_STRLEN_BOUND(time_t) + 1];
+  int ind, aind;
+
+  ind = 0;
+  abuf[sizeof(abuf) - 1] = '\0';
+
+  /* If LNG is non-zero, we want to decompose SEC into minutes and seconds. */
+  if (lng)
+    {
+      min = sec / 60;
+      sec %= 60;
+      aind = sizeof(abuf) - 2;
+      do
+       abuf[aind--] = (min % 10) + '0';
+      while (min /= 10);
+      aind++;
+      while (abuf[aind])
+       buf[ind++] = abuf[aind++];
+      buf[ind++] = 'm';
+    }
+
+  /* Now add the seconds. */
+  aind = sizeof (abuf) - 2;
+  do
+    abuf[aind--] = (sec % 10) + '0';
+  while (sec /= 10);
+  aind++;
+  while (abuf[aind])
+    buf[ind++] = abuf[aind++];
+
+  /* We want to add a decimal point and PREC places after it if PREC is
+     nonzero.  PREC is not greater than 3.  SEC_FRACTION is between 0
+     and 999. */
+  if (prec != 0)
+    {
+      buf[ind++] = decpoint ();
+      for (aind = 1; aind <= prec; aind++)
+       {
+         buf[ind++] = (sec_fraction / precs[aind]) + '0';
+         sec_fraction %= precs[aind];
+       }
+    }
+
+  if (lng)
+    buf[ind++] = 's';
+  buf[ind] = '\0';
+
+  return (ind);
+}
+
+/* Interpret the format string FORMAT, interpolating the following escape
+   sequences:
+               %[prec][l][RUS]
+
+   where the optional `prec' is a precision, meaning the number of
+   characters after the decimal point, the optional `l' means to format
+   using minutes and seconds (MMmNN[.FF]s), like the `times' builtin',
+   and the last character is one of
+   
+               R       number of seconds of `real' time
+               U       number of seconds of `user' time
+               S       number of seconds of `system' time
+
+   An occurrence of `%%' in the format string is translated to a `%'.  The
+   result is printed to FP, a pointer to a FILE.  The other variables are
+   the seconds and thousandths of a second of real, user, and system time,
+   resectively. */
+static void
+print_formatted_time (fp, format, rs, rsf, us, usf, ss, ssf, cpu)
+     FILE *fp;
+     char *format;
+     time_t rs;
+     int rsf;
+     time_t us;
+     int usf;
+     time_t ss;
+     int ssf, cpu;
+{
+  int prec, lng, len;
+  char *str, *s, ts[INT_STRLEN_BOUND (time_t) + sizeof ("mSS.FFFF")];
+  time_t sum;
+  int sum_frac;
+  int sindex, ssize;
+
+  len = strlen (format);
+  ssize = (len + 64) - (len % 64);
+  str = (char *)xmalloc (ssize);
+  sindex = 0;
+
+  for (s = format; *s; s++)
+    {
+      if (*s != '%' || s[1] == '\0')
+       {
+         RESIZE_MALLOCED_BUFFER (str, sindex, 1, ssize, 64);
+         str[sindex++] = *s;
+       }
+      else if (s[1] == '%')
+       {
+         s++;
+         RESIZE_MALLOCED_BUFFER (str, sindex, 1, ssize, 64);
+         str[sindex++] = *s;
+       }
+      else if (s[1] == 'P')
+       {
+         s++;
+#if 0
+         /* clamp CPU usage at 100% */
+         if (cpu > 10000)
+           cpu = 10000;
+#endif
+         sum = cpu / 100;
+         sum_frac = (cpu % 100) * 10;
+         len = mkfmt (ts, 2, 0, sum, sum_frac);
+         RESIZE_MALLOCED_BUFFER (str, sindex, len, ssize, 64);
+         strcpy (str + sindex, ts);
+         sindex += len;
+       }
+      else
+       {
+         prec = 3;     /* default is three places past the decimal point. */
+         lng = 0;      /* default is to not use minutes or append `s' */
+         s++;
+         if (DIGIT (*s))               /* `precision' */
+           {
+             prec = *s++ - '0';
+             if (prec > 3) prec = 3;
+           }
+         if (*s == 'l')                /* `length extender' */
+           {
+             lng = 1;
+             s++;
+           }
+         if (*s == 'R' || *s == 'E')
+           len = mkfmt (ts, prec, lng, rs, rsf);
+         else if (*s == 'U')
+           len = mkfmt (ts, prec, lng, us, usf);
+         else if (*s == 'S')
+           len = mkfmt (ts, prec, lng, ss, ssf);
+         else
+           {
+             internal_error (_("TIMEFORMAT: `%c': invalid format character"), *s);
+             free (str);
+             return;
+           }
+         RESIZE_MALLOCED_BUFFER (str, sindex, len, ssize, 64);
+         strcpy (str + sindex, ts);
+         sindex += len;
+       }
+    }
+
+  str[sindex] = '\0';
+  fprintf (fp, "%s\n", str);
+  fflush (fp);
+
+  free (str);
+}
+
+static int
+time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
+     COMMAND *command;
+     int asynchronous, pipe_in, pipe_out;
+     struct fd_bitmap *fds_to_close;
+{
+  int rv, posix_time, old_flags, nullcmd;
+  time_t rs, us, ss;
+  int rsf, usf, ssf;
+  int cpu;
+  char *time_format;
+
+#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
+  struct timeval real, user, sys;
+  struct timeval before, after;
+#  if defined (HAVE_STRUCT_TIMEZONE)
+  struct timezone dtz;                         /* posix doesn't define this */
+#  endif
+  struct rusage selfb, selfa, kidsb, kidsa;    /* a = after, b = before */
+#else
+#  if defined (HAVE_TIMES)
+  clock_t tbefore, tafter, real, user, sys;
+  struct tms before, after;
+#  endif
+#endif
+
+#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
+#  if defined (HAVE_STRUCT_TIMEZONE)
+  gettimeofday (&before, &dtz);
+#  else
+  gettimeofday (&before, (void *)NULL);
+#  endif /* !HAVE_STRUCT_TIMEZONE */
+  getrusage (RUSAGE_SELF, &selfb);
+  getrusage (RUSAGE_CHILDREN, &kidsb);
+#else
+#  if defined (HAVE_TIMES)
+  tbefore = times (&before);
+#  endif
+#endif
+
+  posix_time = command && (command->flags & CMD_TIME_POSIX);
+
+  nullcmd = (command == 0) || (command->type == cm_simple && command->value.Simple->words == 0 && command->value.Simple->redirects == 0);
+  if (posixly_correct && nullcmd)
+    {
+#if defined (HAVE_GETRUSAGE)
+      selfb.ru_utime.tv_sec = kidsb.ru_utime.tv_sec = selfb.ru_stime.tv_sec = kidsb.ru_stime.tv_sec = 0;
+      selfb.ru_utime.tv_usec = kidsb.ru_utime.tv_usec = selfb.ru_stime.tv_usec = kidsb.ru_stime.tv_usec = 0;
+      before.tv_sec = shell_start_time;
+      before.tv_usec = 0;
+#else
+      before.tms_utime = before.tms_stime = before.tms_cutime = before.tms_cstime = 0;
+      tbefore = shell_start_time;
+#endif
+    }
+
+  old_flags = command->flags;
+  command->flags &= ~(CMD_TIME_PIPELINE|CMD_TIME_POSIX);
+  rv = execute_command_internal (command, asynchronous, pipe_in, pipe_out, fds_to_close);
+  command->flags = old_flags;
+
+  rs = us = ss = 0;
+  rsf = usf = ssf = cpu = 0;
+
+#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
+#  if defined (HAVE_STRUCT_TIMEZONE)
+  gettimeofday (&after, &dtz);
+#  else
+  gettimeofday (&after, (void *)NULL);
+#  endif /* !HAVE_STRUCT_TIMEZONE */
+  getrusage (RUSAGE_SELF, &selfa);
+  getrusage (RUSAGE_CHILDREN, &kidsa);
+
+  difftimeval (&real, &before, &after);
+  timeval_to_secs (&real, &rs, &rsf);
+
+  addtimeval (&user, difftimeval(&after, &selfb.ru_utime, &selfa.ru_utime),
+                    difftimeval(&before, &kidsb.ru_utime, &kidsa.ru_utime));
+  timeval_to_secs (&user, &us, &usf);
+
+  addtimeval (&sys, difftimeval(&after, &selfb.ru_stime, &selfa.ru_stime),
+                   difftimeval(&before, &kidsb.ru_stime, &kidsa.ru_stime));
+  timeval_to_secs (&sys, &ss, &ssf);
+
+  cpu = timeval_to_cpu (&real, &user, &sys);
+#else
+#  if defined (HAVE_TIMES)
+  tafter = times (&after);
+
+  real = tafter - tbefore;
+  clock_t_to_secs (real, &rs, &rsf);
+
+  user = (after.tms_utime - before.tms_utime) + (after.tms_cutime - before.tms_cutime);
+  clock_t_to_secs (user, &us, &usf);
+
+  sys = (after.tms_stime - before.tms_stime) + (after.tms_cstime - before.tms_cstime);
+  clock_t_to_secs (sys, &ss, &ssf);
+
+  cpu = (real == 0) ? 0 : ((user + sys) * 10000) / real;
+
+#  else
+  rs = us = ss = 0;
+  rsf = usf = ssf = cpu = 0;
+#  endif
+#endif
+
+  if (posix_time)
+    time_format = POSIX_TIMEFORMAT;
+  else if ((time_format = get_string_value ("TIMEFORMAT")) == 0)
+    {
+      if (posixly_correct && nullcmd)
+       time_format = "user\t%2lU\nsys\t%2lS";
+      else
+       time_format = BASH_TIMEFORMAT;
+    }
+  if (time_format && *time_format)
+    print_formatted_time (stderr, time_format, rs, rsf, us, usf, ss, ssf, cpu);
+
+  return rv;
+}
+#endif /* COMMAND_TIMING */
+
+/* Execute a command that's supposed to be in a subshell.  This must be
+   called after make_child and we must be running in the child process.
+   The caller will return or exit() immediately with the value this returns. */
+static int
+execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
+     COMMAND *command;
+     int asynchronous;
+     int pipe_in, pipe_out;
+     struct fd_bitmap *fds_to_close;
+{
+  int user_subshell, return_code, function_value, should_redir_stdin, invert;
+  int ois, user_coproc;
+  int result;
+  volatile COMMAND *tcom;
+
+  USE_VAR(user_subshell);
+  USE_VAR(user_coproc);
+  USE_VAR(invert);
+  USE_VAR(tcom);
+  USE_VAR(asynchronous);
+
+  subshell_level++;
+  should_redir_stdin = (asynchronous && (command->flags & CMD_STDIN_REDIR) &&
+                         pipe_in == NO_PIPE &&
+                         stdin_redirects (command->redirects) == 0);
+
+  invert = (command->flags & CMD_INVERT_RETURN) != 0;
+  user_subshell = command->type == cm_subshell || ((command->flags & CMD_WANT_SUBSHELL) != 0);
+  user_coproc = command->type == cm_coproc;
+
+  command->flags &= ~(CMD_FORCE_SUBSHELL | CMD_WANT_SUBSHELL | CMD_INVERT_RETURN);
+
+  /* If a command is asynchronous in a subshell (like ( foo ) & or
+     the special case of an asynchronous GROUP command where the
+     the subshell bit is turned on down in case cm_group: below),
+     turn off `asynchronous', so that two subshells aren't spawned.
+     XXX - asynchronous used to be set to 0 in this block, but that
+     means that setup_async_signals was never run.  Now it's set to
+     0 after subshell_environment is set appropriately and setup_async_signals
+     is run.
+
+     This seems semantically correct to me.  For example,
+     ( foo ) & seems to say ``do the command `foo' in a subshell
+     environment, but don't wait for that subshell to finish'',
+     and "{ foo ; bar ; } &" seems to me to be like functions or
+     builtins in the background, which executed in a subshell
+     environment.  I just don't see the need to fork two subshells. */
+
+  /* Don't fork again, we are already in a subshell.  A `doubly
+     async' shell is not interactive, however. */
+  if (asynchronous)
+    {
+#if defined (JOB_CONTROL)
+      /* If a construct like ( exec xxx yyy ) & is given while job
+        control is active, we want to prevent exec from putting the
+        subshell back into the original process group, carefully
+        undoing all the work we just did in make_child. */
+      original_pgrp = -1;
+#endif /* JOB_CONTROL */
+      ois = interactive_shell;
+      interactive_shell = 0;
+      /* This test is to prevent alias expansion by interactive shells that
+        run `(command) &' but to allow scripts that have enabled alias
+        expansion with `shopt -s expand_alias' to continue to expand
+        aliases. */
+      if (ois != interactive_shell)
+       expand_aliases = 0;
+    }
+
+  /* Subshells are neither login nor interactive. */
+  login_shell = interactive = 0;
+
+  if (user_subshell)
+    subshell_environment = SUBSHELL_PAREN;
+  else
+    {
+      subshell_environment = 0;                        /* XXX */
+      if (asynchronous)
+       subshell_environment |= SUBSHELL_ASYNC;
+      if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
+       subshell_environment |= SUBSHELL_PIPE;
+      if (user_coproc)
+       subshell_environment |= SUBSHELL_COPROC;
+    }
+
+  reset_terminating_signals ();                /* in sig.c */
+  /* Cancel traps, in trap.c. */
+  /* Reset the signal handlers in the child, but don't free the
+     trap strings.  Set a flag noting that we have to free the
+     trap strings if we run trap to change a signal disposition. */
+  reset_signal_handlers ();
+  subshell_environment |= SUBSHELL_RESETTRAP;
+
+  /* Make sure restore_original_signals doesn't undo the work done by
+     make_child to ensure that asynchronous children are immune to SIGINT
+     and SIGQUIT.  Turn off asynchronous to make sure more subshells are
+     not spawned. */
+  if (asynchronous)
+    {
+      setup_async_signals ();
+      asynchronous = 0;
+    }
+
+#if defined (JOB_CONTROL)
+  set_sigchld_handler ();
+#endif /* JOB_CONTROL */
+
+  set_sigint_handler ();
+
+#if defined (JOB_CONTROL)
+  /* Delete all traces that there were any jobs running.  This is
+     only for subshells. */
+  without_job_control ();
+#endif /* JOB_CONTROL */
+
+  if (fds_to_close)
+    close_fd_bitmap (fds_to_close);
+
+  do_piping (pipe_in, pipe_out);
+
+#if defined (COPROCESS_SUPPORT)
+  coproc_closeall ();
+#endif
+
+  /* If this is a user subshell, set a flag if stdin was redirected.
+     This is used later to decide whether to redirect fd 0 to
+     /dev/null for async commands in the subshell.  This adds more
+     sh compatibility, but I'm not sure it's the right thing to do. */
+  if (user_subshell)
+    {
+      stdin_redir = stdin_redirects (command->redirects);
+      restore_default_signal (EXIT_TRAP);
+    }
+
+  /* If this is an asynchronous command (command &), we want to
+     redirect the standard input from /dev/null in the absence of
+     any specific redirection involving stdin. */
+  if (should_redir_stdin && stdin_redir == 0)
+    async_redirect_stdin ();
+
+  /* Do redirections, then dispose of them before recursive call. */
+  if (command->redirects)
+    {
+      if (do_redirections (command->redirects, RX_ACTIVE) != 0)
+       exit (invert ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
+
+      dispose_redirects (command->redirects);
+      command->redirects = (REDIRECT *)NULL;
+    }
+
+  if (command->type == cm_subshell)
+    tcom = command->value.Subshell->command;
+  else if (user_coproc)
+    tcom = command->value.Coproc->command;
+  else
+    tcom = command;
+
+  if (command->flags & CMD_TIME_PIPELINE)
+    tcom->flags |= CMD_TIME_PIPELINE;
+  if (command->flags & CMD_TIME_POSIX)
+    tcom->flags |= CMD_TIME_POSIX;
+  
+  /* Make sure the subshell inherits any CMD_IGNORE_RETURN flag. */
+  if ((command->flags & CMD_IGNORE_RETURN) && tcom != command)
+    tcom->flags |= CMD_IGNORE_RETURN;
+
+  /* If this is a simple command, tell execute_disk_command that it
+     might be able to get away without forking and simply exec.
+     This means things like ( sleep 10 ) will only cause one fork.
+     If we're timing the command or inverting its return value, however,
+     we cannot do this optimization. */
+  if ((user_subshell || user_coproc) && (tcom->type == cm_simple || tcom->type == cm_subshell) &&
+      ((tcom->flags & CMD_TIME_PIPELINE) == 0) &&
+      ((tcom->flags & CMD_INVERT_RETURN) == 0))
+    {
+      tcom->flags |= CMD_NO_FORK;
+      if (tcom->type == cm_simple)
+       tcom->value.Simple->flags |= CMD_NO_FORK;
+    }
+
+  invert = (tcom->flags & CMD_INVERT_RETURN) != 0;
+  tcom->flags &= ~CMD_INVERT_RETURN;
+
+  result = setjmp_nosigs (top_level);
+
+  /* If we're inside a function while executing this subshell, we
+     need to handle a possible `return'. */
+  function_value = 0;
+  if (return_catch_flag)
+    function_value = setjmp_nosigs (return_catch);
+
+  /* If we're going to exit the shell, we don't want to invert the return
+     status. */
+  if (result == EXITPROG)
+    invert = 0, return_code = last_command_exit_value;
+  else if (result)
+    return_code = (last_command_exit_value == EXECUTION_SUCCESS) ? EXECUTION_FAILURE : last_command_exit_value;
+  else if (function_value)
+    return_code = return_catch_value;
+  else
+    return_code = execute_command_internal ((COMMAND *)tcom, asynchronous, NO_PIPE, NO_PIPE, fds_to_close);
+
+  /* If we are asked to, invert the return value. */
+  if (invert)
+    return_code = (return_code == EXECUTION_SUCCESS) ? EXECUTION_FAILURE
+                                                    : EXECUTION_SUCCESS;
+
+  /* If we were explicitly placed in a subshell with (), we need
+     to do the `shell cleanup' things, such as running traps[0]. */
+  if (user_subshell && signal_is_trapped (0))
+    {
+      last_command_exit_value = return_code;
+      return_code = run_exit_trap ();
+    }
+
+  subshell_level--;
+  return (return_code);
+  /* NOTREACHED */
+}
+
+#if defined (COPROCESS_SUPPORT)
+#define COPROC_MAX     16
+
+typedef struct cpelement
+  {
+    struct cpelement *next;
+    struct coproc *coproc;
+  }
+cpelement_t;
+    
+typedef struct cplist
+  {
+    struct cpelement *head;
+    struct cpelement *tail;
+    int ncoproc;
+    int lock;
+  }
+cplist_t;
+
+static struct cpelement *cpe_alloc __P((struct coproc *));
+static void cpe_dispose __P((struct cpelement *));
+static struct cpelement *cpl_add __P((struct coproc *));
+static struct cpelement *cpl_delete __P((pid_t));
+static void cpl_reap __P((void));
+static void cpl_flush __P((void));
+static void cpl_closeall __P((void));
+static struct cpelement *cpl_search __P((pid_t));
+static struct cpelement *cpl_searchbyname __P((const char *));
+static void cpl_prune __P((void));
+
+static void coproc_free __P((struct coproc *));
+
+/* Will go away when there is fully-implemented support for multiple coprocs. */
+Coproc sh_coproc = { 0, NO_PID, -1, -1, 0, 0, 0, 0, 0 };
+
+cplist_t coproc_list = {0, 0, 0};
+
+/* Functions to manage the list of coprocs */
+
+static struct cpelement *
+cpe_alloc (cp)
+     Coproc *cp;
+{
+  struct cpelement *cpe;
+
+  cpe = (struct cpelement *)xmalloc (sizeof (struct cpelement));
+  cpe->coproc = cp;
+  cpe->next = (struct cpelement *)0;
+  return cpe;
+}
+
+static void
+cpe_dispose (cpe)
+      struct cpelement *cpe;
+{
+  free (cpe);
+}
+
+static struct cpelement *
+cpl_add (cp)
+     Coproc *cp;
+{
+  struct cpelement *cpe;
+
+  cpe = cpe_alloc (cp);
+
+  if (coproc_list.head == 0)
+    {
+      coproc_list.head = coproc_list.tail = cpe;
+      coproc_list.ncoproc = 0;                 /* just to make sure */
+    }
+  else
+    {
+      coproc_list.tail->next = cpe;
+      coproc_list.tail = cpe;
+    }
+  coproc_list.ncoproc++;
+
+  return cpe;
+}
+
+static struct cpelement *
+cpl_delete (pid)
+     pid_t pid;
+{
+  struct cpelement *prev, *p;
+
+  for (prev = p = coproc_list.head; p; prev = p, p = p->next)
+    if (p->coproc->c_pid == pid)
+      {
+        prev->next = p->next;  /* remove from list */
+        break;
+      }
+
+  if (p == 0)
+    return 0;          /* not found */
+
+#if defined (DEBUG)
+  itrace("cpl_delete: deleting %d", pid);
+#endif
+
+  /* Housekeeping in the border cases. */
+  if (p == coproc_list.head)
+    coproc_list.head = coproc_list.head->next;
+  else if (p == coproc_list.tail)
+    coproc_list.tail = prev;
+
+  coproc_list.ncoproc--;
+  if (coproc_list.ncoproc == 0)
+    coproc_list.head = coproc_list.tail = 0;
+  else if (coproc_list.ncoproc == 1)
+    coproc_list.tail = coproc_list.head;               /* just to make sure */
+
+  return (p);
+}
+
+static void
+cpl_reap ()
+{
+  struct cpelement *p, *next, *nh, *nt;
+
+  /* Build a new list by removing dead coprocs and fix up the coproc_list
+     pointers when done. */
+  nh = nt = next = (struct cpelement *)0;
+  for (p = coproc_list.head; p; p = next)
+    {
+      next = p->next;
+      if (p->coproc->c_flags & COPROC_DEAD)
+       {
+         coproc_list.ncoproc--;        /* keep running count, fix up pointers later */
+
+#if defined (DEBUG)
+         itrace("cpl_reap: deleting %d", p->coproc->c_pid);
+#endif
+
+         coproc_dispose (p->coproc);
+         cpe_dispose (p);
+       }
+      else if (nh == 0)
+       nh = nt = p;
+      else
+       {
+         nt->next = p;
+         nt = nt->next;
+       }
+    }
+
+  if (coproc_list.ncoproc == 0)
+    coproc_list.head = coproc_list.tail = 0;
+  else
+    {
+      if (nt)
+        nt->next = 0;
+      coproc_list.head = nh;
+      coproc_list.tail = nt;
+      if (coproc_list.ncoproc == 1)
+       coproc_list.tail = coproc_list.head;            /* just to make sure */  
+    }
+}
+
+/* Clear out the list of saved statuses */
+static void
+cpl_flush ()
+{
+  struct cpelement *cpe, *p;
+
+  for (cpe = coproc_list.head; cpe; )
+    {
+      p = cpe;
+      cpe = cpe->next;
+
+      coproc_dispose (p->coproc);
+      cpe_dispose (p);
+    }
+
+  coproc_list.head = coproc_list.tail = 0;
+  coproc_list.ncoproc = 0;
+}
+
+static void
+cpl_closeall ()
+{
+  struct cpelement *cpe;
+
+  for (cpe = coproc_list.head; cpe; cpe = cpe->next)
+    coproc_close (cpe->coproc);
+}
+
+static void
+cpl_fdchk (fd)
+     int fd;
+{
+  struct cpelement *cpe;
+
+  for (cpe = coproc_list.head; cpe; cpe = cpe->next)
+    coproc_checkfd (cpe->coproc, fd);
+}
+
+/* Search for PID in the list of coprocs; return the cpelement struct if
+   found.  If not found, return NULL. */
+static struct cpelement *
+cpl_search (pid)
+     pid_t pid;
+{
+  struct cpelement *cpe;
+
+  for (cpe = coproc_list.head ; cpe; cpe = cpe->next)
+    if (cpe->coproc->c_pid == pid)
+      return cpe;
+  return (struct cpelement *)NULL;
+}
+
+/* Search for the coproc named NAME in the list of coprocs; return the
+   cpelement struct if found.  If not found, return NULL. */
+static struct cpelement *
+cpl_searchbyname (name)
+     const char *name;
+{
+  struct cpelement *cp;
+
+  for (cp = coproc_list.head ; cp; cp = cp->next)
+    if (STREQ (cp->coproc->c_name, name))
+      return cp;
+  return (struct cpelement *)NULL;
+}
+
+#if 0
+static void
+cpl_prune ()
+{
+  struct cpelement *cp;
+
+  while (coproc_list.head && coproc_list.ncoproc > COPROC_MAX)
+    {
+      cp = coproc_list.head;
+      coproc_list.head = coproc_list.head->next;
+      coproc_dispose (cp->coproc);
+      cpe_dispose (cp);
+      coproc_list.ncoproc--;
+    }
+}
+#endif
+
+/* These currently use a single global "shell coproc" but are written in a
+   way to not preclude additional coprocs later (using the list management
+   package above). */
+
+struct coproc *
+getcoprocbypid (pid)
+     pid_t pid;
+{
+#if MULTIPLE_COPROCS
+  struct cpelement *p;
+
+  p = cpl_search (pid);
+  return (p ? p->coproc : 0);
+#else
+  return (pid == sh_coproc.c_pid ? &sh_coproc : 0);
+#endif
+}
+
+struct coproc *
+getcoprocbyname (name)
+     const char *name;
+{
+#if MULTIPLE_COPROCS
+  struct cpelement *p;
+
+  p = cpl_searchbyname (name);
+  return (p ? p->coproc : 0);
+#else
+  return ((sh_coproc.c_name && STREQ (sh_coproc.c_name, name)) ? &sh_coproc : 0);
+#endif
+}
+
+void
+coproc_init (cp)
+     struct coproc *cp;
+{
+  cp->c_name = 0;
+  cp->c_pid = NO_PID;
+  cp->c_rfd = cp->c_wfd = -1;
+  cp->c_rsave = cp->c_wsave = -1;
+  cp->c_flags = cp->c_status = cp->c_lock = 0;
+}
+
+struct coproc *
+coproc_alloc (name, pid)
+     char *name;
+     pid_t pid;
+{
+  struct coproc *cp;
+
+#if MULTIPLE_COPROCS
+  cp = (struct coproc *)xmalloc (sizeof (struct coproc));
+#else
+  cp = &sh_coproc;
+#endif
+  coproc_init (cp);
+  cp->c_lock = 2;
+
+  cp->c_pid = pid;
+  cp->c_name = savestring (name);
+#if MULTIPLE_COPROCS
+  cpl_add (cp);
+#endif
+  cp->c_lock = 0;
+  return (cp);
+}
+
+static void
+coproc_free (cp)
+     struct coproc *cp;
+{
+  free (cp);
+}
+
+void
+coproc_dispose (cp)
+     struct coproc *cp;
+{
+  sigset_t set, oset;
+
+  if (cp == 0)
+    return;
+
+  BLOCK_SIGNAL (SIGCHLD, set, oset);
+  cp->c_lock = 3;
+  coproc_unsetvars (cp);
+  FREE (cp->c_name);
+  coproc_close (cp);
+#if MULTIPLE_COPROCS
+  coproc_free (cp);
+#else
+  coproc_init (cp);
+  cp->c_lock = 0;
+#endif
+  UNBLOCK_SIGNAL (oset);
+}
+
+/* Placeholder for now.  Will require changes for multiple coprocs */
+void
+coproc_flush ()
+{
+#if MULTIPLE_COPROCS
+  cpl_flush ();
+#else
+  coproc_dispose (&sh_coproc);
+#endif
+}
+
+void
+coproc_close (cp)
+     struct coproc *cp;
+{
+  if (cp->c_rfd >= 0)
+    {
+      close (cp->c_rfd);
+      cp->c_rfd = -1;
+    }
+  if (cp->c_wfd >= 0)
+    {
+      close (cp->c_wfd);
+      cp->c_wfd = -1;
+    }
+  cp->c_rsave = cp->c_wsave = -1;
+}
+
+void
+coproc_closeall ()
+{
+#if MULTIPLE_COPROCS
+  cpl_closeall ();
+#else
+  coproc_close (&sh_coproc);   /* XXX - will require changes for multiple coprocs */
+#endif
+}
+
+void
+coproc_reap ()
+{
+#if MULTIPLE_COPROCS
+  cpl_reap ();
+#else
+  struct coproc *cp;
+
+  cp = &sh_coproc;             /* XXX - will require changes for multiple coprocs */
+  if (cp && (cp->c_flags & COPROC_DEAD))
+    coproc_dispose (cp);
+#endif
+}
+
+void
+coproc_rclose (cp, fd)
+     struct coproc *cp;
+     int fd;
+{
+  if (cp->c_rfd >= 0 && cp->c_rfd == fd)
+    {
+      close (cp->c_rfd);
+      cp->c_rfd = -1;
+    }
+}
+
+void
+coproc_wclose (cp, fd)
+     struct coproc *cp;
+     int fd;
+{
+  if (cp->c_wfd >= 0 && cp->c_wfd == fd)
+    {
+      close (cp->c_wfd);
+      cp->c_wfd = -1;
+    }
+}
+
+void
+coproc_checkfd (cp, fd)
+     struct coproc *cp;
+     int fd;
+{
+  int update;
+
+  update = 0;
+  if (cp->c_rfd >= 0 && cp->c_rfd == fd)
+    update = cp->c_rfd = -1;
+  if (cp->c_wfd >= 0 && cp->c_wfd == fd)
+    update = cp->c_wfd = -1;
+  if (update)
+    coproc_setvars (cp);
+}
+
+void
+coproc_fdchk (fd)
+     int fd;
+{
+#if MULTIPLE_COPROCS
+  cpl_fdchk (fd);
+#else
+  coproc_checkfd (&sh_coproc, fd);
+#endif
+}
+
+void
+coproc_fdclose (cp, fd)
+     struct coproc *cp;
+     int fd;
+{
+  coproc_rclose (cp, fd);
+  coproc_wclose (cp, fd);
+  coproc_setvars (cp);
+}
+
+void
+coproc_fdsave (cp)
+     struct coproc *cp;
+{
+  cp->c_rsave = cp->c_rfd;
+  cp->c_wsave = cp->c_wfd;
+}
+
+void
+coproc_fdrestore (cp)
+     struct coproc *cp;
+{
+  cp->c_rfd = cp->c_rsave;
+  cp->c_wfd = cp->c_wsave;
+}
+
+void
+coproc_pidchk (pid, status)
+     pid_t pid;
+{
+  struct coproc *cp;
+
+#if MULTIPLE_COPROCS
+  struct cpelement *cpe;
+
+  cpe = cpl_delete (pid);
+  cp = cpe ? cpe->coproc : 0;
+#else
+  cp = getcoprocbypid (pid);
+#endif
+  if (cp)
+    {
+      cp->c_lock = 4;
+      cp->c_status = status;
+      cp->c_flags |= COPROC_DEAD;
+      cp->c_flags &= ~COPROC_RUNNING;
+      /* Don't dispose the coproc or unset the COPROC_XXX variables because
+        this is executed in a signal handler context.  Wait until coproc_reap
+        takes care of it. */
+      cp->c_lock = 0;
+    }
+}
+
+void
+coproc_setvars (cp)
+     struct coproc *cp;
+{
+  SHELL_VAR *v;
+  char *namevar, *t;
+  int l;
+#if defined (ARRAY_VARS)
+  arrayind_t ind;
+#endif
+
+  if (cp->c_name == 0)
+    return;
+
+  l = strlen (cp->c_name);
+  namevar = xmalloc (l + 16);
+
+#if defined (ARRAY_VARS)
+  v = find_variable (cp->c_name);
+  if (v == 0)
+    v = make_new_array_variable (cp->c_name);
+  if (array_p (v) == 0)
+    v = convert_var_to_array (v);
+
+  t = itos (cp->c_rfd);
+  ind = 0;
+  v = bind_array_variable (cp->c_name, ind, t, 0);
+  free (t);
+
+  t = itos (cp->c_wfd);
+  ind = 1;
+  bind_array_variable (cp->c_name, ind, t, 0);
+  free (t);
+#else
+  sprintf (namevar, "%s_READ", cp->c_name);
+  t = itos (cp->c_rfd);
+  bind_variable (namevar, t, 0);
+  free (t);
+  sprintf (namevar, "%s_WRITE", cp->c_name);
+  t = itos (cp->c_wfd);
+  bind_variable (namevar, t, 0);
+  free (t);
+#endif
+
+  sprintf (namevar, "%s_PID", cp->c_name);
+  t = itos (cp->c_pid);
+  bind_variable (namevar, t, 0);
+  free (t);
+
+  free (namevar);
+}
+
+void
+coproc_unsetvars (cp)
+     struct coproc *cp;
+{
+  int l;
+  char *namevar;
+
+  if (cp->c_name == 0)
+    return;
+
+  l = strlen (cp->c_name);
+  namevar = xmalloc (l + 16);
+
+  sprintf (namevar, "%s_PID", cp->c_name);
+  unbind_variable (namevar);  
+
+#if defined (ARRAY_VARS)
+  unbind_variable (cp->c_name);
+#else
+  sprintf (namevar, "%s_READ", cp->c_name);
+  unbind_variable (namevar);
+  sprintf (namevar, "%s_WRITE", cp->c_name);
+  unbind_variable (namevar);
+#endif  
+
+  free (namevar);
+}
+
+static int
+execute_coproc (command, pipe_in, pipe_out, fds_to_close)
+     COMMAND *command;
+     int pipe_in, pipe_out;
+     struct fd_bitmap *fds_to_close;
+{
+  int rpipe[2], wpipe[2], estat, invert;
+  pid_t coproc_pid;
+  Coproc *cp;
+  char *tcmd;
+  sigset_t set, oset;
+
+  /* XXX -- can be removed after changes to handle multiple coprocs */
+#if !MULTIPLE_COPROCS
+  if (sh_coproc.c_pid != NO_PID)
+    internal_warning ("execute_coproc: coproc [%d:%s] still exists", sh_coproc.c_pid, sh_coproc.c_name);
+  coproc_init (&sh_coproc);
+#endif
+
+  invert = (command->flags & CMD_INVERT_RETURN) != 0;
+  command_string_index = 0;
+  tcmd = make_command_string (command);
+
+  sh_openpipe ((int *)&rpipe); /* 0 = parent read, 1 = child write */
+  sh_openpipe ((int *)&wpipe); /* 0 = child read, 1 = parent write */
+
+  BLOCK_SIGNAL (SIGCHLD, set, oset);
+
+  coproc_pid = make_child (savestring (tcmd), 1);
+
+  if (coproc_pid == 0)
+    {
+      close (rpipe[0]);
+      close (wpipe[1]);
+
+      UNBLOCK_SIGNAL (oset);
+      estat = execute_in_subshell (command, 1, wpipe[0], rpipe[1], fds_to_close);
+
+      fflush (stdout);
+      fflush (stderr);
+
+      exit (estat);
+    }
+
+  close (rpipe[1]);
+  close (wpipe[0]);
+
+  /* XXX - possibly run Coproc->name through word expansion? */
+  cp = coproc_alloc (command->value.Coproc->name, coproc_pid);
+  cp->c_rfd = rpipe[0];
+  cp->c_wfd = wpipe[1];
+
+  SET_CLOSE_ON_EXEC (cp->c_rfd);
+  SET_CLOSE_ON_EXEC (cp->c_wfd);
+
+  coproc_setvars (cp);
+
+  UNBLOCK_SIGNAL (oset);
+
+#if 0
+  itrace ("execute_coproc: [%d] %s", coproc_pid, the_printed_command);
+#endif
+
+  close_pipes (pipe_in, pipe_out);
+#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
+  unlink_fifo_list ();
+#endif
+  stop_pipeline (1, (COMMAND *)NULL);
+  DESCRIBE_PID (coproc_pid);
+  run_pending_traps ();
+
+  return (invert ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
+}
+#endif
+
+static void
+restore_stdin (s)
+     int s;
+{
+  dup2 (s, 0);
+  close (s);
+}
+
+/* Catch-all cleanup function for lastpipe code for unwind-protects */
+static void
+lastpipe_cleanup (s)
+     int s;
+{
+  unfreeze_jobs_list ();
+}
+
+static int
+execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close)
+     COMMAND *command;
+     int asynchronous, pipe_in, pipe_out;
+     struct fd_bitmap *fds_to_close;
+{
+  int prev, fildes[2], new_bitmap_size, dummyfd, ignore_return, exec_result;
+  int lstdin, lastpipe_flag, lastpipe_jid;
+  COMMAND *cmd;
+  struct fd_bitmap *fd_bitmap;
+  pid_t lastpid;
+
+#if defined (JOB_CONTROL)
+  sigset_t set, oset;
+  BLOCK_CHILD (set, oset);
+#endif /* JOB_CONTROL */
+
+  ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
+
+  prev = pipe_in;
+  cmd = command;
+
+  while (cmd && cmd->type == cm_connection &&
+        cmd->value.Connection && cmd->value.Connection->connector == '|')
+    {
+      /* Make a pipeline between the two commands. */
+      if (pipe (fildes) < 0)
+       {
+         sys_error (_("pipe error"));
+#if defined (JOB_CONTROL)
+         terminate_current_pipeline ();
+         kill_current_pipeline ();
+         UNBLOCK_CHILD (oset);
+#endif /* JOB_CONTROL */
+         last_command_exit_value = EXECUTION_FAILURE;
+         /* The unwind-protects installed below will take care
+            of closing all of the open file descriptors. */
+         throw_to_top_level ();
+         return (EXECUTION_FAILURE);   /* XXX */
+       }
+
+      /* Here is a problem: with the new file close-on-exec
+        code, the read end of the pipe (fildes[0]) stays open
+        in the first process, so that process will never get a
+        SIGPIPE.  There is no way to signal the first process
+        that it should close fildes[0] after forking, so it
+        remains open.  No SIGPIPE is ever sent because there
+        is still a file descriptor open for reading connected
+        to the pipe.  We take care of that here.  This passes
+        around a bitmap of file descriptors that must be
+        closed after making a child process in execute_simple_command. */
+
+      /* We need fd_bitmap to be at least as big as fildes[0].
+        If fildes[0] is less than fds_to_close->size, then
+        use fds_to_close->size. */
+      new_bitmap_size = (fildes[0] < fds_to_close->size)
+                               ? fds_to_close->size
+                               : fildes[0] + 8;
+
+      fd_bitmap = new_fd_bitmap (new_bitmap_size);
+
+      /* Now copy the old information into the new bitmap. */
+      xbcopy ((char *)fds_to_close->bitmap, (char *)fd_bitmap->bitmap, fds_to_close->size);
+
+      /* And mark the pipe file descriptors to be closed. */
+      fd_bitmap->bitmap[fildes[0]] = 1;
+
+      /* In case there are pipe or out-of-processes errors, we
+        want all these file descriptors to be closed when
+        unwind-protects are run, and the storage used for the
+        bitmaps freed up. */
+      begin_unwind_frame ("pipe-file-descriptors");
+      add_unwind_protect (dispose_fd_bitmap, fd_bitmap);
+      add_unwind_protect (close_fd_bitmap, fd_bitmap);
+      if (prev >= 0)
+       add_unwind_protect (close, prev);
+      dummyfd = fildes[1];
+      add_unwind_protect (close, dummyfd);
+
+#if defined (JOB_CONTROL)
+      add_unwind_protect (restore_signal_mask, &oset);
+#endif /* JOB_CONTROL */
+
+      if (ignore_return && cmd->value.Connection->first)
+       cmd->value.Connection->first->flags |= CMD_IGNORE_RETURN;
+      execute_command_internal (cmd->value.Connection->first, asynchronous,
+                               prev, fildes[1], fd_bitmap);
+
+      if (prev >= 0)
+       close (prev);
+
+      prev = fildes[0];
+      close (fildes[1]);
+
+      dispose_fd_bitmap (fd_bitmap);
+      discard_unwind_frame ("pipe-file-descriptors");
+
+      cmd = cmd->value.Connection->second;
+    }
+
+  lastpid = last_made_pid;
+
+  /* Now execute the rightmost command in the pipeline.  */
+  if (ignore_return && cmd)
+    cmd->flags |= CMD_IGNORE_RETURN;
+
+  lastpipe_flag = 0;
+
+  begin_unwind_frame ("lastpipe-exec");
+  lstdin = -1;
+  /* If the `lastpipe' option is set with shopt, and job control is not
+     enabled, execute the last element of non-async pipelines in the
+     current shell environment. */
+  if (lastpipe_opt && job_control == 0 && asynchronous == 0 && pipe_out == NO_PIPE && prev > 0)
+    {
+      lstdin = move_to_high_fd (0, 1, -1);
+      if (lstdin > 0)
+       {
+         do_piping (prev, pipe_out);
+         prev = NO_PIPE;
+         add_unwind_protect (restore_stdin, lstdin);
+         lastpipe_flag = 1;
+         freeze_jobs_list ();
+         lastpipe_jid = stop_pipeline (0, (COMMAND *)NULL);    /* XXX */
+         add_unwind_protect (lastpipe_cleanup, lastpipe_jid);
+       }
+      if (cmd)
+       cmd->flags |= CMD_LASTPIPE;
+    }    
+  if (prev >= 0)
+    add_unwind_protect (close, prev);
+
+  exec_result = execute_command_internal (cmd, asynchronous, prev, pipe_out, fds_to_close);
+
+  if (lstdin > 0)
+    restore_stdin (lstdin);
+
+  if (prev >= 0)
+    close (prev);
+
+#if defined (JOB_CONTROL)
+  UNBLOCK_CHILD (oset);
+#endif
+
+  QUIT;
+
+  if (lastpipe_flag)
+    {
+#if defined (JOB_CONTROL)
+      append_process (savestring (the_printed_command), dollar_dollar_pid, exec_result, lastpipe_jid);
+#endif
+      lstdin = wait_for (lastpid);
+#if defined (JOB_CONTROL)
+      exec_result = job_exit_status (lastpipe_jid);
+#endif
+      unfreeze_jobs_list ();
+    }
+
+  discard_unwind_frame ("lastpipe-exec");
+
+  return (exec_result);
+}
+
+static int
+execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close)
+     COMMAND *command;
+     int asynchronous, pipe_in, pipe_out;
+     struct fd_bitmap *fds_to_close;
+{
+  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;
+
+  switch (command->value.Connection->connector)
+    {
+    /* Do the first command asynchronously. */
+    case '&':
+      tc = command->value.Connection->first;
+      if (tc == 0)
+       return (EXECUTION_SUCCESS);
+
+      if (ignore_return)
+       tc->flags |= CMD_IGNORE_RETURN;
+      tc->flags |= CMD_AMPERSAND;
+
+      /* If this shell was compiled without job control support,
+        if we are currently in a subshell via `( xxx )', or if job
+        control is not active then the standard input for an
+        asynchronous command is forced to /dev/null. */
+#if defined (JOB_CONTROL)
+      if ((subshell_environment || !job_control) && !stdin_redir)
+#else
+      if (!stdin_redir)
+#endif /* JOB_CONTROL */
+       tc->flags |= CMD_STDIN_REDIR;
+
+      exec_result = execute_command_internal (tc, 1, pipe_in, pipe_out, fds_to_close);
+      QUIT;
+
+      if (tc->flags & CMD_STDIN_REDIR)
+       tc->flags &= ~CMD_STDIN_REDIR;
+
+      second = command->value.Connection->second;
+      if (second)
+       {
+         if (ignore_return)
+           second->flags |= CMD_IGNORE_RETURN;
+
+         exec_result = execute_command_internal (second, asynchronous, pipe_in, pipe_out, fds_to_close);
+       }
+
+      break;
+
+    /* Just call execute command on both sides. */
+    case ';':
+      if (ignore_return)
+       {
+         if (command->value.Connection->first)
+           command->value.Connection->first->flags |= CMD_IGNORE_RETURN;
+         if (command->value.Connection->second)
+           command->value.Connection->second->flags |= CMD_IGNORE_RETURN;
+       }
+      executing_list++;
+      QUIT;
+      execute_command (command->value.Connection->first);
+      QUIT;
+      exec_result = execute_command_internal (command->value.Connection->second,
+                                     asynchronous, pipe_in, pipe_out,
+                                     fds_to_close);
+      executing_list--;
+      break;
+
+    case '|':
+      was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
+      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)
+       {
+         last_command_exit_value = exec_result;
+         run_pending_traps ();
+         jump_to_top_level (ERREXIT);
+       }
+
+      break;
+
+    case AND_AND:
+    case OR_OR:
+      if (asynchronous)
+       {
+         /* If we have something like `a && b &' or `a || b &', run the
+            && or || stuff in a subshell.  Force a subshell and just call
+            execute_command_internal again.  Leave asynchronous on
+            so that we get a report from the parent shell about the
+            background job. */
+         command->flags |= CMD_FORCE_SUBSHELL;
+         exec_result = execute_command_internal (command, 1, pipe_in, pipe_out, fds_to_close);
+         break;
+       }
+
+      /* Execute the first command.  If the result of that is successful
+        and the connector is AND_AND, or the result is not successful
+        and the connector is OR_OR, then execute the second command,
+        otherwise return. */
+
+      executing_list++;
+      if (command->value.Connection->first)
+       command->value.Connection->first->flags |= CMD_IGNORE_RETURN;
+
+      exec_result = execute_command (command->value.Connection->first);
+      QUIT;
+      if (((command->value.Connection->connector == AND_AND) &&
+          (exec_result == EXECUTION_SUCCESS)) ||
+         ((command->value.Connection->connector == OR_OR) &&
+          (exec_result != EXECUTION_SUCCESS)))
+       {
+         if (ignore_return && command->value.Connection->second)
+           command->value.Connection->second->flags |= CMD_IGNORE_RETURN;
+
+         exec_result = execute_command (command->value.Connection->second);
+       }
+      executing_list--;
+      break;
+
+    default:
+      command_error ("execute_connection", CMDERR_BADCONN, command->value.Connection->connector, 0);
+      jump_to_top_level (DISCARD);
+      exec_result = EXECUTION_FAILURE;
+    }
+
+  return exec_result;
+}
+
+#define REAP() \
+  do \
+    { \
+      if (!interactive_shell) \
+       reap_dead_jobs (); \
+    } \
+  while (0)
+
+/* Execute a FOR command.  The syntax is: FOR word_desc IN word_list;
+   DO command; DONE */
+static int
+execute_for_command (for_command)
+     FOR_COM *for_command;
+{
+  register WORD_LIST *releaser, *list;
+  SHELL_VAR *v;
+  char *identifier;
+  int retval, save_line_number;
+#if 0
+  SHELL_VAR *old_value = (SHELL_VAR *)NULL; /* Remember the old value of x. */
+#endif
+
+  save_line_number = line_number;
+  if (check_identifier (for_command->name, 1) == 0)
+    {
+      if (posixly_correct && interactive_shell == 0)
+       {
+         last_command_exit_value = EX_BADUSAGE;
+         jump_to_top_level (ERREXIT);
+       }
+      return (EXECUTION_FAILURE);
+    }
+
+  loop_level++;
+  identifier = for_command->name->word;
+
+  line_number = for_command->line;     /* for expansion error messages */
+  list = releaser = expand_words_no_vars (for_command->map_list);
+
+  begin_unwind_frame ("for");
+  add_unwind_protect (dispose_words, releaser);
+
+#if 0
+  if (lexical_scoping)
+    {
+      old_value = copy_variable (find_variable (identifier));
+      if (old_value)
+       add_unwind_protect (dispose_variable, old_value);
+    }
+#endif
+
+  if (for_command->flags & CMD_IGNORE_RETURN)
+    for_command->action->flags |= CMD_IGNORE_RETURN;
+
+  for (retval = EXECUTION_SUCCESS; list; list = list->next)
+    {
+      QUIT;
+
+      line_number = for_command->line;
+
+      /* Remember what this command looks like, for debugger. */
+      command_string_index = 0;
+      print_for_command_head (for_command);
+
+      if (echo_command_at_execute)
+       xtrace_print_for_command_head (for_command);
+
+      /* Save this command unless it's a trap command and we're not running
+        a debug trap. */
+      if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
+       {
+         FREE (the_printed_command_except_trap);
+         the_printed_command_except_trap = savestring (the_printed_command);
+       }
+
+      retval = run_debug_trap ();
+#if defined (DEBUGGER)
+      /* In debugging mode, if the DEBUG trap returns a non-zero status, we
+        skip the command. */
+      if (debugging_mode && retval != EXECUTION_SUCCESS)
+        continue;
+#endif
+
+      this_command_name = (char *)NULL;
+      /* XXX - special ksh93 for command index variable handling */
+      v = find_variable_last_nameref (identifier);
+      if (v && nameref_p (v))
+        {
+          v = bind_variable_value (v, list->word->word, 0);
+        }
+      else
+        v = bind_variable (identifier, list->word->word, 0);
+      if (readonly_p (v) || noassign_p (v))
+       {
+         line_number = save_line_number;
+         if (readonly_p (v) && interactive_shell == 0 && posixly_correct)
+           {
+             last_command_exit_value = EXECUTION_FAILURE;
+             jump_to_top_level (FORCE_EOF);
+           }
+         else
+           {
+             dispose_words (releaser);
+             discard_unwind_frame ("for");
+             loop_level--;
+             return (EXECUTION_FAILURE);
+           }
+       }
+      retval = execute_command (for_command->action);
+      REAP ();
+      QUIT;
+
+      if (breaking)
+       {
+         breaking--;
+         break;
+       }
+
+      if (continuing)
+       {
+         continuing--;
+         if (continuing)
+           break;
+       }
+    }
+
+  loop_level--;
+  line_number = save_line_number;
+
+#if 0
+  if (lexical_scoping)
+    {
+      if (!old_value)
+        unbind_variable (identifier);
+      else
+       {
+         SHELL_VAR *new_value;
+
+         new_value = bind_variable (identifier, value_cell(old_value), 0);
+         new_value->attributes = old_value->attributes;
+         dispose_variable (old_value);
+       }
+    }
+#endif
+
+  dispose_words (releaser);
+  discard_unwind_frame ("for");
+  return (retval);
+}
+
+#if defined (ARITH_FOR_COMMAND)
+/* Execute an arithmetic for command.  The syntax is
+
+       for (( init ; step ; test ))
+       do
+               body
+       done
+
+   The execution should be exactly equivalent to
+
+       eval \(\( init \)\)
+       while eval \(\( test \)\) ; do
+               body;
+               eval \(\( step \)\)
+       done
+*/
+static intmax_t
+eval_arith_for_expr (l, okp)
+     WORD_LIST *l;
+     int *okp;
+{
+  WORD_LIST *new;
+  intmax_t expresult;
+  int r;
+
+  new = expand_words_no_vars (l);
+  if (new)
+    {
+      if (echo_command_at_execute)
+       xtrace_print_arith_cmd (new);
+      this_command_name = "((";                /* )) for expression error messages */
+
+      command_string_index = 0;
+      print_arith_command (new);
+      if (signal_in_progress (DEBUG_TRAP) == 0)
+       {
+         FREE (the_printed_command_except_trap);
+         the_printed_command_except_trap = savestring (the_printed_command);
+       }
+
+      r = run_debug_trap ();
+      /* In debugging mode, if the DEBUG trap returns a non-zero status, we
+        skip the command. */
+#if defined (DEBUGGER)
+      if (debugging_mode == 0 || r == EXECUTION_SUCCESS)
+       expresult = evalexp (new->word->word, okp);
+      else
+       {
+         expresult = 0;
+         if (okp)
+           *okp = 1;
+       }
+#else
+      expresult = evalexp (new->word->word, okp);
+#endif
+      dispose_words (new);
+    }
+  else
+    {
+      expresult = 0;
+      if (okp)
+       *okp = 1;
+    }
+  return (expresult);
+}
+
+static int
+execute_arith_for_command (arith_for_command)
+     ARITH_FOR_COM *arith_for_command;
+{
+  intmax_t expresult;
+  int expok, body_status, arith_lineno, save_lineno;
+
+  body_status = EXECUTION_SUCCESS;
+  loop_level++;
+  save_lineno = line_number;
+
+  if (arith_for_command->flags & CMD_IGNORE_RETURN)
+    arith_for_command->action->flags |= CMD_IGNORE_RETURN;
+
+  this_command_name = "((";    /* )) for expression error messages */
+
+  /* save the starting line number of the command so we can reset
+     line_number before executing each expression -- for $LINENO
+     and the DEBUG trap. */
+  line_number = arith_lineno = arith_for_command->line;
+  if (variable_context && interactive_shell)
+    line_number -= function_line_number;
+
+  /* Evaluate the initialization expression. */
+  expresult = eval_arith_for_expr (arith_for_command->init, &expok);
+  if (expok == 0)
+    {
+      line_number = save_lineno;
+      return (EXECUTION_FAILURE);
+    }
+
+  while (1)
+    {
+      /* Evaluate the test expression. */
+      line_number = arith_lineno;
+      expresult = eval_arith_for_expr (arith_for_command->test, &expok);
+      line_number = save_lineno;
+
+      if (expok == 0)
+       {
+         body_status = EXECUTION_FAILURE;
+         break;
+       }
+      REAP ();
+      if (expresult == 0)
+       break;
+
+      /* Execute the body of the arithmetic for command. */
+      QUIT;
+      body_status = execute_command (arith_for_command->action);
+      QUIT;
+
+      /* Handle any `break' or `continue' commands executed by the body. */
+      if (breaking)
+       {
+         breaking--;
+         break;
+       }
+
+      if (continuing)
+       {
+         continuing--;
+         if (continuing)
+           break;
+       }
+
+      /* Evaluate the step expression. */
+      line_number = arith_lineno;
+      expresult = eval_arith_for_expr (arith_for_command->step, &expok);
+      line_number = save_lineno;
+
+      if (expok == 0)
+       {
+         body_status = EXECUTION_FAILURE;
+         break;
+       }
+    }
+
+  loop_level--;
+  line_number = save_lineno;
+
+  return (body_status);
+}
+#endif
+
+#if defined (SELECT_COMMAND)
+static int LINES, COLS, tabsize;
+
+#define RP_SPACE ") "
+#define RP_SPACE_LEN 2
+
+/* XXX - does not handle numbers > 1000000 at all. */
+#define NUMBER_LEN(s) \
+((s < 10) ? 1 \
+         : ((s < 100) ? 2 \
+                     : ((s < 1000) ? 3 \
+                                  : ((s < 10000) ? 4 \
+                                                : ((s < 100000) ? 5 \
+                                                               : 6)))))
+
+static int
+displen (s)
+     const char *s;
+{
+#if defined (HANDLE_MULTIBYTE)
+  wchar_t *wcstr;
+  size_t slen;
+  int wclen;
+
+  wcstr = 0;
+  slen = mbstowcs (wcstr, s, 0);
+  if (slen == -1)
+    slen = 0;
+  wcstr = (wchar_t *)xmalloc (sizeof (wchar_t) * (slen + 1));
+  mbstowcs (wcstr, s, slen + 1);
+  wclen = wcswidth (wcstr, slen);
+  free (wcstr);
+  return (wclen < 0 ? STRLEN(s) : wclen);
+#else
+  return (STRLEN (s));
+#endif
+}
+
+static int
+print_index_and_element (len, ind, list)
+      int len, ind;
+      WORD_LIST *list;
+{
+  register WORD_LIST *l;
+  register int i;
+
+  if (list == 0)
+    return (0);
+  for (i = ind, l = list; l && --i; l = l->next)
+    ;
+  if (l == 0)          /* don't think this can happen */
+    return (0);
+  fprintf (stderr, "%*d%s%s", len, ind, RP_SPACE, l->word->word);
+  return (displen (l->word->word));
+}
+
+static void
+indent (from, to)
+     int from, to;
+{
+  while (from < to)
+    {
+      if ((to / tabsize) > (from / tabsize))
+       {
+         putc ('\t', stderr);
+         from += tabsize - from % tabsize;
+       }
+      else
+       {
+         putc (' ', stderr);
+         from++;
+       }
+    }
+}
+
+static void
+print_select_list (list, list_len, max_elem_len, indices_len)
+     WORD_LIST *list;
+     int list_len, max_elem_len, indices_len;
+{
+  int ind, row, elem_len, pos, cols, rows;
+  int first_column_indices_len, other_indices_len;
+
+  if (list == 0)
+    {
+      putc ('\n', stderr);
+      return;
+    }
+
+  cols = max_elem_len ? COLS / max_elem_len : 1;
+  if (cols == 0)
+    cols = 1;
+  rows = list_len ? list_len / cols + (list_len % cols != 0) : 1;
+  cols = list_len ? list_len / rows + (list_len % rows != 0) : 1;
+
+  if (rows == 1)
+    {
+      rows = cols;
+      cols = 1;
+    }
+
+  first_column_indices_len = NUMBER_LEN (rows);
+  other_indices_len = indices_len;
+
+  for (row = 0; row < rows; row++)
+    {
+      ind = row;
+      pos = 0;
+      while (1)
+       {
+         indices_len = (pos == 0) ? first_column_indices_len : other_indices_len;
+         elem_len = print_index_and_element (indices_len, ind + 1, list);
+         elem_len += indices_len + RP_SPACE_LEN;
+         ind += rows;
+         if (ind >= list_len)
+           break;
+         indent (pos + elem_len, pos + max_elem_len);
+         pos += max_elem_len;
+       }
+      putc ('\n', stderr);
+    }
+}
+
+/* Print the elements of LIST, one per line, preceded by an index from 1 to
+   LIST_LEN.  Then display PROMPT and wait for the user to enter a number.
+   If the number is between 1 and LIST_LEN, return that selection.  If EOF
+   is read, return a null string.  If a blank line is entered, or an invalid
+   number is entered, the loop is executed again. */
+static char *
+select_query (list, list_len, prompt, print_menu)
+     WORD_LIST *list;
+     int list_len;
+     char *prompt;
+     int print_menu;
+{
+  int max_elem_len, indices_len, len;
+  intmax_t reply;
+  WORD_LIST *l;
+  char *repl_string, *t;
+
+#if 0
+  t = get_string_value ("LINES");
+  LINES = (t && *t) ? atoi (t) : 24;
+#endif
+  t = get_string_value ("COLUMNS");
+  COLS =  (t && *t) ? atoi (t) : 80;
+
+#if 0
+  t = get_string_value ("TABSIZE");
+  tabsize = (t && *t) ? atoi (t) : 8;
+  if (tabsize <= 0)
+    tabsize = 8;
+#else
+  tabsize = 8;
+#endif
+
+  max_elem_len = 0;
+  for (l = list; l; l = l->next)
+    {
+      len = displen (l->word->word);
+      if (len > max_elem_len)
+       max_elem_len = len;
+    }
+  indices_len = NUMBER_LEN (list_len);
+  max_elem_len += indices_len + RP_SPACE_LEN + 2;
+
+  while (1)
+    {
+      if (print_menu)
+       print_select_list (list, list_len, max_elem_len, indices_len);
+      fprintf (stderr, "%s", prompt);
+      fflush (stderr);
+      QUIT;
+
+      if (read_builtin ((WORD_LIST *)NULL) != EXECUTION_SUCCESS)
+       {
+         putchar ('\n');
+         return ((char *)NULL);
+       }
+      repl_string = get_string_value ("REPLY");
+      if (*repl_string == 0)
+       {
+         print_menu = 1;
+         continue;
+       }
+      if (legal_number (repl_string, &reply) == 0)
+       return "";
+      if (reply < 1 || reply > list_len)
+       return "";
+
+      for (l = list; l && --reply; l = l->next)
+       ;
+      return (l->word->word);          /* XXX - can't be null? */
+    }
+}
+
+/* Execute a SELECT command.  The syntax is:
+   SELECT word IN list DO command_list DONE
+   Only `break' or `return' in command_list will terminate
+   the command. */
+static int
+execute_select_command (select_command)
+     SELECT_COM *select_command;
+{
+  WORD_LIST *releaser, *list;
+  SHELL_VAR *v;
+  char *identifier, *ps3_prompt, *selection;
+  int retval, list_len, show_menu, save_line_number;
+
+  if (check_identifier (select_command->name, 1) == 0)
+    return (EXECUTION_FAILURE);
+
+  save_line_number = line_number;
+  line_number = select_command->line;
+
+  command_string_index = 0;
+  print_select_command_head (select_command);
+
+  if (echo_command_at_execute)
+    xtrace_print_select_command_head (select_command);
+
+#if 0
+  if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
+#else
+  if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
+#endif
+    {
+      FREE (the_printed_command_except_trap);
+      the_printed_command_except_trap = savestring (the_printed_command);
+    }
+
+  retval = run_debug_trap ();
+#if defined (DEBUGGER)
+  /* In debugging mode, if the DEBUG trap returns a non-zero status, we
+     skip the command. */
+  if (debugging_mode && retval != EXECUTION_SUCCESS)
+    return (EXECUTION_SUCCESS);
+#endif
+
+  loop_level++;
+  identifier = select_command->name->word;
+
+  /* command and arithmetic substitution, parameter and variable expansion,
+     word splitting, pathname expansion, and quote removal. */
+  list = releaser = expand_words_no_vars (select_command->map_list);
+  list_len = list_length (list);
+  if (list == 0 || list_len == 0)
+    {
+      if (list)
+       dispose_words (list);
+      line_number = save_line_number;
+      return (EXECUTION_SUCCESS);
+    }
+
+  begin_unwind_frame ("select");
+  add_unwind_protect (dispose_words, releaser);
+
+  if (select_command->flags & CMD_IGNORE_RETURN)
+    select_command->action->flags |= CMD_IGNORE_RETURN;
+
+  retval = EXECUTION_SUCCESS;
+  show_menu = 1;
+
+  while (1)
+    {
+      line_number = select_command->line;
+      ps3_prompt = get_string_value ("PS3");
+      if (ps3_prompt == 0)
+       ps3_prompt = "#? ";
+
+      QUIT;
+      selection = select_query (list, list_len, ps3_prompt, show_menu);
+      QUIT;
+      if (selection == 0)
+       {
+         /* select_query returns EXECUTION_FAILURE if the read builtin
+            fails, so we want to return failure in this case. */
+         retval = EXECUTION_FAILURE;
+         break;
+       }
+
+      v = bind_variable (identifier, selection, 0);
+      if (readonly_p (v) || noassign_p (v))
+       {
+         if (readonly_p (v) && interactive_shell == 0 && posixly_correct)
+           {
+             last_command_exit_value = EXECUTION_FAILURE;
+             jump_to_top_level (FORCE_EOF);
+           }
+         else
+           {
+             dispose_words (releaser);
+             discard_unwind_frame ("select");
+             loop_level--;
+             line_number = save_line_number;
+             return (EXECUTION_FAILURE);
+           }
+       }
+
+      retval = execute_command (select_command->action);
+
+      REAP ();
+      QUIT;
+
+      if (breaking)
+       {
+         breaking--;
+         break;
+       }
+
+      if (continuing)
+       {
+         continuing--;
+         if (continuing)
+           break;
+       }
+
+#if defined (KSH_COMPATIBLE_SELECT)
+      show_menu = 0;
+      selection = get_string_value ("REPLY");
+      if (selection && *selection == '\0')
+        show_menu = 1;
+#endif
+    }
+
+  loop_level--;
+  line_number = save_line_number;
+
+  dispose_words (releaser);
+  discard_unwind_frame ("select");
+  return (retval);
+}
+#endif /* SELECT_COMMAND */
+
+/* Execute a CASE command.  The syntax is: CASE word_desc IN pattern_list ESAC.
+   The pattern_list is a linked list of pattern clauses; each clause contains
+   some patterns to compare word_desc against, and an associated command to
+   execute. */
+static int
+execute_case_command (case_command)
+     CASE_COM *case_command;
+{
+  register WORD_LIST *list;
+  WORD_LIST *wlist, *es;
+  PATTERN_LIST *clauses;
+  char *word, *pattern;
+  int retval, match, ignore_return, save_line_number;
+
+  save_line_number = line_number;
+  line_number = case_command->line;
+
+  command_string_index = 0;
+  print_case_command_head (case_command);
+
+  if (echo_command_at_execute)
+    xtrace_print_case_command_head (case_command);
+
+#if 0
+  if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
+#else
+  if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
+#endif
+    {
+      FREE (the_printed_command_except_trap);
+      the_printed_command_except_trap = savestring (the_printed_command);
+    }
+
+  retval = run_debug_trap();
+#if defined (DEBUGGER)
+  /* In debugging mode, if the DEBUG trap returns a non-zero status, we
+     skip the command. */
+  if (debugging_mode && retval != EXECUTION_SUCCESS)
+    {
+      line_number = save_line_number;
+      return (EXECUTION_SUCCESS);
+    }
+#endif
+
+  wlist = expand_word_unsplit (case_command->word, 0);
+  word = wlist ? string_list (wlist) : savestring ("");
+  dispose_words (wlist);
+
+  retval = EXECUTION_SUCCESS;
+  ignore_return = case_command->flags & CMD_IGNORE_RETURN;
+
+  begin_unwind_frame ("case");
+  add_unwind_protect ((Function *)xfree, word);
+
+#define EXIT_CASE()  goto exit_case_command
+
+  for (clauses = case_command->clauses; clauses; clauses = clauses->next)
+    {
+      QUIT;
+      for (list = clauses->patterns; list; list = list->next)
+       {
+         es = expand_word_leave_quoted (list->word, 0);
+
+         if (es && es->word && es->word->word && *(es->word->word))
+           pattern = quote_string_for_globbing (es->word->word, QGLOB_CVTNULL);
+         else
+           {
+             pattern = (char *)xmalloc (1);
+             pattern[0] = '\0';
+           }
+
+         /* Since the pattern does not undergo quote removal (as per
+            Posix.2, section 3.9.4.3), the strmatch () call must be able
+            to recognize backslashes as escape characters. */
+         match = strmatch (pattern, word, FNMATCH_EXTFLAG|FNMATCH_IGNCASE) != FNM_NOMATCH;
+         free (pattern);
+
+         dispose_words (es);
+
+         if (match)
+           {
+             do
+               {
+                 if (clauses->action && ignore_return)
+                   clauses->action->flags |= CMD_IGNORE_RETURN;
+                 retval = execute_command (clauses->action);
+               }
+             while ((clauses->flags & CASEPAT_FALLTHROUGH) && (clauses = clauses->next));
+             if (clauses == 0 || (clauses->flags & CASEPAT_TESTNEXT) == 0)
+               EXIT_CASE ();
+             else
+               break;
+           }
+
+         QUIT;
+       }
+    }
+
+exit_case_command:
+  free (word);
+  discard_unwind_frame ("case");
+  line_number = save_line_number;
+  return (retval);
+}
+
+#define CMD_WHILE 0
+#define CMD_UNTIL 1
+
+/* The WHILE command.  Syntax: WHILE test DO action; DONE.
+   Repeatedly execute action while executing test produces
+   EXECUTION_SUCCESS. */
+static int
+execute_while_command (while_command)
+     WHILE_COM *while_command;
+{
+  return (execute_while_or_until (while_command, CMD_WHILE));
+}
+
+/* UNTIL is just like WHILE except that the test result is negated. */
+static int
+execute_until_command (while_command)
+     WHILE_COM *while_command;
+{
+  return (execute_while_or_until (while_command, CMD_UNTIL));
+}
+
+/* The body for both while and until.  The only difference between the
+   two is that the test value is treated differently.  TYPE is
+   CMD_WHILE or CMD_UNTIL.  The return value for both commands should
+   be EXECUTION_SUCCESS if no commands in the body are executed, and
+   the status of the last command executed in the body otherwise. */
+static int
+execute_while_or_until (while_command, type)
+     WHILE_COM *while_command;
+     int type;
+{
+  int return_value, body_status;
+
+  body_status = EXECUTION_SUCCESS;
+  loop_level++;
+
+  while_command->test->flags |= CMD_IGNORE_RETURN;
+  if (while_command->flags & CMD_IGNORE_RETURN)
+    while_command->action->flags |= CMD_IGNORE_RETURN;
+
+  while (1)
+    {
+      return_value = execute_command (while_command->test);
+      REAP ();
+
+      /* Need to handle `break' in the test when we would break out of the
+         loop.  The job control code will set `breaking' to loop_level
+         when a job in a loop is stopped with SIGTSTP.  If the stopped job
+         is in the loop test, `breaking' will not be reset unless we do
+         this, and the shell will cease to execute commands. */
+      if (type == CMD_WHILE && return_value != EXECUTION_SUCCESS)
+       {
+         if (breaking)
+           breaking--;
+         break;
+       }
+      if (type == CMD_UNTIL && return_value == EXECUTION_SUCCESS)
+       {
+         if (breaking)
+           breaking--;
+         break;
+       }
+
+      QUIT;
+      body_status = execute_command (while_command->action);
+      QUIT;
+
+      if (breaking)
+       {
+         breaking--;
+         break;
+       }
+
+      if (continuing)
+       {
+         continuing--;
+         if (continuing)
+           break;
+       }
+    }
+  loop_level--;
+
+  return (body_status);
+}
+
+/* IF test THEN command [ELSE command].
+   IF also allows ELIF in the place of ELSE IF, but
+   the parser makes *that* stupidity transparent. */
+static int
+execute_if_command (if_command)
+     IF_COM *if_command;
+{
+  int return_value, save_line_number;
+
+  save_line_number = line_number;
+  if_command->test->flags |= CMD_IGNORE_RETURN;
+  return_value = execute_command (if_command->test);
+  line_number = save_line_number;
+
+  if (return_value == EXECUTION_SUCCESS)
+    {
+      QUIT;
+
+      if (if_command->true_case && (if_command->flags & CMD_IGNORE_RETURN))
+       if_command->true_case->flags |= CMD_IGNORE_RETURN;
+
+      return (execute_command (if_command->true_case));
+    }
+  else
+    {
+      QUIT;
+
+      if (if_command->false_case && (if_command->flags & CMD_IGNORE_RETURN))
+       if_command->false_case->flags |= CMD_IGNORE_RETURN;
+
+      return (execute_command (if_command->false_case));
+    }
+}
+
+#if defined (DPAREN_ARITHMETIC)
+static int
+execute_arith_command (arith_command)
+     ARITH_COM *arith_command;
+{
+  int expok, save_line_number, retval;
+  intmax_t expresult;
+  WORD_LIST *new;
+  char *exp;
+
+  expresult = 0;
+
+  save_line_number = line_number;
+  this_command_name = "((";    /* )) */
+  line_number = arith_command->line;
+  /* If we're in a function, update the line number information. */
+  if (variable_context && interactive_shell)
+    line_number -= function_line_number;
+
+  command_string_index = 0;
+  print_arith_command (arith_command->exp);
+
+  if (signal_in_progress (DEBUG_TRAP) == 0)
+    {
+      FREE (the_printed_command_except_trap);
+      the_printed_command_except_trap = savestring (the_printed_command);
+    }
+
+  /* Run the debug trap before each arithmetic command, but do it after we
+     update the line number information and before we expand the various
+     words in the expression. */
+  retval = run_debug_trap ();
+#if defined (DEBUGGER)
+  /* In debugging mode, if the DEBUG trap returns a non-zero status, we
+     skip the command. */
+  if (debugging_mode && retval != EXECUTION_SUCCESS)
+    {
+      line_number = save_line_number;
+      return (EXECUTION_SUCCESS);
+    }
+#endif
+
+  new = expand_words_no_vars (arith_command->exp);
+
+  /* If we're tracing, make a new word list with `((' at the front and `))'
+     at the back and print it. */
+  if (echo_command_at_execute)
+    xtrace_print_arith_cmd (new);
+
+  if (new)
+    {
+      exp = new->next ? string_list (new) : new->word->word;
+      expresult = evalexp (exp, &expok);
+      line_number = save_line_number;
+      if (exp != new->word->word)
+       free (exp);
+      dispose_words (new);
+    }
+  else
+    {
+      expresult = 0;
+      expok = 1;
+    }
+
+  if (expok == 0)
+    return (EXECUTION_FAILURE);
+
+  return (expresult == 0 ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
+}
+#endif /* DPAREN_ARITHMETIC */
+
+#if defined (COND_COMMAND)
+
+static char * const nullstr = "";
+
+/* XXX - can COND ever be NULL when this is called? */
+static int
+execute_cond_node (cond)
+     COND_COM *cond;
+{
+  int result, invert, patmatch, rmatch, mflags, ignore;
+  char *arg1, *arg2;
+#if 0
+  char *t1, *t2;
+#endif
+
+  invert = (cond->flags & CMD_INVERT_RETURN);
+  ignore = (cond->flags & CMD_IGNORE_RETURN);
+  if (ignore)
+    {
+      if (cond->left)
+       cond->left->flags |= CMD_IGNORE_RETURN;
+      if (cond->right)
+       cond->right->flags |= CMD_IGNORE_RETURN;
+    }
+      
+  if (cond->type == COND_EXPR)
+    result = execute_cond_node (cond->left);
+  else if (cond->type == COND_OR)
+    {
+      result = execute_cond_node (cond->left);
+      if (result != EXECUTION_SUCCESS)
+       result = execute_cond_node (cond->right);
+    }
+  else if (cond->type == COND_AND)
+    {
+      result = execute_cond_node (cond->left);
+      if (result == EXECUTION_SUCCESS)
+       result = execute_cond_node (cond->right);
+    }
+  else if (cond->type == COND_UNARY)
+    {
+      if (ignore)
+       comsub_ignore_return++;
+      arg1 = cond_expand_word (cond->left->op, 0);
+      if (ignore)
+       comsub_ignore_return--;
+      if (arg1 == 0)
+       arg1 = nullstr;
+      if (echo_command_at_execute)
+       xtrace_print_cond_term (cond->type, invert, cond->op, arg1, (char *)NULL);
+      result = unary_test (cond->op->word, arg1) ? EXECUTION_SUCCESS : EXECUTION_FAILURE;
+      if (arg1 != nullstr)
+       free (arg1);
+    }
+  else if (cond->type == COND_BINARY)
+    {
+      rmatch = 0;
+      patmatch = (((cond->op->word[1] == '=') && (cond->op->word[2] == '\0') &&
+                  (cond->op->word[0] == '!' || cond->op->word[0] == '=')) ||
+                 (cond->op->word[0] == '=' && cond->op->word[1] == '\0'));
+#if defined (COND_REGEXP)
+      rmatch = (cond->op->word[0] == '=' && cond->op->word[1] == '~' &&
+               cond->op->word[2] == '\0');
+#endif
+
+      if (ignore)
+       comsub_ignore_return++;
+      arg1 = cond_expand_word (cond->left->op, 0);
+      if (ignore)
+       comsub_ignore_return--;
+      if (arg1 == 0)
+       arg1 = nullstr;
+      if (ignore)
+       comsub_ignore_return++;
+      arg2 = cond_expand_word (cond->right->op,
+                              (rmatch && shell_compatibility_level > 31) ? 2 : (patmatch ? 1 : 0));
+      if (ignore)
+       comsub_ignore_return--;
+      if (arg2 == 0)
+       arg2 = nullstr;
+
+      if (echo_command_at_execute)
+       xtrace_print_cond_term (cond->type, invert, cond->op, arg1, arg2);
+
+#if defined (COND_REGEXP)
+      if (rmatch)
+       {
+         mflags = SHMAT_PWARN;
+#if defined (ARRAY_VARS)
+         mflags |= SHMAT_SUBEXP;
+#endif
+
+#if 0
+         t1 = strescape(arg1);
+         t2 = strescape(arg2);
+         itrace("execute_cond_node: sh_regmatch on `%s' and `%s'", t1, t2);
+         free(t1);
+         free(t2);
+#endif
+
+         result = sh_regmatch (arg1, arg2, mflags);
+       }
+      else
+#endif /* COND_REGEXP */
+       {
+         int oe;
+         oe = extended_glob;
+         extended_glob = 1;
+         result = binary_test (cond->op->word, arg1, arg2, TEST_PATMATCH|TEST_ARITHEXP|TEST_LOCALE)
+                                 ? EXECUTION_SUCCESS
+                                 : EXECUTION_FAILURE;
+         extended_glob = oe;
+       }
+      if (arg1 != nullstr)
+       free (arg1);
+      if (arg2 != nullstr)
+       free (arg2);
+    }
+  else
+    {
+      command_error ("execute_cond_node", CMDERR_BADTYPE, cond->type, 0);
+      jump_to_top_level (DISCARD);
+      result = EXECUTION_FAILURE;
+    }
+
+  if (invert)
+    result = (result == EXECUTION_SUCCESS) ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
+
+  return result;
+}
+
+static int
+execute_cond_command (cond_command)
+     COND_COM *cond_command;
+{
+  int retval, save_line_number;
+
+  retval = EXECUTION_SUCCESS;
+  save_line_number = line_number;
+
+  this_command_name = "[[";
+  line_number = cond_command->line;
+  /* If we're in a function, update the line number information. */
+  if (variable_context && interactive_shell)
+    line_number -= function_line_number;
+  command_string_index = 0;
+  print_cond_command (cond_command);
+
+  if (signal_in_progress (DEBUG_TRAP) == 0)
+    {
+      FREE (the_printed_command_except_trap);
+      the_printed_command_except_trap = savestring (the_printed_command);
+    }
+
+  /* Run the debug trap before each conditional command, but do it after we
+     update the line number information. */
+  retval = run_debug_trap ();
+#if defined (DEBUGGER)
+  /* In debugging mode, if the DEBUG trap returns a non-zero status, we
+     skip the command. */
+  if (debugging_mode && retval != EXECUTION_SUCCESS)
+    {
+      line_number = save_line_number;
+      return (EXECUTION_SUCCESS);
+    }
+#endif
+
+#if 0
+  debug_print_cond_command (cond_command);
+#endif
+
+  last_command_exit_value = retval = execute_cond_node (cond_command);
+  line_number = save_line_number;
+  return (retval);
+}
+#endif /* COND_COMMAND */
+
+static void
+bind_lastarg (arg)
+     char *arg;
+{
+  SHELL_VAR *var;
+
+  if (arg == 0)
+    arg = "";
+  var = bind_variable ("_", arg, 0);
+  VUNSETATTR (var, att_exported);
+}
+
+/* Execute a null command.  Fork a subshell if the command uses pipes or is
+   to be run asynchronously.  This handles all the side effects that are
+   supposed to take place. */
+static int
+execute_null_command (redirects, pipe_in, pipe_out, async)
+     REDIRECT *redirects;
+     int pipe_in, pipe_out, async;
+{
+  int r;
+  int forcefork;
+  REDIRECT *rd;
+
+  for (forcefork = 0, rd = redirects; rd; rd = rd->next)
+    forcefork += rd->rflags & REDIR_VARASSIGN;
+
+  if (forcefork || pipe_in != NO_PIPE || pipe_out != NO_PIPE || async)
+    {
+      /* We have a null command, but we really want a subshell to take
+        care of it.  Just fork, do piping and redirections, and exit. */
+      if (make_child ((char *)NULL, async) == 0)
+       {
+         /* Cancel traps, in trap.c. */
+         restore_original_signals ();          /* XXX */
+
+         do_piping (pipe_in, pipe_out);
+
+#if defined (COPROCESS_SUPPORT)
+         coproc_closeall ();
+#endif
+
+         subshell_environment = 0;
+         if (async)
+           subshell_environment |= SUBSHELL_ASYNC;
+         if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
+           subshell_environment |= SUBSHELL_PIPE;
+
+         if (do_redirections (redirects, RX_ACTIVE) == 0)
+           exit (EXECUTION_SUCCESS);
+         else
+           exit (EXECUTION_FAILURE);
+       }
+      else
+       {
+         close_pipes (pipe_in, pipe_out);
+#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
+         if (pipe_out == NO_PIPE)
+           unlink_fifo_list ();
+#endif
+         return (EXECUTION_SUCCESS);
+       }
+    }
+  else
+    {
+      /* Even if there aren't any command names, pretend to do the
+        redirections that are specified.  The user expects the side
+        effects to take place.  If the redirections fail, then return
+        failure.  Otherwise, if a command substitution took place while
+        expanding the command or a redirection, return the value of that
+        substitution.  Otherwise, return EXECUTION_SUCCESS. */
+
+      r = do_redirections (redirects, RX_ACTIVE|RX_UNDOABLE);
+      cleanup_redirects (redirection_undo_list);
+      redirection_undo_list = (REDIRECT *)NULL;
+
+      if (r != 0)
+       return (EXECUTION_FAILURE);
+      else if (last_command_subst_pid != NO_PID)
+       return (last_command_exit_value);
+      else
+       return (EXECUTION_SUCCESS);
+    }
+}
+
+/* This is a hack to suppress word splitting for assignment statements
+   given as arguments to builtins with the ASSIGNMENT_BUILTIN flag set. */
+static void
+fix_assignment_words (words)
+     WORD_LIST *words;
+{
+  WORD_LIST *w, *wcmd;
+  struct builtin *b;
+  int assoc, global, array, integer;
+
+  if (words == 0)
+    return;
+
+  b = 0;
+  assoc = global = array = integer = 0;
+
+  /* Skip over assignment statements preceding a command name */
+  wcmd = words;
+  for (wcmd = words; wcmd; wcmd = wcmd->next)
+    if ((wcmd->word->flags & W_ASSIGNMENT) == 0)
+      break;
+
+  for (w = wcmd; w; w = w->next)
+    if (w->word->flags & W_ASSIGNMENT)
+      {
+       if (b == 0)
+         {
+           /* Posix (post-2008) says that `command' doesn't change whether
+              or not the builtin it shadows is a `declaration command', even
+              though it removes other special builtin properties.  In Posix
+              mode, we skip over one or more instances of `command' and
+              deal with the next word as the assignment builtin. */
+           while (posixly_correct && wcmd && wcmd->word && wcmd->word->word && STREQ (wcmd->word->word, "command"))
+             wcmd = wcmd->next;
+           b = builtin_address_internal (wcmd->word->word, 0);
+           if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
+             return;
+           else if (b && (b->flags & ASSIGNMENT_BUILTIN))
+             wcmd->word->flags |= W_ASSNBLTIN;
+         }
+       w->word->flags |= (W_NOSPLIT|W_NOGLOB|W_TILDEEXP|W_ASSIGNARG);
+#if defined (ARRAY_VARS)
+       if (assoc)
+         w->word->flags |= W_ASSIGNASSOC;
+       if (array)
+         w->word->flags |= W_ASSIGNARRAY;
+#endif
+       if (global)
+         w->word->flags |= W_ASSNGLOBAL;
+       if (integer)
+         w->word->flags |= W_ASSIGNINT;
+      }
+#if defined (ARRAY_VARS)
+    /* Note that we saw an associative array option to a builtin that takes
+       assignment statements.  This is a bit of a kludge. */
+    else if (w->word->word[0] == '-' && (strchr (w->word->word+1, 'A') || strchr (w->word->word+1, 'a') || strchr (w->word->word+1, 'g')))
+#else
+    else if (w->word->word[0] == '-' && strchr (w->word->word+1, 'g'))
+#endif
+      {
+       if (b == 0)
+         {
+           while (posixly_correct && wcmd && wcmd->word && wcmd->word->word && STREQ (wcmd->word->word, "command"))
+             wcmd = wcmd->next;
+           b = builtin_address_internal (wcmd->word->word, 0);
+           if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
+             return;
+           else if (b && (b->flags & ASSIGNMENT_BUILTIN))
+             wcmd->word->flags |= W_ASSNBLTIN;
+         }
+       if ((wcmd->word->flags & W_ASSNBLTIN) && strchr (w->word->word+1, 'A'))
+         assoc = 1;
+       else if ((wcmd->word->flags & W_ASSNBLTIN) && strchr (w->word->word+1, 'a'))
+         array = 1;
+       if ((wcmd->word->flags & W_ASSNBLTIN) && strchr (w->word->word+1, 'g'))
+         global = 1;
+       if ((wcmd->word->flags & W_ASSNBLTIN) && strchr (w->word->word+1, 'i'))
+         integer = 1;
+      }
+}
+
+/* Return 1 if the file found by searching $PATH for PATHNAME, defaulting
+   to PATHNAME, is a directory.  Used by the autocd code below. */
+static int
+is_dirname (pathname)
+     char *pathname;
+{
+  char *temp;
+  int ret;
+
+  temp = search_for_command (pathname, 0);
+  ret = (temp ? file_isdir (temp) : file_isdir (pathname));
+  free (temp);
+  return ret;
+}
+
+/* The meaty part of all the executions.  We have to start hacking the
+   real execution of commands here.  Fork a process, set things up,
+   execute the command. */
+static int
+execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
+     SIMPLE_COM *simple_command;
+     int pipe_in, pipe_out, async;
+     struct fd_bitmap *fds_to_close;
+{
+  WORD_LIST *words, *lastword;
+  char *command_line, *lastarg, *temp;
+  int first_word_quoted, result, builtin_is_special, already_forked, dofork;
+  pid_t old_last_async_pid;
+  sh_builtin_func_t *builtin;
+  SHELL_VAR *func;
+  volatile int old_builtin, old_command_builtin;
+
+  result = EXECUTION_SUCCESS;
+  special_builtin_failed = builtin_is_special = 0;
+  command_line = (char *)0;
+
+  QUIT;
+
+  /* If we're in a function, update the line number information. */
+  if (variable_context && interactive_shell && sourcelevel == 0)
+    line_number -= function_line_number;
+
+  /* Remember what this command line looks like at invocation. */
+  command_string_index = 0;
+  print_simple_command (simple_command);
+
+#if 0
+  if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
+#else
+  if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
+#endif
+    {
+      FREE (the_printed_command_except_trap);
+      the_printed_command_except_trap = the_printed_command ? savestring (the_printed_command) : (char *)0;
+    }
+
+  /* Run the debug trap before each simple command, but do it after we
+     update the line number information. */
+  result = run_debug_trap ();
+#if defined (DEBUGGER)
+  /* In debugging mode, if the DEBUG trap returns a non-zero status, we
+     skip the command. */
+  if (debugging_mode && result != EXECUTION_SUCCESS)
+    return (EXECUTION_SUCCESS);
+#endif
+
+  first_word_quoted =
+    simple_command->words ? (simple_command->words->word->flags & W_QUOTED) : 0;
+
+  last_command_subst_pid = NO_PID;
+  old_last_async_pid = last_asynchronous_pid;
+
+  already_forked = dofork = 0;
+
+  /* If we're in a pipeline or run in the background, set DOFORK so we
+     make the child early, before word expansion.  This keeps assignment
+     statements from affecting the parent shell's environment when they
+     should not. */
+  dofork = pipe_in != NO_PIPE || pipe_out != NO_PIPE || async;
+
+  /* Something like `%2 &' should restart job 2 in the background, not cause
+     the shell to fork here. */
+  if (dofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE &&
+       simple_command->words && simple_command->words->word &&
+       simple_command->words->word->word &&
+       (simple_command->words->word->word[0] == '%'))
+    dofork = 0;
+
+  if (dofork)
+    {
+      /* Do this now, because execute_disk_command will do it anyway in the
+        vast majority of cases. */
+      maybe_make_export_env ();
+
+      /* Don't let a DEBUG trap overwrite the command string to be saved with
+        the process/job associated with this child. */
+      if (make_child (savestring (the_printed_command_except_trap), async) == 0)
+       {
+         already_forked = 1;
+         simple_command->flags |= CMD_NO_FORK;
+
+         subshell_environment = SUBSHELL_FORK;
+         if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
+           subshell_environment |= SUBSHELL_PIPE;
+         if (async)
+           subshell_environment |= SUBSHELL_ASYNC;
+
+         /* We need to do this before piping to handle some really
+            pathological cases where one of the pipe file descriptors
+            is < 2. */
+         if (fds_to_close)
+           close_fd_bitmap (fds_to_close);
+
+         do_piping (pipe_in, pipe_out);
+         pipe_in = pipe_out = NO_PIPE;
+#if defined (COPROCESS_SUPPORT)
+         coproc_closeall ();
+#endif
+
+         last_asynchronous_pid = old_last_async_pid;
+
+         CHECK_SIGTERM;
+       }
+      else
+       {
+         /* Don't let simple commands that aren't the last command in a
+            pipeline change $? for the rest of the pipeline (or at all). */
+         if (pipe_out != NO_PIPE)
+           result = last_command_exit_value;
+         close_pipes (pipe_in, pipe_out);
+#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
+         /* Close /dev/fd file descriptors in the parent after forking the
+            last child in a (possibly one-element) pipeline.  Defer this
+            until any running shell function completes. */
+         if (pipe_out == NO_PIPE && variable_context == 0)     /* XXX */
+           unlink_fifo_list ();                /* XXX */
+#endif
+         command_line = (char *)NULL;      /* don't free this. */
+         bind_lastarg ((char *)NULL);
+         return (result);
+       }
+    }
+
+  /* If we are re-running this as the result of executing the `command'
+     builtin, do not expand the command words a second time. */
+  if ((simple_command->flags & CMD_INHIBIT_EXPANSION) == 0)
+    {
+      current_fds_to_close = fds_to_close;
+      fix_assignment_words (simple_command->words);
+      /* Pass the ignore return flag down to command substitutions */
+      if (simple_command->flags & CMD_IGNORE_RETURN)   /* XXX */
+       comsub_ignore_return++;
+      words = expand_words (simple_command->words);
+      if (simple_command->flags & CMD_IGNORE_RETURN)
+       comsub_ignore_return--;
+      current_fds_to_close = (struct fd_bitmap *)NULL;
+    }
+  else
+    words = copy_word_list (simple_command->words);
+
+  /* It is possible for WORDS not to have anything left in it.
+     Perhaps all the words consisted of `$foo', and there was
+     no variable `$foo'. */
+  if (words == 0)
+    {
+      this_command_name = 0;
+      result = execute_null_command (simple_command->redirects,
+                                    pipe_in, pipe_out,
+                                    already_forked ? 0 : async);
+      if (already_forked)
+       exit (result);
+      else
+       {
+         bind_lastarg ((char *)NULL);
+         set_pipestatus_from_exit (result);
+         return (result);
+       }
+    }
+
+  lastarg = (char *)NULL;
+
+  begin_unwind_frame ("simple-command");
+
+  if (echo_command_at_execute)
+    xtrace_print_word_list (words, 1);
+
+  builtin = (sh_builtin_func_t *)NULL;
+  func = (SHELL_VAR *)NULL;
+  if ((simple_command->flags & CMD_NO_FUNCTIONS) == 0)
+    {
+      /* Posix.2 says special builtins are found before functions.  We
+        don't set builtin_is_special anywhere other than here, because
+        this path is followed only when the `command' builtin is *not*
+        being used, and we don't want to exit the shell if a special
+        builtin executed with `command builtin' fails.  `command' is not
+        a special builtin. */
+      if (posixly_correct)
+       {
+         builtin = find_special_builtin (words->word->word);
+         if (builtin)
+           builtin_is_special = 1;
+       }
+      if (builtin == 0)
+       func = find_function (words->word->word);
+    }
+
+  /* In POSIX mode, assignment errors in the temporary environment cause a
+     non-interactive shell to exit. */
+  if (posixly_correct && builtin_is_special && interactive_shell == 0 && tempenv_assign_error)
+    {
+      last_command_exit_value = EXECUTION_FAILURE;
+      jump_to_top_level (ERREXIT);
+    }
+  tempenv_assign_error = 0;    /* don't care about this any more */
+
+  add_unwind_protect (dispose_words, words);
+  QUIT;
+
+  /* Bind the last word in this command to "$_" after execution. */
+  for (lastword = words; lastword->next; lastword = lastword->next)
+    ;
+  lastarg = lastword->word->word;
+
+#if defined (JOB_CONTROL)
+  /* Is this command a job control related thing? */
+  if (words->word->word[0] == '%' && already_forked == 0)
+    {
+      this_command_name = async ? "bg" : "fg";
+      last_shell_builtin = this_shell_builtin;
+      this_shell_builtin = builtin_address (this_command_name);
+      result = (*this_shell_builtin) (words);
+      goto return_result;
+    }
+
+  /* One other possibililty.  The user may want to resume an existing job.
+     If they do, find out whether this word is a candidate for a running
+     job. */
+  if (job_control && already_forked == 0 && async == 0 &&
+       !first_word_quoted &&
+       !words->next &&
+       words->word->word[0] &&
+       !simple_command->redirects &&
+       pipe_in == NO_PIPE &&
+       pipe_out == NO_PIPE &&
+       (temp = get_string_value ("auto_resume")))
+    {
+      int job, jflags, started_status;
+
+      jflags = JM_STOPPED|JM_FIRSTMATCH;
+      if (STREQ (temp, "exact"))
+       jflags |= JM_EXACT;
+      else if (STREQ (temp, "substring"))
+       jflags |= JM_SUBSTRING;
+      else
+       jflags |= JM_PREFIX;
+      job = get_job_by_name (words->word->word, jflags);
+      if (job != NO_JOB)
+       {
+         run_unwind_frame ("simple-command");
+         this_command_name = "fg";
+         last_shell_builtin = this_shell_builtin;
+         this_shell_builtin = builtin_address ("fg");
+
+         started_status = start_job (job, 1);
+         return ((started_status < 0) ? EXECUTION_FAILURE : started_status);
+       }
+    }
+#endif /* JOB_CONTROL */
+
+run_builtin:
+  /* Remember the name of this command globally. */
+  this_command_name = words->word->word;
+
+  QUIT;
+
+  /* This command could be a shell builtin or a user-defined function.
+     We have already found special builtins by this time, so we do not
+     set builtin_is_special.  If this is a function or builtin, and we
+     have pipes, then fork a subshell in here.  Otherwise, just execute
+     the command directly. */
+  if (func == 0 && builtin == 0)
+    builtin = find_shell_builtin (this_command_name);
+
+  last_shell_builtin = this_shell_builtin;
+  this_shell_builtin = builtin;
+
+  if (builtin || func)
+    {
+      if (builtin)
+        {
+         old_builtin = executing_builtin;
+         old_command_builtin = executing_command_builtin;
+         unwind_protect_int (executing_builtin);       /* modified in execute_builtin */
+         unwind_protect_int (executing_command_builtin);       /* ditto */
+        }
+      if (already_forked)
+       {
+         /* reset_terminating_signals (); */   /* XXX */
+         /* Reset the signal handlers in the child, but don't free the
+            trap strings.  Set a flag noting that we have to free the
+            trap strings if we run trap to change a signal disposition. */
+         reset_signal_handlers ();
+         subshell_environment |= SUBSHELL_RESETTRAP;
+
+         if (async)
+           {
+             if ((simple_command->flags & CMD_STDIN_REDIR) &&
+                   pipe_in == NO_PIPE &&
+                   (stdin_redirects (simple_command->redirects) == 0))
+               async_redirect_stdin ();
+             setup_async_signals ();
+           }
+
+         subshell_level++;
+         execute_subshell_builtin_or_function
+           (words, simple_command->redirects, builtin, func,
+            pipe_in, pipe_out, async, fds_to_close,
+            simple_command->flags);
+         subshell_level--;
+       }
+      else
+       {
+         result = execute_builtin_or_function
+           (words, builtin, func, simple_command->redirects, fds_to_close,
+            simple_command->flags);
+         if (builtin)
+           {
+             if (result > EX_SHERRBASE)
+               {
+                 switch (result)
+                   {
+                   case EX_REDIRFAIL:
+                   case EX_BADASSIGN:
+                   case EX_EXPFAIL:
+                     /* These errors cause non-interactive posix mode shells to exit */
+                     if (posixly_correct && builtin_is_special && interactive_shell == 0)
+                       {
+                         last_command_exit_value = EXECUTION_FAILURE;
+                         jump_to_top_level (ERREXIT);
+                       }
+                   }
+                 result = builtin_status (result);
+                 if (builtin_is_special)
+                   special_builtin_failed = 1;
+               }
+             /* In POSIX mode, if there are assignment statements preceding
+                a special builtin, they persist after the builtin
+                completes. */
+             if (posixly_correct && builtin_is_special && temporary_env)
+               merge_temporary_env ();
+           }
+         else          /* function */
+           {
+             if (result == EX_USAGE)
+               result = EX_BADUSAGE;
+             else if (result > EX_SHERRBASE)
+               result = EXECUTION_FAILURE;
+           }
+
+         set_pipestatus_from_exit (result);
+
+         goto return_result;
+       }
+    }
+
+  if (autocd && interactive && words->word && is_dirname (words->word->word))
+    {
+      words = make_word_list (make_word ("cd"), words);
+      xtrace_print_word_list (words, 0);
+      goto run_builtin;
+    }
+
+  if (command_line == 0)
+    command_line = savestring (the_printed_command_except_trap ? the_printed_command_except_trap : "");
+
+#if defined (PROCESS_SUBSTITUTION)
+  if ((subshell_environment & SUBSHELL_COMSUB) && (simple_command->flags & CMD_NO_FORK) && fifos_pending() > 0)
+    simple_command->flags &= ~CMD_NO_FORK;
+#endif
+
+  result = execute_disk_command (words, simple_command->redirects, command_line,
+                       pipe_in, pipe_out, async, fds_to_close,
+                       simple_command->flags);
+
+ return_result:
+  bind_lastarg (lastarg);
+  FREE (command_line);
+  dispose_words (words);
+  if (builtin)
+    {
+      executing_builtin = old_builtin;
+      executing_command_builtin = old_command_builtin;
+    }
+  discard_unwind_frame ("simple-command");
+  this_command_name = (char *)NULL;    /* points to freed memory now */
+  return (result);
+}
+
+/* Translate the special builtin exit statuses.  We don't really need a
+   function for this; it's a placeholder for future work. */
+static int
+builtin_status (result)
+     int result;
+{
+  int r;
+
+  switch (result)
+    {
+    case EX_USAGE:
+      r = EX_BADUSAGE;
+      break;
+    case EX_REDIRFAIL:
+    case EX_BADSYNTAX:
+    case EX_BADASSIGN:
+    case EX_EXPFAIL:
+      r = EXECUTION_FAILURE;
+      break;
+    default:
+      r = EXECUTION_SUCCESS;
+      break;
+    }
+  return (r);
+}
+
+static int
+execute_builtin (builtin, words, flags, subshell)
+     sh_builtin_func_t *builtin;
+     WORD_LIST *words;
+     int flags, subshell;
+{
+  int old_e_flag, result, eval_unwind;
+  int isbltinenv;
+  char *error_trap;
+
+  error_trap = 0;
+  old_e_flag = exit_immediately_on_error;
+  
+  /* The eval builtin calls parse_and_execute, which does not know about
+     the setting of flags, and always calls the execution functions with
+     flags that will exit the shell on an error if -e is set.  If the
+     eval builtin is being called, and we're supposed to ignore the exit
+     value of the command, we turn the -e flag off ourselves and disable
+     the ERR trap, then restore them when the command completes.  This is
+     also a problem (as below) for the command and source/. builtins. */
+  if (subshell == 0 && (flags & CMD_IGNORE_RETURN) &&
+       (builtin == eval_builtin || builtin == command_builtin || builtin == source_builtin))
+    {
+      begin_unwind_frame ("eval_builtin");
+      unwind_protect_int (exit_immediately_on_error);
+      unwind_protect_int (builtin_ignoring_errexit);
+      error_trap = TRAP_STRING (ERROR_TRAP);
+      if (error_trap)
+       {
+         error_trap = savestring (error_trap);
+         add_unwind_protect (xfree, error_trap);
+         add_unwind_protect (set_error_trap, error_trap);
+         restore_default_signal (ERROR_TRAP);
+       }
+      exit_immediately_on_error = 0;
+      builtin_ignoring_errexit = 1;
+      eval_unwind = 1;
+    }
+  else
+    eval_unwind = 0;
+
+  /* The temporary environment for a builtin is supposed to apply to
+     all commands executed by that builtin.  Currently, this is a
+     problem only with the `unset', `source' and `eval' builtins.
+     `mapfile' is a special case because it uses evalstring (same as
+     eval or source) to run its callbacks. */
+  isbltinenv = (builtin == source_builtin || builtin == eval_builtin || builtin == unset_builtin || builtin == mapfile_builtin);
+
+  if (isbltinenv)
+    {
+      if (subshell == 0)
+       begin_unwind_frame ("builtin_env");
+
+      if (temporary_env)
+       {
+         push_scope (VC_BLTNENV, temporary_env);
+         if (subshell == 0)
+           add_unwind_protect (pop_scope, (flags & CMD_COMMAND_BUILTIN) ? 0 : "1");
+          temporary_env = (HASH_TABLE *)NULL;    
+       }
+    }
+
+  /* `return' does a longjmp() back to a saved environment in execute_function.
+     If a variable assignment list preceded the command, and the shell is
+     running in POSIX mode, we need to merge that into the shell_variables
+     table, since `return' is a POSIX special builtin. */
+  if (posixly_correct && subshell == 0 && builtin == return_builtin && temporary_env)
+    {
+      begin_unwind_frame ("return_temp_env");
+      add_unwind_protect (merge_temporary_env, (char *)NULL);
+    }
+
+  executing_builtin++;
+  executing_command_builtin |= builtin == command_builtin;
+  result = ((*builtin) (words->next));
+
+  /* This shouldn't happen, but in case `return' comes back instead of
+     longjmp'ing, we need to unwind. */
+  if (posixly_correct && subshell == 0 && builtin == return_builtin && temporary_env)
+    discard_unwind_frame ("return_temp_env");
+
+  if (subshell == 0 && isbltinenv)
+    run_unwind_frame ("builtin_env");
+
+  if (eval_unwind)
+    {
+      exit_immediately_on_error = errexit_flag;
+      builtin_ignoring_errexit = 0;
+      if (error_trap)
+       {
+         set_error_trap (error_trap);
+         xfree (error_trap);
+       }
+      discard_unwind_frame ("eval_builtin");
+    }
+
+  return (result);
+}
+
+static int
+execute_function (var, words, flags, fds_to_close, async, subshell)
+     SHELL_VAR *var;
+     WORD_LIST *words;
+     int flags;
+     struct fd_bitmap *fds_to_close;
+     int async, subshell;
+{
+  int return_val, result;
+  COMMAND *tc, *fc, *save_current;
+  char *debug_trap, *error_trap, *return_trap;
+#if defined (ARRAY_VARS)
+  SHELL_VAR *funcname_v, *nfv, *bash_source_v, *bash_lineno_v;
+  ARRAY *funcname_a;
+  volatile ARRAY *bash_source_a;
+  volatile ARRAY *bash_lineno_a;
+#endif
+  FUNCTION_DEF *shell_fn;
+  char *sfile, *t;
+
+  USE_VAR(fc);
+
+  if (funcnest_max > 0 && funcnest >= funcnest_max)
+    {
+      internal_error (_("%s: maximum function nesting level exceeded (%d)"), var->name, funcnest);
+      funcnest = 0;    /* XXX - should we reset it somewhere else? */
+      jump_to_top_level (DISCARD);
+    }
+
+#if defined (ARRAY_VARS)
+  GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a);
+  GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a);
+  GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a);
+#endif
+
+  tc = (COMMAND *)copy_command (function_cell (var));
+  if (tc && (flags & CMD_IGNORE_RETURN))
+    tc->flags |= CMD_IGNORE_RETURN;
+
+  if (subshell == 0)
+    {
+      begin_unwind_frame ("function_calling");
+      push_context (var->name, subshell, temporary_env);
+      add_unwind_protect (pop_context, (char *)NULL);
+      unwind_protect_int (line_number);
+      unwind_protect_int (return_catch_flag);
+      unwind_protect_jmp_buf (return_catch);
+      add_unwind_protect (dispose_command, (char *)tc);
+      unwind_protect_pointer (this_shell_function);
+      unwind_protect_int (loop_level);
+      unwind_protect_int (funcnest);
+    }
+  else
+    push_context (var->name, subshell, temporary_env); /* don't unwind-protect for subshells */
+
+  temporary_env = (HASH_TABLE *)NULL;
+
+  this_shell_function = var;
+  make_funcname_visible (1);
+
+  debug_trap = TRAP_STRING(DEBUG_TRAP);
+  error_trap = TRAP_STRING(ERROR_TRAP);
+  return_trap = TRAP_STRING(RETURN_TRAP);
+  
+  /* The order of the unwind protects for debug_trap, error_trap and
+     return_trap is important here!  unwind-protect commands are run
+     in reverse order of registration.  If this causes problems, take
+     out the xfree unwind-protect calls and live with the small memory leak. */
+
+  /* function_trace_mode != 0 means that all functions inherit the DEBUG trap.
+     if the function has the trace attribute set, it inherits the DEBUG trap */
+  if (debug_trap && ((trace_p (var) == 0) && function_trace_mode == 0))
+    {
+      if (subshell == 0)
+       {
+         debug_trap = savestring (debug_trap);
+         add_unwind_protect (xfree, debug_trap);
+         add_unwind_protect (set_debug_trap, debug_trap);
+       }
+      restore_default_signal (DEBUG_TRAP);
+    }
+
+  /* error_trace_mode != 0 means that functions inherit the ERR trap. */
+  if (error_trap && error_trace_mode == 0)
+    {
+      if (subshell == 0)
+       {
+         error_trap = savestring (error_trap);
+         add_unwind_protect (xfree, error_trap);
+         add_unwind_protect (set_error_trap, error_trap);
+       }
+      restore_default_signal (ERROR_TRAP);
+    }
+
+  /* Shell functions inherit the RETURN trap if function tracing is on
+     globally or on individually for this function. */
+#if 0
+  if (return_trap && ((trace_p (var) == 0) && function_trace_mode == 0))
+#else
+  if (return_trap && (signal_in_progress (DEBUG_TRAP) || ((trace_p (var) == 0) && function_trace_mode == 0)))
+#endif
+    {
+      if (subshell == 0)
+       {
+         return_trap = savestring (return_trap);
+         add_unwind_protect (xfree, return_trap);
+         add_unwind_protect (set_return_trap, return_trap);
+       }
+      restore_default_signal (RETURN_TRAP);
+    }
+  
+  funcnest++;
+#if defined (ARRAY_VARS)
+  /* This is quite similar to the code in shell.c and elsewhere. */
+  shell_fn = find_function_def (this_shell_function->name);
+  sfile = shell_fn ? shell_fn->source_file : "";
+  array_push ((ARRAY *)funcname_a, this_shell_function->name);
+
+  array_push ((ARRAY *)bash_source_a, sfile);
+  t = itos (executing_line_number ());
+  array_push ((ARRAY *)bash_lineno_a, t);
+  free (t);
+#endif
+
+  /* The temporary environment for a function is supposed to apply to
+     all commands executed within the function body. */
+
+  remember_args (words->next, 1);
+
+  /* Update BASH_ARGV and BASH_ARGC */
+  if (debugging_mode)
+    push_args (words->next);
+
+  /* Number of the line on which the function body starts. */
+  line_number = function_line_number = tc->line;
+
+#if defined (JOB_CONTROL)
+  if (subshell)
+    stop_pipeline (async, (COMMAND *)NULL);
+#endif
+
+  fc = tc;
+
+  from_return_trap = 0;
+
+  return_catch_flag++;
+  return_val = setjmp_nosigs (return_catch);
+
+  if (return_val)
+    {
+      result = return_catch_value;
+      /* Run the RETURN trap in the function's context. */
+      save_current = currently_executing_command;
+      if (from_return_trap == 0)
+       run_return_trap ();
+      currently_executing_command = save_current;
+    }
+  else
+    {
+      /* Run the debug trap here so we can trap at the start of a function's
+        execution rather than the execution of the body's first command. */
+      showing_function_line = 1;
+      save_current = currently_executing_command;
+      result = run_debug_trap ();
+#if defined (DEBUGGER)
+      /* In debugging mode, if the DEBUG trap returns a non-zero status, we
+        skip the command. */
+      if (debugging_mode == 0 || result == EXECUTION_SUCCESS)
+       {
+         showing_function_line = 0;
+         currently_executing_command = save_current;
+         result = execute_command_internal (fc, 0, NO_PIPE, NO_PIPE, fds_to_close);
+
+         /* Run the RETURN trap in the function's context */
+         save_current = currently_executing_command;
+         run_return_trap ();
+         currently_executing_command = save_current;
+       }
+#else
+      result = execute_command_internal (fc, 0, NO_PIPE, NO_PIPE, fds_to_close);
+
+      save_current = currently_executing_command;
+      run_return_trap ();
+      currently_executing_command = save_current;
+#endif
+      showing_function_line = 0;
+    }
+
+  /* Restore BASH_ARGC and BASH_ARGV */
+  if (debugging_mode)
+    pop_args ();
+
+  if (subshell == 0)
+    run_unwind_frame ("function_calling");
+
+#if defined (ARRAY_VARS)
+  /* These two variables cannot be unset, and cannot be affected by the
+     function. */
+  array_pop ((ARRAY *)bash_source_a);
+  array_pop ((ARRAY *)bash_lineno_a);
+
+  /* FUNCNAME can be unset, and so can potentially be changed by the
+     function. */
+  GET_ARRAY_FROM_VAR ("FUNCNAME", nfv, funcname_a);
+  if (nfv == funcname_v)
+    array_pop (funcname_a);
+#endif
+  
+  if (variable_context == 0 || this_shell_function == 0)
+    {
+      make_funcname_visible (0);
+#if defined (PROCESS_SUBSTITUTION)
+      unlink_fifo_list ();
+#endif
+    }
+  
+  return (result);
+}
+
+/* A convenience routine for use by other parts of the shell to execute
+   a particular shell function. */
+int
+execute_shell_function (var, words)
+     SHELL_VAR *var;
+     WORD_LIST *words;
+{
+  int ret;
+  struct fd_bitmap *bitmap;
+
+  bitmap = new_fd_bitmap (FD_BITMAP_DEFAULT_SIZE);
+  begin_unwind_frame ("execute-shell-function");
+  add_unwind_protect (dispose_fd_bitmap, (char *)bitmap);
+      
+  ret = execute_function (var, words, 0, bitmap, 0, 0);
+
+  dispose_fd_bitmap (bitmap);
+  discard_unwind_frame ("execute-shell-function");
+
+  return ret;
+}
+
+/* Execute a shell builtin or function in a subshell environment.  This
+   routine does not return; it only calls exit().  If BUILTIN is non-null,
+   it points to a function to call to execute a shell builtin; otherwise
+   VAR points at the body of a function to execute.  WORDS is the arguments
+   to the command, REDIRECTS specifies redirections to perform before the
+   command is executed. */
+static void
+execute_subshell_builtin_or_function (words, redirects, builtin, var,
+                                     pipe_in, pipe_out, async, fds_to_close,
+                                     flags)
+     WORD_LIST *words;
+     REDIRECT *redirects;
+     sh_builtin_func_t *builtin;
+     SHELL_VAR *var;
+     int pipe_in, pipe_out, async;
+     struct fd_bitmap *fds_to_close;
+     int flags;
+{
+  int result, r, funcvalue;
+#if defined (JOB_CONTROL)
+  int jobs_hack;
+
+  jobs_hack = (builtin == jobs_builtin) &&
+               ((subshell_environment & SUBSHELL_ASYNC) == 0 || pipe_out != NO_PIPE);
+#endif
+
+  /* A subshell is neither a login shell nor interactive. */
+  login_shell = interactive = 0;
+
+  if (async)
+    subshell_environment |= SUBSHELL_ASYNC;
+  if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
+    subshell_environment |= SUBSHELL_PIPE;
+
+  maybe_make_export_env ();    /* XXX - is this needed? */
+
+#if defined (JOB_CONTROL)
+  /* Eradicate all traces of job control after we fork the subshell, so
+     all jobs begun by this subshell are in the same process group as
+     the shell itself. */
+
+  /* Allow the output of `jobs' to be piped. */
+  if (jobs_hack)
+    kill_current_pipeline ();
+  else
+    without_job_control ();
+
+  set_sigchld_handler ();
+#endif /* JOB_CONTROL */
+
+  set_sigint_handler ();
+
+  if (fds_to_close)
+    close_fd_bitmap (fds_to_close);
+
+  do_piping (pipe_in, pipe_out);
+
+  if (do_redirections (redirects, RX_ACTIVE) != 0)
+    exit (EXECUTION_FAILURE);
+
+  if (builtin)
+    {
+      /* Give builtins a place to jump back to on failure,
+        so we don't go back up to main(). */
+      result = setjmp_nosigs (top_level);
+
+      /* Give the return builtin a place to jump to when executed in a subshell
+         or pipeline */
+      funcvalue = 0;
+      if (return_catch_flag && builtin == return_builtin)
+        funcvalue = setjmp_nosigs (return_catch);
+
+      if (result == EXITPROG)
+       exit (last_command_exit_value);
+      else if (result)
+       exit (EXECUTION_FAILURE);
+      else if (funcvalue)
+       exit (return_catch_value);
+      else
+       {
+         r = execute_builtin (builtin, words, flags, 1);
+         fflush (stdout);
+         if (r == EX_USAGE)
+           r = EX_BADUSAGE;
+         exit (r);
+       }
+    }
+  else
+    {
+      r = execute_function (var, words, flags, fds_to_close, async, 1);
+      fflush (stdout);
+      exit (r);
+    }
+}
+
+/* Execute a builtin or function in the current shell context.  If BUILTIN
+   is non-null, it is the builtin command to execute, otherwise VAR points
+   to the body of a function.  WORDS are the command's arguments, REDIRECTS
+   are the redirections to perform.  FDS_TO_CLOSE is the usual bitmap of
+   file descriptors to close.
+
+   If BUILTIN is exec_builtin, the redirections specified in REDIRECTS are
+   not undone before this function returns. */
+static int
+execute_builtin_or_function (words, builtin, var, redirects,
+                            fds_to_close, flags)
+     WORD_LIST *words;
+     sh_builtin_func_t *builtin;
+     SHELL_VAR *var;
+     REDIRECT *redirects;
+     struct fd_bitmap *fds_to_close;
+     int flags;
+{
+  int result;
+  REDIRECT *saved_undo_list;
+#if defined (PROCESS_SUBSTITUTION)
+  int ofifo, nfifo, osize;
+  char *ofifo_list;
+#endif
+
+
+#if defined (PROCESS_SUBSTITUTION)  
+  ofifo = num_fifos ();
+  ofifo_list = copy_fifo_list (&osize);
+#endif
+
+  if (do_redirections (redirects, RX_ACTIVE|RX_UNDOABLE) != 0)
+    {
+      cleanup_redirects (redirection_undo_list);
+      redirection_undo_list = (REDIRECT *)NULL;
+      dispose_exec_redirects ();
+#if defined (PROCESS_SUBSTITUTION)
+      free (ofifo_list);
+#endif
+      return (EX_REDIRFAIL);   /* was EXECUTION_FAILURE */
+    }
+
+  saved_undo_list = redirection_undo_list;
+
+  /* Calling the "exec" builtin changes redirections forever. */
+  if (builtin == exec_builtin)
+    {
+      dispose_redirects (saved_undo_list);
+      saved_undo_list = exec_redirection_undo_list;
+      exec_redirection_undo_list = (REDIRECT *)NULL;
+    }
+  else
+    dispose_exec_redirects ();
+
+  if (saved_undo_list)
+    {
+      begin_unwind_frame ("saved redirects");
+      add_unwind_protect (cleanup_redirects, (char *)saved_undo_list);
+    }
+
+  redirection_undo_list = (REDIRECT *)NULL;
+
+  if (builtin)
+    result = execute_builtin (builtin, words, flags, 0);
+  else
+    result = execute_function (var, words, flags, fds_to_close, 0, 0);
+
+  /* We do this before undoing the effects of any redirections. */
+  fflush (stdout);
+  fpurge (stdout);
+  if (ferror (stdout))
+    clearerr (stdout);  
+
+  /* If we are executing the `command' builtin, but this_shell_builtin is
+     set to `exec_builtin', we know that we have something like
+     `command exec [redirection]', since otherwise `exec' would have
+     overwritten the shell and we wouldn't get here.  In this case, we
+     want to behave as if the `command' builtin had not been specified
+     and preserve the redirections. */
+  if (builtin == command_builtin && this_shell_builtin == exec_builtin)
+    {
+      int discard;
+
+      discard = 0;
+      if (saved_undo_list)
+       {
+         dispose_redirects (saved_undo_list);
+         discard = 1;
+       }
+      redirection_undo_list = exec_redirection_undo_list;
+      saved_undo_list = exec_redirection_undo_list = (REDIRECT *)NULL;      
+      if (discard)
+       discard_unwind_frame ("saved redirects");
+    }
+
+  if (saved_undo_list)
+    {
+      redirection_undo_list = saved_undo_list;
+      discard_unwind_frame ("saved redirects");
+    }
+
+  if (redirection_undo_list)
+    {
+      cleanup_redirects (redirection_undo_list);
+      redirection_undo_list = (REDIRECT *)NULL;
+    }
+
+#if defined (PROCESS_SUBSTITUTION)
+  /* Close any FIFOs created by this builtin or function. */
+  nfifo = num_fifos ();
+  if (nfifo > ofifo)
+    close_new_fifos (ofifo_list, osize);
+  free (ofifo_list);
+#endif
+
+  return (result);
+}
+
+void
+setup_async_signals ()
+{
+#if defined (__BEOS__)
+  set_signal_handler (SIGHUP, SIG_IGN);        /* they want csh-like behavior */
+#endif
+
+#if defined (JOB_CONTROL)
+  if (job_control == 0)
+#endif
+    {
+      /* Make sure we get the original signal dispositions now so we don't
+        confuse the trap builtin later if the subshell tries to use it to
+        reset SIGINT/SIGQUIT.  Don't call set_signal_ignored; that sets
+        the value of original_signals to SIG_IGN. Posix interpretation 751. */
+      get_original_signal (SIGINT);
+      set_signal_handler (SIGINT, SIG_IGN);
+
+      get_original_signal (SIGQUIT);
+      set_signal_handler (SIGQUIT, SIG_IGN);
+    }
+}
+
+/* Execute a simple command that is hopefully defined in a disk file
+   somewhere.
+
+   1) fork ()
+   2) connect pipes
+   3) look up the command
+   4) do redirections
+   5) execve ()
+   6) If the execve failed, see if the file has executable mode set.
+   If so, and it isn't a directory, then execute its contents as
+   a shell script.
+
+   Note that the filename hashing stuff has to take place up here,
+   in the parent.  This is probably why the Bourne style shells
+   don't handle it, since that would require them to go through
+   this gnarly hair, for no good reason.
+
+   NOTE: callers expect this to fork or exit(). */
+
+/* Name of a shell function to call when a command name is not found. */
+#ifndef NOTFOUND_HOOK
+#  define NOTFOUND_HOOK "command_not_found_handle"
+#endif
+
+static int
+execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
+                     async, fds_to_close, cmdflags)
+     WORD_LIST *words;
+     REDIRECT *redirects;
+     char *command_line;
+     int pipe_in, pipe_out, async;
+     struct fd_bitmap *fds_to_close;
+     int cmdflags;
+{
+  char *pathname, *command, **args;
+  int nofork, result;
+  pid_t pid;
+  SHELL_VAR *hookf;
+  WORD_LIST *wl;
+
+  nofork = (cmdflags & CMD_NO_FORK);  /* Don't fork, just exec, if no pipes */
+  pathname = words->word->word;
+
+  result = EXECUTION_SUCCESS;
+#if defined (RESTRICTED_SHELL)
+  command = (char *)NULL;
+  if (restricted && mbschr (pathname, '/'))
+    {
+      internal_error (_("%s: restricted: cannot specify `/' in command names"),
+                   pathname);
+      result = last_command_exit_value = EXECUTION_FAILURE;
+
+      /* If we're not going to fork below, we must already be in a child
+         process or a context in which it's safe to call exit(2).  */
+      if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE)
+       exit (last_command_exit_value);
+      else
+       goto parent_return;
+    }
+#endif /* RESTRICTED_SHELL */
+
+  command = search_for_command (pathname, 1);
+
+  if (command)
+    {
+      maybe_make_export_env ();
+      put_command_name_into_env (command);
+    }
+
+  /* We have to make the child before we check for the non-existence
+     of COMMAND, since we want the error messages to be redirected. */
+  /* If we can get away without forking and there are no pipes to deal with,
+     don't bother to fork, just directly exec the command. */
+  if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE)
+    pid = 0;
+  else
+    pid = make_child (savestring (command_line), async);
+
+  if (pid == 0)
+    {
+      int old_interactive;
+
+      reset_terminating_signals ();    /* XXX */
+      /* Cancel traps, in trap.c. */
+      restore_original_signals ();
+
+      CHECK_SIGTERM;
+
+      /* restore_original_signals may have undone the work done
+        by make_child to ensure that SIGINT and SIGQUIT are ignored
+        in asynchronous children. */
+      if (async)
+       {
+         if ((cmdflags & CMD_STDIN_REDIR) &&
+               pipe_in == NO_PIPE &&
+               (stdin_redirects (redirects) == 0))
+           async_redirect_stdin ();
+         setup_async_signals ();
+       }
+
+      /* This functionality is now provided by close-on-exec of the
+        file descriptors manipulated by redirection and piping.
+        Some file descriptors still need to be closed in all children
+        because of the way bash does pipes; fds_to_close is a
+        bitmap of all such file descriptors. */
+      if (fds_to_close)
+       close_fd_bitmap (fds_to_close);
+
+      do_piping (pipe_in, pipe_out);
+
+      old_interactive = interactive;
+      if (async)
+       interactive = 0;
+
+      subshell_environment = SUBSHELL_FORK;
+
+      if (redirects && (do_redirections (redirects, RX_ACTIVE) != 0))
+       {
+#if defined (PROCESS_SUBSTITUTION)
+         /* Try to remove named pipes that may have been created as the
+            result of redirections. */
+         unlink_fifo_list ();
+#endif /* PROCESS_SUBSTITUTION */
+         exit (EXECUTION_FAILURE);
+       }
+
+      if (async)
+       interactive = old_interactive;
+
+      if (command == 0)
+       {
+         hookf = find_function (NOTFOUND_HOOK);
+         if (hookf == 0)
+           {
+             /* Make sure filenames are displayed using printable characters */
+             if (ansic_shouldquote (pathname))
+               pathname = ansic_quote (pathname, 0, NULL);
+             internal_error (_("%s: command not found"), pathname);
+             exit (EX_NOTFOUND);       /* Posix.2 says the exit status is 127 */
+           }
+
+#if defined (JOB_CONTROL)
+         /* May need to reinitialize more of the job control state here. */
+         kill_current_pipeline ();
+#endif
+
+         wl = make_word_list (make_word (NOTFOUND_HOOK), words);
+         exit (execute_shell_function (hookf, wl));
+       }
+
+      CHECK_SIGTERM;
+
+      /* Execve expects the command name to be in args[0].  So we
+        leave it there, in the same format that the user used to
+        type it in. */
+      args = strvec_from_word_list (words, 0, 0, (int *)NULL);
+      exit (shell_execve (command, args, export_env));
+    }
+  else
+    {
+parent_return:
+      QUIT;
+
+      /* Make sure that the pipes are closed in the parent. */
+      close_pipes (pipe_in, pipe_out);
+#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
+      if (variable_context == 0)
+        unlink_fifo_list ();
+#endif
+      FREE (command);
+      return (result);
+    }
+}
+
+/* CPP defines to decide whether a particular index into the #! line
+   corresponds to a valid interpreter name or argument character, or
+   whitespace.  The MSDOS define is to allow \r to be treated the same
+   as \n. */
+
+#if !defined (MSDOS)
+#  define STRINGCHAR(ind) \
+    (ind < sample_len && !whitespace (sample[ind]) && sample[ind] != '\n')
+#  define WHITECHAR(ind) \
+    (ind < sample_len && whitespace (sample[ind]))
+#else  /* MSDOS */
+#  define STRINGCHAR(ind) \
+    (ind < sample_len && !whitespace (sample[ind]) && sample[ind] != '\n' && sample[ind] != '\r')
+#  define WHITECHAR(ind) \
+    (ind < sample_len && whitespace (sample[ind]))
+#endif /* MSDOS */
+
+static char *
+getinterp (sample, sample_len, endp)
+     char *sample;
+     int sample_len, *endp;
+{
+  register int i;
+  char *execname;
+  int start;
+
+  /* Find the name of the interpreter to exec. */
+  for (i = 2; i < sample_len && whitespace (sample[i]); i++)
+    ;
+
+  for (start = i; STRINGCHAR(i); i++)
+    ;
+
+  execname = substring (sample, start, i);
+
+  if (endp)
+    *endp = i;
+  return execname;
+}
+
+#if !defined (HAVE_HASH_BANG_EXEC)
+/* If the operating system on which we're running does not handle
+   the #! executable format, then help out.  SAMPLE is the text read
+   from the file, SAMPLE_LEN characters.  COMMAND is the name of
+   the script; it and ARGS, the arguments given by the user, will
+   become arguments to the specified interpreter.  ENV is the environment
+   to pass to the interpreter.
+
+   The word immediately following the #! is the interpreter to execute.
+   A single argument to the interpreter is allowed. */
+
+static int
+execute_shell_script (sample, sample_len, command, args, env)
+     char *sample;
+     int sample_len;
+     char *command;
+     char **args, **env;
+{
+  char *execname, *firstarg;
+  int i, start, size_increment, larry;
+
+  /* Find the name of the interpreter to exec. */
+  execname = getinterp (sample, sample_len, &i);
+  size_increment = 1;
+
+  /* Now the argument, if any. */
+  for (firstarg = (char *)NULL, start = i; WHITECHAR(i); i++)
+    ;
+
+  /* If there is more text on the line, then it is an argument for the
+     interpreter. */
+
+  if (STRINGCHAR(i))  
+    {
+      for (start = i; STRINGCHAR(i); i++)
+       ;
+      firstarg = substring ((char *)sample, start, i);
+      size_increment = 2;
+    }
+
+  larry = strvec_len (args) + size_increment;
+  args = strvec_resize (args, larry + 1);
+
+  for (i = larry - 1; i; i--)
+    args[i] = args[i - size_increment];
+
+  args[0] = execname;
+  if (firstarg)
+    {
+      args[1] = firstarg;
+      args[2] = command;
+    }
+  else
+    args[1] = command;
+
+  args[larry] = (char *)NULL;
+
+  return (shell_execve (execname, args, env));
+}
+#undef STRINGCHAR
+#undef WHITECHAR
+
+#endif /* !HAVE_HASH_BANG_EXEC */
+
+static void
+initialize_subshell ()
+{
+#if defined (ALIAS)
+  /* Forget about any aliases that we knew of.  We are in a subshell. */
+  delete_all_aliases ();
+#endif /* ALIAS */
+
+#if defined (HISTORY)
+  /* Forget about the history lines we have read.  This is a non-interactive
+     subshell. */
+  history_lines_this_session = 0;
+#endif
+
+#if defined (JOB_CONTROL)
+  /* Forget about the way job control was working. We are in a subshell. */
+  without_job_control ();
+  set_sigchld_handler ();
+  init_job_stats ();
+#endif /* JOB_CONTROL */
+
+  /* Reset the values of the shell flags and options. */
+  reset_shell_flags ();
+  reset_shell_options ();
+  reset_shopt_options ();
+
+  /* Zero out builtin_env, since this could be a shell script run from a
+     sourced file with a temporary environment supplied to the `source/.'
+     builtin.  Such variables are not supposed to be exported (empirical
+     testing with sh and ksh).  Just throw it away; don't worry about a
+     memory leak. */
+  if (vc_isbltnenv (shell_variables))
+    shell_variables = shell_variables->down;
+
+  clear_unwind_protect_list (0);
+  /* XXX -- are there other things we should be resetting here? */
+  parse_and_execute_level = 0;         /* nothing left to restore it */
+
+  /* We're no longer inside a shell function. */
+  variable_context = return_catch_flag = funcnest = 0;
+
+  executing_list = 0;          /* XXX */
+
+  /* If we're not interactive, close the file descriptor from which we're
+     reading the current shell script. */
+  if (interactive_shell == 0)
+    unset_bash_input (0);
+}
+
+#if defined (HAVE_SETOSTYPE) && defined (_POSIX_SOURCE)
+#  define SETOSTYPE(x) __setostype(x)
+#else
+#  define SETOSTYPE(x)
+#endif
+
+#define READ_SAMPLE_BUF(file, buf, len) \
+  do \
+    { \
+      fd = open(file, O_RDONLY); \
+      if (fd >= 0) \
+       { \
+         len = read (fd, buf, 80); \
+         close (fd); \
+       } \
+      else \
+       len = -1; \
+    } \
+  while (0)
+      
+/* Call execve (), handling interpreting shell scripts, and handling
+   exec failures. */
+int
+shell_execve (command, args, env)
+     char *command;
+     char **args, **env;
+{
+  int larray, i, fd;
+  char sample[80];
+  int sample_len;
+
+  SETOSTYPE (0);               /* Some systems use for USG/POSIX semantics */
+  execve (command, args, env);
+  i = errno;                   /* error from execve() */
+  CHECK_TERMSIG;
+  SETOSTYPE (1);
+
+  /* If we get to this point, then start checking out the file.
+     Maybe it is something we can hack ourselves. */
+  if (i != ENOEXEC)
+    {
+      if (file_isdir (command))
+#if defined (EISDIR)
+       internal_error (_("%s: %s"), command, strerror (EISDIR));
+#else
+       internal_error (_("%s: is a directory"), command);
+#endif
+      else if (executable_file (command) == 0)
+       {
+         errno = i;
+         file_error (command);
+       }
+      /* errors not involving the path argument to execve. */
+      else if (i == E2BIG || i == ENOMEM)
+       {
+         errno = i;
+         file_error (command);
+       }
+      else
+       {
+         /* The file has the execute bits set, but the kernel refuses to
+            run it for some reason.  See why. */
+#if defined (HAVE_HASH_BANG_EXEC)
+         READ_SAMPLE_BUF (command, sample, sample_len);
+         sample[sample_len - 1] = '\0';
+         if (sample_len > 2 && sample[0] == '#' && sample[1] == '!')
+           {
+             char *interp;
+             int ilen;
+
+             interp = getinterp (sample, sample_len, (int *)NULL);
+             ilen = strlen (interp);
+             errno = i;
+             if (interp[ilen - 1] == '\r')
+               {
+                 interp = xrealloc (interp, ilen + 2);
+                 interp[ilen - 1] = '^';
+                 interp[ilen] = 'M';
+                 interp[ilen + 1] = '\0';
+               }
+             sys_error (_("%s: %s: bad interpreter"), command, interp ? interp : "");
+             FREE (interp);
+             return (EX_NOEXEC);
+           }
+#endif
+         errno = i;
+         file_error (command);
+       }
+      return ((i == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);        /* XXX Posix.2 says that exit status is 126 */
+    }
+
+  /* This file is executable.
+     If it begins with #!, then help out people with losing operating
+     systems.  Otherwise, check to see if it is a binary file by seeing
+     if the contents of the first line (or up to 80 characters) are in the
+     ASCII set.  If it's a text file, execute the contents as shell commands,
+     otherwise return 126 (EX_BINARY_FILE). */
+  READ_SAMPLE_BUF (command, sample, sample_len);
+
+  if (sample_len == 0)
+    return (EXECUTION_SUCCESS);
+
+  /* Is this supposed to be an executable script?
+     If so, the format of the line is "#! interpreter [argument]".
+     A single argument is allowed.  The BSD kernel restricts
+     the length of the entire line to 32 characters (32 bytes
+     being the size of the BSD exec header), but we allow 80
+     characters. */
+  if (sample_len > 0)
+    {
+#if !defined (HAVE_HASH_BANG_EXEC)
+      if (sample_len > 2 && sample[0] == '#' && sample[1] == '!')
+       return (execute_shell_script (sample, sample_len, command, args, env));
+      else
+#endif
+      if (check_binary_file (sample, sample_len))
+       {
+         internal_error (_("%s: cannot execute binary file: %s"), command, strerror (i));
+         return (EX_BINARY_FILE);
+       }
+    }
+
+  /* We have committed to attempting to execute the contents of this file
+     as shell commands. */
+
+  initialize_subshell ();
+
+  set_sigint_handler ();
+
+  /* Insert the name of this shell into the argument list. */
+  larray = strvec_len (args) + 1;
+  args = strvec_resize (args, larray + 1);
+
+  for (i = larray - 1; i; i--)
+    args[i] = args[i - 1];
+
+  args[0] = shell_name;
+  args[1] = command;
+  args[larray] = (char *)NULL;
+
+  if (args[0][0] == '-')
+    args[0]++;
+
+#if defined (RESTRICTED_SHELL)
+  if (restricted)
+    change_flag ('r', FLAG_OFF);
+#endif
+
+  if (subshell_argv)
+    {
+      /* Can't free subshell_argv[0]; that is shell_name. */
+      for (i = 1; i < subshell_argc; i++)
+       free (subshell_argv[i]);
+      free (subshell_argv);
+    }
+
+  dispose_command (currently_executing_command);       /* XXX */
+  currently_executing_command = (COMMAND *)NULL;
+
+  subshell_argc = larray;
+  subshell_argv = args;
+  subshell_envp = env;
+
+  unbind_args ();      /* remove the positional parameters */
+
+  longjmp (subshell_top_level, 1);
+  /*NOTREACHED*/
+}
+
+static int
+execute_intern_function (name, funcdef)
+     WORD_DESC *name;
+     FUNCTION_DEF *funcdef;
+{
+  SHELL_VAR *var;
+
+  if (check_identifier (name, posixly_correct) == 0)
+    {
+      if (posixly_correct && interactive_shell == 0)
+       {
+         last_command_exit_value = EX_BADUSAGE;
+         jump_to_top_level (ERREXIT);
+       }
+      return (EXECUTION_FAILURE);
+    }
+
+  /* Posix interpretation 383 */
+  if (posixly_correct && find_special_builtin (name->word))
+    {
+      internal_error (_("`%s': is a special builtin"), name->word);
+      last_command_exit_value = EX_BADUSAGE;
+      jump_to_top_level (interactive_shell ? DISCARD : ERREXIT);
+    }
+
+  var = find_function (name->word);
+  if (var && (readonly_p (var) || noassign_p (var)))
+    {
+      if (readonly_p (var))
+       internal_error (_("%s: readonly function"), var->name);
+      return (EXECUTION_FAILURE);
+    }
+
+#if defined (DEBUGGER)
+  bind_function_def (name->word, funcdef);
+#endif
+
+  bind_function (name->word, funcdef->command);
+  return (EXECUTION_SUCCESS);
+}
+
+#if defined (INCLUDE_UNUSED)
+#if defined (PROCESS_SUBSTITUTION)
+void
+close_all_files ()
+{
+  register int i, fd_table_size;
+
+  fd_table_size = getdtablesize ();
+  if (fd_table_size > 256)     /* clamp to a reasonable value */
+    fd_table_size = 256;
+
+  for (i = 3; i < fd_table_size; i++)
+    close (i);
+}
+#endif /* PROCESS_SUBSTITUTION */
+#endif
+
+static void
+close_pipes (in, out)
+     int in, out;
+{
+  if (in >= 0)
+    close (in);
+  if (out >= 0)
+    close (out);
+}
+
+static void
+dup_error (oldd, newd)
+     int oldd, newd;
+{
+  sys_error (_("cannot duplicate fd %d to fd %d"), oldd, newd);
+}
+
+/* Redirect input and output to be from and to the specified pipes.
+   NO_PIPE and REDIRECT_BOTH are handled correctly. */
+static void
+do_piping (pipe_in, pipe_out)
+     int pipe_in, pipe_out;
+{
+  if (pipe_in != NO_PIPE)
+    {
+      if (dup2 (pipe_in, 0) < 0)
+       dup_error (pipe_in, 0);
+      if (pipe_in > 0)
+       close (pipe_in);
+#ifdef __CYGWIN__
+      /* Let stdio know the fd may have changed from text to binary mode. */
+      freopen (NULL, "r", stdin);
+#endif /* __CYGWIN__ */
+    }
+  if (pipe_out != NO_PIPE)
+    {
+      if (pipe_out != REDIRECT_BOTH)
+       {
+         if (dup2 (pipe_out, 1) < 0)
+           dup_error (pipe_out, 1);
+         if (pipe_out == 0 || pipe_out > 1)
+           close (pipe_out);
+       }
+      else
+       {
+         if (dup2 (1, 2) < 0)
+           dup_error (1, 2);
+       }
+#ifdef __CYGWIN__
+      /* Let stdio know the fd may have changed from text to binary mode, and
+        make sure to preserve stdout line buffering. */
+      freopen (NULL, "w", stdout);
+      sh_setlinebuf (stdout);
+#endif /* __CYGWIN__ */
+    }
+}
index 913e0da0cf8497cc454fb3ce937aef298ab7de9e..dccfdc7eb2c4bf56a012900321ed5d62bd5589a7 100644 (file)
@@ -2677,7 +2677,8 @@ _rl_clean_up_for_exit ()
 {
   if (_rl_echoing_p)
     {
-      _rl_move_vert (_rl_vis_botlin);
+      if (_rl_vis_botlin > 0)  /* minor optimization plus bug fix */
+       _rl_move_vert (_rl_vis_botlin);
       _rl_vis_botlin = 0;
       fflush (rl_outstream);
       rl_restart_output (1, 0);
index 1a78783f9aac29bc5c60b92d2ef6d217bd5ba0c1..62011bb8e5e178904cd7e829fe0acb5b39e54032 100644 (file)
@@ -506,7 +506,7 @@ rl_yank (count, ignore)
   if (rl_kill_ring == 0)
     {
       _rl_abort_internal ();
-      return -1;
+      return 1;
     }
 
   _rl_set_mark_at_pos (rl_point);
@@ -528,7 +528,7 @@ rl_yank_pop (count, key)
       !rl_kill_ring)
     {
       _rl_abort_internal ();
-      return -1;
+      return 1;
     }
 
   l = strlen (rl_kill_ring[rl_kill_index]);
@@ -546,7 +546,7 @@ rl_yank_pop (count, key)
   else
     {
       _rl_abort_internal ();
-      return -1;
+      return 1;
     }
 }
 
@@ -575,7 +575,7 @@ rl_yank_nth_arg_internal (count, ignore, history_skip)
   if (entry == 0)
     {
       rl_ding ();
-      return -1;
+      return 1;
     }
 
   arg = history_arg_extract (count, count, entry->line);
@@ -583,7 +583,7 @@ rl_yank_nth_arg_internal (count, ignore, history_skip)
     {
       rl_ding ();
       FREE (arg);
-      return -1;
+      return 1;
     }
 
   rl_begin_undo_group ();
diff --git a/lib/readline/kill.c~ b/lib/readline/kill.c~
new file mode 100644 (file)
index 0000000..1a78783
--- /dev/null
@@ -0,0 +1,694 @@
+/* kill.c -- kill ring management. */
+
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library (Readline), a library
+   for reading lines of text with interactive input and history editing.      
+
+   Readline is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Readline is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Readline.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>           /* for _POSIX_VERSION */
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Killing Mechanism                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* What we assume for a max number of kills. */
+#define DEFAULT_MAX_KILLS 10
+
+/* The real variable to look at to find out when to flush kills. */
+static int rl_max_kills =  DEFAULT_MAX_KILLS;
+
+/* Where to store killed text. */
+static char **rl_kill_ring = (char **)NULL;
+
+/* Where we are in the kill ring. */
+static int rl_kill_index;
+
+/* How many slots we have in the kill ring. */
+static int rl_kill_ring_length;
+
+static int _rl_copy_to_kill_ring PARAMS((char *, int));
+static int region_kill_internal PARAMS((int));
+static int _rl_copy_word_as_kill PARAMS((int, int));
+static int rl_yank_nth_arg_internal PARAMS((int, int, int));
+
+/* How to say that you only want to save a certain amount
+   of kill material. */
+int
+rl_set_retained_kills (num)
+     int num;
+{
+  return 0;
+}
+
+/* Add TEXT to the kill ring, allocating a new kill ring slot as necessary.
+   This uses TEXT directly, so the caller must not free it.  If APPEND is
+   non-zero, and the last command was a kill, the text is appended to the
+   current kill ring slot, otherwise prepended. */
+static int
+_rl_copy_to_kill_ring (text, append)
+     char *text;
+     int append;
+{
+  char *old, *new;
+  int slot;
+
+  /* First, find the slot to work with. */
+  if (_rl_last_command_was_kill == 0)
+    {
+      /* Get a new slot.  */
+      if (rl_kill_ring == 0)
+       {
+         /* If we don't have any defined, then make one. */
+         rl_kill_ring = (char **)
+           xmalloc (((rl_kill_ring_length = 1) + 1) * sizeof (char *));
+         rl_kill_ring[slot = 0] = (char *)NULL;
+       }
+      else
+       {
+         /* We have to add a new slot on the end, unless we have
+            exceeded the max limit for remembering kills. */
+         slot = rl_kill_ring_length;
+         if (slot == rl_max_kills)
+           {
+             register int i;
+             xfree (rl_kill_ring[0]);
+             for (i = 0; i < slot; i++)
+               rl_kill_ring[i] = rl_kill_ring[i + 1];
+           }
+         else
+           {
+             slot = rl_kill_ring_length += 1;
+             rl_kill_ring = (char **)xrealloc (rl_kill_ring, slot * sizeof (char *));
+           }
+         rl_kill_ring[--slot] = (char *)NULL;
+       }
+    }
+  else
+    slot = rl_kill_ring_length - 1;
+
+  /* If the last command was a kill, prepend or append. */
+  if (_rl_last_command_was_kill && rl_editing_mode != vi_mode)
+    {
+      old = rl_kill_ring[slot];
+      new = (char *)xmalloc (1 + strlen (old) + strlen (text));
+
+      if (append)
+       {
+         strcpy (new, old);
+         strcat (new, text);
+       }
+      else
+       {
+         strcpy (new, text);
+         strcat (new, old);
+       }
+      xfree (old);
+      xfree (text);
+      rl_kill_ring[slot] = new;
+    }
+  else
+    rl_kill_ring[slot] = text;
+
+  rl_kill_index = slot;
+  return 0;
+}
+
+/* The way to kill something.  This appends or prepends to the last
+   kill, if the last command was a kill command.  if FROM is less
+   than TO, then the text is appended, otherwise prepended.  If the
+   last command was not a kill command, then a new slot is made for
+   this kill. */
+int
+rl_kill_text (from, to)
+     int from, to;
+{
+  char *text;
+
+  /* Is there anything to kill? */
+  if (from == to)
+    {
+      _rl_last_command_was_kill++;
+      return 0;
+    }
+
+  text = rl_copy_text (from, to);
+
+  /* Delete the copied text from the line. */
+  rl_delete_text (from, to);
+
+  _rl_copy_to_kill_ring (text, from < to);
+
+  _rl_last_command_was_kill++;
+  return 0;
+}
+
+/* Now REMEMBER!  In order to do prepending or appending correctly, kill
+   commands always make rl_point's original position be the FROM argument,
+   and rl_point's extent be the TO argument. */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Killing Commands                            */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Delete the word at point, saving the text in the kill ring. */
+int
+rl_kill_word (count, key)
+     int count, key;
+{
+  int orig_point;
+
+  if (count < 0)
+    return (rl_backward_kill_word (-count, key));
+  else
+    {
+      orig_point = rl_point;
+      rl_forward_word (count, key);
+
+      if (rl_point != orig_point)
+       rl_kill_text (orig_point, rl_point);
+
+      rl_point = orig_point;
+      if (rl_editing_mode == emacs_mode)
+       rl_mark = rl_point;
+    }
+  return 0;
+}
+
+/* Rubout the word before point, placing it on the kill ring. */
+int
+rl_backward_kill_word (count, ignore)
+     int count, ignore;
+{
+  int orig_point;
+
+  if (count < 0)
+    return (rl_kill_word (-count, ignore));
+  else
+    {
+      orig_point = rl_point;
+      rl_backward_word (count, ignore);
+
+      if (rl_point != orig_point)
+       rl_kill_text (orig_point, rl_point);
+
+      if (rl_editing_mode == emacs_mode)
+       rl_mark = rl_point;
+    }
+  return 0;
+}
+
+/* Kill from here to the end of the line.  If DIRECTION is negative, kill
+   back to the line start instead. */
+int
+rl_kill_line (direction, ignore)
+     int direction, ignore;
+{
+  int orig_point;
+
+  if (direction < 0)
+    return (rl_backward_kill_line (1, ignore));
+  else
+    {
+      orig_point = rl_point;
+      rl_end_of_line (1, ignore);
+      if (orig_point != rl_point)
+       rl_kill_text (orig_point, rl_point);
+      rl_point = orig_point;
+      if (rl_editing_mode == emacs_mode)
+       rl_mark = rl_point;
+    }
+  return 0;
+}
+
+/* Kill backwards to the start of the line.  If DIRECTION is negative, kill
+   forwards to the line end instead. */
+int
+rl_backward_kill_line (direction, ignore)
+     int direction, ignore;
+{
+  int orig_point;
+
+  if (direction < 0)
+    return (rl_kill_line (1, ignore));
+  else
+    {
+      if (!rl_point)
+       rl_ding ();
+      else
+       {
+         orig_point = rl_point;
+         rl_beg_of_line (1, ignore);
+         if (rl_point != orig_point)
+           rl_kill_text (orig_point, rl_point);
+         if (rl_editing_mode == emacs_mode)
+           rl_mark = rl_point;
+       }
+    }
+  return 0;
+}
+
+/* Kill the whole line, no matter where point is. */
+int
+rl_kill_full_line (count, ignore)
+     int count, ignore;
+{
+  rl_begin_undo_group ();
+  rl_point = 0;
+  rl_kill_text (rl_point, rl_end);
+  rl_mark = 0;
+  rl_end_undo_group ();
+  return 0;
+}
+
+/* The next two functions mimic unix line editing behaviour, except they
+   save the deleted text on the kill ring.  This is safer than not saving
+   it, and since we have a ring, nobody should get screwed. */
+
+/* This does what C-w does in Unix.  We can't prevent people from
+   using behaviour that they expect. */
+int
+rl_unix_word_rubout (count, key)
+     int count, key;
+{
+  int orig_point;
+
+  if (rl_point == 0)
+    rl_ding ();
+  else
+    {
+      orig_point = rl_point;
+      if (count <= 0)
+       count = 1;
+
+      while (count--)
+       {
+         while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
+           rl_point--;
+
+         while (rl_point && (whitespace (rl_line_buffer[rl_point - 1]) == 0))
+           rl_point--;
+       }
+
+      rl_kill_text (orig_point, rl_point);
+      if (rl_editing_mode == emacs_mode)
+       rl_mark = rl_point;
+    }
+
+  return 0;
+}
+
+/* This deletes one filename component in a Unix pathname.  That is, it
+   deletes backward to directory separator (`/') or whitespace.  */
+int
+rl_unix_filename_rubout (count, key)
+     int count, key;
+{
+  int orig_point, c;
+
+  if (rl_point == 0)
+    rl_ding ();
+  else
+    {
+      orig_point = rl_point;
+      if (count <= 0)
+       count = 1;
+
+      while (count--)
+       {
+         c = rl_line_buffer[rl_point - 1];
+         while (rl_point && (whitespace (c) || c == '/'))
+           {
+             rl_point--;
+             c = rl_line_buffer[rl_point - 1];
+           }
+
+         while (rl_point && (whitespace (c) == 0) && c != '/')
+           {
+             rl_point--;
+             c = rl_line_buffer[rl_point - 1];
+           }
+       }
+
+      rl_kill_text (orig_point, rl_point);
+      if (rl_editing_mode == emacs_mode)
+       rl_mark = rl_point;
+    }
+
+  return 0;
+}
+
+/* Here is C-u doing what Unix does.  You don't *have* to use these
+   key-bindings.  We have a choice of killing the entire line, or
+   killing from where we are to the start of the line.  We choose the
+   latter, because if you are a Unix weenie, then you haven't backspaced
+   into the line at all, and if you aren't, then you know what you are
+   doing. */
+int
+rl_unix_line_discard (count, key)
+     int count, key;
+{
+  if (rl_point == 0)
+    rl_ding ();
+  else
+    {
+      rl_kill_text (rl_point, 0);
+      rl_point = 0;
+      if (rl_editing_mode == emacs_mode)
+       rl_mark = rl_point;
+    }
+  return 0;
+}
+
+/* Copy the text in the `region' to the kill ring.  If DELETE is non-zero,
+   delete the text from the line as well. */
+static int
+region_kill_internal (delete)
+     int delete;
+{
+  char *text;
+
+  if (rl_mark != rl_point)
+    {
+      text = rl_copy_text (rl_point, rl_mark);
+      if (delete)
+       rl_delete_text (rl_point, rl_mark);
+      _rl_copy_to_kill_ring (text, rl_point < rl_mark);
+    }
+
+  _rl_last_command_was_kill++;
+  return 0;
+}
+
+/* Copy the text in the region to the kill ring. */
+int
+rl_copy_region_to_kill (count, ignore)
+     int count, ignore;
+{
+  return (region_kill_internal (0));
+}
+
+/* Kill the text between the point and mark. */
+int
+rl_kill_region (count, ignore)
+     int count, ignore;
+{
+  int r, npoint;
+
+  npoint = (rl_point < rl_mark) ? rl_point : rl_mark;
+  r = region_kill_internal (1);
+  _rl_fix_point (1);
+  rl_point = npoint;
+  return r;
+}
+
+/* Copy COUNT words to the kill ring.  DIR says which direction we look
+   to find the words. */
+static int
+_rl_copy_word_as_kill (count, dir)
+     int count, dir;
+{
+  int om, op, r;
+
+  om = rl_mark;
+  op = rl_point;
+
+  if (dir > 0)
+    rl_forward_word (count, 0);
+  else
+    rl_backward_word (count, 0);
+
+  rl_mark = rl_point;
+
+  if (dir > 0)
+    rl_backward_word (count, 0);
+  else
+    rl_forward_word (count, 0);
+
+  r = region_kill_internal (0);
+
+  rl_mark = om;
+  rl_point = op;
+
+  return r;
+}
+
+int
+rl_copy_forward_word (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_copy_backward_word (-count, key));
+
+  return (_rl_copy_word_as_kill (count, 1));
+}
+
+int
+rl_copy_backward_word (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_copy_forward_word (-count, key));
+
+  return (_rl_copy_word_as_kill (count, -1));
+}
+  
+/* Yank back the last killed text.  This ignores arguments. */
+int
+rl_yank (count, ignore)
+     int count, ignore;
+{
+  if (rl_kill_ring == 0)
+    {
+      _rl_abort_internal ();
+      return -1;
+    }
+
+  _rl_set_mark_at_pos (rl_point);
+  rl_insert_text (rl_kill_ring[rl_kill_index]);
+  return 0;
+}
+
+/* If the last command was yank, or yank_pop, and the text just
+   before point is identical to the current kill item, then
+   delete that text from the line, rotate the index down, and
+   yank back some other text. */
+int
+rl_yank_pop (count, key)
+     int count, key;
+{
+  int l, n;
+
+  if (((rl_last_func != rl_yank_pop) && (rl_last_func != rl_yank)) ||
+      !rl_kill_ring)
+    {
+      _rl_abort_internal ();
+      return -1;
+    }
+
+  l = strlen (rl_kill_ring[rl_kill_index]);
+  n = rl_point - l;
+  if (n >= 0 && STREQN (rl_line_buffer + n, rl_kill_ring[rl_kill_index], l))
+    {
+      rl_delete_text (n, rl_point);
+      rl_point = n;
+      rl_kill_index--;
+      if (rl_kill_index < 0)
+       rl_kill_index = rl_kill_ring_length - 1;
+      rl_yank (1, 0);
+      return 0;
+    }
+  else
+    {
+      _rl_abort_internal ();
+      return -1;
+    }
+}
+
+/* Yank the COUNTh argument from the previous history line, skipping
+   HISTORY_SKIP lines before looking for the `previous line'. */
+static int
+rl_yank_nth_arg_internal (count, ignore, history_skip)
+     int count, ignore, history_skip;
+{
+  register HIST_ENTRY *entry;
+  char *arg;
+  int i, pos;
+
+  pos = where_history ();
+
+  if (history_skip)
+    {
+      for (i = 0; i < history_skip; i++)
+       entry = previous_history ();
+    }
+
+  entry = previous_history ();
+
+  history_set_pos (pos);
+
+  if (entry == 0)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  arg = history_arg_extract (count, count, entry->line);
+  if (!arg || !*arg)
+    {
+      rl_ding ();
+      FREE (arg);
+      return -1;
+    }
+
+  rl_begin_undo_group ();
+
+  _rl_set_mark_at_pos (rl_point);
+
+#if defined (VI_MODE)
+  /* Vi mode always inserts a space before yanking the argument, and it
+     inserts it right *after* rl_point. */
+  if (rl_editing_mode == vi_mode)
+    {
+      rl_vi_append_mode (1, ignore);
+      rl_insert_text (" ");
+    }
+#endif /* VI_MODE */
+
+  rl_insert_text (arg);
+  xfree (arg);
+
+  rl_end_undo_group ();
+  return 0;
+}
+
+/* Yank the COUNTth argument from the previous history line. */
+int
+rl_yank_nth_arg (count, ignore)
+     int count, ignore;
+{
+  return (rl_yank_nth_arg_internal (count, ignore, 0));
+}
+
+/* Yank the last argument from the previous history line.  This `knows'
+   how rl_yank_nth_arg treats a count of `$'.  With an argument, this
+   behaves the same as rl_yank_nth_arg. */
+int
+rl_yank_last_arg (count, key)
+     int count, key;
+{
+  static int history_skip = 0;
+  static int explicit_arg_p = 0;
+  static int count_passed = 1;
+  static int direction = 1;
+  static int undo_needed = 0;
+  int retval;
+
+  if (rl_last_func != rl_yank_last_arg)
+    {
+      history_skip = 0;
+      explicit_arg_p = rl_explicit_arg;
+      count_passed = count;
+      direction = 1;
+    }
+  else
+    {
+      if (undo_needed)
+       rl_do_undo ();
+      if (count < 0)           /* XXX - was < 1 */
+        direction = -direction;
+      history_skip += direction;
+      if (history_skip < 0)
+       history_skip = 0;
+    }
+  if (explicit_arg_p)
+    retval = rl_yank_nth_arg_internal (count_passed, key, history_skip);
+  else
+    retval = rl_yank_nth_arg_internal ('$', key, history_skip);
+
+  undo_needed = retval == 0;
+  return retval;
+}
+
+/* A special paste command for users of Cygnus's cygwin32. */
+#if defined (__CYGWIN__)
+#include <windows.h>
+
+int
+rl_paste_from_clipboard (count, key)
+     int count, key;
+{
+  char *data, *ptr;
+  int len;
+
+  if (OpenClipboard (NULL) == 0)
+    return (0);
+
+  data = (char *)GetClipboardData (CF_TEXT);
+  if (data)
+    {
+      ptr = strchr (data, '\r');
+      if (ptr)
+       {
+         len = ptr - data;
+         ptr = (char *)xmalloc (len + 1);
+         ptr[len] = '\0';
+         strncpy (ptr, data, len);
+       }
+      else
+        ptr = data;
+      _rl_set_mark_at_pos (rl_point);
+      rl_insert_text (ptr);
+      if (ptr != data)
+       xfree (ptr);
+      CloseClipboard ();
+    }
+  return (0);
+}
+#endif /* __CYGWIN__ */
index b99a1a69fe6920c712f2631b69dfef24f487b6e7..c7017cc6b3dab6303d9278031b557bcfd0862f02 100644 (file)
@@ -219,7 +219,7 @@ rl_start_kbd_macro (ignore1, ignore2)
   if (RL_ISSTATE (RL_STATE_MACRODEF))
     {
       _rl_abort_internal ();
-      return -1;
+      return 1;
     }
 
   if (rl_explicit_arg)
@@ -244,7 +244,7 @@ rl_end_kbd_macro (count, ignore)
   if (RL_ISSTATE (RL_STATE_MACRODEF) == 0)
     {
       _rl_abort_internal ();
-      return -1;
+      return 1;
     }
 
   current_macro_index -= rl_key_sequence_length;
diff --git a/lib/readline/macro.c~ b/lib/readline/macro.c~
new file mode 100644 (file)
index 0000000..b99a1a6
--- /dev/null
@@ -0,0 +1,307 @@
+/* macro.c -- keyboard macros for readline. */
+
+/* Copyright (C) 1994-2009 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library (Readline), a library
+   for reading lines of text with interactive input and history editing.      
+
+   Readline is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Readline is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Readline.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>           /* for _POSIX_VERSION */
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Hacking Keyboard Macros                     */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The currently executing macro string.  If this is non-zero,
+   then it is a malloc ()'ed string where input is coming from. */
+char *rl_executing_macro = (char *)NULL;
+
+/* The offset in the above string to the next character to be read. */
+static int executing_macro_index;
+
+/* The current macro string being built.  Characters get stuffed
+   in here by add_macro_char (). */
+static char *current_macro = (char *)NULL;
+
+/* The size of the buffer allocated to current_macro. */
+static int current_macro_size;
+
+/* The index at which characters are being added to current_macro. */
+static int current_macro_index;
+
+/* A structure used to save nested macro strings.
+   It is a linked list of string/index for each saved macro. */
+struct saved_macro {
+  struct saved_macro *next;
+  char *string;
+  int sindex;
+};
+
+/* The list of saved macros. */
+static struct saved_macro *macro_list = (struct saved_macro *)NULL;
+
+/* Set up to read subsequent input from STRING.
+   STRING is free ()'ed when we are done with it. */
+void
+_rl_with_macro_input (string)
+     char *string;
+{
+  _rl_push_executing_macro ();
+  rl_executing_macro = string;
+  executing_macro_index = 0;
+  RL_SETSTATE(RL_STATE_MACROINPUT);
+}
+
+/* Return the next character available from a macro, or 0 if
+   there are no macro characters. */
+int
+_rl_next_macro_key ()
+{
+  int c;
+
+  if (rl_executing_macro == 0)
+    return (0);
+
+  if (rl_executing_macro[executing_macro_index] == 0)
+    {
+      _rl_pop_executing_macro ();
+      return (_rl_next_macro_key ());
+    }
+
+#if defined (READLINE_CALLBACKS)
+  c = rl_executing_macro[executing_macro_index++];
+  if (RL_ISSTATE (RL_STATE_CALLBACK) && RL_ISSTATE (RL_STATE_READCMD|RL_STATE_MOREINPUT) && rl_executing_macro[executing_macro_index] == 0)
+      _rl_pop_executing_macro ();
+  return c;
+#else
+  return (rl_executing_macro[executing_macro_index++]);
+#endif
+}
+
+int
+_rl_prev_macro_key ()
+{
+  if (rl_executing_macro == 0)
+    return (0);
+
+  if (executing_macro_index == 0)
+    return (0);
+
+  executing_macro_index--;
+  return (rl_executing_macro[executing_macro_index]);
+}
+
+/* Save the currently executing macro on a stack of saved macros. */
+void
+_rl_push_executing_macro ()
+{
+  struct saved_macro *saver;
+
+  saver = (struct saved_macro *)xmalloc (sizeof (struct saved_macro));
+  saver->next = macro_list;
+  saver->sindex = executing_macro_index;
+  saver->string = rl_executing_macro;
+
+  macro_list = saver;
+}
+
+/* Discard the current macro, replacing it with the one
+   on the top of the stack of saved macros. */
+void
+_rl_pop_executing_macro ()
+{
+  struct saved_macro *macro;
+
+  FREE (rl_executing_macro);
+  rl_executing_macro = (char *)NULL;
+  executing_macro_index = 0;
+
+  if (macro_list)
+    {
+      macro = macro_list;
+      rl_executing_macro = macro_list->string;
+      executing_macro_index = macro_list->sindex;
+      macro_list = macro_list->next;
+      xfree (macro);
+    }
+
+  if (rl_executing_macro == 0)
+    RL_UNSETSTATE(RL_STATE_MACROINPUT);
+}
+
+/* Add a character to the macro being built. */
+void
+_rl_add_macro_char (c)
+     int c;
+{
+  if (current_macro_index + 1 >= current_macro_size)
+    {
+      if (current_macro == 0)
+       current_macro = (char *)xmalloc (current_macro_size = 25);
+      else
+       current_macro = (char *)xrealloc (current_macro, current_macro_size += 25);
+    }
+
+  current_macro[current_macro_index++] = c;
+  current_macro[current_macro_index] = '\0';
+}
+
+void
+_rl_kill_kbd_macro ()
+{
+  if (current_macro)
+    {
+      xfree (current_macro);
+      current_macro = (char *) NULL;
+    }
+  current_macro_size = current_macro_index = 0;
+
+  FREE (rl_executing_macro);
+  rl_executing_macro = (char *) NULL;
+  executing_macro_index = 0;
+
+  RL_UNSETSTATE(RL_STATE_MACRODEF);
+}
+
+/* Begin defining a keyboard macro.
+   Keystrokes are recorded as they are executed.
+   End the definition with rl_end_kbd_macro ().
+   If a numeric argument was explicitly typed, then append this
+   definition to the end of the existing macro, and start by
+   re-executing the existing macro. */
+int
+rl_start_kbd_macro (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  if (RL_ISSTATE (RL_STATE_MACRODEF))
+    {
+      _rl_abort_internal ();
+      return -1;
+    }
+
+  if (rl_explicit_arg)
+    {
+      if (current_macro)
+       _rl_with_macro_input (savestring (current_macro));
+    }
+  else
+    current_macro_index = 0;
+
+  RL_SETSTATE(RL_STATE_MACRODEF);
+  return 0;
+}
+
+/* Stop defining a keyboard macro.
+   A numeric argument says to execute the macro right now,
+   that many times, counting the definition as the first time. */
+int
+rl_end_kbd_macro (count, ignore)
+     int count, ignore;
+{
+  if (RL_ISSTATE (RL_STATE_MACRODEF) == 0)
+    {
+      _rl_abort_internal ();
+      return -1;
+    }
+
+  current_macro_index -= rl_key_sequence_length;
+  current_macro[current_macro_index] = '\0';
+
+  RL_UNSETSTATE(RL_STATE_MACRODEF);
+
+  return (rl_call_last_kbd_macro (--count, 0));
+}
+
+/* Execute the most recently defined keyboard macro.
+   COUNT says how many times to execute it. */
+int
+rl_call_last_kbd_macro (count, ignore)
+     int count, ignore;
+{
+  if (current_macro == 0)
+    _rl_abort_internal ();
+
+  if (RL_ISSTATE (RL_STATE_MACRODEF))
+    {
+      rl_ding ();              /* no recursive macros */
+      current_macro[--current_macro_index] = '\0';     /* erase this char */
+      return 0;
+    }
+
+  while (count--)
+    _rl_with_macro_input (savestring (current_macro));
+  return 0;
+}
+
+int
+rl_print_last_kbd_macro (count, ignore)
+     int count, ignore;
+{
+  char *m;
+
+  if (current_macro == 0)
+    {
+      rl_ding ();
+      return 0;
+    }
+  m = _rl_untranslate_macro_value (current_macro, 1);
+  rl_crlf ();
+  printf ("%s", m);
+  fflush (stdout);
+  rl_crlf ();
+  FREE (m);
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+
+  return 0;
+}
+
+void
+rl_push_macro_input (macro)
+     char *macro;
+{
+  _rl_with_macro_input (macro);
+}
index f29adf8101c1d53ab8d4e813cab3eff442f784c8..0370029c50f8315665b1cf0c10d5cd76ad6fb146 100644 (file)
@@ -906,7 +906,7 @@ _rl_insert_next (count)
   RL_UNSETSTATE(RL_STATE_MOREINPUT);
 
   if (c < 0)
-    return -1;
+    return 1;
 
   if (RL_ISSTATE (RL_STATE_MACRODEF))
     _rl_add_macro_char (c);
@@ -1066,7 +1066,7 @@ rl_rubout (count, key)
   if (!rl_point)
     {
       rl_ding ();
-      return -1;
+      return 1;
     }
 
   if (rl_insert_mode == RL_IM_OVERWRITE)
@@ -1089,7 +1089,7 @@ _rl_rubout_char (count, key)
   if (rl_point == 0)
     {
       rl_ding ();
-      return -1;
+      return 1;
     }
 
   orig_point = rl_point;
@@ -1133,7 +1133,7 @@ rl_delete (count, key)
   if (rl_point == rl_end)
     {
       rl_ding ();
-      return -1;
+      return 1;
     }
 
   if (count > 1 || rl_explicit_arg)
@@ -1303,7 +1303,7 @@ rl_change_case (count, op)
   if (op != UpCase && op != DownCase && op != CapCase)
     {
       rl_ding ();
-      return -1;
+      return 1;
     }
 
   if (count < 0)
@@ -1403,7 +1403,7 @@ rl_transpose_words (count, key)
     {
       rl_ding ();
       rl_point = orig_point;
-      return -1;
+      return 1;
     }
 
   /* Get the text of the words. */
@@ -1456,7 +1456,7 @@ rl_transpose_chars (count, key)
   if (!rl_point || rl_end < 2)
     {
       rl_ding ();
-      return -1;
+      return 1;
     }
 
   rl_begin_undo_group ();
@@ -1519,7 +1519,7 @@ _rl_char_search_internal (count, dir, schar)
 #endif
 
   if (dir == 0)
-    return -1;
+    return 1;
 
   pos = rl_point;
   inc = (dir < 0) ? -1 : 1;
@@ -1528,7 +1528,7 @@ _rl_char_search_internal (count, dir, schar)
       if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
        {
          rl_ding ();
-         return -1;
+         return 1;
        }
 
 #if defined (HANDLE_MULTIBYTE)
@@ -1583,7 +1583,7 @@ _rl_char_search (count, fdir, bdir)
   mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
 
   if (mb_len <= 0)
-    return -1;
+    return 1;
 
   if (count < 0)
     return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
@@ -1602,7 +1602,7 @@ _rl_char_search (count, fdir, bdir)
   RL_UNSETSTATE(RL_STATE_MOREINPUT);
 
   if (c < 0)
-    return -1;
+    return 1;
 
   if (count < 0)
     return (_rl_char_search_internal (-count, bdir, c));
@@ -1671,7 +1671,7 @@ _rl_set_mark_at_pos (position)
      int position;
 {
   if (position > rl_end)
-    return -1;
+    return 1;
 
   rl_mark = position;
   return 0;
@@ -1696,7 +1696,7 @@ rl_exchange_point_and_mark (count, key)
   if (rl_mark == -1)
     {
       rl_ding ();
-      return -1;
+      return 1;
     }
   else
     SWAP (rl_point, rl_mark);
diff --git a/lib/readline/text.c~ b/lib/readline/text.c~
new file mode 100644 (file)
index 0000000..18a9c11
--- /dev/null
@@ -0,0 +1,1705 @@
+/* text.c -- text handling commands for readline. */
+
+/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library (Readline), a library
+   for reading lines of text with interactive input and history editing.      
+
+   Readline is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Readline is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Readline.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_LOCALE_H)
+#  include <locale.h>
+#endif
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#if defined (__EMX__)
+#  define INCL_DOSPROCESS
+#  include <os2.h>
+#endif /* __EMX__ */
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+/* Forward declarations. */
+static int rl_change_case PARAMS((int, int));
+static int _rl_char_search PARAMS((int, int, int));
+
+#if defined (READLINE_CALLBACKS)
+static int _rl_insert_next_callback PARAMS((_rl_callback_generic_arg *));
+static int _rl_char_search_callback PARAMS((_rl_callback_generic_arg *));
+#endif
+
+/* The largest chunk of text that can be inserted in one call to
+   rl_insert_text.  Text blocks larger than this are divided. */
+#define TEXT_COUNT_MAX 1024
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Insert and Delete                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Insert a string of text into the line at point.  This is the only
+   way that you should do insertion.  _rl_insert_char () calls this
+   function.  Returns the number of characters inserted. */
+int
+rl_insert_text (string)
+     const char *string;
+{
+  register int i, l;
+
+  l = (string && *string) ? strlen (string) : 0;
+  if (l == 0)
+    return 0;
+
+  if (rl_end + l >= rl_line_buffer_len)
+    rl_extend_line_buffer (rl_end + l);
+
+  for (i = rl_end; i >= rl_point; i--)
+    rl_line_buffer[i + l] = rl_line_buffer[i];
+  strncpy (rl_line_buffer + rl_point, string, l);
+
+  /* Remember how to undo this if we aren't undoing something. */
+  if (_rl_doing_an_undo == 0)
+    {
+      /* If possible and desirable, concatenate the undos. */
+      if ((l == 1) &&
+         rl_undo_list &&
+         (rl_undo_list->what == UNDO_INSERT) &&
+         (rl_undo_list->end == rl_point) &&
+         (rl_undo_list->end - rl_undo_list->start < 20))
+       rl_undo_list->end++;
+      else
+       rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
+    }
+  rl_point += l;
+  rl_end += l;
+  rl_line_buffer[rl_end] = '\0';
+  return l;
+}
+
+/* Delete the string between FROM and TO.  FROM is inclusive, TO is not.
+   Returns the number of characters deleted. */
+int
+rl_delete_text (from, to)
+     int from, to;
+{
+  register char *text;
+  register int diff, i;
+
+  /* Fix it if the caller is confused. */
+  if (from > to)
+    SWAP (from, to);
+
+  /* fix boundaries */
+  if (to > rl_end)
+    {
+      to = rl_end;
+      if (from > to)
+       from = to;
+    }
+  if (from < 0)
+    from = 0;
+
+  text = rl_copy_text (from, to);
+
+  /* Some versions of strncpy() can't handle overlapping arguments. */
+  diff = to - from;
+  for (i = from; i < rl_end - diff; i++)
+    rl_line_buffer[i] = rl_line_buffer[i + diff];
+
+  /* Remember how to undo this delete. */
+  if (_rl_doing_an_undo == 0)
+    rl_add_undo (UNDO_DELETE, from, to, text);
+  else
+    xfree (text);
+
+  rl_end -= diff;
+  rl_line_buffer[rl_end] = '\0';
+  return (diff);
+}
+
+/* Fix up point so that it is within the line boundaries after killing
+   text.  If FIX_MARK_TOO is non-zero, the mark is forced within line
+   boundaries also. */
+
+#define _RL_FIX_POINT(x) \
+       do { \
+       if (x > rl_end) \
+         x = rl_end; \
+       else if (x < 0) \
+         x = 0; \
+       } while (0)
+
+void
+_rl_fix_point (fix_mark_too)
+     int fix_mark_too;
+{
+  _RL_FIX_POINT (rl_point);
+  if (fix_mark_too)
+    _RL_FIX_POINT (rl_mark);
+}
+#undef _RL_FIX_POINT
+
+/* Replace the contents of the line buffer between START and END with
+   TEXT.  The operation is undoable.  To replace the entire line in an
+   undoable mode, use _rl_replace_text(text, 0, rl_end); */
+int
+_rl_replace_text (text, start, end)
+     const char *text;
+     int start, end;
+{
+  int n;
+
+  n = 0;
+  rl_begin_undo_group ();
+  if (start <= end)
+    rl_delete_text (start, end + 1);
+  rl_point = start;
+  if (*text)
+    n = rl_insert_text (text);
+  rl_end_undo_group ();
+
+  return n;
+}
+
+/* Replace the current line buffer contents with TEXT.  If CLEAR_UNDO is
+   non-zero, we free the current undo list. */
+void
+rl_replace_line (text, clear_undo)
+     const char *text;
+     int clear_undo;
+{
+  int len;
+
+  len = strlen (text);
+  if (len >= rl_line_buffer_len)
+    rl_extend_line_buffer (len);
+  strcpy (rl_line_buffer, text);
+  rl_end = len;
+
+  if (clear_undo)
+    rl_free_undo_list ();
+
+  _rl_fix_point (1);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Readline character functions                */
+/*                                                                 */
+/* **************************************************************** */
+
+/* This is not a gap editor, just a stupid line input routine.  No hair
+   is involved in writing any of the functions, and none should be. */
+
+/* Note that:
+
+   rl_end is the place in the string that we would place '\0';
+   i.e., it is always safe to place '\0' there.
+
+   rl_point is the place in the string where the cursor is.  Sometimes
+   this is the same as rl_end.
+
+   Any command that is called interactively receives two arguments.
+   The first is a count: the numeric arg passed to this command.
+   The second is the key which invoked this command.
+*/
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Movement Commands                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Note that if you `optimize' the display for these functions, you cannot
+   use said functions in other functions which do not do optimizing display.
+   I.e., you will have to update the data base for rl_redisplay, and you
+   might as well let rl_redisplay do that job. */
+
+/* Move forward COUNT bytes. */
+int
+rl_forward_byte (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_backward_byte (-count, key));
+
+  if (count > 0)
+    {
+      int end, lend;
+
+      end = rl_point + count;
+#if defined (VI_MODE)
+      lend = rl_end > 0 ? rl_end - (VI_COMMAND_MODE()) : rl_end;
+#else
+      lend = rl_end;
+#endif
+
+      if (end > lend)
+       {
+         rl_point = lend;
+         rl_ding ();
+       }
+      else
+       rl_point = end;
+    }
+
+  if (rl_end < 0)
+    rl_end = 0;
+
+  return 0;
+}
+
+int
+_rl_forward_char_internal (count)
+     int count;
+{
+  int point;
+
+#if defined (HANDLE_MULTIBYTE)
+  point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+
+#if defined (VI_MODE)
+  if (point >= rl_end && VI_COMMAND_MODE())
+    point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO);
+#endif
+
+    if (rl_end < 0)
+       rl_end = 0;
+#else
+  point = rl_point + count;
+  if (point > rl_end)
+    point = rl_end;
+#endif
+
+  return (point);
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Move forward COUNT characters. */
+int
+rl_forward_char (count, key)
+     int count, key;
+{
+  int point;
+
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    return (rl_forward_byte (count, key));
+
+  if (count < 0)
+    return (rl_backward_char (-count, key));
+
+  if (count > 0)
+    {
+      if (rl_point == rl_end && EMACS_MODE())
+       {
+         rl_ding ();
+         return 0;
+       }
+
+      point = _rl_forward_char_internal (count);
+
+      if (rl_point == point)
+       rl_ding ();
+
+      rl_point = point;
+    }
+
+  return 0;
+}
+#else /* !HANDLE_MULTIBYTE */
+int
+rl_forward_char (count, key)
+     int count, key;
+{
+  return (rl_forward_byte (count, key));
+}
+#endif /* !HANDLE_MULTIBYTE */
+  
+/* Backwards compatibility. */
+int
+rl_forward (count, key)
+     int count, key;
+{
+  return (rl_forward_char (count, key));
+}
+
+/* Move backward COUNT bytes. */
+int
+rl_backward_byte (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_forward_byte (-count, key));
+
+  if (count > 0)
+    {
+      if (rl_point < count)
+       {
+         rl_point = 0;
+         rl_ding ();
+       }
+      else
+       rl_point -= count;
+    }
+
+  if (rl_point < 0)
+    rl_point = 0;
+
+  return 0;
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Move backward COUNT characters. */
+int
+rl_backward_char (count, key)
+     int count, key;
+{
+  int point;
+
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    return (rl_backward_byte (count, key));
+
+  if (count < 0)
+    return (rl_forward_char (-count, key));
+
+  if (count > 0)
+    {
+      point = rl_point;
+
+      while (count > 0 && point > 0)
+       {
+         point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO);
+         count--;
+       }
+      if (count > 0)
+       {
+         rl_point = 0;
+         rl_ding ();
+       }
+      else
+        rl_point = point;
+    }
+
+  return 0;
+}
+#else
+int
+rl_backward_char (count, key)
+     int count, key;
+{
+  return (rl_backward_byte (count, key));
+}
+#endif
+
+/* Backwards compatibility. */
+int
+rl_backward (count, key)
+     int count, key;
+{
+  return (rl_backward_char (count, key));
+}
+
+/* Move to the beginning of the line. */
+int
+rl_beg_of_line (count, key)
+     int count, key;
+{
+  rl_point = 0;
+  return 0;
+}
+
+/* Move to the end of the line. */
+int
+rl_end_of_line (count, key)
+     int count, key;
+{
+  rl_point = rl_end;
+  return 0;
+}
+
+/* Move forward a word.  We do what Emacs does.  Handles multibyte chars. */
+int
+rl_forward_word (count, key)
+     int count, key;
+{
+  int c;
+
+  if (count < 0)
+    return (rl_backward_word (-count, key));
+
+  while (count)
+    {
+      if (rl_point == rl_end)
+       return 0;
+
+      /* If we are not in a word, move forward until we are in one.
+        Then, move forward until we hit a non-alphabetic character. */
+      c = _rl_char_value (rl_line_buffer, rl_point);
+
+      if (_rl_walphabetic (c) == 0)
+       {
+         rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+         while (rl_point < rl_end)
+           {
+             c = _rl_char_value (rl_line_buffer, rl_point);
+             if (_rl_walphabetic (c))
+               break;
+             rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+           }
+       }
+
+      if (rl_point == rl_end)
+       return 0;
+
+      rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+      while (rl_point < rl_end)
+       {
+         c = _rl_char_value (rl_line_buffer, rl_point);
+         if (_rl_walphabetic (c) == 0)
+           break;
+         rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+       }
+
+      --count;
+    }
+
+  return 0;
+}
+
+/* Move backward a word.  We do what Emacs does.  Handles multibyte chars. */
+int
+rl_backward_word (count, key)
+     int count, key;
+{
+  int c, p;
+
+  if (count < 0)
+    return (rl_forward_word (-count, key));
+
+  while (count)
+    {
+      if (rl_point == 0)
+       return 0;
+
+      /* Like rl_forward_word (), except that we look at the characters
+        just before point. */
+
+      p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+      c = _rl_char_value (rl_line_buffer, p);
+
+      if (_rl_walphabetic (c) == 0)
+       {
+         rl_point = p;
+         while (rl_point > 0)
+           {
+             p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+             c = _rl_char_value (rl_line_buffer, p);
+             if (_rl_walphabetic (c))
+               break;
+             rl_point = p;
+           }
+       }
+
+      while (rl_point)
+       {
+         p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+         c = _rl_char_value (rl_line_buffer, p);         
+         if (_rl_walphabetic (c) == 0)
+           break;
+         else
+           rl_point = p;
+       }
+
+      --count;
+    }
+
+  return 0;
+}
+
+/* Clear the current line.  Numeric argument to C-l does this. */
+int
+rl_refresh_line (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  int curr_line;
+
+  curr_line = _rl_current_display_line ();
+
+  _rl_move_vert (curr_line);
+  _rl_move_cursor_relative (0, rl_line_buffer);   /* XXX is this right */
+
+  _rl_clear_to_eol (0);                /* arg of 0 means to not use spaces */
+
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+
+  return 0;
+}
+
+/* C-l typed to a line without quoting clears the screen, and then reprints
+   the prompt and the current input line.  Given a numeric arg, redraw only
+   the current line. */
+int
+rl_clear_screen (count, key)
+     int count, key;
+{
+  if (rl_explicit_arg)
+    {
+      rl_refresh_line (count, key);
+      return 0;
+    }
+
+  _rl_clear_screen ();         /* calls termcap function to clear screen */
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+
+  return 0;
+}
+
+int
+rl_skip_csi_sequence (count, key)
+     int count, key;
+{
+  int ch;
+
+  RL_SETSTATE (RL_STATE_MOREINPUT);
+  do
+    ch = rl_read_key ();
+  while (ch >= 0x20 && ch < 0x40);
+  RL_UNSETSTATE (RL_STATE_MOREINPUT);
+
+  return 0;
+}
+
+int
+rl_arrow_keys (count, c)
+     int count, c;
+{
+  int ch;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  ch = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  switch (_rl_to_upper (ch))
+    {
+    case 'A':
+      rl_get_previous_history (count, ch);
+      break;
+
+    case 'B':
+      rl_get_next_history (count, ch);
+      break;
+
+    case 'C':
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_forward_char (count, ch);
+      else
+       rl_forward_byte (count, ch);
+      break;
+
+    case 'D':
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_backward_char (count, ch);
+      else
+       rl_backward_byte (count, ch);
+      break;
+
+    default:
+      rl_ding ();
+    }
+
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Text commands                               */
+/*                                                                 */
+/* **************************************************************** */
+
+#ifdef HANDLE_MULTIBYTE
+static char pending_bytes[MB_LEN_MAX];
+static int pending_bytes_length = 0;
+static mbstate_t ps = {0};
+#endif
+
+/* Insert the character C at the current location, moving point forward.
+   If C introduces a multibyte sequence, we read the whole sequence and
+   then insert the multibyte char into the line buffer. */
+int
+_rl_insert_char (count, c)
+     int count, c;
+{
+  register int i;
+  char *string;
+#ifdef HANDLE_MULTIBYTE
+  int string_size;
+  char incoming[MB_LEN_MAX + 1];
+  int incoming_length = 0;
+  mbstate_t ps_back;
+  static int stored_count = 0;
+#endif
+
+  if (count <= 0)
+    return 0;
+
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    {
+      incoming[0] = c;
+      incoming[1] = '\0';
+      incoming_length = 1;
+    }
+  else
+    {
+      wchar_t wc;
+      size_t ret;
+
+      if (stored_count <= 0)
+       stored_count = count;
+      else
+       count = stored_count;
+
+      ps_back = ps;
+      pending_bytes[pending_bytes_length++] = c;
+      ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps);
+
+      if (ret == (size_t)-2)
+       {
+         /* Bytes too short to compose character, try to wait for next byte.
+            Restore the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         ps = ps_back;
+         return 1;
+       }
+      else if (ret == (size_t)-1)
+       {
+         /* Invalid byte sequence for the current locale.  Treat first byte
+            as a single character. */
+         incoming[0] = pending_bytes[0];
+         incoming[1] = '\0';
+         incoming_length = 1;
+         pending_bytes_length--;
+         memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
+         /* Clear the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         memset (&ps, 0, sizeof (mbstate_t));
+       }
+      else if (ret == (size_t)0)
+       {
+         incoming[0] = '\0';
+         incoming_length = 0;
+         pending_bytes_length--;
+         /* Clear the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         memset (&ps, 0, sizeof (mbstate_t));
+       }
+      else
+       {
+         /* We successfully read a single multibyte character. */
+         memcpy (incoming, pending_bytes, pending_bytes_length);
+         incoming[pending_bytes_length] = '\0';
+         incoming_length = pending_bytes_length;
+         pending_bytes_length = 0;
+       }
+    }
+#endif /* HANDLE_MULTIBYTE */
+         
+  /* If we can optimize, then do it.  But don't let people crash
+     readline because of extra large arguments. */
+  if (count > 1 && count <= TEXT_COUNT_MAX)
+    {
+#if defined (HANDLE_MULTIBYTE)
+      string_size = count * incoming_length;
+      string = (char *)xmalloc (1 + string_size);
+
+      i = 0;
+      while (i < string_size)
+       {
+         strncpy (string + i, incoming, incoming_length);
+         i += incoming_length;
+       }
+      incoming_length = 0;
+      stored_count = 0;
+#else /* !HANDLE_MULTIBYTE */
+      string = (char *)xmalloc (1 + count);
+
+      for (i = 0; i < count; i++)
+       string[i] = c;
+#endif /* !HANDLE_MULTIBYTE */
+
+      string[i] = '\0';
+      rl_insert_text (string);
+      xfree (string);
+
+      return 0;
+    }
+
+  if (count > TEXT_COUNT_MAX)
+    {
+      int decreaser;
+#if defined (HANDLE_MULTIBYTE)
+      string_size = incoming_length * TEXT_COUNT_MAX;
+      string = (char *)xmalloc (1 + string_size);
+
+      i = 0;
+      while (i < string_size)
+       {
+         strncpy (string + i, incoming, incoming_length);
+         i += incoming_length;
+       }
+
+      while (count)
+       {
+         decreaser = (count > TEXT_COUNT_MAX) ? TEXT_COUNT_MAX : count;
+         string[decreaser*incoming_length] = '\0';
+         rl_insert_text (string);
+         count -= decreaser;
+       }
+
+      xfree (string);
+      incoming_length = 0;
+      stored_count = 0;
+#else /* !HANDLE_MULTIBYTE */
+      char str[TEXT_COUNT_MAX+1];
+
+      for (i = 0; i < TEXT_COUNT_MAX; i++)
+       str[i] = c;
+
+      while (count)
+       {
+         decreaser = (count > TEXT_COUNT_MAX ? TEXT_COUNT_MAX : count);
+         str[decreaser] = '\0';
+         rl_insert_text (str);
+         count -= decreaser;
+       }
+#endif /* !HANDLE_MULTIBYTE */
+
+      return 0;
+    }
+
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    {
+      /* We are inserting a single character.
+        If there is pending input, then make a string of all of the
+        pending characters that are bound to rl_insert, and insert
+        them all.  Don't do this if we're current reading input from
+        a macro. */
+      if ((RL_ISSTATE (RL_STATE_MACROINPUT) == 0) && _rl_pushed_input_available ())
+       _rl_insert_typein (c);
+      else
+       {
+         /* Inserting a single character. */
+         char str[2];
+
+         str[1] = '\0';
+         str[0] = c;
+         rl_insert_text (str);
+       }
+    }
+#if defined (HANDLE_MULTIBYTE)
+  else
+    {
+      rl_insert_text (incoming);
+      stored_count = 0;
+    }
+#endif
+
+  return 0;
+}
+
+/* Overwrite the character at point (or next COUNT characters) with C.
+   If C introduces a multibyte character sequence, read the entire sequence
+   before starting the overwrite loop. */
+int
+_rl_overwrite_char (count, c)
+     int count, c;
+{
+  int i;
+#if defined (HANDLE_MULTIBYTE)
+  char mbkey[MB_LEN_MAX];
+  int k;
+
+  /* Read an entire multibyte character sequence to insert COUNT times. */
+  if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX);
+#endif
+
+  rl_begin_undo_group ();
+
+  for (i = 0; i < count; i++)
+    {
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_insert_text (mbkey);
+      else
+#endif
+       _rl_insert_char (1, c);
+
+      if (rl_point < rl_end)
+       rl_delete (1, c);
+    }
+
+  rl_end_undo_group ();
+
+  return 0;
+}
+
+int
+rl_insert (count, c)
+     int count, c;
+{
+  return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c)
+                                        : _rl_overwrite_char (count, c));
+}
+
+/* Insert the next typed character verbatim. */
+static int
+_rl_insert_next (count)
+     int count;
+{
+  int c;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  c = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  if (c < 0)
+    return 1;
+
+  if (RL_ISSTATE (RL_STATE_MACRODEF))
+    _rl_add_macro_char (c);
+
+#if defined (HANDLE_SIGNALS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
+    _rl_restore_tty_signals ();
+#endif
+
+  return (_rl_insert_char (count, c));  
+}
+
+#if defined (READLINE_CALLBACKS)
+static int
+_rl_insert_next_callback (data)
+     _rl_callback_generic_arg *data;
+{
+  int count;
+
+  count = data->count;
+
+  /* Deregister function, let rl_callback_read_char deallocate data */
+  _rl_callback_func = 0;
+  _rl_want_redisplay = 1;
+  return _rl_insert_next (count);
+}
+#endif
+  
+int
+rl_quoted_insert (count, key)
+     int count, key;
+{
+  /* Let's see...should the callback interface futz with signal handling? */
+#if defined (HANDLE_SIGNALS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
+    _rl_disable_tty_signals ();
+#endif
+
+#if defined (READLINE_CALLBACKS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK))
+    {
+      _rl_callback_data = _rl_callback_data_alloc (count);
+      _rl_callback_func = _rl_insert_next_callback;
+      return (0);
+    }
+#endif
+      
+  return _rl_insert_next (count);
+}
+
+/* Insert a tab character. */
+int
+rl_tab_insert (count, key)
+     int count, key;
+{
+  return (_rl_insert_char (count, '\t'));
+}
+
+/* What to do when a NEWLINE is pressed.  We accept the whole line.
+   KEY is the key that invoked this command.  I guess it could have
+   meaning in the future. */
+int
+rl_newline (count, key)
+     int count, key;
+{
+  rl_done = 1;
+
+  if (_rl_history_preserve_point)
+    _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
+
+  RL_SETSTATE(RL_STATE_DONE);
+
+#if defined (VI_MODE)
+  if (rl_editing_mode == vi_mode)
+    {
+      _rl_vi_done_inserting ();
+      if (_rl_vi_textmod_command (_rl_vi_last_command) == 0)   /* XXX */
+       _rl_vi_reset_last ();
+    }
+#endif /* VI_MODE */
+
+  /* If we've been asked to erase empty lines, suppress the final update,
+     since _rl_update_final calls rl_crlf(). */
+  if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
+    return 0;
+
+  if (_rl_echoing_p)
+    _rl_update_final ();
+  return 0;
+}
+
+/* What to do for some uppercase characters, like meta characters,
+   and some characters appearing in emacs_ctlx_keymap.  This function
+   is just a stub, you bind keys to it and the code in _rl_dispatch ()
+   is special cased. */
+int
+rl_do_lowercase_version (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  return 0;
+}
+
+/* This is different from what vi does, so the code's not shared.  Emacs
+   rubout in overwrite mode has one oddity:  it replaces a control
+   character that's displayed as two characters (^X) with two spaces. */
+int
+_rl_overwrite_rubout (count, key)
+     int count, key;
+{
+  int opoint;
+  int i, l;
+
+  if (rl_point == 0)
+    {
+      rl_ding ();
+      return 1;
+    }
+
+  opoint = rl_point;
+
+  /* L == number of spaces to insert */
+  for (i = l = 0; i < count; i++)
+    {
+      rl_backward_char (1, key);
+      l += rl_character_len (rl_line_buffer[rl_point], rl_point);      /* not exactly right */
+    }
+
+  rl_begin_undo_group ();
+
+  if (count > 1 || rl_explicit_arg)
+    rl_kill_text (opoint, rl_point);
+  else
+    rl_delete_text (opoint, rl_point);
+
+  /* Emacs puts point at the beginning of the sequence of spaces. */
+  if (rl_point < rl_end)
+    {
+      opoint = rl_point;
+      _rl_insert_char (l, ' ');
+      rl_point = opoint;
+    }
+
+  rl_end_undo_group ();
+
+  return 0;
+}
+  
+/* Rubout the character behind point. */
+int
+rl_rubout (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_delete (-count, key));
+
+  if (!rl_point)
+    {
+      rl_ding ();
+      return 1;
+    }
+
+  if (rl_insert_mode == RL_IM_OVERWRITE)
+    return (_rl_overwrite_rubout (count, key));
+
+  return (_rl_rubout_char (count, key));
+}
+
+int
+_rl_rubout_char (count, key)
+     int count, key;
+{
+  int orig_point;
+  unsigned char c;
+
+  /* Duplicated code because this is called from other parts of the library. */
+  if (count < 0)
+    return (rl_delete (-count, key));
+
+  if (rl_point == 0)
+    {
+      rl_ding ();
+      return 1;
+    }
+
+  orig_point = rl_point;
+  if (count > 1 || rl_explicit_arg)
+    {
+      rl_backward_char (count, key);
+      rl_kill_text (orig_point, rl_point);
+    }
+  else if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    {
+      c = rl_line_buffer[--rl_point];
+      rl_delete_text (rl_point, orig_point);
+      /* The erase-at-end-of-line hack is of questionable merit now. */
+      if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos)
+       {
+         int l;
+         l = rl_character_len (c, rl_point);
+         _rl_erase_at_end_of_line (l);
+       }
+    }
+  else
+    {
+      rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+      rl_delete_text (rl_point, orig_point);
+    }
+
+  return 0;
+}
+
+/* Delete the character under the cursor.  Given a numeric argument,
+   kill that many characters instead. */
+int
+rl_delete (count, key)
+     int count, key;
+{
+  int xpoint;
+
+  if (count < 0)
+    return (_rl_rubout_char (-count, key));
+
+  if (rl_point == rl_end)
+    {
+      rl_ding ();
+      return 1;
+    }
+
+  if (count > 1 || rl_explicit_arg)
+    {
+      xpoint = rl_point;
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_forward_char (count, key);
+      else
+       rl_forward_byte (count, key);
+
+      rl_kill_text (xpoint, rl_point);
+      rl_point = xpoint;
+    }
+  else
+    {
+      xpoint = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+      rl_delete_text (rl_point, xpoint);
+    }
+  return 0;
+}
+
+/* Delete the character under the cursor, unless the insertion
+   point is at the end of the line, in which case the character
+   behind the cursor is deleted.  COUNT is obeyed and may be used
+   to delete forward or backward that many characters. */      
+int
+rl_rubout_or_delete (count, key)
+     int count, key;
+{
+  if (rl_end != 0 && rl_point == rl_end)
+    return (_rl_rubout_char (count, key));
+  else
+    return (rl_delete (count, key));
+}  
+
+/* Delete all spaces and tabs around point. */
+int
+rl_delete_horizontal_space (count, ignore)
+     int count, ignore;
+{
+  int start;
+
+  while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
+    rl_point--;
+
+  start = rl_point;
+
+  while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+    rl_point++;
+
+  if (start != rl_point)
+    {
+      rl_delete_text (start, rl_point);
+      rl_point = start;
+    }
+
+  if (rl_point < 0)
+    rl_point = 0;
+
+  return 0;
+}
+
+/* Like the tcsh editing function delete-char-or-list.  The eof character
+   is caught before this is invoked, so this really does the same thing as
+   delete-char-or-list-or-eof, as long as it's bound to the eof character. */
+int
+rl_delete_or_show_completions (count, key)
+     int count, key;
+{
+  if (rl_end != 0 && rl_point == rl_end)
+    return (rl_possible_completions (count, key));
+  else
+    return (rl_delete (count, key));
+}
+
+#ifndef RL_COMMENT_BEGIN_DEFAULT
+#define RL_COMMENT_BEGIN_DEFAULT "#"
+#endif
+
+/* Turn the current line into a comment in shell history.
+   A K*rn shell style function. */
+int
+rl_insert_comment (count, key)
+     int count, key;
+{
+  char *rl_comment_text;
+  int rl_comment_len;
+
+  rl_beg_of_line (1, key);
+  rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT;
+
+  if (rl_explicit_arg == 0)
+    rl_insert_text (rl_comment_text);
+  else
+    {
+      rl_comment_len = strlen (rl_comment_text);
+      if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len))
+       rl_delete_text (rl_point, rl_point + rl_comment_len);
+      else
+       rl_insert_text (rl_comment_text);
+    }
+
+  (*rl_redisplay_function) ();
+  rl_newline (1, '\n');
+
+  return (0);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Changing Case                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The three kinds of things that we know how to do. */
+#define UpCase 1
+#define DownCase 2
+#define CapCase 3
+
+/* Uppercase the word at point. */
+int
+rl_upcase_word (count, key)
+     int count, key;
+{
+  return (rl_change_case (count, UpCase));
+}
+
+/* Lowercase the word at point. */
+int
+rl_downcase_word (count, key)
+     int count, key;
+{
+  return (rl_change_case (count, DownCase));
+}
+
+/* Upcase the first letter, downcase the rest. */
+int
+rl_capitalize_word (count, key)
+     int count, key;
+{
+ return (rl_change_case (count, CapCase));
+}
+
+/* The meaty function.
+   Change the case of COUNT words, performing OP on them.
+   OP is one of UpCase, DownCase, or CapCase.
+   If a negative argument is given, leave point where it started,
+   otherwise, leave it where it moves to. */
+static int
+rl_change_case (count, op)
+     int count, op;
+{
+  int start, next, end;
+  int inword, c, nc, nop;
+#if defined (HANDLE_MULTIBYTE)
+  wchar_t wc, nwc;
+  char mb[MB_LEN_MAX+1];
+  int mlen;
+  size_t m;
+  mbstate_t mps;
+#endif
+
+  start = rl_point;
+  rl_forward_word (count, 0);
+  end = rl_point;
+
+  if (op != UpCase && op != DownCase && op != CapCase)
+    {
+      rl_ding ();
+      return 1;
+    }
+
+  if (count < 0)
+    SWAP (start, end);
+
+#if defined (HANDLE_MULTIBYTE)
+  memset (&mps, 0, sizeof (mbstate_t));
+#endif
+
+  /* We are going to modify some text, so let's prepare to undo it. */
+  rl_modifying (start, end);
+
+  inword = 0;
+  while (start < end)
+    {
+      c = _rl_char_value (rl_line_buffer, start);
+      /*  This assumes that the upper and lower case versions are the same width. */
+      next = MB_NEXTCHAR (rl_line_buffer, start, 1, MB_FIND_NONZERO);
+
+      if (_rl_walphabetic (c) == 0)
+       {
+         inword = 0;
+         start = next;
+         continue;
+       }
+
+      if (op == CapCase)
+       {
+         nop = inword ? DownCase : UpCase;
+         inword = 1;
+       }
+      else
+       nop = op;
+      if (MB_CUR_MAX == 1 || rl_byte_oriented || isascii (c))
+       {
+         nc = (nop == UpCase) ? _rl_to_upper (c) : _rl_to_lower (c);
+         rl_line_buffer[start] = nc;
+       }
+#if defined (HANDLE_MULTIBYTE)
+      else
+       {
+         m = mbrtowc (&wc, rl_line_buffer + start, end - start, &mps);
+         if (MB_INVALIDCH (m))
+           wc = (wchar_t)rl_line_buffer[start];
+         else if (MB_NULLWCH (m))
+           wc = L'\0';
+         nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc);
+         if  (nwc != wc)       /*  just skip unchanged characters */
+           {
+             mlen = wcrtomb (mb, nwc, &mps);
+             if (mlen > 0)
+               mb[mlen] = '\0';
+             /* Assume the same width */
+             strncpy (rl_line_buffer + start, mb, mlen);
+           }
+       }
+#endif
+
+      start = next;
+    }
+
+  rl_point = end;
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Transposition                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Transpose the words at point.  If point is at the end of the line,
+   transpose the two words before point. */
+int
+rl_transpose_words (count, key)
+     int count, key;
+{
+  char *word1, *word2;
+  int w1_beg, w1_end, w2_beg, w2_end;
+  int orig_point = rl_point;
+
+  if (!count)
+    return 0;
+
+  /* Find the two words. */
+  rl_forward_word (count, key);
+  w2_end = rl_point;
+  rl_backward_word (1, key);
+  w2_beg = rl_point;
+  rl_backward_word (count, key);
+  w1_beg = rl_point;
+  rl_forward_word (1, key);
+  w1_end = rl_point;
+
+  /* Do some check to make sure that there really are two words. */
+  if ((w1_beg == w2_beg) || (w2_beg < w1_end))
+    {
+      rl_ding ();
+      rl_point = orig_point;
+      return 1;
+    }
+
+  /* Get the text of the words. */
+  word1 = rl_copy_text (w1_beg, w1_end);
+  word2 = rl_copy_text (w2_beg, w2_end);
+
+  /* We are about to do many insertions and deletions.  Remember them
+     as one operation. */
+  rl_begin_undo_group ();
+
+  /* Do the stuff at word2 first, so that we don't have to worry
+     about word1 moving. */
+  rl_point = w2_beg;
+  rl_delete_text (w2_beg, w2_end);
+  rl_insert_text (word1);
+
+  rl_point = w1_beg;
+  rl_delete_text (w1_beg, w1_end);
+  rl_insert_text (word2);
+
+  /* This is exactly correct since the text before this point has not
+     changed in length. */
+  rl_point = w2_end;
+
+  /* I think that does it. */
+  rl_end_undo_group ();
+  xfree (word1);
+  xfree (word2);
+
+  return 0;
+}
+
+/* Transpose the characters at point.  If point is at the end of the line,
+   then transpose the characters before point. */
+int
+rl_transpose_chars (count, key)
+     int count, key;
+{
+#if defined (HANDLE_MULTIBYTE)
+  char *dummy;
+  int i;
+#else
+  char dummy[2];
+#endif
+  int char_length, prev_point;
+
+  if (count == 0)
+    return 0;
+
+  if (!rl_point || rl_end < 2)
+    {
+      rl_ding ();
+      return 1;
+    }
+
+  rl_begin_undo_group ();
+
+  if (rl_point == rl_end)
+    {
+      rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+      count = 1;
+    }
+
+  prev_point = rl_point;
+  rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+
+#if defined (HANDLE_MULTIBYTE)
+  char_length = prev_point - rl_point;
+  dummy = (char *)xmalloc (char_length + 1);
+  for (i = 0; i < char_length; i++)
+    dummy[i] = rl_line_buffer[rl_point + i];
+  dummy[i] = '\0';
+#else
+  dummy[0] = rl_line_buffer[rl_point];
+  dummy[char_length = 1] = '\0';
+#endif
+
+  rl_delete_text (rl_point, rl_point + char_length);
+
+  rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+
+  _rl_fix_point (0);
+  rl_insert_text (dummy);
+  rl_end_undo_group ();
+
+#if defined (HANDLE_MULTIBYTE)
+  xfree (dummy);
+#endif
+
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Character Searching                         */
+/*                                                                 */
+/* **************************************************************** */
+
+int
+#if defined (HANDLE_MULTIBYTE)
+_rl_char_search_internal (count, dir, smbchar, len)
+     int count, dir;
+     char *smbchar;
+     int len;
+#else
+_rl_char_search_internal (count, dir, schar)
+     int count, dir, schar;
+#endif
+{
+  int pos, inc;
+#if defined (HANDLE_MULTIBYTE)
+  int prepos;
+#endif
+
+  if (dir == 0)
+    return -1;
+
+  pos = rl_point;
+  inc = (dir < 0) ? -1 : 1;
+  while (count)
+    {
+      if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
+       {
+         rl_ding ();
+         return -1;
+       }
+
+#if defined (HANDLE_MULTIBYTE)
+      pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
+                     : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
+#else
+      pos += inc;
+#endif
+      do
+       {
+#if defined (HANDLE_MULTIBYTE)
+         if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len))
+#else
+         if (rl_line_buffer[pos] == schar)
+#endif
+           {
+             count--;
+             if (dir < 0)
+               rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
+                                       : pos;
+             else
+               rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)
+                                       : pos;
+             break;
+           }
+#if defined (HANDLE_MULTIBYTE)
+         prepos = pos;
+#endif
+       }
+#if defined (HANDLE_MULTIBYTE)
+      while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos
+                      : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos);
+#else
+      while ((dir < 0) ? pos-- : ++pos < rl_end);
+#endif
+    }
+  return (0);
+}
+
+/* Search COUNT times for a character read from the current input stream.
+   FDIR is the direction to search if COUNT is non-negative; otherwise
+   the search goes in BDIR.  So much is dependent on HANDLE_MULTIBYTE
+   that there are two separate versions of this function. */
+#if defined (HANDLE_MULTIBYTE)
+static int
+_rl_char_search (count, fdir, bdir)
+     int count, fdir, bdir;
+{
+  char mbchar[MB_LEN_MAX];
+  int mb_len;
+
+  mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
+
+  if (mb_len <= 0)
+    return -1;
+
+  if (count < 0)
+    return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
+  else
+    return (_rl_char_search_internal (count, fdir, mbchar, mb_len));
+}
+#else /* !HANDLE_MULTIBYTE */
+static int
+_rl_char_search (count, fdir, bdir)
+     int count, fdir, bdir;
+{
+  int c;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  c = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  if (c < 0)
+    return -1;
+
+  if (count < 0)
+    return (_rl_char_search_internal (-count, bdir, c));
+  else
+    return (_rl_char_search_internal (count, fdir, c));
+}
+#endif /* !HANDLE_MULTIBYTE */
+
+#if defined (READLINE_CALLBACKS)
+static int
+_rl_char_search_callback (data)
+     _rl_callback_generic_arg *data;
+{
+  _rl_callback_func = 0;
+  _rl_want_redisplay = 1;
+
+  return (_rl_char_search (data->count, data->i1, data->i2));
+}
+#endif
+
+int
+rl_char_search (count, key)
+     int count, key;
+{
+#if defined (READLINE_CALLBACKS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK))
+    {
+      _rl_callback_data = _rl_callback_data_alloc (count);
+      _rl_callback_data->i1 = FFIND;
+      _rl_callback_data->i2 = BFIND;
+      _rl_callback_func = _rl_char_search_callback;
+      return (0);
+    }
+#endif
+  
+  return (_rl_char_search (count, FFIND, BFIND));
+}
+
+int
+rl_backward_char_search (count, key)
+     int count, key;
+{
+#if defined (READLINE_CALLBACKS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK))
+    {
+      _rl_callback_data = _rl_callback_data_alloc (count);
+      _rl_callback_data->i1 = BFIND;
+      _rl_callback_data->i2 = FFIND;
+      _rl_callback_func = _rl_char_search_callback;
+      return (0);
+    }
+#endif
+
+  return (_rl_char_search (count, BFIND, FFIND));
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                The Mark and the Region.                         */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Set the mark at POSITION. */
+int
+_rl_set_mark_at_pos (position)
+     int position;
+{
+  if (position > rl_end)
+    return 1;
+
+  rl_mark = position;
+  return 0;
+}
+
+/* A bindable command to set the mark. */
+int
+rl_set_mark (count, key)
+     int count, key;
+{
+  return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
+}
+
+/* Exchange the position of mark and point. */
+int
+rl_exchange_point_and_mark (count, key)
+     int count, key;
+{
+  if (rl_mark > rl_end)
+    rl_mark = -1;
+
+  if (rl_mark == -1)
+    {
+      rl_ding ();
+      return 1;
+    }
+  else
+    SWAP (rl_point, rl_mark);
+
+  return 0;
+}
index a1c409aae7b52372568c504934aba73bee6797a0..cae80cac8c407191b3382b4e8065987bfa581b3a 100644 (file)
@@ -471,7 +471,7 @@ rl_vi_end_word (count, key)
   if (count < 0)
     {
       rl_ding ();
-      return -1;
+      return 1;
     }
 
   if (_rl_uppercase_p (key))
@@ -1541,7 +1541,7 @@ rl_vi_rubout (count, key)
   if (rl_point == 0)
     {
       rl_ding ();
-      return -1;
+      return 1;
     }
 
   opoint = rl_point;
@@ -1572,7 +1572,7 @@ rl_vi_delete (count, key)
   if (rl_end == 0)
     {
       rl_ding ();
-      return -1;
+      return 1;
     }
 
   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
@@ -1657,13 +1657,13 @@ rl_vi_char_search (count, key)
   if (key == ';' || key == ',')
     {
       if (_rl_cs_orig_dir == 0)
-       return -1;
+       return 1;
 #if defined (HANDLE_MULTIBYTE)
       if (_rl_vi_last_search_mblen == 0)
-       return -1;
+       return 1;
 #else
       if (_rl_vi_last_search_char == 0)
-       return -1;
+       return 1;
 #endif
       _rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir;
     }
@@ -1762,7 +1762,7 @@ rl_vi_match (ignore, key)
        {
          rl_point = pos;
          rl_ding ();
-         return -1;
+         return 1;
        }
     }
 
@@ -1792,7 +1792,7 @@ rl_vi_match (ignore, key)
          else
            {
              rl_ding ();
-             return -1;
+             return 1;
            }
        }
     }
@@ -1816,7 +1816,7 @@ rl_vi_match (ignore, key)
          else
            {
              rl_ding ();
-             return -1;
+             return 1;
            }
        }
     }
@@ -2090,7 +2090,7 @@ _rl_vi_set_mark ()
   if (ch < 0 || ch < 'a' || ch > 'z')  /* make test against 0 explicit */
     {
       rl_ding ();
-      return -1;
+      return 1;
     }
   ch -= 'a';
   vi_mark_chars[ch] = rl_point;
@@ -2142,14 +2142,14 @@ _rl_vi_goto_mark ()
   else if (ch < 0 || ch < 'a' || ch > 'z')     /* make test against 0 explicit */
     {
       rl_ding ();
-      return -1;
+      return 1;
     }
 
   ch -= 'a';
   if (vi_mark_chars[ch] == -1)
     {
       rl_ding ();
-      return -1;
+      return 1;
     }
   rl_point = vi_mark_chars[ch];
   return 0;
diff --git a/lib/readline/vi_mode.c~ b/lib/readline/vi_mode.c~
new file mode 100644 (file)
index 0000000..a1c409a
--- /dev/null
@@ -0,0 +1,2185 @@
+/* vi_mode.c -- A vi emulation mode for Bash.
+   Derived from code written by Jeff Sparkes (jsparkes@bnr.ca).  */
+
+/* Copyright (C) 1987-2012 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library (Readline), a library
+   for reading lines of text with interactive input and history editing.      
+
+   Readline is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Readline is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Readline.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define READLINE_LIBRARY
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     VI Emulation Mode                           */
+/*                                                                 */
+/* **************************************************************** */
+#include "rlconf.h"
+
+#if defined (VI_MODE)
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include <stdio.h>
+
+/* Some standard library routines. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+#ifndef member
+#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
+#endif
+
+int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
+
+_rl_vimotion_cxt *_rl_vimvcxt = 0;
+
+/* Non-zero means enter insertion mode. */
+static int _rl_vi_doing_insert;
+
+/* Command keys which do movement for xxx_to commands. */
+static const char * const vi_motion = " hl^$0ftFT;,%wbeWBE|`";
+
+/* Keymap used for vi replace characters.  Created dynamically since
+   rarely used. */
+static Keymap vi_replace_map;
+
+/* The number of characters inserted in the last replace operation. */
+static int vi_replace_count;
+
+/* If non-zero, we have text inserted after a c[motion] command that put
+   us implicitly into insert mode.  Some people want this text to be
+   attached to the command so that it is `redoable' with `.'. */
+static int vi_continued_command;
+static char *vi_insert_buffer;
+static int vi_insert_buffer_size;
+
+static int _rl_vi_last_repeat = 1;
+static int _rl_vi_last_arg_sign = 1;
+static int _rl_vi_last_motion;
+#if defined (HANDLE_MULTIBYTE)
+static char _rl_vi_last_search_mbchar[MB_LEN_MAX];
+static int _rl_vi_last_search_mblen;
+#else
+static int _rl_vi_last_search_char;
+#endif
+static int _rl_vi_last_replacement;
+
+static int _rl_vi_last_key_before_insert;
+
+static int vi_redoing;
+
+/* Text modification commands.  These are the `redoable' commands. */
+static const char * const vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
+
+/* Arrays for the saved marks. */
+static int vi_mark_chars['z' - 'a' + 1];
+
+static void _rl_vi_replace_insert PARAMS((int));
+static void _rl_vi_save_replace PARAMS((void));
+static void _rl_vi_stuff_insert PARAMS((int));
+static void _rl_vi_save_insert PARAMS((UNDO_LIST *));
+
+static void vi_save_insert_buffer PARAMS ((int, int));
+
+static void _rl_vi_backup PARAMS((void));
+
+static int _rl_vi_arg_dispatch PARAMS((int));
+static int rl_digit_loop1 PARAMS((void));
+
+static int _rl_vi_set_mark PARAMS((void));
+static int _rl_vi_goto_mark PARAMS((void));
+
+static void _rl_vi_append_forward PARAMS((int));
+
+static int _rl_vi_callback_getchar PARAMS((char *, int));
+
+#if defined (READLINE_CALLBACKS)
+static int _rl_vi_callback_set_mark PARAMS((_rl_callback_generic_arg *));
+static int _rl_vi_callback_goto_mark PARAMS((_rl_callback_generic_arg *));
+static int _rl_vi_callback_change_char PARAMS((_rl_callback_generic_arg *));
+static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *));
+#endif
+
+static int rl_domove_read_callback PARAMS((_rl_vimotion_cxt *));
+static int rl_domove_motion_callback PARAMS((_rl_vimotion_cxt *));
+static int rl_vi_domove_getchar PARAMS((_rl_vimotion_cxt *));
+
+static int vi_change_dispatch PARAMS((_rl_vimotion_cxt *));
+static int vi_delete_dispatch PARAMS((_rl_vimotion_cxt *));
+static int vi_yank_dispatch PARAMS((_rl_vimotion_cxt *));
+
+static int vidomove_dispatch PARAMS((_rl_vimotion_cxt *));
+
+void
+_rl_vi_initialize_line ()
+{
+  register int i, n;
+
+  n = sizeof (vi_mark_chars) / sizeof (vi_mark_chars[0]);
+  for (i = 0; i < n; i++)
+    vi_mark_chars[i] = -1;
+
+  RL_UNSETSTATE(RL_STATE_VICMDONCE);
+}
+
+void
+_rl_vi_reset_last ()
+{
+  _rl_vi_last_command = 'i';
+  _rl_vi_last_repeat = 1;
+  _rl_vi_last_arg_sign = 1;
+  _rl_vi_last_motion = 0;
+}
+
+void
+_rl_vi_set_last (key, repeat, sign)
+     int key, repeat, sign;
+{
+  _rl_vi_last_command = key;
+  _rl_vi_last_repeat = repeat;
+  _rl_vi_last_arg_sign = sign;
+}
+
+/* A convenience function that calls _rl_vi_set_last to save the last command
+   information and enters insertion mode. */
+void
+rl_vi_start_inserting (key, repeat, sign)
+     int key, repeat, sign;
+{
+  _rl_vi_set_last (key, repeat, sign);
+  rl_vi_insertion_mode (1, key);
+}
+
+/* Is the command C a VI mode text modification command? */
+int
+_rl_vi_textmod_command (c)
+     int c;
+{
+  return (member (c, vi_textmod));
+}
+
+int
+_rl_vi_motion_command (c)
+     int c;
+{
+  return (member (c, vi_motion));
+}
+
+static void
+_rl_vi_replace_insert (count)
+     int count;
+{
+  int nchars;
+
+  nchars = strlen (vi_insert_buffer);
+
+  rl_begin_undo_group ();
+  while (count--)
+    /* nchars-1 to compensate for _rl_replace_text using `end+1' in call
+       to rl_delete_text */
+    _rl_replace_text (vi_insert_buffer, rl_point, rl_point+nchars-1);
+  rl_end_undo_group ();
+}
+
+static void
+_rl_vi_stuff_insert (count)
+     int count;
+{
+  rl_begin_undo_group ();
+  while (count--)
+    rl_insert_text (vi_insert_buffer);
+  rl_end_undo_group ();
+}
+
+/* Bound to `.'.  Called from command mode, so we know that we have to
+   redo a text modification command.  The default for _rl_vi_last_command
+   puts you back into insert mode. */
+int
+rl_vi_redo (count, c)
+     int count, c;
+{
+  int r;
+
+  if (rl_explicit_arg == 0)
+    {
+      rl_numeric_arg = _rl_vi_last_repeat;
+      rl_arg_sign = _rl_vi_last_arg_sign;
+    }
+
+  r = 0;
+  vi_redoing = 1;
+  /* If we're redoing an insert with `i', stuff in the inserted text
+     and do not go into insertion mode. */
+  if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
+    {
+      _rl_vi_stuff_insert (count);
+      /* And back up point over the last character inserted. */
+      if (rl_point > 0)
+       _rl_vi_backup ();
+    }
+  else if (_rl_vi_last_command == 'R' && vi_insert_buffer && *vi_insert_buffer)
+    {
+      _rl_vi_replace_insert (count);
+      /* And back up point over the last character inserted. */
+      if (rl_point > 0)
+       _rl_vi_backup ();
+    }
+  /* Ditto for redoing an insert with `I', but move to the beginning of the
+     line like the `I' command does. */
+  else if (_rl_vi_last_command == 'I' && vi_insert_buffer && *vi_insert_buffer)
+    {
+      rl_beg_of_line (1, 'I');
+      _rl_vi_stuff_insert (count);
+      if (rl_point > 0)
+       _rl_vi_backup ();
+    }
+  /* Ditto for redoing an insert with `a', but move forward a character first
+     like the `a' command does. */
+  else if (_rl_vi_last_command == 'a' && vi_insert_buffer && *vi_insert_buffer)
+    {
+      _rl_vi_append_forward ('a');
+      _rl_vi_stuff_insert (count);
+      if (rl_point > 0)
+       _rl_vi_backup ();
+    }
+  /* Ditto for redoing an insert with `A', but move to the end of the line
+     like the `A' command does. */
+  else if (_rl_vi_last_command == 'A' && vi_insert_buffer && *vi_insert_buffer)
+    {
+      rl_end_of_line (1, 'A');
+      _rl_vi_stuff_insert (count);
+      if (rl_point > 0)
+       _rl_vi_backup ();
+    }
+  else
+    r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
+  vi_redoing = 0;
+
+  return (r);
+}
+
+/* A placeholder for further expansion. */
+int
+rl_vi_undo (count, key)
+     int count, key;
+{
+  return (rl_undo_command (count, key));
+}
+    
+/* Yank the nth arg from the previous line into this line at point. */
+int
+rl_vi_yank_arg (count, key)
+     int count, key;
+{
+  /* Readline thinks that the first word on a line is the 0th, while vi
+     thinks the first word on a line is the 1st.  Compensate. */
+  if (rl_explicit_arg)
+    rl_yank_nth_arg (count - 1, 0);
+  else
+    rl_yank_nth_arg ('$', 0);
+
+  return (0);
+}
+
+/* With an argument, move back that many history lines, else move to the
+   beginning of history. */
+int
+rl_vi_fetch_history (count, c)
+     int count, c;
+{
+  int wanted;
+
+  /* Giving an argument of n means we want the nth command in the history
+     file.  The command number is interpreted the same way that the bash
+     `history' command does it -- that is, giving an argument count of 450
+     to this command would get the command listed as number 450 in the
+     output of `history'. */
+  if (rl_explicit_arg)
+    {
+      wanted = history_base + where_history () - count;
+      if (wanted <= 0)
+        rl_beginning_of_history (0, 0);
+      else
+        rl_get_previous_history (wanted, c);
+    }
+  else
+    rl_beginning_of_history (count, 0);
+  return (0);
+}
+
+/* Search again for the last thing searched for. */
+int
+rl_vi_search_again (count, key)
+     int count, key;
+{
+  switch (key)
+    {
+    case 'n':
+      rl_noninc_reverse_search_again (count, key);
+      break;
+
+    case 'N':
+      rl_noninc_forward_search_again (count, key);
+      break;
+    }
+  return (0);
+}
+
+/* Do a vi style search. */
+int
+rl_vi_search (count, key)
+     int count, key;
+{
+  switch (key)
+    {
+    case '?':
+      _rl_free_saved_history_line ();
+      rl_noninc_forward_search (count, key);
+      break;
+
+    case '/':
+      _rl_free_saved_history_line ();
+      rl_noninc_reverse_search (count, key);
+      break;
+
+    default:
+      rl_ding ();
+      break;
+    }
+  return (0);
+}
+
+/* Completion, from vi's point of view. */
+int
+rl_vi_complete (ignore, key)
+     int ignore, key;
+{
+  if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
+    {
+      if (!whitespace (rl_line_buffer[rl_point + 1]))
+       rl_vi_end_word (1, 'E');
+      rl_point++;
+    }
+
+  if (key == '*')
+    rl_complete_internal ('*');        /* Expansion and replacement. */
+  else if (key == '=')
+    rl_complete_internal ('?');        /* List possible completions. */
+  else if (key == '\\')
+    rl_complete_internal (TAB);        /* Standard Readline completion. */
+  else
+    rl_complete (0, key);
+
+  if (key == '*' || key == '\\')
+    rl_vi_start_inserting (key, 1, rl_arg_sign);
+
+  return (0);
+}
+
+/* Tilde expansion for vi mode. */
+int
+rl_vi_tilde_expand (ignore, key)
+     int ignore, key;
+{
+  rl_tilde_expand (0, key);
+  rl_vi_start_inserting (key, 1, rl_arg_sign);
+  return (0);
+}
+
+/* Previous word in vi mode. */
+int
+rl_vi_prev_word (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_vi_next_word (-count, key));
+
+  if (rl_point == 0)
+    {
+      rl_ding ();
+      return (0);
+    }
+
+  if (_rl_uppercase_p (key))
+    rl_vi_bWord (count, key);
+  else
+    rl_vi_bword (count, key);
+
+  return (0);
+}
+
+/* Next word in vi mode. */
+int
+rl_vi_next_word (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_vi_prev_word (-count, key));
+
+  if (rl_point >= (rl_end - 1))
+    {
+      rl_ding ();
+      return (0);
+    }
+
+  if (_rl_uppercase_p (key))
+    rl_vi_fWord (count, key);
+  else
+    rl_vi_fword (count, key);
+  return (0);
+}
+
+/* Move to the end of the ?next? word. */
+int
+rl_vi_end_word (count, key)
+     int count, key;
+{
+  if (count < 0)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  if (_rl_uppercase_p (key))
+    rl_vi_eWord (count, key);
+  else
+    rl_vi_eword (count, key);
+  return (0);
+}
+
+/* Move forward a word the way that 'W' does. */
+int
+rl_vi_fWord (count, ignore)
+     int count, ignore;
+{
+  while (count-- && rl_point < (rl_end - 1))
+    {
+      /* Skip until whitespace. */
+      while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+       rl_point++;
+
+      /* Now skip whitespace. */
+      while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+       rl_point++;
+    }
+  return (0);
+}
+
+int
+rl_vi_bWord (count, ignore)
+     int count, ignore;
+{
+  while (count-- && rl_point > 0)
+    {
+      /* If we are at the start of a word, move back to whitespace so
+        we will go back to the start of the previous word. */
+      if (!whitespace (rl_line_buffer[rl_point]) &&
+         whitespace (rl_line_buffer[rl_point - 1]))
+       rl_point--;
+
+      while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
+       rl_point--;
+
+      if (rl_point > 0)
+       {
+         while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
+         rl_point++;
+       }
+    }
+  return (0);
+}
+
+int
+rl_vi_eWord (count, ignore)
+     int count, ignore;
+{
+  while (count-- && rl_point < (rl_end - 1))
+    {
+      if (!whitespace (rl_line_buffer[rl_point]))
+       rl_point++;
+
+      /* Move to the next non-whitespace character (to the start of the
+        next word). */
+      while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+       rl_point++;
+
+      if (rl_point && rl_point < rl_end)
+       {
+         /* Skip whitespace. */
+         while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+           rl_point++;
+
+         /* Skip until whitespace. */
+         while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
+           rl_point++;
+
+         /* Move back to the last character of the word. */
+         rl_point--;
+       }
+    }
+  return (0);
+}
+
+int
+rl_vi_fword (count, ignore)
+     int count, ignore;
+{
+  while (count-- && rl_point < (rl_end - 1))
+    {
+      /* Move to white space (really non-identifer). */
+      if (_rl_isident (rl_line_buffer[rl_point]))
+       {
+         while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
+           rl_point++;
+       }
+      else /* if (!whitespace (rl_line_buffer[rl_point])) */
+       {
+         while (!_rl_isident (rl_line_buffer[rl_point]) &&
+                !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+           rl_point++;
+       }
+
+      /* Move past whitespace. */
+      while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+       rl_point++;
+    }
+  return (0);
+}
+
+int
+rl_vi_bword (count, ignore)
+     int count, ignore;
+{
+  while (count-- && rl_point > 0)
+    {
+      int last_is_ident;
+
+      /* If we are at the start of a word, move back to whitespace
+        so we will go back to the start of the previous word. */
+      if (!whitespace (rl_line_buffer[rl_point]) &&
+         whitespace (rl_line_buffer[rl_point - 1]))
+       rl_point--;
+
+      /* If this character and the previous character are `opposite', move
+        back so we don't get messed up by the rl_point++ down there in
+        the while loop.  Without this code, words like `l;' screw up the
+        function. */
+      last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]);
+      if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
+         (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident))
+       rl_point--;
+
+      while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
+       rl_point--;
+
+      if (rl_point > 0)
+       {
+         if (_rl_isident (rl_line_buffer[rl_point]))
+           while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point]));
+         else
+           while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) &&
+                  !whitespace (rl_line_buffer[rl_point]));
+         rl_point++;
+       }
+    }
+  return (0);
+}
+
+int
+rl_vi_eword (count, ignore)
+     int count, ignore;
+{
+  while (count-- && rl_point < rl_end - 1)
+    {
+      if (!whitespace (rl_line_buffer[rl_point]))
+       rl_point++;
+
+      while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+       rl_point++;
+
+      if (rl_point < rl_end)
+       {
+         if (_rl_isident (rl_line_buffer[rl_point]))
+           while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point]));
+         else
+           while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point])
+                  && !whitespace (rl_line_buffer[rl_point]));
+       }
+      rl_point--;
+    }
+  return (0);
+}
+
+int
+rl_vi_insert_beg (count, key)
+     int count, key;
+{
+  rl_beg_of_line (1, key);
+  rl_vi_insert_mode (1, key);
+  return (0);
+}
+
+static void
+_rl_vi_append_forward (key)
+     int key;
+{
+  int point;
+
+  if (rl_point < rl_end)
+    {
+      if (MB_CUR_MAX == 1 || rl_byte_oriented)
+       rl_point++;
+      else
+       {
+         point = rl_point;
+#if 0
+         rl_forward_char (1, key);
+#else
+         rl_point = _rl_forward_char_internal (1);
+#endif
+         if (point == rl_point)
+           rl_point = rl_end;
+       }
+    }
+}
+
+int
+rl_vi_append_mode (count, key)
+     int count, key;
+{
+  _rl_vi_append_forward (key);
+  rl_vi_start_inserting (key, 1, rl_arg_sign);
+  return (0);
+}
+
+int
+rl_vi_append_eol (count, key)
+     int count, key;
+{
+  rl_end_of_line (1, key);
+  rl_vi_append_mode (1, key);
+  return (0);
+}
+
+/* What to do in the case of C-d. */
+int
+rl_vi_eof_maybe (count, c)
+     int count, c;
+{
+  return (rl_newline (1, '\n'));
+}
+
+/* Insertion mode stuff. */
+
+/* Switching from one mode to the other really just involves
+   switching keymaps. */
+int
+rl_vi_insertion_mode (count, key)
+     int count, key;
+{
+  _rl_keymap = vi_insertion_keymap;
+  _rl_vi_last_key_before_insert = key;
+  if (_rl_show_mode_in_prompt)
+    _rl_reset_prompt ();
+  return (0);
+}
+
+int
+rl_vi_insert_mode (count, key)
+     int count, key;
+{
+  rl_vi_start_inserting (key, 1, rl_arg_sign);
+  return (0);
+}
+
+static void
+vi_save_insert_buffer (start, len)
+     int start, len;
+{
+  /* Same code as _rl_vi_save_insert below */
+  if (len >= vi_insert_buffer_size)
+    {
+      vi_insert_buffer_size += (len + 32) - (len % 32);
+      vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
+    }
+  strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
+  vi_insert_buffer[len-1] = '\0';
+}
+
+static void
+_rl_vi_save_replace ()
+{
+  int len, start, end;
+  UNDO_LIST *up;
+
+  up = rl_undo_list;
+  if (up == 0 || up->what != UNDO_END || vi_replace_count <= 0)
+    {
+      if (vi_insert_buffer_size >= 1)
+       vi_insert_buffer[0] = '\0';
+      return;
+    }
+  /* Let's try it the quick and easy way for now.  This should essentially
+     accommodate every UNDO_INSERT and save the inserted text to
+     vi_insert_buffer */
+  end = rl_point;
+  start = end - vi_replace_count + 1;
+  len = vi_replace_count + 1;
+
+  vi_save_insert_buffer (start, len);  
+}
+
+static void
+_rl_vi_save_insert (up)
+      UNDO_LIST *up;
+{
+  int len, start, end;
+
+  if (up == 0 || up->what != UNDO_INSERT)
+    {
+      if (vi_insert_buffer_size >= 1)
+       vi_insert_buffer[0] = '\0';
+      return;
+    }
+
+  start = up->start;
+  end = up->end;
+  len = end - start + 1;
+
+  vi_save_insert_buffer (start, len);
+}
+    
+void
+_rl_vi_done_inserting ()
+{
+  if (_rl_vi_doing_insert)
+    {
+      /* The `C', `s', and `S' commands set this. */
+      rl_end_undo_group ();
+      /* Now, the text between rl_undo_list->next->start and
+        rl_undo_list->next->end is what was inserted while in insert
+        mode.  It gets copied to VI_INSERT_BUFFER because it depends
+        on absolute indices into the line which may change (though they
+        probably will not). */
+      _rl_vi_doing_insert = 0;
+      if (_rl_vi_last_key_before_insert == 'R')
+       _rl_vi_save_replace ();         /* Half the battle */
+      else
+       _rl_vi_save_insert (rl_undo_list->next);
+      vi_continued_command = 1;
+    }
+  else
+    {
+      if (rl_undo_list && (_rl_vi_last_key_before_insert == 'i' ||
+                          _rl_vi_last_key_before_insert == 'a' ||
+                          _rl_vi_last_key_before_insert == 'I' ||
+                          _rl_vi_last_key_before_insert == 'A'))
+       _rl_vi_save_insert (rl_undo_list);
+      /* XXX - Other keys probably need to be checked. */
+      else if (_rl_vi_last_key_before_insert == 'C')
+       rl_end_undo_group ();
+      while (_rl_undo_group_level > 0)
+       rl_end_undo_group ();
+      vi_continued_command = 0;
+    }
+}
+
+int
+rl_vi_movement_mode (count, key)
+     int count, key;
+{
+  if (rl_point > 0)
+    rl_backward_char (1, key);
+
+  _rl_keymap = vi_movement_keymap;
+  _rl_vi_done_inserting ();
+
+  /* This is how POSIX.2 says `U' should behave -- everything up until the
+     first time you go into command mode should not be undone. */
+  if (RL_ISSTATE (RL_STATE_VICMDONCE) == 0)
+    rl_free_undo_list ();
+
+  if (_rl_show_mode_in_prompt)
+    _rl_reset_prompt ();
+
+  RL_SETSTATE (RL_STATE_VICMDONCE);
+  return (0);
+}
+
+int
+rl_vi_arg_digit (count, c)
+     int count, c;
+{
+  if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
+    return (rl_beg_of_line (1, c));
+  else
+    return (rl_digit_argument (count, c));
+}
+
+/* Change the case of the next COUNT characters. */
+#if defined (HANDLE_MULTIBYTE)
+static int
+_rl_vi_change_mbchar_case (count)
+     int count;
+{
+  wchar_t wc;
+  char mb[MB_LEN_MAX+1];
+  int mlen, p;
+  size_t m;
+  mbstate_t ps;
+
+  memset (&ps, 0, sizeof (mbstate_t));
+  if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0)
+    count--;
+  while (count-- && rl_point < rl_end)
+    {
+      m = mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
+      if (MB_INVALIDCH (m))
+       wc = (wchar_t)rl_line_buffer[rl_point];
+      else if (MB_NULLWCH (m))
+       wc = L'\0';
+      if (iswupper (wc))
+       wc = towlower (wc);
+      else if (iswlower (wc))
+       wc = towupper (wc);
+      else
+       {
+         /* Just skip over chars neither upper nor lower case */
+         rl_forward_char (1, 0);
+         continue;
+       }
+
+      /* Vi is kind of strange here. */
+      if (wc)
+       {
+         p = rl_point;
+         mlen = wcrtomb (mb, wc, &ps);
+         if (mlen >= 0)
+           mb[mlen] = '\0';
+         rl_begin_undo_group ();
+         rl_vi_delete (1, 0);
+         if (rl_point < p)     /* Did we retreat at EOL? */
+           rl_point++; /* XXX - should we advance more than 1 for mbchar? */
+         rl_insert_text (mb);
+         rl_end_undo_group ();
+         rl_vi_check ();
+       }
+      else
+       rl_forward_char (1, 0);
+    }
+
+  return 0;
+}
+#endif
+
+int
+rl_vi_change_case (count, ignore)
+     int count, ignore;
+{
+  int c, p;
+
+  /* Don't try this on an empty line. */
+  if (rl_point >= rl_end)
+    return (0);
+
+  c = 0;
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    return (_rl_vi_change_mbchar_case (count));
+#endif
+
+  while (count-- && rl_point < rl_end)
+    {
+      if (_rl_uppercase_p (rl_line_buffer[rl_point]))
+       c = _rl_to_lower (rl_line_buffer[rl_point]);
+      else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
+       c = _rl_to_upper (rl_line_buffer[rl_point]);
+      else
+       {
+         /* Just skip over characters neither upper nor lower case. */
+         rl_forward_char (1, c);
+         continue;
+       }
+
+      /* Vi is kind of strange here. */
+      if (c)
+       {
+         p = rl_point;
+         rl_begin_undo_group ();
+         rl_vi_delete (1, c);
+         if (rl_point < p)     /* Did we retreat at EOL? */
+           rl_point++;
+         _rl_insert_char (1, c);
+         rl_end_undo_group ();
+         rl_vi_check ();
+       }
+      else
+       rl_forward_char (1, c);
+    }
+  return (0);
+}
+
+int
+rl_vi_put (count, key)
+     int count, key;
+{
+  if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
+    rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+
+  while (count--)
+    rl_yank (1, key);
+
+  rl_backward_char (1, key);
+  return (0);
+}
+
+static void
+_rl_vi_backup ()
+{
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+  else
+    rl_point--;
+}
+
+int
+rl_vi_check ()
+{
+  if (rl_point && rl_point == rl_end)
+    {
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+      else
+       rl_point--;
+    }
+  return (0);
+}
+
+int
+rl_vi_column (count, key)
+     int count, key;
+{
+  if (count > rl_end)
+    rl_end_of_line (1, key);
+  else
+    rl_point = count - 1;
+  return (0);
+}
+
+/* Process C as part of the current numeric argument.  Return -1 if the
+   argument should be aborted, 0 if we should not read any more chars, and
+   1 if we should continue to read chars. */
+static int
+_rl_vi_arg_dispatch (c)
+     int c;
+{
+  int key;
+
+  key = c;
+  if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
+    {
+      rl_numeric_arg *= 4;
+      return 1;
+    }
+
+  c = UNMETA (c);
+
+  if (_rl_digit_p (c))
+    {
+      if (rl_explicit_arg)
+       rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
+      else
+       rl_numeric_arg = _rl_digit_value (c);
+      rl_explicit_arg = 1;
+      return 1;                /* keep going */
+    }
+  else
+    {
+      rl_clear_message ();
+      rl_stuff_char (key);
+      return 0;                /* done */
+    }
+}
+
+/* A simplified loop for vi. Don't dispatch key at end.
+   Don't recognize minus sign?
+   Should this do rl_save_prompt/rl_restore_prompt? */
+static int
+rl_digit_loop1 ()
+{
+  int c, r;
+
+  while (1)
+    {
+      if (_rl_arg_overflow ())
+       return 1;
+
+      c = _rl_arg_getchar ();
+
+      r = _rl_vi_arg_dispatch (c);
+      if (r <= 0)
+       break;
+    }
+
+  RL_UNSETSTATE(RL_STATE_NUMERICARG);
+  return (0);
+}
+
+static void
+_rl_mvcxt_init (m, op, key)
+     _rl_vimotion_cxt *m;
+     int op, key;
+{
+  m->op = op;
+  m->state = m->flags = 0;
+  m->ncxt = 0;
+  m->numeric_arg = -1;
+  m->start = rl_point;
+  m->end = rl_end;
+  m->key = key;
+  m->motion = -1;
+}
+
+static _rl_vimotion_cxt *
+_rl_mvcxt_alloc (op, key)
+     int op, key;
+{
+  _rl_vimotion_cxt *m;
+
+  m = xmalloc (sizeof (_rl_vimotion_cxt));
+  _rl_mvcxt_init (m, op, key);
+  return m;
+}
+
+static void
+_rl_mvcxt_dispose (m)
+     _rl_vimotion_cxt *m;
+{
+  xfree (m);
+}
+
+static int
+rl_domove_motion_callback (m)
+     _rl_vimotion_cxt *m;
+{
+  int c, save, r;
+  int old_end;
+
+  _rl_vi_last_motion = c = m->motion;
+
+  /* Append a blank character temporarily so that the motion routines
+     work right at the end of the line. */
+  old_end = rl_end;
+  rl_line_buffer[rl_end++] = ' ';
+  rl_line_buffer[rl_end] = '\0';
+
+  _rl_dispatch (c, _rl_keymap);
+
+  /* Remove the blank that we added. */
+  rl_end = old_end;
+  rl_line_buffer[rl_end] = '\0';
+  if (rl_point > rl_end)
+    rl_point = rl_end;
+
+  /* No change in position means the command failed. */
+  if (rl_mark == rl_point)
+    return (-1);
+
+  /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
+     word.  If we are not at the end of the line, and we are on a
+     non-whitespace character, move back one (presumably to whitespace). */
+  if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
+      !whitespace (rl_line_buffer[rl_point]))
+    rl_point--;
+
+  /* If cw or cW, back up to the end of a word, so the behaviour of ce
+     or cE is the actual result.  Brute-force, no subtlety. */
+  if (m->key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
+    {
+      /* Don't move farther back than where we started. */
+      while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
+       rl_point--;
+
+      /* Posix.2 says that if cw or cW moves the cursor towards the end of
+        the line, the character under the cursor should be deleted. */
+      if (rl_point == rl_mark)
+       rl_point++;
+      else
+       {
+         /* Move past the end of the word so that the kill doesn't
+            remove the last letter of the previous word.  Only do this
+            if we are not at the end of the line. */
+         if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
+           rl_point++;
+       }
+    }
+
+  if (rl_mark < rl_point)
+    SWAP (rl_point, rl_mark);
+
+#if defined (READLINE_CALLBACKS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK))
+    (*rl_redisplay_function)();                /* make sure motion is displayed */
+#endif
+
+  r = vidomove_dispatch (m);
+
+  return (r);
+}
+
+#define RL_VIMOVENUMARG()      (RL_ISSTATE (RL_STATE_VIMOTION) && RL_ISSTATE (RL_STATE_NUMERICARG))
+
+static int
+rl_domove_read_callback (m)
+     _rl_vimotion_cxt *m;
+{
+  int c, save;
+
+  c = m->motion;
+
+  if (member (c, vi_motion))
+    {
+#if defined (READLINE_CALLBACKS)
+      /* If we just read a vi-mode motion command numeric argument, turn off
+        the `reading numeric arg' state */
+      if (RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG())
+       RL_UNSETSTATE (RL_STATE_NUMERICARG);
+#endif
+      /* Should do everything, including turning off RL_STATE_VIMOTION */
+      return (rl_domove_motion_callback (m));
+    }
+  else if (m->key == c && (m->key == 'd' || m->key == 'y' || m->key == 'c'))
+    {
+      rl_mark = rl_end;
+      rl_beg_of_line (1, c);
+      _rl_vi_last_motion = c;
+      RL_UNSETSTATE (RL_STATE_VIMOTION);
+      return (vidomove_dispatch (m));
+    }
+#if defined (READLINE_CALLBACKS)
+  /* XXX - these need to handle rl_universal_argument bindings */
+  /* Reading vi motion char continuing numeric argument */
+  else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG())
+    {
+      return (_rl_vi_arg_dispatch (c));
+    }
+  /* Readine vi motion char starting numeric argument */
+  else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_ISSTATE (RL_STATE_VIMOTION) && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
+    {
+      RL_SETSTATE (RL_STATE_NUMERICARG);
+      return (_rl_vi_arg_dispatch (c));
+    }
+#endif
+  else if (_rl_digit_p (c))
+    {
+      /* This code path taken when not in callback mode */
+      save = rl_numeric_arg;
+      rl_numeric_arg = _rl_digit_value (c);
+      rl_explicit_arg = 1;
+      RL_SETSTATE (RL_STATE_NUMERICARG);
+      rl_digit_loop1 ();
+      rl_numeric_arg *= save;
+      c = rl_vi_domove_getchar (m);
+      if (c < 0)
+       {
+         m->motion = 0;
+         return -1;
+       }
+      m->motion = c;
+      return (rl_domove_motion_callback (m));
+    }
+  else
+    {
+      RL_UNSETSTATE (RL_STATE_VIMOTION);
+      RL_UNSETSTATE (RL_STATE_NUMERICARG);
+      return (1);
+    }
+}
+
+static int
+rl_vi_domove_getchar (m)
+     _rl_vimotion_cxt *m;
+{
+  int c;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  c = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  return c;
+}
+
+#if defined (READLINE_CALLBACKS)
+int
+_rl_vi_domove_callback (m)
+     _rl_vimotion_cxt *m;
+{
+  int c, r;
+
+  m->motion = c = rl_vi_domove_getchar (m);
+  /* XXX - what to do if this returns -1?  Should we return 1 for eof to
+     callback code? */
+  r = rl_domove_read_callback (m);
+
+  return ((r == 0) ? r : 1);   /* normalize return values */
+}
+#endif
+
+/* This code path taken when not in callback mode. */
+int
+rl_vi_domove (x, ignore)
+     int x, *ignore;
+{
+  int r;
+  _rl_vimotion_cxt *m;
+
+  m = _rl_vimvcxt;
+  *ignore = m->motion = rl_vi_domove_getchar (m);
+
+  if (m->motion < 0)
+    {
+      m->motion = 0;
+      return -1;
+    }
+
+  return (rl_domove_read_callback (m));
+}
+
+static int
+vi_delete_dispatch (m)
+     _rl_vimotion_cxt *m;
+{
+  /* These are the motion commands that do not require adjusting the
+     mark. */
+  if (((strchr (" l|h^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
+      (rl_mark < rl_end))
+    rl_mark++;
+
+  rl_kill_text (rl_point, rl_mark);
+  return (0);
+}
+
+int
+rl_vi_delete_to (count, key)
+     int count, key;
+{
+  int c, r;
+
+  _rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
+  _rl_vimvcxt->start = rl_point;
+
+  rl_mark = rl_point;
+  if (_rl_uppercase_p (key))
+    {
+      _rl_vimvcxt->motion = '$';
+      r = rl_domove_motion_callback (_rl_vimvcxt);
+    }
+  else if (vi_redoing && _rl_vi_last_motion != 'd')    /* `dd' is special */
+    {
+      _rl_vimvcxt->motion = _rl_vi_last_motion;
+      r = rl_domove_motion_callback (_rl_vimvcxt);
+    }
+  else if (vi_redoing)         /* handle redoing `dd' here */
+    {
+      _rl_vimvcxt->motion = _rl_vi_last_motion;
+      rl_mark = rl_end;
+      rl_beg_of_line (1, key);
+      RL_UNSETSTATE (RL_STATE_VIMOTION);
+      r = vidomove_dispatch (_rl_vimvcxt);
+    }
+#if defined (READLINE_CALLBACKS)
+  else if (RL_ISSTATE (RL_STATE_CALLBACK))
+    {
+      RL_SETSTATE (RL_STATE_VIMOTION);
+      return (0);
+    }
+#endif
+  else
+    r = rl_vi_domove (key, &c);
+
+  if (r < 0)
+    {
+      rl_ding ();
+      r = -1;
+    }
+
+  _rl_mvcxt_dispose (_rl_vimvcxt);
+  _rl_vimvcxt = 0;
+
+  return r;
+}
+
+static int
+vi_change_dispatch (m)
+     _rl_vimotion_cxt *m;
+{
+  /* These are the motion commands that do not require adjusting the
+     mark.  c[wW] are handled by special-case code in rl_vi_domove(),
+     and already leave the mark at the correct location. */
+  if (((strchr (" l|hwW^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
+      (rl_mark < rl_end))
+    rl_mark++;
+
+  /* The cursor never moves with c[wW]. */
+  if ((_rl_to_upper (m->motion) == 'W') && rl_point < m->start)
+    rl_point = m->start;
+
+  if (vi_redoing)
+    {
+      if (vi_insert_buffer && *vi_insert_buffer)
+       rl_begin_undo_group ();
+      rl_delete_text (rl_point, rl_mark);
+      if (vi_insert_buffer && *vi_insert_buffer)
+       {
+         rl_insert_text (vi_insert_buffer);
+         rl_end_undo_group ();
+       }
+    }
+  else
+    {
+      rl_begin_undo_group ();          /* to make the `u' command work */
+      rl_kill_text (rl_point, rl_mark);
+      /* `C' does not save the text inserted for undoing or redoing. */
+      if (_rl_uppercase_p (m->key) == 0)
+       _rl_vi_doing_insert = 1;
+      /* XXX -- TODO -- use m->numericarg? */
+      rl_vi_start_inserting (m->key, rl_numeric_arg, rl_arg_sign);
+    }
+
+  return (0);
+}
+
+int
+rl_vi_change_to (count, key)
+     int count, key;
+{
+  int c, r;
+
+  _rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
+  _rl_vimvcxt->start = rl_point;
+
+  rl_mark = rl_point;
+  if (_rl_uppercase_p (key))
+    {
+      _rl_vimvcxt->motion = '$';
+      r = rl_domove_motion_callback (_rl_vimvcxt);
+    }
+  else if (vi_redoing && _rl_vi_last_motion != 'c')    /* `cc' is special */
+    {
+      _rl_vimvcxt->motion = _rl_vi_last_motion;
+      r = rl_domove_motion_callback (_rl_vimvcxt);
+    }
+  else if (vi_redoing)         /* handle redoing `cc' here */
+    {
+      _rl_vimvcxt->motion = _rl_vi_last_motion;
+      rl_mark = rl_end;
+      rl_beg_of_line (1, key);
+      RL_UNSETSTATE (RL_STATE_VIMOTION);
+      r = vidomove_dispatch (_rl_vimvcxt);
+    }
+#if defined (READLINE_CALLBACKS)
+  else if (RL_ISSTATE (RL_STATE_CALLBACK))
+    {
+      RL_SETSTATE (RL_STATE_VIMOTION);
+      return (0);
+    }
+#endif
+  else
+    r = rl_vi_domove (key, &c);
+
+  if (r < 0)
+    {
+      rl_ding ();
+      r = -1;  /* normalize return value */
+    }
+
+  _rl_mvcxt_dispose (_rl_vimvcxt);
+  _rl_vimvcxt = 0;
+
+  return r;
+}
+
+static int
+vi_yank_dispatch (m)
+     _rl_vimotion_cxt *m;
+{
+  /* These are the motion commands that do not require adjusting the
+     mark. */
+  if (((strchr (" l|h^0%bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
+      (rl_mark < rl_end))
+    rl_mark++;
+
+  rl_begin_undo_group ();
+  rl_kill_text (rl_point, rl_mark);
+  rl_end_undo_group ();
+  rl_do_undo ();
+  rl_point = m->start;
+
+  return (0);
+}
+
+int
+rl_vi_yank_to (count, key)
+     int count, key;
+{
+  int c, r;
+
+  _rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
+  _rl_vimvcxt->start = rl_point;
+
+  rl_mark = rl_point;
+  if (_rl_uppercase_p (key))
+    {
+      _rl_vimvcxt->motion = '$';
+      r = rl_domove_motion_callback (_rl_vimvcxt);
+    }
+  else if (vi_redoing && _rl_vi_last_motion != 'y')    /* `yy' is special */
+    {
+      _rl_vimvcxt->motion = _rl_vi_last_motion;
+      r = rl_domove_motion_callback (_rl_vimvcxt);
+    }
+  else if (vi_redoing)                 /* handle redoing `yy' here */
+    {
+      _rl_vimvcxt->motion = _rl_vi_last_motion;
+      rl_mark = rl_end;
+      rl_beg_of_line (1, key);
+      RL_UNSETSTATE (RL_STATE_VIMOTION);
+      r = vidomove_dispatch (_rl_vimvcxt);
+    }
+#if defined (READLINE_CALLBACKS)
+  else if (RL_ISSTATE (RL_STATE_CALLBACK))
+    {
+      RL_SETSTATE (RL_STATE_VIMOTION);
+      return (0);
+    }
+#endif
+  else
+    r = rl_vi_domove (key, &c);
+
+  if (r < 0)
+    {
+      rl_ding ();
+      r = -1;
+    }
+
+  _rl_mvcxt_dispose (_rl_vimvcxt);
+  _rl_vimvcxt = 0;
+
+  return r;
+}
+
+static int
+vidomove_dispatch (m)
+     _rl_vimotion_cxt *m;
+{
+  int r;
+
+  switch (m->op)
+    {
+    case VIM_DELETE:
+      r = vi_delete_dispatch (m);
+      break;
+    case VIM_CHANGE:
+      r = vi_change_dispatch (m);
+      break;
+    case VIM_YANK:
+      r = vi_yank_dispatch (m);
+      break;
+    default:
+      _rl_errmsg ("vidomove_dispatch: unknown operator %d", m->op);
+      r = 1;
+      break;
+    }
+
+  RL_UNSETSTATE (RL_STATE_VIMOTION);
+  return r;
+}
+
+int
+rl_vi_rubout (count, key)
+     int count, key;
+{
+  int opoint;
+
+  if (count < 0)
+    return (rl_vi_delete (-count, key));
+
+  if (rl_point == 0)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  opoint = rl_point;
+  if (count > 1 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    rl_backward_char (count, key);
+  else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+  else
+    rl_point -= count;
+
+  if (rl_point < 0)
+    rl_point = 0;
+
+  rl_kill_text (rl_point, opoint);
+  
+  return (0);
+}
+
+int
+rl_vi_delete (count, key)
+     int count, key;
+{
+  int end;
+
+  if (count < 0)
+    return (rl_vi_rubout (-count, key));
+
+  if (rl_end == 0)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+  else
+    end = rl_point + count;
+
+  if (end >= rl_end)
+    end = rl_end;
+
+  rl_kill_text (rl_point, end);
+  
+  if (rl_point > 0 && rl_point == rl_end)
+    rl_backward_char (1, key);
+
+  return (0);
+}
+
+int
+rl_vi_back_to_indent (count, key)
+     int count, key;
+{
+  rl_beg_of_line (1, key);
+  while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+    rl_point++;
+  return (0);
+}
+
+int
+rl_vi_first_print (count, key)
+     int count, key;
+{
+  return (rl_vi_back_to_indent (1, key));
+}
+
+static int _rl_cs_dir, _rl_cs_orig_dir;
+
+#if defined (READLINE_CALLBACKS)
+static int
+_rl_vi_callback_char_search (data)
+     _rl_callback_generic_arg *data;
+{
+  int c;
+#if defined (HANDLE_MULTIBYTE)
+  c = _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
+#else
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  c = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+#endif
+
+  if (c <= 0)
+    return -1;
+
+#if !defined (HANDLE_MULTIBYTE)
+  _rl_vi_last_search_char = c;
+#endif
+
+  _rl_callback_func = 0;
+  _rl_want_redisplay = 1;
+
+#if defined (HANDLE_MULTIBYTE)
+  return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_mbchar, _rl_vi_last_search_mblen));
+#else
+  return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_char));
+#endif  
+}
+#endif
+
+int
+rl_vi_char_search (count, key)
+     int count, key;
+{
+  int c;
+#if defined (HANDLE_MULTIBYTE)
+  static char *target;
+  static int tlen;
+#else
+  static char target;
+#endif
+
+  if (key == ';' || key == ',')
+    {
+      if (_rl_cs_orig_dir == 0)
+       return -1;
+#if defined (HANDLE_MULTIBYTE)
+      if (_rl_vi_last_search_mblen == 0)
+       return -1;
+#else
+      if (_rl_vi_last_search_char == 0)
+       return -1;
+#endif
+      _rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir;
+    }
+  else
+    {
+      switch (key)
+       {
+       case 't':
+         _rl_cs_orig_dir = _rl_cs_dir = FTO;
+         break;
+
+       case 'T':
+         _rl_cs_orig_dir = _rl_cs_dir = BTO;
+         break;
+
+       case 'f':
+         _rl_cs_orig_dir = _rl_cs_dir = FFIND;
+         break;
+
+       case 'F':
+         _rl_cs_orig_dir = _rl_cs_dir = BFIND;
+         break;
+       }
+
+      if (vi_redoing)
+       {
+         /* set target and tlen below */
+       }
+#if defined (READLINE_CALLBACKS)
+      else if (RL_ISSTATE (RL_STATE_CALLBACK))
+       {
+         _rl_callback_data = _rl_callback_data_alloc (count);
+         _rl_callback_data->i1 = _rl_cs_dir;
+         _rl_callback_func = _rl_vi_callback_char_search;
+         return (0);
+       }
+#endif
+      else
+       {
+#if defined (HANDLE_MULTIBYTE)
+         c = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
+         if (c <= 0)
+           return -1;
+         _rl_vi_last_search_mblen = c;
+#else
+         RL_SETSTATE(RL_STATE_MOREINPUT);
+         c = rl_read_key ();
+         RL_UNSETSTATE(RL_STATE_MOREINPUT);
+         if (c < 0)
+           return -1;
+         _rl_vi_last_search_char = c;
+#endif
+       }
+    }
+
+#if defined (HANDLE_MULTIBYTE)
+  target = _rl_vi_last_search_mbchar;
+  tlen = _rl_vi_last_search_mblen;
+#else
+  target = _rl_vi_last_search_char;
+#endif
+
+#if defined (HANDLE_MULTIBYTE)
+  return (_rl_char_search_internal (count, _rl_cs_dir, target, tlen));
+#else
+  return (_rl_char_search_internal (count, _rl_cs_dir, target));
+#endif
+}
+
+/* Match brackets */
+int
+rl_vi_match (ignore, key)
+     int ignore, key;
+{
+  int count = 1, brack, pos, tmp, pre;
+
+  pos = rl_point;
+  if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
+    {
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
+           {
+             pre = rl_point;
+             rl_forward_char (1, key);
+             if (pre == rl_point)
+               break;
+           }
+       }
+      else
+       while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
+               rl_point < rl_end - 1)
+         rl_forward_char (1, key);
+
+      if (brack <= 0)
+       {
+         rl_point = pos;
+         rl_ding ();
+         return -1;
+       }
+    }
+
+  pos = rl_point;
+
+  if (brack < 0)
+    {
+      while (count)
+       {
+         tmp = pos;
+         if (MB_CUR_MAX == 1 || rl_byte_oriented)
+           pos--;
+         else
+           {
+             pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
+             if (tmp == pos)
+               pos--;
+           }
+         if (pos >= 0)
+           {
+             int b = rl_vi_bracktype (rl_line_buffer[pos]);
+             if (b == -brack)
+               count--;
+             else if (b == brack)
+               count++;
+           }
+         else
+           {
+             rl_ding ();
+             return -1;
+           }
+       }
+    }
+  else
+    {                  /* brack > 0 */
+      while (count)
+       {
+         if (MB_CUR_MAX == 1 || rl_byte_oriented)
+           pos++;
+         else
+           pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY);
+
+         if (pos < rl_end)
+           {
+             int b = rl_vi_bracktype (rl_line_buffer[pos]);
+             if (b == -brack)
+               count--;
+             else if (b == brack)
+               count++;
+           }
+         else
+           {
+             rl_ding ();
+             return -1;
+           }
+       }
+    }
+  rl_point = pos;
+  return (0);
+}
+
+int
+rl_vi_bracktype (c)
+     int c;
+{
+  switch (c)
+    {
+    case '(': return  1;
+    case ')': return -1;
+    case '[': return  2;
+    case ']': return -2;
+    case '{': return  3;
+    case '}': return -3;
+    default:  return  0;
+    }
+}
+
+static int
+_rl_vi_change_char (count, c, mb)
+     int count, c;
+     char *mb;
+{
+  int p;
+
+  if (c == '\033' || c == CTRL ('C'))
+    return -1;
+
+  rl_begin_undo_group ();
+  while (count-- && rl_point < rl_end)
+    {
+      p = rl_point;
+      rl_vi_delete (1, c);
+      if (rl_point < p)                /* Did we retreat at EOL? */
+       rl_point++;
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_insert_text (mb);
+      else
+#endif
+       _rl_insert_char (1, c);
+    }
+
+  /* The cursor shall be left on the last character changed. */
+  rl_backward_char (1, c);
+
+  rl_end_undo_group ();
+
+  return (0);
+}
+
+static int
+_rl_vi_callback_getchar (mb, mlen)
+     char *mb;
+     int mlen;
+{
+  int c;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  c = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  if (c < 0)
+    return -1;
+
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    c = _rl_read_mbstring (c, mb, mlen);
+#endif
+
+  return c;
+}
+
+#if defined (READLINE_CALLBACKS)
+static int
+_rl_vi_callback_change_char (data)
+     _rl_callback_generic_arg *data;
+{
+  int c;
+  char mb[MB_LEN_MAX];
+
+  _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
+
+  if (c < 0)
+    return -1;
+
+  _rl_callback_func = 0;
+  _rl_want_redisplay = 1;
+
+  return (_rl_vi_change_char (data->count, c, mb));
+}
+#endif
+
+int
+rl_vi_change_char (count, key)
+     int count, key;
+{
+  int c;
+  char mb[MB_LEN_MAX];
+
+  if (vi_redoing)
+    {
+      c = _rl_vi_last_replacement;
+      mb[0] = c;
+      mb[1] = '\0';
+    }
+#if defined (READLINE_CALLBACKS)
+  else if (RL_ISSTATE (RL_STATE_CALLBACK))
+    {
+      _rl_callback_data = _rl_callback_data_alloc (count);
+      _rl_callback_func = _rl_vi_callback_change_char;
+      return (0);
+    }
+#endif
+  else
+    _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
+
+  if (c < 0)
+    return -1;
+
+  return (_rl_vi_change_char (count, c, mb));
+}
+
+int
+rl_vi_subst (count, key)
+     int count, key;
+{
+  /* If we are redoing, rl_vi_change_to will stuff the last motion char */
+  if (vi_redoing == 0)
+    rl_stuff_char ((key == 'S') ? 'c' : 'l');  /* `S' == `cc', `s' == `cl' */
+
+  return (rl_vi_change_to (count, 'c'));
+}
+
+int
+rl_vi_overstrike (count, key)
+     int count, key;
+{
+  if (_rl_vi_doing_insert == 0)
+    {
+      _rl_vi_doing_insert = 1;
+      rl_begin_undo_group ();
+    }
+
+  if (count > 0)
+    {
+      _rl_overwrite_char (count, key);
+      vi_replace_count += count;
+    }
+
+  return (0);
+}
+
+int
+rl_vi_overstrike_delete (count, key)
+     int count, key;
+{
+  int i, s;
+
+  for (i = 0; i < count; i++)
+    {
+      if (vi_replace_count == 0)
+       {
+         rl_ding ();
+         break;
+       }
+      s = rl_point;
+
+      if (rl_do_undo ())
+       vi_replace_count--;
+
+      if (rl_point == s)
+       rl_backward_char (1, key);
+    }
+
+  if (vi_replace_count == 0 && _rl_vi_doing_insert)
+    {
+      rl_end_undo_group ();
+      rl_do_undo ();
+      _rl_vi_doing_insert = 0;
+    }
+  return (0);
+}
+
+int
+rl_vi_replace (count, key)
+     int count, key;
+{
+  int i;
+
+  vi_replace_count = 0;
+
+  if (vi_replace_map == 0)
+    {
+      vi_replace_map = rl_make_bare_keymap ();
+
+      for (i = 0; i < ' '; i++)
+       if (vi_insertion_keymap[i].type == ISFUNC)
+         vi_replace_map[i].function = vi_insertion_keymap[i].function;
+
+      for (i = ' '; i < KEYMAP_SIZE; i++)
+       vi_replace_map[i].function = rl_vi_overstrike;
+
+      vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
+
+      /* Make sure these are what we want. */
+      vi_replace_map[ESC].function = rl_vi_movement_mode;
+      vi_replace_map[RETURN].function = rl_newline;
+      vi_replace_map[NEWLINE].function = rl_newline;
+
+      /* If the normal vi insertion keymap has ^H bound to erase, do the
+        same here.  Probably should remove the assignment to RUBOUT up
+        there, but I don't think it will make a difference in real life. */
+      if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
+         vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
+       vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
+
+    }
+
+  rl_vi_start_inserting (key, 1, rl_arg_sign);
+
+  _rl_vi_last_key_before_insert = key;
+  _rl_keymap = vi_replace_map;
+
+  return (0);
+}
+
+#if 0
+/* Try to complete the word we are standing on or the word that ends with
+   the previous character.  A space matches everything.  Word delimiters are
+   space and ;. */
+int
+rl_vi_possible_completions()
+{
+  int save_pos = rl_point;
+
+  if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
+    {
+      while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
+            rl_line_buffer[rl_point] != ';')
+       rl_point++;
+    }
+  else if (rl_line_buffer[rl_point - 1] == ';')
+    {
+      rl_ding ();
+      return (0);
+    }
+
+  rl_possible_completions ();
+  rl_point = save_pos;
+
+  return (0);
+}
+#endif
+
+/* Functions to save and restore marks. */
+static int
+_rl_vi_set_mark ()
+{
+  int ch;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  ch = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  if (ch < 0 || ch < 'a' || ch > 'z')  /* make test against 0 explicit */
+    {
+      rl_ding ();
+      return -1;
+    }
+  ch -= 'a';
+  vi_mark_chars[ch] = rl_point;
+  return 0;
+}
+
+#if defined (READLINE_CALLBACKS)
+static int
+_rl_vi_callback_set_mark (data)
+     _rl_callback_generic_arg *data;
+{
+  _rl_callback_func = 0;
+  _rl_want_redisplay = 1;
+
+  return (_rl_vi_set_mark ());
+}
+#endif
+
+int
+rl_vi_set_mark (count, key)
+     int count, key;
+{
+#if defined (READLINE_CALLBACKS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK))
+    {
+      _rl_callback_data = 0;
+      _rl_callback_func = _rl_vi_callback_set_mark;
+      return (0);
+    }
+#endif
+
+  return (_rl_vi_set_mark ());
+}
+
+static int
+_rl_vi_goto_mark ()
+{
+  int ch;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  ch = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  if (ch == '`')
+    {
+      rl_point = rl_mark;
+      return 0;
+    }
+  else if (ch < 0 || ch < 'a' || ch > 'z')     /* make test against 0 explicit */
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  ch -= 'a';
+  if (vi_mark_chars[ch] == -1)
+    {
+      rl_ding ();
+      return -1;
+    }
+  rl_point = vi_mark_chars[ch];
+  return 0;
+}
+
+#if defined (READLINE_CALLBACKS)
+static int
+_rl_vi_callback_goto_mark (data)
+     _rl_callback_generic_arg *data;
+{
+  _rl_callback_func = 0;
+  _rl_want_redisplay = 1;
+
+  return (_rl_vi_goto_mark ());
+}
+#endif
+
+int
+rl_vi_goto_mark (count, key)
+     int count, key;
+{
+#if defined (READLINE_CALLBACKS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK))
+    {
+      _rl_callback_data = 0;
+      _rl_callback_func = _rl_vi_callback_goto_mark;
+      return (0);
+    }
+#endif
+
+  return (_rl_vi_goto_mark ());
+}
+#endif /* VI_MODE */
diff --git a/parse.y b/parse.y
index 6e95ea6906c39eeb8d5b68d2b03eca615f8fca5b..91bf3bf649bd85476758436c54504b2b9eab3bf3 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -2424,7 +2424,7 @@ shell_getc (remove_quoted_newline)
         not already end in an EOF character.  */
       if (shell_input_line_terminator != EOF)
        {
-         if (shell_input_line_size < SIZE_MAX && (shell_input_line_len+3 > shell_input_line_size))
+         if (shell_input_line_size < SIZE_MAX-3 && (shell_input_line_len+3 > shell_input_line_size))
            shell_input_line = (char *)xrealloc (shell_input_line,
                                        1 + (shell_input_line_size += 2));
 
index 15198d67538db9459b5a74e537c4093704ec0ec8..70cbc98a0accd5bf7c2875ac3e17d1ef722ad610 100644 (file)
@@ -777,6 +777,7 @@ pcomp_filename_completion_function (text, state)
       else if (iscompgen && iscompleting && rl_filename_dequoting_function &&
               pcomp_curtxt && text &&
               STREQ (pcomp_curtxt, text) == 0 &&
+              variable_context &&
               sh_contains_quotes (text))       /* guess */
        dfn = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
       else
index 837ccc297b38a52043ff170998f30862fa8f9cee..84a52252fc291a9b526484068934e0256abdf3f3 100644 (file)
@@ -92,3 +92,11 @@ a ab
 a ab
 a ab
 a
+. ..
+. .. a.log
+a.log
+?(foo)
+a.log
+a.log
+. ..
+a.log
index 0fa310aa754b3b534b46b4bac64eda731b354263..ac1df77a09ae2a159e7a71d82c6abe6f15542f4a 100644 (file)
@@ -370,4 +370,6 @@ ${THIS_SH} ./extglob1.sub
 
 ${THIS_SH} ./extglob1a.sub
 
+${THIS_SH} ./extglob3.sub
+
 exit 0
diff --git a/tests/extglob3.sub b/tests/extglob3.sub
new file mode 100644 (file)
index 0000000..94567ee
--- /dev/null
@@ -0,0 +1,21 @@
+shopt -s extglob
+DIR=/tmp/extglob-$$
+mkdir $DIR
+cd $DIR
+
+touch a.log
+
+echo *(.)
+echo *(.)*
+echo ?(foo)*
+echo ?(foo)
+echo *(foo)*
+echo @(|foo)*
+
+echo *(foo).*
+
+echo !(foo)*
+
+cd $OLDPWD
+rm -rf $DIR
+
diff --git a/variables.c~ b/variables.c~
new file mode 100644 (file)
index 0000000..70fac3b
--- /dev/null
@@ -0,0 +1,5334 @@
+/* variables.c -- Functions for hacking shell variables. */
+
+/* Copyright (C) 1987-2013 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Bash is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#include "bashtypes.h"
+#include "posixstat.h"
+#include "posixtime.h"
+
+#if defined (__QNX__)
+#  if defined (__QNXNTO__)
+#    include <sys/netmgr.h>
+#  else
+#    include <sys/vc.h>
+#  endif /* !__QNXNTO__ */
+#endif /* __QNX__ */
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include "chartypes.h"
+#if defined (HAVE_PWD_H)
+#  include <pwd.h>
+#endif
+#include "bashansi.h"
+#include "bashintl.h"
+
+#define NEED_XTRACE_SET_DECL
+
+#include "shell.h"
+#include "flags.h"
+#include "execute_cmd.h"
+#include "findcmd.h"
+#include "mailcheck.h"
+#include "input.h"
+#include "hashcmd.h"
+#include "pathexp.h"
+#include "alias.h"
+#include "jobs.h"
+
+#include "version.h"
+
+#include "builtins/getopt.h"
+#include "builtins/common.h"
+#include "builtins/builtext.h"
+
+#if defined (READLINE)
+#  include "bashline.h"
+#  include <readline/readline.h>
+#else
+#  include <tilde/tilde.h>
+#endif
+
+#if defined (HISTORY)
+#  include "bashhist.h"
+#  include <readline/history.h>
+#endif /* HISTORY */
+
+#if defined (PROGRAMMABLE_COMPLETION)
+#  include "pcomplete.h"
+#endif
+
+#define TEMPENV_HASH_BUCKETS   4       /* must be power of two */
+
+#define ifsname(s)     ((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0')
+
+extern char **environ;
+
+/* Variables used here and defined in other files. */
+extern int posixly_correct;
+extern int line_number, line_number_base;
+extern int subshell_environment, indirection_level, subshell_level;
+extern int build_version, patch_level;
+extern int expanding_redir;
+extern int last_command_exit_value;
+extern char *dist_version, *release_status;
+extern char *shell_name;
+extern char *primary_prompt, *secondary_prompt;
+extern char *current_host_name;
+extern sh_builtin_func_t *this_shell_builtin;
+extern SHELL_VAR *this_shell_function;
+extern char *the_printed_command_except_trap;
+extern char *this_command_name;
+extern char *command_execution_string;
+extern time_t shell_start_time;
+extern int assigning_in_environment;
+extern int executing_builtin;
+extern int funcnest_max;
+
+#if defined (READLINE)
+extern int no_line_editing;
+extern int perform_hostname_completion;
+#endif
+
+/* The list of shell variables that the user has created at the global
+   scope, or that came from the environment. */
+VAR_CONTEXT *global_variables = (VAR_CONTEXT *)NULL;
+
+/* The current list of shell variables, including function scopes */
+VAR_CONTEXT *shell_variables = (VAR_CONTEXT *)NULL;
+
+/* The list of shell functions that the user has created, or that came from
+   the environment. */
+HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
+
+#if defined (DEBUGGER)
+/* The table of shell function definitions that the user defined or that
+   came from the environment. */
+HASH_TABLE *shell_function_defs = (HASH_TABLE *)NULL;
+#endif
+
+/* The current variable context.  This is really a count of how deep into
+   executing functions we are. */
+int variable_context = 0;
+
+/* The set of shell assignments which are made only in the environment
+   for a single command. */
+HASH_TABLE *temporary_env = (HASH_TABLE *)NULL;
+
+/* Set to non-zero if an assignment error occurs while putting variables
+   into the temporary environment. */
+int tempenv_assign_error;
+
+/* Some funky variables which are known about specially.  Here is where
+   "$*", "$1", and all the cruft is kept. */
+char *dollar_vars[10];
+WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
+
+/* The value of $$. */
+pid_t dollar_dollar_pid;
+
+/* Non-zero means that we have to remake EXPORT_ENV. */
+int array_needs_making = 1;
+
+/* The number of times BASH has been executed.  This is set
+   by initialize_variables (). */
+int shell_level = 0;
+
+/* An array which is passed to commands as their environment.  It is
+   manufactured from the union of the initial environment and the
+   shell variables that are marked for export. */
+char **export_env = (char **)NULL;
+static int export_env_index;
+static int export_env_size;
+
+#if defined (READLINE)
+static int winsize_assignment;         /* currently assigning to LINES or COLUMNS */
+#endif
+
+static HASH_TABLE *last_table_searched;        /* hash_lookup sets this */
+
+/* Some forward declarations. */
+static void create_variable_tables __P((void));
+
+static void set_machine_vars __P((void));
+static void set_home_var __P((void));
+static void set_shell_var __P((void));
+static char *get_bash_name __P((void));
+static void initialize_shell_level __P((void));
+static void uidset __P((void));
+#if defined (ARRAY_VARS)
+static void make_vers_array __P((void));
+#endif
+
+static SHELL_VAR *null_assign __P((SHELL_VAR *, char *, arrayind_t, char *));
+#if defined (ARRAY_VARS)
+static SHELL_VAR *null_array_assign __P((SHELL_VAR *, char *, arrayind_t, char *));
+#endif
+static SHELL_VAR *get_self __P((SHELL_VAR *));
+
+#if defined (ARRAY_VARS)
+static SHELL_VAR *init_dynamic_array_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int));
+static SHELL_VAR *init_dynamic_assoc_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int));
+#endif
+
+static SHELL_VAR *assign_seconds __P((SHELL_VAR *, char *, arrayind_t, char *));
+static SHELL_VAR *get_seconds __P((SHELL_VAR *));
+static SHELL_VAR *init_seconds_var __P((void));
+
+static int brand __P((void));
+static void sbrand __P((unsigned long));               /* set bash random number generator. */
+static void seedrand __P((void));                      /* seed generator randomly */
+static SHELL_VAR *assign_random __P((SHELL_VAR *, char *, arrayind_t, char *));
+static SHELL_VAR *get_random __P((SHELL_VAR *));
+
+static SHELL_VAR *assign_lineno __P((SHELL_VAR *, char *, arrayind_t, char *));
+static SHELL_VAR *get_lineno __P((SHELL_VAR *));
+
+static SHELL_VAR *assign_subshell __P((SHELL_VAR *, char *, arrayind_t, char *));
+static SHELL_VAR *get_subshell __P((SHELL_VAR *));
+
+static SHELL_VAR *get_bashpid __P((SHELL_VAR *));
+
+#if defined (HISTORY)
+static SHELL_VAR *get_histcmd __P((SHELL_VAR *));
+#endif
+
+#if defined (READLINE)
+static SHELL_VAR *get_comp_wordbreaks __P((SHELL_VAR *));
+static SHELL_VAR *assign_comp_wordbreaks __P((SHELL_VAR *, char *, arrayind_t, char *));
+#endif
+
+#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
+static SHELL_VAR *assign_dirstack __P((SHELL_VAR *, char *, arrayind_t, char *));
+static SHELL_VAR *get_dirstack __P((SHELL_VAR *));
+#endif
+
+#if defined (ARRAY_VARS)
+static SHELL_VAR *get_groupset __P((SHELL_VAR *));
+
+static SHELL_VAR *build_hashcmd __P((SHELL_VAR *));
+static SHELL_VAR *get_hashcmd __P((SHELL_VAR *));
+static SHELL_VAR *assign_hashcmd __P((SHELL_VAR *,  char *, arrayind_t, char *));
+#  if defined (ALIAS)
+static SHELL_VAR *build_aliasvar __P((SHELL_VAR *));
+static SHELL_VAR *get_aliasvar __P((SHELL_VAR *));
+static SHELL_VAR *assign_aliasvar __P((SHELL_VAR *,  char *, arrayind_t, char *));
+#  endif
+#endif
+
+static SHELL_VAR *get_funcname __P((SHELL_VAR *));
+static SHELL_VAR *init_funcname_var __P((void));
+
+static void initialize_dynamic_variables __P((void));
+
+static SHELL_VAR *hash_lookup __P((const char *, HASH_TABLE *));
+static SHELL_VAR *new_shell_variable __P((const char *));
+static SHELL_VAR *make_new_variable __P((const char *, HASH_TABLE *));
+static SHELL_VAR *bind_variable_internal __P((const char *, char *, HASH_TABLE *, int, int));
+
+static void dispose_variable_value __P((SHELL_VAR *));
+static void free_variable_hash_data __P((PTR_T));
+
+static VARLIST *vlist_alloc __P((int));
+static VARLIST *vlist_realloc __P((VARLIST *, int));
+static void vlist_add __P((VARLIST *, SHELL_VAR *, int));
+
+static void flatten __P((HASH_TABLE *, sh_var_map_func_t *, VARLIST *, int));
+
+static int qsort_var_comp __P((SHELL_VAR **, SHELL_VAR **));
+
+static SHELL_VAR **vapply __P((sh_var_map_func_t *));
+static SHELL_VAR **fapply __P((sh_var_map_func_t *));
+
+static int visible_var __P((SHELL_VAR *));
+static int visible_and_exported __P((SHELL_VAR *));
+static int export_environment_candidate __P((SHELL_VAR *));
+static int local_and_exported __P((SHELL_VAR *));
+static int variable_in_context __P((SHELL_VAR *));
+#if defined (ARRAY_VARS)
+static int visible_array_vars __P((SHELL_VAR *));
+#endif
+
+static SHELL_VAR *find_nameref_at_context __P((SHELL_VAR *, VAR_CONTEXT *));
+static SHELL_VAR *find_variable_nameref_context __P((SHELL_VAR *, VAR_CONTEXT *, VAR_CONTEXT **));
+static SHELL_VAR *find_variable_last_nameref_context __P((SHELL_VAR *, VAR_CONTEXT *, VAR_CONTEXT **));
+
+static SHELL_VAR *bind_tempenv_variable __P((const char *, char *));
+static void push_temp_var __P((PTR_T));
+static void propagate_temp_var __P((PTR_T));
+static void dispose_temporary_env __P((sh_free_func_t *));     
+
+static inline char *mk_env_string __P((const char *, const char *));
+static char **make_env_array_from_var_list __P((SHELL_VAR **));
+static char **make_var_export_array __P((VAR_CONTEXT *));
+static char **make_func_export_array __P((void));
+static void add_temp_array_to_env __P((char **, int, int));
+
+static int n_shell_variables __P((void));
+static int set_context __P((SHELL_VAR *));
+
+static void push_func_var __P((PTR_T));
+static void push_exported_var __P((PTR_T));
+
+static inline int find_special_var __P((const char *));
+
+static void
+create_variable_tables ()
+{
+  if (shell_variables == 0)
+    {
+      shell_variables = global_variables = new_var_context ((char *)NULL, 0);
+      shell_variables->scope = 0;
+      shell_variables->table = hash_create (0);
+    }
+
+  if (shell_functions == 0)
+    shell_functions = hash_create (0);
+
+#if defined (DEBUGGER)
+  if (shell_function_defs == 0)
+    shell_function_defs = hash_create (0);
+#endif
+}
+
+/* Initialize the shell variables from the current environment.
+   If PRIVMODE is nonzero, don't import functions from ENV or
+   parse $SHELLOPTS. */
+void
+initialize_shell_variables (env, privmode)
+     char **env;
+     int privmode;
+{
+  char *name, *string, *temp_string;
+  int c, char_index, string_index, string_length, ro;
+  SHELL_VAR *temp_var;
+
+  create_variable_tables ();
+
+  for (string_index = 0; string = env[string_index++]; )
+    {
+      char_index = 0;
+      name = string;
+      while ((c = *string++) && c != '=')
+       ;
+      if (string[-1] == '=')
+       char_index = string - name - 1;
+
+      /* If there are weird things in the environment, like `=xxx' or a
+        string without an `=', just skip them. */
+      if (char_index == 0)
+       continue;
+
+      /* ASSERT(name[char_index] == '=') */
+      name[char_index] = '\0';
+      /* Now, name = env variable name, string = env variable value, and
+        char_index == strlen (name) */
+
+      temp_var = (SHELL_VAR *)NULL;
+
+      /* If exported function, define it now.  Don't import functions from
+        the environment in privileged mode. */
+      if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
+       {
+         string_length = strlen (string);
+         temp_string = (char *)xmalloc (3 + string_length + char_index);
+
+         strcpy (temp_string, name);
+         temp_string[char_index] = ' ';
+         strcpy (temp_string + char_index + 1, string);
+
+         if (posixly_correct == 0 || legal_identifier (name))
+           parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
+
+         /* Ancient backwards compatibility.  Old versions of bash exported
+            functions like name()=() {...} */
+         if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
+           name[char_index - 2] = '\0';
+
+         if (temp_var = find_function (name))
+           {
+             VSETATTR (temp_var, (att_exported|att_imported));
+             array_needs_making = 1;
+           }
+         else
+           {
+             if (temp_var = bind_variable (name, string, 0))
+               {
+                 VSETATTR (temp_var, (att_exported | att_imported | att_invisible));
+                 array_needs_making = 1;
+               }
+             last_command_exit_value = 1;
+             report_error (_("error importing function definition for `%s'"), name);
+           }
+
+         /* ( */
+         if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
+           name[char_index - 2] = '(';         /* ) */
+       }
+#if defined (ARRAY_VARS)
+#  if ARRAY_EXPORT
+      /* Array variables may not yet be exported. */
+      else if (*string == '(' && string[1] == '[' && string[strlen (string) - 1] == ')')
+       {
+         string_length = 1;
+         temp_string = extract_array_assignment_list (string, &string_length);
+         temp_var = assign_array_from_string (name, temp_string);
+         FREE (temp_string);
+         VSETATTR (temp_var, (att_exported | att_imported));
+         array_needs_making = 1;
+       }
+#  endif /* ARRAY_EXPORT */
+#endif
+#if 0
+      else if (legal_identifier (name))
+#else
+      else
+#endif
+       {
+         ro = 0;
+         if (posixly_correct && STREQ (name, "SHELLOPTS"))
+           {
+             temp_var = find_variable ("SHELLOPTS");
+             ro = temp_var && readonly_p (temp_var);
+             if (temp_var)
+               VUNSETATTR (temp_var, att_readonly);
+           }
+         temp_var = bind_variable (name, string, 0);
+         if (temp_var)
+           {
+             if (legal_identifier (name))
+               VSETATTR (temp_var, (att_exported | att_imported));
+             else
+               VSETATTR (temp_var, (att_exported | att_imported | att_invisible));
+             if (ro)
+               VSETATTR (temp_var, att_readonly);
+             array_needs_making = 1;
+           }
+       }
+
+      name[char_index] = '=';
+      /* temp_var can be NULL if it was an exported function with a syntax
+        error (a different bug, but it still shouldn't dump core). */
+      if (temp_var && function_p (temp_var) == 0)      /* XXX not yet */
+       {
+         CACHE_IMPORTSTR (temp_var, name);
+       }
+    }
+
+  set_pwd ();
+
+  /* Set up initial value of $_ */
+  temp_var = set_if_not ("_", dollar_vars[0]);
+
+  /* Remember this pid. */
+  dollar_dollar_pid = getpid ();
+
+  /* Now make our own defaults in case the vars that we think are
+     important are missing. */
+  temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
+#if 0
+  set_auto_export (temp_var);  /* XXX */
+#endif
+
+  temp_var = set_if_not ("TERM", "dumb");
+#if 0
+  set_auto_export (temp_var);  /* XXX */
+#endif
+
+#if defined (__QNX__)
+  /* set node id -- don't import it from the environment */
+  {
+    char node_name[22];
+#  if defined (__QNXNTO__)
+    netmgr_ndtostr(ND2S_LOCAL_STR, ND_LOCAL_NODE, node_name, sizeof(node_name));
+#  else
+    qnx_nidtostr (getnid (), node_name, sizeof (node_name));
+#  endif
+    temp_var = bind_variable ("NODE", node_name, 0);
+    set_auto_export (temp_var);
+  }
+#endif
+
+  /* set up the prompts. */
+  if (interactive_shell)
+    {
+#if defined (PROMPT_STRING_DECODE)
+      set_if_not ("PS1", primary_prompt);
+#else
+      if (current_user.uid == -1)
+       get_current_user_info ();
+      set_if_not ("PS1", current_user.euid == 0 ? "# " : primary_prompt);
+#endif
+      set_if_not ("PS2", secondary_prompt);
+    }
+  set_if_not ("PS4", "+ ");
+
+  /* Don't allow IFS to be imported from the environment. */
+  temp_var = bind_variable ("IFS", " \t\n", 0);
+  setifs (temp_var);
+
+  /* Magic machine types.  Pretty convenient. */
+  set_machine_vars ();
+
+  /* Default MAILCHECK for interactive shells.  Defer the creation of a
+     default MAILPATH until the startup files are read, because MAIL
+     names a mail file if MAILPATH is not set, and we should provide a
+     default only if neither is set. */
+  if (interactive_shell)
+    {
+      temp_var = set_if_not ("MAILCHECK", posixly_correct ? "600" : "60");
+      VSETATTR (temp_var, att_integer);
+    }
+
+  /* Do some things with shell level. */
+  initialize_shell_level ();
+
+  set_ppid ();
+
+  /* Initialize the `getopts' stuff. */
+  temp_var = bind_variable ("OPTIND", "1", 0);
+  VSETATTR (temp_var, att_integer);
+  getopts_reset (0);
+  bind_variable ("OPTERR", "1", 0);
+  sh_opterr = 1;
+
+  if (login_shell == 1 && posixly_correct == 0)
+    set_home_var ();
+
+  /* Get the full pathname to THIS shell, and set the BASH variable
+     to it. */
+  name = get_bash_name ();
+  temp_var = bind_variable ("BASH", name, 0);
+  free (name);
+
+  /* Make the exported environment variable SHELL be the user's login
+     shell.  Note that the `tset' command looks at this variable
+     to determine what style of commands to output; if it ends in "csh",
+     then C-shell commands are output, else Bourne shell commands. */
+  set_shell_var ();
+
+  /* Make a variable called BASH_VERSION which contains the version info. */
+  bind_variable ("BASH_VERSION", shell_version_string (), 0);
+#if defined (ARRAY_VARS)
+  make_vers_array ();
+#endif
+
+  if (command_execution_string)
+    bind_variable ("BASH_EXECUTION_STRING", command_execution_string, 0);
+
+  /* Find out if we're supposed to be in Posix.2 mode via an
+     environment variable. */
+  temp_var = find_variable ("POSIXLY_CORRECT");
+  if (!temp_var)
+    temp_var = find_variable ("POSIX_PEDANTIC");
+  if (temp_var && imported_p (temp_var))
+    sv_strict_posix (temp_var->name);
+
+#if defined (HISTORY)
+  /* Set history variables to defaults, and then do whatever we would
+     do if the variable had just been set.  Do this only in the case
+     that we are remembering commands on the history list. */
+  if (remember_on_history)
+    {
+      name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history", 0);
+
+      set_if_not ("HISTFILE", name);
+      free (name);
+    }
+#endif /* HISTORY */
+
+  /* Seed the random number generator. */
+  seedrand ();
+
+  /* Handle some "special" variables that we may have inherited from a
+     parent shell. */
+  if (interactive_shell)
+    {
+      temp_var = find_variable ("IGNOREEOF");
+      if (!temp_var)
+       temp_var = find_variable ("ignoreeof");
+      if (temp_var && imported_p (temp_var))
+       sv_ignoreeof (temp_var->name);
+    }
+
+#if defined (HISTORY)
+  if (interactive_shell && remember_on_history)
+    {
+      sv_history_control ("HISTCONTROL");
+      sv_histignore ("HISTIGNORE");
+      sv_histtimefmt ("HISTTIMEFORMAT");
+    }
+#endif /* HISTORY */
+
+#if defined (READLINE) && defined (STRICT_POSIX)
+  /* POSIXLY_CORRECT will only be 1 here if the shell was compiled
+     -DSTRICT_POSIX */
+  if (interactive_shell && posixly_correct && no_line_editing == 0)
+    rl_prefer_env_winsize = 1;
+#endif /* READLINE && STRICT_POSIX */
+
+     /*
+      * 24 October 2001
+      *
+      * I'm tired of the arguing and bug reports.  Bash now leaves SSH_CLIENT
+      * and SSH2_CLIENT alone.  I'm going to rely on the shell_level check in
+      * isnetconn() to avoid running the startup files more often than wanted.
+      * That will, of course, only work if the user's login shell is bash, so
+      * I've made that behavior conditional on SSH_SOURCE_BASHRC being defined
+      * in config-top.h.
+      */
+#if 0
+  temp_var = find_variable ("SSH_CLIENT");
+  if (temp_var && imported_p (temp_var))
+    {
+      VUNSETATTR (temp_var, att_exported);
+      array_needs_making = 1;
+    }
+  temp_var = find_variable ("SSH2_CLIENT");
+  if (temp_var && imported_p (temp_var))
+    {
+      VUNSETATTR (temp_var, att_exported);
+      array_needs_making = 1;
+    }
+#endif
+
+  /* Get the user's real and effective user ids. */
+  uidset ();
+
+  temp_var = find_variable ("BASH_XTRACEFD");
+  if (temp_var && imported_p (temp_var))
+    sv_xtracefd (temp_var->name);
+
+  /* Initialize the dynamic variables, and seed their values. */
+  initialize_dynamic_variables ();
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*          Setting values for special shell variables             */
+/*                                                                 */
+/* **************************************************************** */
+
+static void
+set_machine_vars ()
+{
+  SHELL_VAR *temp_var;
+
+  temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
+  temp_var = set_if_not ("OSTYPE", OSTYPE);
+  temp_var = set_if_not ("MACHTYPE", MACHTYPE);
+
+  temp_var = set_if_not ("HOSTNAME", current_host_name);
+}
+
+/* Set $HOME to the information in the password file if we didn't get
+   it from the environment. */
+
+/* This function is not static so the tilde and readline libraries can
+   use it. */
+char *
+sh_get_home_dir ()
+{
+  if (current_user.home_dir == 0)
+    get_current_user_info ();
+  return current_user.home_dir;
+}
+
+static void
+set_home_var ()
+{
+  SHELL_VAR *temp_var;
+
+  temp_var = find_variable ("HOME");
+  if (temp_var == 0)
+    temp_var = bind_variable ("HOME", sh_get_home_dir (), 0);
+#if 0
+  VSETATTR (temp_var, att_exported);
+#endif
+}
+
+/* Set $SHELL to the user's login shell if it is not already set.  Call
+   get_current_user_info if we haven't already fetched the shell. */
+static void
+set_shell_var ()
+{
+  SHELL_VAR *temp_var;
+
+  temp_var = find_variable ("SHELL");
+  if (temp_var == 0)
+    {
+      if (current_user.shell == 0)
+       get_current_user_info ();
+      temp_var = bind_variable ("SHELL", current_user.shell, 0);
+    }
+#if 0
+  VSETATTR (temp_var, att_exported);
+#endif
+}
+
+static char *
+get_bash_name ()
+{
+  char *name;
+
+  if ((login_shell == 1) && RELPATH(shell_name))
+    {
+      if (current_user.shell == 0)
+       get_current_user_info ();
+      name = savestring (current_user.shell);
+    }
+  else if (ABSPATH(shell_name))
+    name = savestring (shell_name);
+  else if (shell_name[0] == '.' && shell_name[1] == '/')
+    {
+      /* Fast path for common case. */
+      char *cdir;
+      int len;
+
+      cdir = get_string_value ("PWD");
+      if (cdir)
+       {
+         len = strlen (cdir);
+         name = (char *)xmalloc (len + strlen (shell_name) + 1);
+         strcpy (name, cdir);
+         strcpy (name + len, shell_name + 1);
+       }
+      else
+       name = savestring (shell_name);
+    }
+  else
+    {
+      char *tname;
+      int s;
+
+      tname = find_user_command (shell_name);
+
+      if (tname == 0)
+       {
+         /* Try the current directory.  If there is not an executable
+            there, just punt and use the login shell. */
+         s = file_status (shell_name);
+         if (s & FS_EXECABLE)
+           {
+             tname = make_absolute (shell_name, get_string_value ("PWD"));
+             if (*shell_name == '.')
+               {
+                 name = sh_canonpath (tname, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
+                 if (name == 0)
+                   name = tname;
+                 else
+                   free (tname);
+               }
+            else
+               name = tname;
+           }
+         else
+           {
+             if (current_user.shell == 0)
+               get_current_user_info ();
+             name = savestring (current_user.shell);
+           }
+       }
+      else
+       {
+         name = full_pathname (tname);
+         free (tname);
+       }
+    }
+
+  return (name);
+}
+
+void
+adjust_shell_level (change)
+     int change;
+{
+  char new_level[5], *old_SHLVL;
+  intmax_t old_level;
+  SHELL_VAR *temp_var;
+
+  old_SHLVL = get_string_value ("SHLVL");
+  if (old_SHLVL == 0 || *old_SHLVL == '\0' || legal_number (old_SHLVL, &old_level) == 0)
+    old_level = 0;
+
+  shell_level = old_level + change;
+  if (shell_level < 0)
+    shell_level = 0;
+  else if (shell_level > 1000)
+    {
+      internal_warning (_("shell level (%d) too high, resetting to 1"), shell_level);
+      shell_level = 1;
+    }
+
+  /* We don't need the full generality of itos here. */
+  if (shell_level < 10)
+    {
+      new_level[0] = shell_level + '0';
+      new_level[1] = '\0';
+    }
+  else if (shell_level < 100)
+    {
+      new_level[0] = (shell_level / 10) + '0';
+      new_level[1] = (shell_level % 10) + '0';
+      new_level[2] = '\0';
+    }
+  else if (shell_level < 1000)
+    {
+      new_level[0] = (shell_level / 100) + '0';
+      old_level = shell_level % 100;
+      new_level[1] = (old_level / 10) + '0';
+      new_level[2] = (old_level % 10) + '0';
+      new_level[3] = '\0';
+    }
+
+  temp_var = bind_variable ("SHLVL", new_level, 0);
+  set_auto_export (temp_var);
+}
+
+static void
+initialize_shell_level ()
+{
+  adjust_shell_level (1);
+}
+
+/* If we got PWD from the environment, update our idea of the current
+   working directory.  In any case, make sure that PWD exists before
+   checking it.  It is possible for getcwd () to fail on shell startup,
+   and in that case, PWD would be undefined.  If this is an interactive
+   login shell, see if $HOME is the current working directory, and if
+   that's not the same string as $PWD, set PWD=$HOME. */
+
+void
+set_pwd ()
+{
+  SHELL_VAR *temp_var, *home_var;
+  char *temp_string, *home_string;
+
+  home_var = find_variable ("HOME");
+  home_string = home_var ? value_cell (home_var) : (char *)NULL;
+
+  temp_var = find_variable ("PWD");
+  if (temp_var && imported_p (temp_var) &&
+      (temp_string = value_cell (temp_var)) &&
+      same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL))
+    set_working_directory (temp_string);
+  else if (home_string && interactive_shell && login_shell &&
+          same_file (home_string, ".", (struct stat *)NULL, (struct stat *)NULL))
+    {
+      set_working_directory (home_string);
+      temp_var = bind_variable ("PWD", home_string, 0);
+      set_auto_export (temp_var);
+    }
+  else
+    {
+      temp_string = get_working_directory ("shell-init");
+      if (temp_string)
+       {
+         temp_var = bind_variable ("PWD", temp_string, 0);
+         set_auto_export (temp_var);
+         free (temp_string);
+       }
+    }
+
+  /* According to the Single Unix Specification, v2, $OLDPWD is an
+     `environment variable' and therefore should be auto-exported.
+     Make a dummy invisible variable for OLDPWD, and mark it as exported. */
+  temp_var = bind_variable ("OLDPWD", (char *)NULL, 0);
+  VSETATTR (temp_var, (att_exported | att_invisible));
+}
+
+/* Make a variable $PPID, which holds the pid of the shell's parent.  */
+void
+set_ppid ()
+{
+  char namebuf[INT_STRLEN_BOUND(pid_t) + 1], *name;
+  SHELL_VAR *temp_var;
+
+  name = inttostr (getppid (), namebuf, sizeof(namebuf));
+  temp_var = find_variable ("PPID");
+  if (temp_var)
+    VUNSETATTR (temp_var, (att_readonly | att_exported));
+  temp_var = bind_variable ("PPID", name, 0);
+  VSETATTR (temp_var, (att_readonly | att_integer));
+}
+
+static void
+uidset ()
+{
+  char buff[INT_STRLEN_BOUND(uid_t) + 1], *b;
+  register SHELL_VAR *v;
+
+  b = inttostr (current_user.uid, buff, sizeof (buff));
+  v = find_variable ("UID");
+  if (v == 0)
+    {
+      v = bind_variable ("UID", b, 0);
+      VSETATTR (v, (att_readonly | att_integer));
+    }
+
+  if (current_user.euid != current_user.uid)
+    b = inttostr (current_user.euid, buff, sizeof (buff));
+
+  v = find_variable ("EUID");
+  if (v == 0)
+    {
+      v = bind_variable ("EUID", b, 0);
+      VSETATTR (v, (att_readonly | att_integer));
+    }
+}
+
+#if defined (ARRAY_VARS)
+static void
+make_vers_array ()
+{
+  SHELL_VAR *vv;
+  ARRAY *av;
+  char *s, d[32], b[INT_STRLEN_BOUND(int) + 1];
+
+  unbind_variable ("BASH_VERSINFO");
+
+  vv = make_new_array_variable ("BASH_VERSINFO");
+  av = array_cell (vv);
+  strcpy (d, dist_version);
+  s = strchr (d, '.');
+  if (s)
+    *s++ = '\0';
+  array_insert (av, 0, d);
+  array_insert (av, 1, s);
+  s = inttostr (patch_level, b, sizeof (b));
+  array_insert (av, 2, s);
+  s = inttostr (build_version, b, sizeof (b));
+  array_insert (av, 3, s);
+  array_insert (av, 4, release_status);
+  array_insert (av, 5, MACHTYPE);
+
+  VSETATTR (vv, att_readonly);
+}
+#endif /* ARRAY_VARS */
+
+/* Set the environment variables $LINES and $COLUMNS in response to
+   a window size change. */
+void
+sh_set_lines_and_columns (lines, cols)
+     int lines, cols;
+{
+  char val[INT_STRLEN_BOUND(int) + 1], *v;
+
+#if defined (READLINE)
+  /* If we are currently assigning to LINES or COLUMNS, don't do anything. */
+  if (winsize_assignment)
+    return;
+#endif
+
+  v = inttostr (lines, val, sizeof (val));
+  bind_variable ("LINES", v, 0);
+
+  v = inttostr (cols, val, sizeof (val));
+  bind_variable ("COLUMNS", v, 0);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                Printing variables and values                    */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Print LIST (a list of shell variables) to stdout in such a way that
+   they can be read back in. */
+void
+print_var_list (list)
+     register SHELL_VAR **list;
+{
+  register int i;
+  register SHELL_VAR *var;
+
+  for (i = 0; list && (var = list[i]); i++)
+    if (invisible_p (var) == 0)
+      print_assignment (var);
+}
+
+/* Print LIST (a list of shell functions) to stdout in such a way that
+   they can be read back in. */
+void
+print_func_list (list)
+     register SHELL_VAR **list;
+{
+  register int i;
+  register SHELL_VAR *var;
+
+  for (i = 0; list && (var = list[i]); i++)
+    {
+      printf ("%s ", var->name);
+      print_var_function (var);
+      printf ("\n");
+    }
+}
+      
+/* Print the value of a single SHELL_VAR.  No newline is
+   output, but the variable is printed in such a way that
+   it can be read back in. */
+void
+print_assignment (var)
+     SHELL_VAR *var;
+{
+  if (var_isset (var) == 0)
+    return;
+
+  if (function_p (var))
+    {
+      printf ("%s", var->name);
+      print_var_function (var);
+      printf ("\n");
+    }
+#if defined (ARRAY_VARS)
+  else if (array_p (var))
+    print_array_assignment (var, 0);
+  else if (assoc_p (var))
+    print_assoc_assignment (var, 0);
+#endif /* ARRAY_VARS */
+  else
+    {
+      printf ("%s=", var->name);
+      print_var_value (var, 1);
+      printf ("\n");
+    }
+}
+
+/* Print the value cell of VAR, a shell variable.  Do not print
+   the name, nor leading/trailing newline.  If QUOTE is non-zero,
+   and the value contains shell metacharacters, quote the value
+   in such a way that it can be read back in. */
+void
+print_var_value (var, quote)
+     SHELL_VAR *var;
+     int quote;
+{
+  char *t;
+
+  if (var_isset (var) == 0)
+    return;
+
+  if (quote && posixly_correct == 0 && ansic_shouldquote (value_cell (var)))
+    {
+      t = ansic_quote (value_cell (var), 0, (int *)0);
+      printf ("%s", t);
+      free (t);
+    }
+  else if (quote && sh_contains_shell_metas (value_cell (var)))
+    {
+      t = sh_single_quote (value_cell (var));
+      printf ("%s", t);
+      free (t);
+    }
+  else
+    printf ("%s", value_cell (var));
+}
+
+/* Print the function cell of VAR, a shell variable.  Do not
+   print the name, nor leading/trailing newline. */
+void
+print_var_function (var)
+     SHELL_VAR *var;
+{
+  char *x;
+
+  if (function_p (var) && var_isset (var))
+    {
+      x = named_function_string ((char *)NULL, function_cell(var), FUNC_MULTILINE|FUNC_EXTERNAL);
+      printf ("%s", x);
+    }
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Dynamic Variables                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* DYNAMIC VARIABLES
+
+   These are variables whose values are generated anew each time they are
+   referenced.  These are implemented using a pair of function pointers
+   in the struct variable: assign_func, which is called from bind_variable
+   and, if arrays are compiled into the shell, some of the functions in
+   arrayfunc.c, and dynamic_value, which is called from find_variable.
+
+   assign_func is called from bind_variable_internal, if
+   bind_variable_internal discovers that the variable being assigned to
+   has such a function.  The function is called as
+       SHELL_VAR *temp = (*(entry->assign_func)) (entry, value, ind)
+   and the (SHELL_VAR *)temp is returned as the value of bind_variable.  It
+   is usually ENTRY (self).  IND is an index for an array variable, and
+   unused otherwise.
+
+   dynamic_value is called from find_variable_internal to return a `new'
+   value for the specified dynamic varible.  If this function is NULL,
+   the variable is treated as a `normal' shell variable.  If it is not,
+   however, then this function is called like this:
+       tempvar = (*(var->dynamic_value)) (var);
+
+   Sometimes `tempvar' will replace the value of `var'.  Other times, the
+   shell will simply use the string value.  Pretty object-oriented, huh?
+
+   Be warned, though: if you `unset' a special variable, it loses its
+   special meaning, even if you subsequently set it.
+
+   The special assignment code would probably have been better put in
+   subst.c: do_assignment_internal, in the same style as
+   stupidly_hack_special_variables, but I wanted the changes as
+   localized as possible.  */
+
+#define INIT_DYNAMIC_VAR(var, val, gfunc, afunc) \
+  do \
+    { \
+      v = bind_variable (var, (val), 0); \
+      v->dynamic_value = gfunc; \
+      v->assign_func = afunc; \
+    } \
+  while (0)
+
+#define INIT_DYNAMIC_ARRAY_VAR(var, gfunc, afunc) \
+  do \
+    { \
+      v = make_new_array_variable (var); \
+      v->dynamic_value = gfunc; \
+      v->assign_func = afunc; \
+    } \
+  while (0)
+
+#define INIT_DYNAMIC_ASSOC_VAR(var, gfunc, afunc) \
+  do \
+    { \
+      v = make_new_assoc_variable (var); \
+      v->dynamic_value = gfunc; \
+      v->assign_func = afunc; \
+    } \
+  while (0)
+
+static SHELL_VAR *
+null_assign (self, value, unused, key)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t unused;
+     char *key;
+{
+  return (self);
+}
+
+#if defined (ARRAY_VARS)
+static SHELL_VAR *
+null_array_assign (self, value, ind, key)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t ind;
+     char *key;
+{
+  return (self);
+}
+#endif
+
+/* Degenerate `dynamic_value' function; just returns what's passed without
+   manipulation. */
+static SHELL_VAR *
+get_self (self)
+     SHELL_VAR *self;
+{
+  return (self);
+}
+
+#if defined (ARRAY_VARS)
+/* A generic dynamic array variable initializer.  Initialize array variable
+   NAME with dynamic value function GETFUNC and assignment function SETFUNC. */
+static SHELL_VAR *
+init_dynamic_array_var (name, getfunc, setfunc, attrs)
+     char *name;
+     sh_var_value_func_t *getfunc;
+     sh_var_assign_func_t *setfunc;
+     int attrs;
+{
+  SHELL_VAR *v;
+
+  v = find_variable (name);
+  if (v)
+    return (v);
+  INIT_DYNAMIC_ARRAY_VAR (name, getfunc, setfunc);
+  if (attrs)
+    VSETATTR (v, attrs);
+  return v;
+}
+
+static SHELL_VAR *
+init_dynamic_assoc_var (name, getfunc, setfunc, attrs)
+     char *name;
+     sh_var_value_func_t *getfunc;
+     sh_var_assign_func_t *setfunc;
+     int attrs;
+{
+  SHELL_VAR *v;
+
+  v = find_variable (name);
+  if (v)
+    return (v);
+  INIT_DYNAMIC_ASSOC_VAR (name, getfunc, setfunc);
+  if (attrs)
+    VSETATTR (v, attrs);
+  return v;
+}
+#endif
+
+/* The value of $SECONDS.  This is the number of seconds since shell
+   invocation, or, the number of seconds since the last assignment + the
+   value of the last assignment. */
+static intmax_t seconds_value_assigned;
+
+static SHELL_VAR *
+assign_seconds (self, value, unused, key)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t unused;
+     char *key;
+{
+  if (legal_number (value, &seconds_value_assigned) == 0)
+    seconds_value_assigned = 0;
+  shell_start_time = NOW;
+  return (self);
+}
+
+static SHELL_VAR *
+get_seconds (var)
+     SHELL_VAR *var;
+{
+  time_t time_since_start;
+  char *p;
+
+  time_since_start = NOW - shell_start_time;
+  p = itos(seconds_value_assigned + time_since_start);
+
+  FREE (value_cell (var));
+
+  VSETATTR (var, att_integer);
+  var_setvalue (var, p);
+  return (var);
+}
+
+static SHELL_VAR *
+init_seconds_var ()
+{
+  SHELL_VAR *v;
+
+  v = find_variable ("SECONDS");
+  if (v)
+    {
+      if (legal_number (value_cell(v), &seconds_value_assigned) == 0)
+       seconds_value_assigned = 0;
+    }
+  INIT_DYNAMIC_VAR ("SECONDS", (v ? value_cell (v) : (char *)NULL), get_seconds, assign_seconds);
+  return v;      
+}
+     
+/* The random number seed.  You can change this by setting RANDOM. */
+static unsigned long rseed = 1;
+static int last_random_value;
+static int seeded_subshell = 0;
+
+/* A linear congruential random number generator based on the example
+   one in the ANSI C standard.  This one isn't very good, but a more
+   complicated one is overkill. */
+
+/* Returns a pseudo-random number between 0 and 32767. */
+static int
+brand ()
+{
+  /* From "Random number generators: good ones are hard to find",
+     Park and Miller, Communications of the ACM, vol. 31, no. 10,
+     October 1988, p. 1195. filtered through FreeBSD */
+  long h, l;
+
+  /* Can't seed with 0. */
+  if (rseed == 0)
+    rseed = 123459876;
+  h = rseed / 127773;
+  l = rseed % 127773;
+  rseed = 16807 * l - 2836 * h;
+#if 0
+  if (rseed < 0)
+    rseed += 0x7fffffff;
+#endif
+  return ((unsigned int)(rseed & 32767));      /* was % 32768 */
+}
+
+/* Set the random number generator seed to SEED. */
+static void
+sbrand (seed)
+     unsigned long seed;
+{
+  rseed = seed;
+  last_random_value = 0;
+}
+
+static void
+seedrand ()
+{
+  struct timeval tv;
+
+  gettimeofday (&tv, NULL);
+  sbrand (tv.tv_sec ^ tv.tv_usec ^ getpid ());
+}
+
+static SHELL_VAR *
+assign_random (self, value, unused, key)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t unused;
+     char *key;
+{
+  sbrand (strtoul (value, (char **)NULL, 10));
+  if (subshell_environment)
+    seeded_subshell = getpid ();
+  return (self);
+}
+
+int
+get_random_number ()
+{
+  int rv, pid;
+
+  /* Reset for command and process substitution. */
+  pid = getpid ();
+  if (subshell_environment && seeded_subshell != pid)
+    {
+      seedrand ();
+      seeded_subshell = pid;
+    }
+
+  do
+    rv = brand ();
+  while (rv == last_random_value);
+  return rv;
+}
+
+static SHELL_VAR *
+get_random (var)
+     SHELL_VAR *var;
+{
+  int rv;
+  char *p;
+
+  rv = get_random_number ();
+  last_random_value = rv;
+  p = itos (rv);
+
+  FREE (value_cell (var));
+
+  VSETATTR (var, att_integer);
+  var_setvalue (var, p);
+  return (var);
+}
+
+static SHELL_VAR *
+assign_lineno (var, value, unused, key)
+     SHELL_VAR *var;
+     char *value;
+     arrayind_t unused;
+     char *key;
+{
+  intmax_t new_value;
+
+  if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
+    new_value = 0;
+  line_number = line_number_base = new_value;
+  return var;
+}
+
+/* Function which returns the current line number. */
+static SHELL_VAR *
+get_lineno (var)
+     SHELL_VAR *var;
+{
+  char *p;
+  int ln;
+
+  ln = executing_line_number ();
+  p = itos (ln);
+  FREE (value_cell (var));
+  var_setvalue (var, p);
+  return (var);
+}
+
+static SHELL_VAR *
+assign_subshell (var, value, unused, key)
+     SHELL_VAR *var;
+     char *value;
+     arrayind_t unused;
+     char *key;
+{
+  intmax_t new_value;
+
+  if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
+    new_value = 0;
+  subshell_level = new_value;
+  return var;
+}
+
+static SHELL_VAR *
+get_subshell (var)
+     SHELL_VAR *var;
+{
+  char *p;
+
+  p = itos (subshell_level);
+  FREE (value_cell (var));
+  var_setvalue (var, p);
+  return (var);
+}
+
+static SHELL_VAR *
+get_bashpid (var)
+     SHELL_VAR *var;
+{
+  int pid;
+  char *p;
+
+  pid = getpid ();
+  p = itos (pid);
+
+  FREE (value_cell (var));
+  VSETATTR (var, att_integer|att_readonly);
+  var_setvalue (var, p);
+  return (var);
+}
+
+static SHELL_VAR *
+get_bash_command (var)
+     SHELL_VAR *var;
+{
+  char *p;
+
+  if (the_printed_command_except_trap)
+    p = savestring (the_printed_command_except_trap);
+  else
+    {
+      p = (char *)xmalloc (1);
+      p[0] = '\0';
+    }
+  FREE (value_cell (var));
+  var_setvalue (var, p);
+  return (var);
+}
+
+#if defined (HISTORY)
+static SHELL_VAR *
+get_histcmd (var)
+     SHELL_VAR *var;
+{
+  char *p;
+
+  p = itos (history_number ());
+  FREE (value_cell (var));
+  var_setvalue (var, p);
+  return (var);
+}
+#endif
+
+#if defined (READLINE)
+/* When this function returns, VAR->value points to malloced memory. */
+static SHELL_VAR *
+get_comp_wordbreaks (var)
+     SHELL_VAR *var;
+{
+  /* If we don't have anything yet, assign a default value. */
+  if (rl_completer_word_break_characters == 0 && bash_readline_initialized == 0)
+    enable_hostname_completion (perform_hostname_completion);
+
+  FREE (value_cell (var));
+  var_setvalue (var, savestring (rl_completer_word_break_characters));
+
+  return (var);
+}
+
+/* When this function returns, rl_completer_word_break_characters points to
+   malloced memory. */
+static SHELL_VAR *
+assign_comp_wordbreaks (self, value, unused, key)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t unused;
+     char *key;
+{
+  if (rl_completer_word_break_characters &&
+      rl_completer_word_break_characters != rl_basic_word_break_characters)
+    free (rl_completer_word_break_characters);
+
+  rl_completer_word_break_characters = savestring (value);
+  return self;
+}
+#endif /* READLINE */
+
+#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
+static SHELL_VAR *
+assign_dirstack (self, value, ind, key)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t ind;
+     char *key;
+{
+  set_dirstack_element (ind, 1, value);
+  return self;
+}
+
+static SHELL_VAR *
+get_dirstack (self)
+     SHELL_VAR *self;
+{
+  ARRAY *a;
+  WORD_LIST *l;
+
+  l = get_directory_stack (0);
+  a = array_from_word_list (l);
+  array_dispose (array_cell (self));
+  dispose_words (l);
+  var_setarray (self, a);
+  return self;
+}
+#endif /* PUSHD AND POPD && ARRAY_VARS */
+
+#if defined (ARRAY_VARS)
+/* We don't want to initialize the group set with a call to getgroups()
+   unless we're asked to, but we only want to do it once. */
+static SHELL_VAR *
+get_groupset (self)
+     SHELL_VAR *self;
+{
+  register int i;
+  int ng;
+  ARRAY *a;
+  static char **group_set = (char **)NULL;
+
+  if (group_set == 0)
+    {
+      group_set = get_group_list (&ng);
+      a = array_cell (self);
+      for (i = 0; i < ng; i++)
+       array_insert (a, i, group_set[i]);
+    }
+  return (self);
+}
+
+static SHELL_VAR *
+build_hashcmd (self)
+     SHELL_VAR *self;
+{
+  HASH_TABLE *h;
+  int i;
+  char *k, *v;
+  BUCKET_CONTENTS *item;
+
+  h = assoc_cell (self);
+  if (h)
+    assoc_dispose (h);
+
+  if (hashed_filenames == 0 || HASH_ENTRIES (hashed_filenames) == 0)
+    {
+      var_setvalue (self, (char *)NULL);
+      return self;
+    }
+
+  h = assoc_create (hashed_filenames->nbuckets);
+  for (i = 0; i < hashed_filenames->nbuckets; i++)
+    {
+      for (item = hash_items (i, hashed_filenames); item; item = item->next)
+       {
+         k = savestring (item->key);
+         v = pathdata(item)->path;
+         assoc_insert (h, k, v);
+       }
+    }
+
+  var_setvalue (self, (char *)h);
+  return self;
+}
+
+static SHELL_VAR *
+get_hashcmd (self)
+     SHELL_VAR *self;
+{
+  build_hashcmd (self);
+  return (self);
+}
+
+static SHELL_VAR *
+assign_hashcmd (self, value, ind, key)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t ind;
+     char *key;
+{
+  phash_insert (key, value, 0, 0);
+  return (build_hashcmd (self));
+}
+
+#if defined (ALIAS)
+static SHELL_VAR *
+build_aliasvar (self)
+     SHELL_VAR *self;
+{
+  HASH_TABLE *h;
+  int i;
+  char *k, *v;
+  BUCKET_CONTENTS *item;
+
+  h = assoc_cell (self);
+  if (h)
+    assoc_dispose (h);
+
+  if (aliases == 0 || HASH_ENTRIES (aliases) == 0)
+    {
+      var_setvalue (self, (char *)NULL);
+      return self;
+    }
+
+  h = assoc_create (aliases->nbuckets);
+  for (i = 0; i < aliases->nbuckets; i++)
+    {
+      for (item = hash_items (i, aliases); item; item = item->next)
+       {
+         k = savestring (item->key);
+         v = ((alias_t *)(item->data))->value;
+         assoc_insert (h, k, v);
+       }
+    }
+
+  var_setvalue (self, (char *)h);
+  return self;
+}
+
+static SHELL_VAR *
+get_aliasvar (self)
+     SHELL_VAR *self;
+{
+  build_aliasvar (self);
+  return (self);
+}
+
+static SHELL_VAR *
+assign_aliasvar (self, value, ind, key)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t ind;
+     char *key;
+{
+  add_alias (key, value);
+  return (build_aliasvar (self));
+}
+#endif /* ALIAS */
+
+#endif /* ARRAY_VARS */
+
+/* If ARRAY_VARS is not defined, this just returns the name of any
+   currently-executing function.  If we have arrays, it's a call stack. */
+static SHELL_VAR *
+get_funcname (self)
+     SHELL_VAR *self;
+{
+#if ! defined (ARRAY_VARS)
+  char *t;
+  if (variable_context && this_shell_function)
+    {
+      FREE (value_cell (self));
+      t = savestring (this_shell_function->name);
+      var_setvalue (self, t);
+    }
+#endif
+  return (self);
+}
+
+void
+make_funcname_visible (on_or_off)
+     int on_or_off;
+{
+  SHELL_VAR *v;
+
+  v = find_variable ("FUNCNAME");
+  if (v == 0 || v->dynamic_value == 0)
+    return;
+
+  if (on_or_off)
+    VUNSETATTR (v, att_invisible);
+  else
+    VSETATTR (v, att_invisible);
+}
+
+static SHELL_VAR *
+init_funcname_var ()
+{
+  SHELL_VAR *v;
+
+  v = find_variable ("FUNCNAME");
+  if (v)
+    return v;
+#if defined (ARRAY_VARS)
+  INIT_DYNAMIC_ARRAY_VAR ("FUNCNAME", get_funcname, null_array_assign);
+#else
+  INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign);
+#endif
+  VSETATTR (v, att_invisible|att_noassign);
+  return v;
+}
+
+static void
+initialize_dynamic_variables ()
+{
+  SHELL_VAR *v;
+
+  v = init_seconds_var ();
+
+  INIT_DYNAMIC_VAR ("BASH_COMMAND", (char *)NULL, get_bash_command, (sh_var_assign_func_t *)NULL);
+  INIT_DYNAMIC_VAR ("BASH_SUBSHELL", (char *)NULL, get_subshell, assign_subshell);
+
+  INIT_DYNAMIC_VAR ("RANDOM", (char *)NULL, get_random, assign_random);
+  VSETATTR (v, att_integer);
+  INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno);
+  VSETATTR (v, att_integer);
+
+  INIT_DYNAMIC_VAR ("BASHPID", (char *)NULL, get_bashpid, null_assign);
+  VSETATTR (v, att_integer|att_readonly);
+
+#if defined (HISTORY)
+  INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (sh_var_assign_func_t *)NULL);
+  VSETATTR (v, att_integer);
+#endif
+
+#if defined (READLINE)
+  INIT_DYNAMIC_VAR ("COMP_WORDBREAKS", (char *)NULL, get_comp_wordbreaks, assign_comp_wordbreaks);
+#endif
+
+#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
+  v = init_dynamic_array_var ("DIRSTACK", get_dirstack, assign_dirstack, 0);
+#endif /* PUSHD_AND_POPD && ARRAY_VARS */
+
+#if defined (ARRAY_VARS)
+  v = init_dynamic_array_var ("GROUPS", get_groupset, null_array_assign, att_noassign);
+
+#  if defined (DEBUGGER)
+  v = init_dynamic_array_var ("BASH_ARGC", get_self, null_array_assign, att_noassign|att_nounset);
+  v = init_dynamic_array_var ("BASH_ARGV", get_self, null_array_assign, att_noassign|att_nounset);
+#  endif /* DEBUGGER */
+  v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, att_noassign|att_nounset);
+  v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, att_noassign|att_nounset);
+
+  v = init_dynamic_assoc_var ("BASH_CMDS", get_hashcmd, assign_hashcmd, att_nofree);
+#  if defined (ALIAS)
+  v = init_dynamic_assoc_var ("BASH_ALIASES", get_aliasvar, assign_aliasvar, att_nofree);
+#  endif
+#endif
+
+  v = init_funcname_var ();
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*             Retrieving variables and values                     */
+/*                                                                 */
+/* **************************************************************** */
+
+/* How to get a pointer to the shell variable or function named NAME.
+   HASHED_VARS is a pointer to the hash table containing the list
+   of interest (either variables or functions). */
+
+static SHELL_VAR *
+hash_lookup (name, hashed_vars)
+     const char *name;
+     HASH_TABLE *hashed_vars;
+{
+  BUCKET_CONTENTS *bucket;
+
+  bucket = hash_search (name, hashed_vars, 0);
+  /* If we find the name in HASHED_VARS, set LAST_TABLE_SEARCHED to that
+     table. */
+  if (bucket)
+    last_table_searched = hashed_vars;
+  return (bucket ? (SHELL_VAR *)bucket->data : (SHELL_VAR *)NULL);
+}
+
+SHELL_VAR *
+var_lookup (name, vcontext)
+     const char *name;
+     VAR_CONTEXT *vcontext;
+{
+  VAR_CONTEXT *vc;
+  SHELL_VAR *v;
+
+  v = (SHELL_VAR *)NULL;
+  for (vc = vcontext; vc; vc = vc->down)
+    if (v = hash_lookup (name, vc->table))
+      break;
+
+  return v;
+}
+
+/* Look up the variable entry named NAME.  If SEARCH_TEMPENV is non-zero,
+   then also search the temporarily built list of exported variables.
+   The lookup order is:
+       temporary_env
+       shell_variables list
+*/
+
+SHELL_VAR *
+find_variable_internal (name, force_tempenv)
+     const char *name;
+     int force_tempenv;
+{
+  SHELL_VAR *var;
+  int search_tempenv;
+  VAR_CONTEXT *vc;
+
+  var = (SHELL_VAR *)NULL;
+
+  /* If explicitly requested, first look in the temporary environment for
+     the variable.  This allows constructs such as "foo=x eval 'echo $foo'"
+     to get the `exported' value of $foo.  This happens if we are executing
+     a function or builtin, or if we are looking up a variable in a
+     "subshell environment". */
+  search_tempenv = force_tempenv || (expanding_redir == 0 && subshell_environment);
+
+  if (search_tempenv && temporary_env)         
+    var = hash_lookup (name, temporary_env);
+
+  vc = shell_variables;
+#if 0
+if (search_tempenv == 0 && /* (subshell_environment & SUBSHELL_COMSUB) && */
+    expanding_redir &&
+    (this_shell_builtin == eval_builtin || this_shell_builtin == command_builtin))
+  {
+  itrace("find_variable_internal: search_tempenv == 0: skipping VC_BLTNENV");
+  while (vc && (vc->flags & VC_BLTNENV))
+    vc = vc->down;
+  if (vc == 0)
+    vc = shell_variables;
+  }
+#endif
+
+  if (var == 0)
+    var = var_lookup (name, vc);
+
+  if (var == 0)
+    return ((SHELL_VAR *)NULL);
+
+  return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
+}
+
+/* Look up and resolve the chain of nameref variables starting at V all the
+   way to NULL or non-nameref. */
+SHELL_VAR *
+find_variable_nameref (v)
+     SHELL_VAR *v;
+{
+  int level;
+  char *newname;
+  SHELL_VAR *orig, *oldv;
+
+  level = 0;
+  orig = v;
+  while (v && nameref_p (v))
+    {
+      level++;
+      if (level > NAMEREF_MAX)
+       return ((SHELL_VAR *)0);        /* error message here? */
+      newname = nameref_cell (v);
+      if (newname == 0 || *newname == '\0')
+       return ((SHELL_VAR *)0);
+      oldv = v;
+      v = find_variable_internal (newname, (expanding_redir == 0 && (assigning_in_environment || executing_builtin)));
+      if (v == orig || v == oldv)
+       {
+         internal_warning (_("%s: circular name reference"), orig->name);
+         return ((SHELL_VAR *)0);
+       }
+    }
+  return v;
+}
+
+/* Resolve the chain of nameref variables for NAME.  XXX - could change later */
+SHELL_VAR *
+find_variable_last_nameref (name)
+     const char *name;
+{
+  SHELL_VAR *v, *nv;
+  char *newname;
+  int level;
+
+  nv = v = find_variable_noref (name);
+  level = 0;
+  while (v && nameref_p (v))
+    {
+      level++;
+      if (level > NAMEREF_MAX)
+        return ((SHELL_VAR *)0);       /* error message here? */
+      newname = nameref_cell (v);
+      if (newname == 0 || *newname == '\0')
+       return ((SHELL_VAR *)0);
+      nv = v;
+      v = find_variable_internal (newname, (expanding_redir == 0 && (assigning_in_environment || executing_builtin)));
+    }
+  return nv;
+}
+
+/* Resolve the chain of nameref variables for NAME.  XXX - could change later */
+SHELL_VAR *
+find_global_variable_last_nameref (name)
+     const char *name;
+{
+  SHELL_VAR *v, *nv;
+  char *newname;
+  int level;
+
+  nv = v = find_global_variable_noref (name);
+  level = 0;
+  while (v && nameref_p (v))
+    {
+      level++;
+      if (level > NAMEREF_MAX)
+        return ((SHELL_VAR *)0);       /* error message here? */
+      newname = nameref_cell (v);
+      if (newname == 0 || *newname == '\0')
+       return ((SHELL_VAR *)0);
+      nv = v;
+      v = find_global_variable_noref (newname);
+    }
+  return nv;
+}
+
+static SHELL_VAR *
+find_nameref_at_context (v, vc)
+     SHELL_VAR *v;
+     VAR_CONTEXT *vc;
+{
+  SHELL_VAR *nv, *nv2;
+  VAR_CONTEXT *nvc;
+  char *newname;
+  int level;
+
+  nv = v;
+  level = 1;
+  while (nv && nameref_p (nv))
+    {
+      level++;
+      if (level > NAMEREF_MAX)
+        return ((SHELL_VAR *)NULL);
+      newname = nameref_cell (nv);
+      if (newname == 0 || *newname == '\0')
+        return ((SHELL_VAR *)NULL);      
+      nv2 = hash_lookup (newname, vc->table);
+      if (nv2 == 0)
+        break;
+      nv = nv2;
+    }
+  return nv;
+}
+
+/* Do nameref resolution from the VC, which is the local context for some
+   function or builtin, `up' the chain to the global variables context.  If
+   NVCP is not NULL, return the variable context where we finally ended the
+   nameref resolution (so the bind_variable_internal can use the correct
+   variable context and hash table). */
+static SHELL_VAR *
+find_variable_nameref_context (v, vc, nvcp)
+     SHELL_VAR *v;
+     VAR_CONTEXT *vc;
+     VAR_CONTEXT **nvcp;
+{
+  SHELL_VAR *nv, *nv2;
+  VAR_CONTEXT *nvc;
+
+  /* Look starting at the current context all the way `up' */
+  for (nv = v, nvc = vc; nvc; nvc = nvc->down)
+    {
+      nv2 = find_nameref_at_context (nv, nvc);
+      if (nv2 == 0)
+        continue;
+      nv = nv2;
+      if (*nvcp)
+        *nvcp = nvc;
+      if (nameref_p (nv) == 0)
+        break;
+    }
+  return (nameref_p (nv) ? (SHELL_VAR *)NULL : nv);
+}
+
+/* Do nameref resolution from the VC, which is the local context for some
+   function or builtin, `up' the chain to the global variables context.  If
+   NVCP is not NULL, return the variable context where we finally ended the
+   nameref resolution (so the bind_variable_internal can use the correct
+   variable context and hash table). */
+static SHELL_VAR *
+find_variable_last_nameref_context (v, vc, nvcp)
+     SHELL_VAR *v;
+     VAR_CONTEXT *vc;
+     VAR_CONTEXT **nvcp;
+{
+  SHELL_VAR *nv, *nv2;
+  VAR_CONTEXT *nvc;
+
+  /* Look starting at the current context all the way `up' */
+  for (nv = v, nvc = vc; nvc; nvc = nvc->down)
+    {
+      nv2 = find_nameref_at_context (nv, nvc);
+      if (nv2 == 0)
+       continue;
+      nv = nv2;
+      if (*nvcp)
+        *nvcp = nvc;
+    }
+  return (nameref_p (nv) ? nv : (SHELL_VAR *)NULL);
+}
+
+/* Find a variable, forcing a search of the temporary environment first */
+SHELL_VAR *
+find_variable_tempenv (name)
+     const char *name;
+{
+  SHELL_VAR *var;
+
+  var = find_variable_internal (name, 1);
+  if (var && nameref_p (var))
+    var = find_variable_nameref (var);
+  return (var);
+}
+
+/* Find a variable, not forcing a search of the temporary environment first */
+SHELL_VAR *
+find_variable_notempenv (name)
+     const char *name;
+{
+  SHELL_VAR *var;
+
+  var = find_variable_internal (name, 0);
+  if (var && nameref_p (var))
+    var = find_variable_nameref (var);
+  return (var);
+}
+
+SHELL_VAR *
+find_global_variable (name)
+     const char *name;
+{
+  SHELL_VAR *var;
+
+  var = var_lookup (name, global_variables);
+  if (var && nameref_p (var))
+    var = find_variable_nameref (var);
+
+  if (var == 0)
+    return ((SHELL_VAR *)NULL);
+
+  return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
+}
+
+SHELL_VAR *
+find_global_variable_noref (name)
+     const char *name;
+{
+  SHELL_VAR *var;
+
+  var = var_lookup (name, global_variables);
+
+  if (var == 0)
+    return ((SHELL_VAR *)NULL);
+
+  return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
+}
+
+SHELL_VAR *
+find_shell_variable (name)
+     const char *name;
+{
+  SHELL_VAR *var;
+
+  var = var_lookup (name, shell_variables);
+  if (var && nameref_p (var))
+    var = find_variable_nameref (var);
+
+  if (var == 0)
+    return ((SHELL_VAR *)NULL);
+
+  return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
+}
+
+/* Look up the variable entry named NAME.  Returns the entry or NULL. */
+SHELL_VAR *
+find_variable (name)
+     const char *name;
+{
+  SHELL_VAR *v;
+
+  last_table_searched = 0;
+  v = find_variable_internal (name, (expanding_redir == 0 && (assigning_in_environment || executing_builtin)));
+  if (v && nameref_p (v))
+    v = find_variable_nameref (v);
+  return v;
+}
+
+SHELL_VAR *
+find_variable_noref (name)
+     const char *name;
+{
+  SHELL_VAR *v;
+
+  v = find_variable_internal (name, (expanding_redir == 0 && (assigning_in_environment || executing_builtin)));
+  return v;
+}
+
+/* Look up the function entry whose name matches STRING.
+   Returns the entry or NULL. */
+SHELL_VAR *
+find_function (name)
+     const char *name;
+{
+  return (hash_lookup (name, shell_functions));
+}
+
+/* Find the function definition for the shell function named NAME.  Returns
+   the entry or NULL. */
+FUNCTION_DEF *
+find_function_def (name)
+     const char *name;
+{
+#if defined (DEBUGGER)
+  return ((FUNCTION_DEF *)hash_lookup (name, shell_function_defs));
+#else
+  return ((FUNCTION_DEF *)0);
+#endif
+}
+
+/* Return the value of VAR.  VAR is assumed to have been the result of a
+   lookup without any subscript, if arrays are compiled into the shell. */
+char *
+get_variable_value (var)
+     SHELL_VAR *var;
+{
+  if (var == 0)
+    return ((char *)NULL);
+#if defined (ARRAY_VARS)
+  else if (array_p (var))
+    return (array_reference (array_cell (var), 0));
+  else if (assoc_p (var))
+    return (assoc_reference (assoc_cell (var), "0"));
+#endif
+  else
+    return (value_cell (var));
+}
+
+/* Return the string value of a variable.  Return NULL if the variable
+   doesn't exist.  Don't cons a new string.  This is a potential memory
+   leak if the variable is found in the temporary environment.  Since
+   functions and variables have separate name spaces, returns NULL if
+   var_name is a shell function only. */
+char *
+get_string_value (var_name)
+     const char *var_name;
+{
+  SHELL_VAR *var;
+
+  var = find_variable (var_name);
+  return ((var) ? get_variable_value (var) : (char *)NULL);
+}
+
+/* This is present for use by the tilde and readline libraries. */
+char *
+sh_get_env_value (v)
+     const char *v;
+{
+  return get_string_value (v);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*               Creating and setting variables                    */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Set NAME to VALUE if NAME has no value. */
+SHELL_VAR *
+set_if_not (name, value)
+     char *name, *value;
+{
+  SHELL_VAR *v;
+
+  if (shell_variables == 0)
+    create_variable_tables ();
+
+  v = find_variable (name);
+  if (v == 0)
+    v = bind_variable_internal (name, value, global_variables->table, HASH_NOSRCH, 0);
+  return (v);
+}
+
+/* Create a local variable referenced by NAME. */
+SHELL_VAR *
+make_local_variable (name)
+     const char *name;
+{
+  SHELL_VAR *new_var, *old_var;
+  VAR_CONTEXT *vc;
+  int was_tmpvar;
+  char *tmp_value;
+
+  /* local foo; local foo;  is a no-op. */
+  old_var = find_variable (name);
+  if (old_var && local_p (old_var) && old_var->context == variable_context)
+    {
+      VUNSETATTR (old_var, att_invisible);     /* XXX */
+      return (old_var);
+    }
+
+  was_tmpvar = old_var && tempvar_p (old_var);
+  /* If we're making a local variable in a shell function, the temporary env
+     has already been merged into the function's variable context stack.  We
+     can assume that a temporary var in the same context appears in the same
+     VAR_CONTEXT and can safely be returned without creating a new variable
+     (which results in duplicate names in the same VAR_CONTEXT->table */
+  /* We can't just test tmpvar_p because variables in the temporary env given
+     to a shell function appear in the function's local variable VAR_CONTEXT
+     but retain their tempvar attribute.  We want temporary variables that are
+     found in temporary_env, hence the test for last_table_searched, which is
+     set in hash_lookup and only (so far) checked here. */
+  if (was_tmpvar && old_var->context == variable_context && last_table_searched != temporary_env)
+    {
+      VUNSETATTR (old_var, att_invisible);
+      return (old_var);
+    }
+  if (was_tmpvar)
+    tmp_value = value_cell (old_var);
+
+  for (vc = shell_variables; vc; vc = vc->down)
+    if (vc_isfuncenv (vc) && vc->scope == variable_context)
+      break;
+
+  if (vc == 0)
+    {
+      internal_error (_("make_local_variable: no function context at current scope"));
+      return ((SHELL_VAR *)NULL);
+    }
+  else if (vc->table == 0)
+    vc->table = hash_create (TEMPENV_HASH_BUCKETS);
+
+  /* Since this is called only from the local/declare/typeset code, we can
+     call builtin_error here without worry (of course, it will also work
+     for anything that sets this_command_name).  Variables with the `noassign'
+     attribute may not be made local.  The test against old_var's context
+     level is to disallow local copies of readonly global variables (since I
+     believe that this could be a security hole).  Readonly copies of calling
+     function local variables are OK. */
+  if (old_var && (noassign_p (old_var) ||
+                (readonly_p (old_var) && old_var->context == 0)))
+    {
+      if (readonly_p (old_var))
+       sh_readonly (name);
+      else if (noassign_p (old_var))
+       builtin_error (_("%s: variable may not be assigned value"), name);
+#if 0
+      /* Let noassign variables through with a warning */
+      if (readonly_p (old_var))
+#endif
+       return ((SHELL_VAR *)NULL);
+    }
+
+  if (old_var == 0)
+    new_var = make_new_variable (name, vc->table);
+  else
+    {
+      new_var = make_new_variable (name, vc->table);
+
+      /* If we found this variable in one of the temporary environments,
+        inherit its value.  Watch to see if this causes problems with
+        things like `x=4 local x'. XXX - see above for temporary env
+        variables with the same context level as variable_context */
+      /* XXX - we should only do this if the variable is not an array. */
+      if (was_tmpvar)
+       var_setvalue (new_var, savestring (tmp_value));
+
+      new_var->attributes = exported_p (old_var) ? att_exported : 0;
+    }
+
+  vc->flags |= VC_HASLOCAL;
+
+  new_var->context = variable_context;
+  VSETATTR (new_var, att_local);
+
+  if (ifsname (name))
+    setifs (new_var);
+
+  if (was_tmpvar == 0)
+    VSETATTR (new_var, att_invisible); /* XXX */
+  return (new_var);
+}
+
+/* Create a new shell variable with name NAME. */
+static SHELL_VAR *
+new_shell_variable (name)
+     const char *name;
+{
+  SHELL_VAR *entry;
+
+  entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
+
+  entry->name = savestring (name);
+  var_setvalue (entry, (char *)NULL);
+  CLEAR_EXPORTSTR (entry);
+
+  entry->dynamic_value = (sh_var_value_func_t *)NULL;
+  entry->assign_func = (sh_var_assign_func_t *)NULL;
+
+  entry->attributes = 0;
+
+  /* Always assume variables are to be made at toplevel!
+     make_local_variable has the responsibility of changing the
+     variable context. */
+  entry->context = 0;
+
+  return (entry);
+}
+
+/* Create a new shell variable with name NAME and add it to the hash table
+   TABLE. */
+static SHELL_VAR *
+make_new_variable (name, table)
+     const char *name;
+     HASH_TABLE *table;
+{
+  SHELL_VAR *entry;
+  BUCKET_CONTENTS *elt;
+
+  entry = new_shell_variable (name);
+
+  /* Make sure we have a shell_variables hash table to add to. */
+  if (shell_variables == 0)
+    create_variable_tables ();
+
+  elt = hash_insert (savestring (name), table, HASH_NOSRCH);
+  elt->data = (PTR_T)entry;
+
+  return entry;
+}
+
+#if defined (ARRAY_VARS)
+SHELL_VAR *
+make_new_array_variable (name)
+     char *name;
+{
+  SHELL_VAR *entry;
+  ARRAY *array;
+
+  entry = make_new_variable (name, global_variables->table);
+  array = array_create ();
+
+  var_setarray (entry, array);
+  VSETATTR (entry, att_array);
+  return entry;
+}
+
+SHELL_VAR *
+make_local_array_variable (name, assoc_ok)
+     char *name;
+     int assoc_ok;
+{
+  SHELL_VAR *var;
+  ARRAY *array;
+
+  var = make_local_variable (name);
+  if (var == 0 || array_p (var) || (assoc_ok && assoc_p (var)))
+    return var;
+
+  array = array_create ();
+
+  dispose_variable_value (var);
+  var_setarray (var, array);
+  VSETATTR (var, att_array);
+  return var;
+}
+
+SHELL_VAR *
+make_new_assoc_variable (name)
+     char *name;
+{
+  SHELL_VAR *entry;
+  HASH_TABLE *hash;
+
+  entry = make_new_variable (name, global_variables->table);
+  hash = assoc_create (0);
+
+  var_setassoc (entry, hash);
+  VSETATTR (entry, att_assoc);
+  return entry;
+}
+
+SHELL_VAR *
+make_local_assoc_variable (name)
+     char *name;
+{
+  SHELL_VAR *var;
+  HASH_TABLE *hash;
+
+  var = make_local_variable (name);
+  if (var == 0 || assoc_p (var))
+    return var;
+
+  dispose_variable_value (var);
+  hash = assoc_create (0);
+
+  var_setassoc (var, hash);
+  VSETATTR (var, att_assoc);
+  return var;
+}
+#endif
+
+char *
+make_variable_value (var, value, flags)
+     SHELL_VAR *var;
+     char *value;
+     int flags;
+{
+  char *retval, *oval;
+  intmax_t lval, rval;
+  int expok, olen, op;
+
+  /* If this variable has had its type set to integer (via `declare -i'),
+     then do expression evaluation on it and store the result.  The
+     functions in expr.c (evalexp()) and bind_int_variable() are responsible
+     for turning off the integer flag if they don't want further
+     evaluation done. */
+  if (integer_p (var))
+    {
+      if (flags & ASS_APPEND)
+       {
+         oval = value_cell (var);
+         lval = evalexp (oval, &expok);        /* ksh93 seems to do this */
+         if (expok == 0)
+           {
+             top_level_cleanup ();
+             jump_to_top_level (DISCARD);
+           }
+       }
+      rval = evalexp (value, &expok);
+      if (expok == 0)
+       {
+         top_level_cleanup ();
+         jump_to_top_level (DISCARD);
+       }
+      /* This can be fooled if the variable's value changes while evaluating
+        `rval'.  We can change it if we move the evaluation of lval to here. */
+      if (flags & ASS_APPEND)
+       rval += lval;
+      retval = itos (rval);
+    }
+#if defined (CASEMOD_ATTRS)
+  else if (capcase_p (var) || uppercase_p (var) || lowercase_p (var))
+    {
+      if (flags & ASS_APPEND)
+       {
+         oval = get_variable_value (var);
+         if (oval == 0)        /* paranoia */
+           oval = "";
+         olen = STRLEN (oval);
+         retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1);
+         strcpy (retval, oval);
+         if (value)
+           strcpy (retval+olen, value);
+       }
+      else if (*value)
+       retval = savestring (value);
+      else
+       {
+         retval = (char *)xmalloc (1);
+         retval[0] = '\0';
+       }
+      op = capcase_p (var) ? CASE_CAPITALIZE
+                        : (uppercase_p (var) ? CASE_UPPER : CASE_LOWER);
+      oval = sh_modcase (retval, (char *)0, op);
+      free (retval);
+      retval = oval;
+    }
+#endif /* CASEMOD_ATTRS */
+  else if (value)
+    {
+      if (flags & ASS_APPEND)
+       {
+         oval = get_variable_value (var);
+         if (oval == 0)        /* paranoia */
+           oval = "";
+         olen = STRLEN (oval);
+         retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1);
+         strcpy (retval, oval);
+         if (value)
+           strcpy (retval+olen, value);
+       }
+      else if (*value)
+       retval = savestring (value);
+      else
+       {
+         retval = (char *)xmalloc (1);
+         retval[0] = '\0';
+       }
+    }
+  else
+    retval = (char *)NULL;
+
+  return retval;
+}
+
+/* Bind a variable NAME to VALUE in the HASH_TABLE TABLE, which may be the
+   temporary environment (but usually is not). */
+static SHELL_VAR *
+bind_variable_internal (name, value, table, hflags, aflags)
+     const char *name;
+     char *value;
+     HASH_TABLE *table;
+     int hflags, aflags;
+{
+  char *newval;
+  SHELL_VAR *entry;
+
+  entry = (hflags & HASH_NOSRCH) ? (SHELL_VAR *)NULL : hash_lookup (name, table);
+  /* Follow the nameref chain here if this is the global variables table */
+  if (entry && nameref_p (entry) && (invisible_p (entry) == 0) && table == global_variables->table)
+    {
+      entry = find_global_variable (entry->name);
+      /* Let's see if we have a nameref referencing a variable that hasn't yet
+        been created. */
+      if (entry == 0)
+       entry = find_variable_last_nameref (name);      /* XXX */
+      if (entry == 0)                                  /* just in case */
+        return (entry);
+    }
+
+  /* The first clause handles `declare -n ref; ref=x;' */
+  if (entry && invisible_p (entry) && nameref_p (entry))
+    goto assign_value;
+  else if (entry && nameref_p (entry))
+    {
+      newval = nameref_cell (entry);
+#if defined (ARRAY_VARS)
+      /* declare -n foo=x[2] */
+      if (valid_array_reference (newval))
+        /* XXX - should it be aflags? */
+       entry = assign_array_element (newval, make_variable_value (entry, value, 0), aflags);
+      else
+#endif
+      {
+      entry = make_new_variable (newval, table);
+      var_setvalue (entry, make_variable_value (entry, value, 0));
+      }
+    }
+  else if (entry == 0)
+    {
+      entry = make_new_variable (name, table);
+      var_setvalue (entry, make_variable_value (entry, value, 0)); /* XXX */
+    }
+  else if (entry->assign_func) /* array vars have assign functions now */
+    {
+      INVALIDATE_EXPORTSTR (entry);
+      newval = (aflags & ASS_APPEND) ? make_variable_value (entry, value, aflags) : value;
+      if (assoc_p (entry))
+       entry = (*(entry->assign_func)) (entry, newval, -1, savestring ("0"));
+      else if (array_p (entry))
+       entry = (*(entry->assign_func)) (entry, newval, 0, 0);
+      else
+       entry = (*(entry->assign_func)) (entry, newval, -1, 0);
+      if (newval != value)
+       free (newval);
+      return (entry);
+    }
+  else
+    {
+assign_value:
+      if (readonly_p (entry) || noassign_p (entry))
+       {
+         if (readonly_p (entry))
+           err_readonly (name);
+         return (entry);
+       }
+
+      /* Variables which are bound are visible. */
+      VUNSETATTR (entry, att_invisible);
+
+#if defined (ARRAY_VARS)
+      if (assoc_p (entry) || array_p (entry))
+        newval = make_array_variable_value (entry, 0, "0", value, aflags);
+      else
+#endif
+
+      newval = make_variable_value (entry, value, aflags);     /* XXX */
+
+      /* Invalidate any cached export string */
+      INVALIDATE_EXPORTSTR (entry);
+
+#if defined (ARRAY_VARS)
+      /* XXX -- this bears looking at again -- XXX */
+      /* If an existing array variable x is being assigned to with x=b or
+        `read x' or something of that nature, silently convert it to
+        x[0]=b or `read x[0]'. */
+      if (assoc_p (entry))
+       {
+         assoc_insert (assoc_cell (entry), savestring ("0"), newval);
+         free (newval);
+       }
+      else if (array_p (entry))
+       {
+         array_insert (array_cell (entry), 0, newval);
+         free (newval);
+       }
+      else
+#endif
+       {
+         FREE (value_cell (entry));
+         var_setvalue (entry, newval);
+       }
+    }
+
+  if (mark_modified_vars)
+    VSETATTR (entry, att_exported);
+
+  if (exported_p (entry))
+    array_needs_making = 1;
+
+  return (entry);
+}
+       
+/* Bind a variable NAME to VALUE.  This conses up the name
+   and value strings.  If we have a temporary environment, we bind there
+   first, then we bind into shell_variables. */
+
+SHELL_VAR *
+bind_variable (name, value, flags)
+     const char *name;
+     char *value;
+     int flags;
+{
+  SHELL_VAR *v, *nv;
+  VAR_CONTEXT *vc, *nvc;
+  int level;
+
+  if (shell_variables == 0)
+    create_variable_tables ();
+
+  /* If we have a temporary environment, look there first for the variable,
+     and, if found, modify the value there before modifying it in the
+     shell_variables table.  This allows sourced scripts to modify values
+     given to them in a temporary environment while modifying the variable
+     value that the caller sees. */
+  if (temporary_env)
+    bind_tempenv_variable (name, value);
+
+  /* XXX -- handle local variables here. */
+  for (vc = shell_variables; vc; vc = vc->down)
+    {
+      if (vc_isfuncenv (vc) || vc_isbltnenv (vc))
+       {
+         v = hash_lookup (name, vc->table);
+         nvc = vc;
+         if (v && nameref_p (v))
+           {
+             nv = find_variable_nameref_context (v, vc, &nvc);
+             if (nv == 0)
+               {
+                 nv = find_variable_last_nameref_context (v, vc, &nvc);
+                 if (nv && nameref_p (nv))
+                   {
+                     /* If this nameref variable doesn't have a value yet,
+                        set the value.  Otherwise, assign using the value as
+                        normal. */
+                     if (nameref_cell (nv) == 0)
+                       return (bind_variable_internal (nv->name, value, nvc->table, 0, flags));
+                     return (bind_variable_internal (nameref_cell (nv), value, nvc->table, 0, flags));
+                   }
+                 else
+                   v = nv;
+               }
+             else
+               v = nv;
+           }
+         if (v)
+           return (bind_variable_internal (v->name, value, nvc->table, 0, flags));
+       }
+    }
+  /* bind_variable_internal will handle nameref resolution in this case */
+  return (bind_variable_internal (name, value, global_variables->table, 0, flags));
+}
+
+SHELL_VAR *
+bind_global_variable (name, value, flags)
+     const char *name;
+     char *value;
+     int flags;
+{
+  SHELL_VAR *v, *nv;
+  VAR_CONTEXT *vc, *nvc;
+  int level;
+
+  if (shell_variables == 0)
+    create_variable_tables ();
+
+  /* bind_variable_internal will handle nameref resolution in this case */
+  return (bind_variable_internal (name, value, global_variables->table, 0, flags));
+}
+
+/* Make VAR, a simple shell variable, have value VALUE.  Once assigned a
+   value, variables are no longer invisible.  This is a duplicate of part
+   of the internals of bind_variable.  If the variable is exported, or
+   all modified variables should be exported, mark the variable for export
+   and note that the export environment needs to be recreated. */
+SHELL_VAR *
+bind_variable_value (var, value, aflags)
+     SHELL_VAR *var;
+     char *value;
+     int aflags;
+{
+  char *t;
+  int invis;
+
+  invis = invisible_p (var);
+  VUNSETATTR (var, att_invisible);
+
+  if (var->assign_func)
+    {
+      /* If we're appending, we need the old value, so use
+        make_variable_value */
+      t = (aflags & ASS_APPEND) ? make_variable_value (var, value, aflags) : value;
+      (*(var->assign_func)) (var, t, -1, 0);
+      if (t != value && t)
+       free (t);      
+    }
+  else
+    {
+      t = make_variable_value (var, value, aflags);
+#if defined (ARRAY_VARS)
+      if ((aflags & ASS_NAMEREF) && (t == 0 || *t == 0 || (legal_identifier (t) == 0 && valid_array_reference (t) == 0)))
+#else
+      if ((aflags & ASS_NAMEREF) && (t == 0 || *t == 0 || legal_identifier (t) == 0))
+#endif
+       {
+         free (t);
+         if (invis)
+           VSETATTR (var, att_invisible);      /* XXX */
+         return ((SHELL_VAR *)NULL);
+       }
+      FREE (value_cell (var));
+      var_setvalue (var, t);
+    }
+
+  INVALIDATE_EXPORTSTR (var);
+
+  if (mark_modified_vars)
+    VSETATTR (var, att_exported);
+
+  if (exported_p (var))
+    array_needs_making = 1;
+
+  return (var);
+}
+
+/* Bind/create a shell variable with the name LHS to the RHS.
+   This creates or modifies a variable such that it is an integer.
+
+   This used to be in expr.c, but it is here so that all of the
+   variable binding stuff is localized.  Since we don't want any
+   recursive evaluation from bind_variable() (possible without this code,
+   since bind_variable() calls the evaluator for variables with the integer
+   attribute set), we temporarily turn off the integer attribute for each
+   variable we set here, then turn it back on after binding as necessary. */
+
+SHELL_VAR *
+bind_int_variable (lhs, rhs)
+     char *lhs, *rhs;
+{
+  register SHELL_VAR *v;
+  int isint, isarr, implicitarray;
+
+  isint = isarr = implicitarray = 0;
+#if defined (ARRAY_VARS)
+  if (valid_array_reference (lhs))
+    {
+      isarr = 1;
+      v = array_variable_part (lhs, (char **)0, (int *)0);
+    }
+  else
+#endif
+    v = find_variable (lhs);
+
+  if (v)
+    {
+      isint = integer_p (v);
+      VUNSETATTR (v, att_integer);
+#if defined (ARRAY_VARS)
+      if (array_p (v) && isarr == 0)
+       implicitarray = 1;
+#endif
+    }
+
+#if defined (ARRAY_VARS)
+  if (isarr)
+    v = assign_array_element (lhs, rhs, 0);
+  else if (implicitarray)
+    v = bind_array_variable (lhs, 0, rhs, 0);
+  else
+#endif
+    v = bind_variable (lhs, rhs, 0);
+
+  if (v && isint)
+    VSETATTR (v, att_integer);
+
+  VUNSETATTR (v, att_invisible);
+
+  return (v);
+}
+
+SHELL_VAR *
+bind_var_to_int (var, val)
+     char *var;
+     intmax_t val;
+{
+  char ibuf[INT_STRLEN_BOUND (intmax_t) + 1], *p;
+
+  p = fmtulong (val, 10, ibuf, sizeof (ibuf), 0);
+  return (bind_int_variable (var, p));
+}
+
+/* Do a function binding to a variable.  You pass the name and
+   the command to bind to.  This conses the name and command. */
+SHELL_VAR *
+bind_function (name, value)
+     const char *name;
+     COMMAND *value;
+{
+  SHELL_VAR *entry;
+
+  entry = find_function (name);
+  if (entry == 0)
+    {
+      BUCKET_CONTENTS *elt;
+
+      elt = hash_insert (savestring (name), shell_functions, HASH_NOSRCH);
+      entry = new_shell_variable (name);
+      elt->data = (PTR_T)entry;
+    }
+  else
+    INVALIDATE_EXPORTSTR (entry);
+
+  if (var_isset (entry))
+    dispose_command (function_cell (entry));
+
+  if (value)
+    var_setfunc (entry, copy_command (value));
+  else
+    var_setfunc (entry, 0);
+
+  VSETATTR (entry, att_function);
+
+  if (mark_modified_vars)
+    VSETATTR (entry, att_exported);
+
+  VUNSETATTR (entry, att_invisible);           /* Just to be sure */
+
+  if (exported_p (entry))
+    array_needs_making = 1;
+
+#if defined (PROGRAMMABLE_COMPLETION)
+  set_itemlist_dirty (&it_functions);
+#endif
+
+  return (entry);
+}
+
+#if defined (DEBUGGER)
+/* Bind a function definition, which includes source file and line number
+   information in addition to the command, into the FUNCTION_DEF hash table.*/
+void
+bind_function_def (name, value)
+     const char *name;
+     FUNCTION_DEF *value;
+{
+  FUNCTION_DEF *entry;
+  BUCKET_CONTENTS *elt;
+  COMMAND *cmd;
+
+  entry = find_function_def (name);
+  if (entry)
+    {
+      dispose_function_def_contents (entry);
+      entry = copy_function_def_contents (value, entry);
+    }
+  else
+    {
+      cmd = value->command;
+      value->command = 0;
+      entry = copy_function_def (value);
+      value->command = cmd;
+
+      elt = hash_insert (savestring (name), shell_function_defs, HASH_NOSRCH);
+      elt->data = (PTR_T *)entry;
+    }
+}
+#endif /* DEBUGGER */
+
+/* Add STRING, which is of the form foo=bar, to the temporary environment
+   HASH_TABLE (temporary_env).  The functions in execute_cmd.c are
+   responsible for moving the main temporary env to one of the other
+   temporary environments.  The expansion code in subst.c calls this. */
+int
+assign_in_env (word, flags)
+     WORD_DESC *word;
+     int flags;
+{
+  int offset, aflags;
+  char *name, *temp, *value;
+  SHELL_VAR *var;
+  const char *string;
+
+  string = word->word;
+
+  aflags = 0;
+  offset = assignment (string, 0);
+  name = savestring (string);
+  value = (char *)NULL;
+
+  if (name[offset] == '=')
+    {
+      name[offset] = 0;
+
+      /* don't ignore the `+' when assigning temporary environment */
+      if (name[offset - 1] == '+')
+       {
+         name[offset - 1] = '\0';
+         aflags |= ASS_APPEND;
+       }
+
+      var = find_variable (name);
+      if (var && (readonly_p (var) || noassign_p (var)))
+       {
+         if (readonly_p (var))
+           err_readonly (name);
+         free (name);
+         return (0);
+       }
+
+      temp = name + offset + 1;
+      value = expand_assignment_string_to_string (temp, 0);
+
+      if (var && (aflags & ASS_APPEND))
+       {
+         temp = make_variable_value (var, value, aflags);
+         FREE (value);
+         value = temp;
+       }
+    }
+
+  if (temporary_env == 0)
+    temporary_env = hash_create (TEMPENV_HASH_BUCKETS);
+
+  var = hash_lookup (name, temporary_env);
+  if (var == 0)
+    var = make_new_variable (name, temporary_env);
+  else
+    FREE (value_cell (var));
+
+  if (value == 0)
+    {
+      value = (char *)xmalloc (1);     /* like do_assignment_internal */
+      value[0] = '\0';
+    }
+
+  var_setvalue (var, value);
+  var->attributes |= (att_exported|att_tempvar);
+  var->context = variable_context;     /* XXX */
+
+  INVALIDATE_EXPORTSTR (var);
+  var->exportstr = mk_env_string (name, value);
+
+  array_needs_making = 1;
+
+  if (flags)
+    stupidly_hack_special_variables (name);
+
+  if (echo_command_at_execute)
+    /* The Korn shell prints the `+ ' in front of assignment statements,
+       so we do too. */
+    xtrace_print_assignment (name, value, 0, 1);
+
+  free (name);
+  return 1;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Copying variables                           */
+/*                                                                 */
+/* **************************************************************** */
+
+#ifdef INCLUDE_UNUSED
+/* Copy VAR to a new data structure and return that structure. */
+SHELL_VAR *
+copy_variable (var)
+     SHELL_VAR *var;
+{
+  SHELL_VAR *copy = (SHELL_VAR *)NULL;
+
+  if (var)
+    {
+      copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
+
+      copy->attributes = var->attributes;
+      copy->name = savestring (var->name);
+
+      if (function_p (var))
+       var_setfunc (copy, copy_command (function_cell (var)));
+#if defined (ARRAY_VARS)
+      else if (array_p (var))
+       var_setarray (copy, array_copy (array_cell (var)));
+      else if (assoc_p (var))
+       var_setassoc (copy, assoc_copy (assoc_cell (var)));
+#endif
+      else if (nameref_cell (var))     /* XXX - nameref */
+       var_setref (copy, savestring (nameref_cell (var)));
+      else if (value_cell (var))       /* XXX - nameref */
+       var_setvalue (copy, savestring (value_cell (var)));
+      else
+       var_setvalue (copy, (char *)NULL);
+
+      copy->dynamic_value = var->dynamic_value;
+      copy->assign_func = var->assign_func;
+
+      copy->exportstr = COPY_EXPORTSTR (var);
+
+      copy->context = var->context;
+    }
+  return (copy);
+}
+#endif
+
+/* **************************************************************** */
+/*                                                                 */
+/*               Deleting and unsetting variables                  */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Dispose of the information attached to VAR. */
+static void
+dispose_variable_value (var)
+     SHELL_VAR *var;
+{
+  if (function_p (var))
+    dispose_command (function_cell (var));
+#if defined (ARRAY_VARS)
+  else if (array_p (var))
+    array_dispose (array_cell (var));
+  else if (assoc_p (var))
+    assoc_dispose (assoc_cell (var));
+#endif
+  else if (nameref_p (var))
+    FREE (nameref_cell (var));
+  else
+    FREE (value_cell (var));
+}
+
+void
+dispose_variable (var)
+     SHELL_VAR *var;
+{
+  if (var == 0)
+    return;
+
+  if (nofree_p (var) == 0)
+    dispose_variable_value (var);
+
+  FREE_EXPORTSTR (var);
+
+  free (var->name);
+
+  if (exported_p (var))
+    array_needs_making = 1;
+
+  free (var);
+}
+
+/* Unset the shell variable referenced by NAME.  Unsetting a nameref variable
+   unsets the variable it resolves to but leaves the nameref alone. */
+int
+unbind_variable (name)
+     const char *name;
+{
+  SHELL_VAR *v, *nv;
+  int r;
+
+  v = var_lookup (name, shell_variables);
+  nv = (v && nameref_p (v)) ? find_variable_nameref (v) : (SHELL_VAR *)NULL;
+
+  r = nv ? makunbound (nv->name, shell_variables) : makunbound (name, shell_variables);
+  return r;
+}
+
+/* Unbind NAME, where NAME is assumed to be a nameref variable */
+int
+unbind_nameref (name)
+     const char *name;
+{
+  SHELL_VAR *v;
+
+  v = var_lookup (name, shell_variables);
+  if (v && nameref_p (v))
+    return makunbound (name, shell_variables);
+  return 0;
+}
+
+/* Unset the shell function named NAME. */
+int
+unbind_func (name)
+     const char *name;
+{
+  BUCKET_CONTENTS *elt;
+  SHELL_VAR *func;
+
+  elt = hash_remove (name, shell_functions, 0);
+
+  if (elt == 0)
+    return -1;
+
+#if defined (PROGRAMMABLE_COMPLETION)
+  set_itemlist_dirty (&it_functions);
+#endif
+
+  func = (SHELL_VAR *)elt->data;
+  if (func)
+    {
+      if (exported_p (func))
+       array_needs_making++;
+      dispose_variable (func);
+    }
+
+  free (elt->key);
+  free (elt);
+
+  return 0;  
+}
+
+#if defined (DEBUGGER)
+int
+unbind_function_def (name)
+     const char *name;
+{
+  BUCKET_CONTENTS *elt;
+  FUNCTION_DEF *funcdef;
+
+  elt = hash_remove (name, shell_function_defs, 0);
+
+  if (elt == 0)
+    return -1;
+
+  funcdef = (FUNCTION_DEF *)elt->data;
+  if (funcdef)
+    dispose_function_def (funcdef);
+
+  free (elt->key);
+  free (elt);
+
+  return 0;  
+}
+#endif /* DEBUGGER */
+
+int
+delete_var (name, vc)
+     const char *name;
+     VAR_CONTEXT *vc;
+{
+  BUCKET_CONTENTS *elt;
+  SHELL_VAR *old_var;
+  VAR_CONTEXT *v;
+
+  for (elt = (BUCKET_CONTENTS *)NULL, v = vc; v; v = v->down)
+    if (elt = hash_remove (name, v->table, 0))
+      break;
+
+  if (elt == 0)
+    return (-1);
+
+  old_var = (SHELL_VAR *)elt->data;
+  free (elt->key);
+  free (elt);
+
+  dispose_variable (old_var);
+  return (0);
+}
+
+/* Make the variable associated with NAME go away.  HASH_LIST is the
+   hash table from which this variable should be deleted (either
+   shell_variables or shell_functions).
+   Returns non-zero if the variable couldn't be found. */
+int
+makunbound (name, vc)
+     const char *name;
+     VAR_CONTEXT *vc;
+{
+  BUCKET_CONTENTS *elt, *new_elt;
+  SHELL_VAR *old_var;
+  VAR_CONTEXT *v;
+  char *t;
+
+  for (elt = (BUCKET_CONTENTS *)NULL, v = vc; v; v = v->down)
+    if (elt = hash_remove (name, v->table, 0))
+      break;
+
+  if (elt == 0)
+    return (-1);
+
+  old_var = (SHELL_VAR *)elt->data;
+
+  if (old_var && exported_p (old_var))
+    array_needs_making++;
+
+  /* If we're unsetting a local variable and we're still executing inside
+     the function, just mark the variable as invisible.  The function
+     eventually called by pop_var_context() will clean it up later.  This
+     must be done so that if the variable is subsequently assigned a new
+     value inside the function, the `local' attribute is still present.
+     We also need to add it back into the correct hash table. */
+  if (old_var && local_p (old_var) && variable_context == old_var->context)
+    {
+      if (nofree_p (old_var))
+       var_setvalue (old_var, (char *)NULL);
+#if defined (ARRAY_VARS)
+      else if (array_p (old_var))
+       array_dispose (array_cell (old_var));
+      else if (assoc_p (old_var))
+       assoc_dispose (assoc_cell (old_var));
+#endif
+      else if (nameref_p (old_var))
+       FREE (nameref_cell (old_var));
+      else
+       FREE (value_cell (old_var));
+      /* Reset the attributes.  Preserve the export attribute if the variable
+        came from a temporary environment.  Make sure it stays local, and
+        make it invisible. */ 
+      old_var->attributes = (exported_p (old_var) && tempvar_p (old_var)) ? att_exported : 0;
+      VSETATTR (old_var, att_local);
+      VSETATTR (old_var, att_invisible);
+      var_setvalue (old_var, (char *)NULL);
+      INVALIDATE_EXPORTSTR (old_var);
+
+      new_elt = hash_insert (savestring (old_var->name), v->table, 0);
+      new_elt->data = (PTR_T)old_var;
+      stupidly_hack_special_variables (old_var->name);
+
+      free (elt->key);
+      free (elt);
+      return (0);
+    }
+
+  /* Have to save a copy of name here, because it might refer to
+     old_var->name.  If so, stupidly_hack_special_variables will
+     reference freed memory. */
+  t = savestring (name);
+
+  free (elt->key);
+  free (elt);
+
+  dispose_variable (old_var);
+  stupidly_hack_special_variables (t);
+  free (t);
+
+  return (0);
+}
+
+/* Get rid of all of the variables in the current context. */
+void
+kill_all_local_variables ()
+{
+  VAR_CONTEXT *vc;
+
+  for (vc = shell_variables; vc; vc = vc->down)
+    if (vc_isfuncenv (vc) && vc->scope == variable_context)
+      break;
+  if (vc == 0)
+    return;            /* XXX */
+
+  if (vc->table && vc_haslocals (vc))
+    {
+      delete_all_variables (vc->table);
+      hash_dispose (vc->table);
+    }
+  vc->table = (HASH_TABLE *)NULL;
+}
+
+static void
+free_variable_hash_data (data)
+     PTR_T data;
+{
+  SHELL_VAR *var;
+
+  var = (SHELL_VAR *)data;
+  dispose_variable (var);
+}
+
+/* Delete the entire contents of the hash table. */
+void
+delete_all_variables (hashed_vars)
+     HASH_TABLE *hashed_vars;
+{
+  hash_flush (hashed_vars, free_variable_hash_data);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                  Setting variable attributes                    */
+/*                                                                 */
+/* **************************************************************** */
+
+#define FIND_OR_MAKE_VARIABLE(name, entry) \
+  do \
+    { \
+      entry = find_variable (name); \
+      if (!entry) \
+       { \
+         entry = bind_variable (name, "", 0); \
+         if (!no_invisible_vars && entry) entry->attributes |= att_invisible; \
+       } \
+    } \
+  while (0)
+
+/* Make the variable associated with NAME be readonly.
+   If NAME does not exist yet, create it. */
+void
+set_var_read_only (name)
+     char *name;
+{
+  SHELL_VAR *entry;
+
+  FIND_OR_MAKE_VARIABLE (name, entry);
+  VSETATTR (entry, att_readonly);
+}
+
+#ifdef INCLUDE_UNUSED
+/* Make the function associated with NAME be readonly.
+   If NAME does not exist, we just punt, like auto_export code below. */
+void
+set_func_read_only (name)
+     const char *name;
+{
+  SHELL_VAR *entry;
+
+  entry = find_function (name);
+  if (entry)
+    VSETATTR (entry, att_readonly);
+}
+
+/* Make the variable associated with NAME be auto-exported.
+   If NAME does not exist yet, create it. */
+void
+set_var_auto_export (name)
+     char *name;
+{
+  SHELL_VAR *entry;
+
+  FIND_OR_MAKE_VARIABLE (name, entry);
+  set_auto_export (entry);
+}
+
+/* Make the function associated with NAME be auto-exported. */
+void
+set_func_auto_export (name)
+     const char *name;
+{
+  SHELL_VAR *entry;
+
+  entry = find_function (name);
+  if (entry)
+    set_auto_export (entry);
+}
+#endif
+
+/* **************************************************************** */
+/*                                                                 */
+/*                  Creating lists of variables                    */
+/*                                                                 */
+/* **************************************************************** */
+
+static VARLIST *
+vlist_alloc (nentries)
+     int nentries;
+{
+  VARLIST  *vlist;
+
+  vlist = (VARLIST *)xmalloc (sizeof (VARLIST));
+  vlist->list = (SHELL_VAR **)xmalloc ((nentries + 1) * sizeof (SHELL_VAR *));
+  vlist->list_size = nentries;
+  vlist->list_len = 0;
+  vlist->list[0] = (SHELL_VAR *)NULL;
+
+  return vlist;
+}
+
+static VARLIST *
+vlist_realloc (vlist, n)
+     VARLIST *vlist;
+     int n;
+{
+  if (vlist == 0)
+    return (vlist = vlist_alloc (n));
+  if (n > vlist->list_size)
+    {
+      vlist->list_size = n;
+      vlist->list = (SHELL_VAR **)xrealloc (vlist->list, (vlist->list_size + 1) * sizeof (SHELL_VAR *));
+    }
+  return vlist;
+}
+
+static void
+vlist_add (vlist, var, flags)
+     VARLIST *vlist;
+     SHELL_VAR *var;
+     int flags;
+{
+  register int i;
+
+  for (i = 0; i < vlist->list_len; i++)
+    if (STREQ (var->name, vlist->list[i]->name))
+      break;
+  if (i < vlist->list_len)
+    return;
+
+  if (i >= vlist->list_size)
+    vlist = vlist_realloc (vlist, vlist->list_size + 16);
+
+  vlist->list[vlist->list_len++] = var;
+  vlist->list[vlist->list_len] = (SHELL_VAR *)NULL;
+}
+
+/* Map FUNCTION over the variables in VAR_HASH_TABLE.  Return an array of the
+   variables for which FUNCTION returns a non-zero value.  A NULL value
+   for FUNCTION means to use all variables. */
+SHELL_VAR **
+map_over (function, vc)
+     sh_var_map_func_t *function;
+     VAR_CONTEXT *vc;
+{
+  VAR_CONTEXT *v;
+  VARLIST *vlist;
+  SHELL_VAR **ret;
+  int nentries;
+
+  for (nentries = 0, v = vc; v; v = v->down)
+    nentries += HASH_ENTRIES (v->table);
+
+  if (nentries == 0)
+    return (SHELL_VAR **)NULL;
+
+  vlist = vlist_alloc (nentries);
+
+  for (v = vc; v; v = v->down)
+    flatten (v->table, function, vlist, 0);
+
+  ret = vlist->list;
+  free (vlist);
+  return ret;
+}
+
+SHELL_VAR **
+map_over_funcs (function)
+     sh_var_map_func_t *function;
+{
+  VARLIST *vlist;
+  SHELL_VAR **ret;
+
+  if (shell_functions == 0 || HASH_ENTRIES (shell_functions) == 0)
+    return ((SHELL_VAR **)NULL);
+
+  vlist = vlist_alloc (HASH_ENTRIES (shell_functions));
+
+  flatten (shell_functions, function, vlist, 0);
+
+  ret = vlist->list;
+  free (vlist);
+  return ret;
+}
+
+/* Flatten VAR_HASH_TABLE, applying FUNC to each member and adding those
+   elements for which FUNC succeeds to VLIST->list.  FLAGS is reserved
+   for future use.  Only unique names are added to VLIST.  If FUNC is
+   NULL, each variable in VAR_HASH_TABLE is added to VLIST.  If VLIST is
+   NULL, FUNC is applied to each SHELL_VAR in VAR_HASH_TABLE.  If VLIST
+   and FUNC are both NULL, nothing happens. */
+static void
+flatten (var_hash_table, func, vlist, flags)
+     HASH_TABLE *var_hash_table;
+     sh_var_map_func_t *func;
+     VARLIST *vlist;
+     int flags;
+{
+  register int i;
+  register BUCKET_CONTENTS *tlist;
+  int r;
+  SHELL_VAR *var;
+
+  if (var_hash_table == 0 || (HASH_ENTRIES (var_hash_table) == 0) || (vlist == 0 && func == 0))
+    return;
+
+  for (i = 0; i < var_hash_table->nbuckets; i++)
+    {
+      for (tlist = hash_items (i, var_hash_table); tlist; tlist = tlist->next)
+       {
+         var = (SHELL_VAR *)tlist->data;
+
+         r = func ? (*func) (var) : 1;
+         if (r && vlist)
+           vlist_add (vlist, var, flags);
+       }
+    }
+}
+
+void
+sort_variables (array)
+     SHELL_VAR **array;
+{
+  qsort (array, strvec_len ((char **)array), sizeof (SHELL_VAR *), (QSFUNC *)qsort_var_comp);
+}
+
+static int
+qsort_var_comp (var1, var2)
+     SHELL_VAR **var1, **var2;
+{
+  int result;
+
+  if ((result = (*var1)->name[0] - (*var2)->name[0]) == 0)
+    result = strcmp ((*var1)->name, (*var2)->name);
+
+  return (result);
+}
+
+/* Apply FUNC to each variable in SHELL_VARIABLES, adding each one for
+   which FUNC succeeds to an array of SHELL_VAR *s.  Returns the array. */
+static SHELL_VAR **
+vapply (func)
+     sh_var_map_func_t *func;
+{
+  SHELL_VAR **list;
+
+  list = map_over (func, shell_variables);
+  if (list /* && posixly_correct */)
+    sort_variables (list);
+  return (list);
+}
+
+/* Apply FUNC to each variable in SHELL_FUNCTIONS, adding each one for
+   which FUNC succeeds to an array of SHELL_VAR *s.  Returns the array. */
+static SHELL_VAR **
+fapply (func)
+     sh_var_map_func_t *func;
+{
+  SHELL_VAR **list;
+
+  list = map_over_funcs (func);
+  if (list /* && posixly_correct */)
+    sort_variables (list);
+  return (list);
+}
+
+/* Create a NULL terminated array of all the shell variables. */
+SHELL_VAR **
+all_shell_variables ()
+{
+  return (vapply ((sh_var_map_func_t *)NULL));
+}
+
+/* Create a NULL terminated array of all the shell functions. */
+SHELL_VAR **
+all_shell_functions ()
+{
+  return (fapply ((sh_var_map_func_t *)NULL));
+}
+
+static int
+visible_var (var)
+     SHELL_VAR *var;
+{
+  return (invisible_p (var) == 0);
+}
+
+SHELL_VAR **
+all_visible_functions ()
+{
+  return (fapply (visible_var));
+}
+
+SHELL_VAR **
+all_visible_variables ()
+{
+  return (vapply (visible_var));
+}
+
+/* Return non-zero if the variable VAR is visible and exported.  Array
+   variables cannot be exported. */
+static int
+visible_and_exported (var)
+     SHELL_VAR *var;
+{
+  return (invisible_p (var) == 0 && exported_p (var));
+}
+
+/* Candidate variables for the export environment are either valid variables
+   with the export attribute or invalid variables inherited from the initial
+   environment and simply passed through. */
+static int
+export_environment_candidate (var)
+     SHELL_VAR *var;
+{
+  return (exported_p (var) && (invisible_p (var) == 0 || imported_p (var)));
+}
+
+/* Return non-zero if VAR is a local variable in the current context and
+   is exported. */
+static int
+local_and_exported (var)
+     SHELL_VAR *var;
+{
+  return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context && exported_p (var));
+}
+
+SHELL_VAR **
+all_exported_variables ()
+{
+  return (vapply (visible_and_exported));
+}
+
+SHELL_VAR **
+local_exported_variables ()
+{
+  return (vapply (local_and_exported));
+}
+
+static int
+variable_in_context (var)
+     SHELL_VAR *var;
+{
+  return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context);
+}
+
+SHELL_VAR **
+all_local_variables ()
+{
+  VARLIST *vlist;
+  SHELL_VAR **ret;
+  VAR_CONTEXT *vc;
+
+  vc = shell_variables;
+  for (vc = shell_variables; vc; vc = vc->down)
+    if (vc_isfuncenv (vc) && vc->scope == variable_context)
+      break;
+
+  if (vc == 0)
+    {
+      internal_error (_("all_local_variables: no function context at current scope"));
+      return (SHELL_VAR **)NULL;
+    }
+  if (vc->table == 0 || HASH_ENTRIES (vc->table) == 0 || vc_haslocals (vc) == 0)
+    return (SHELL_VAR **)NULL;
+    
+  vlist = vlist_alloc (HASH_ENTRIES (vc->table));
+
+  flatten (vc->table, variable_in_context, vlist, 0);
+
+  ret = vlist->list;
+  free (vlist);
+  if (ret)
+    sort_variables (ret);
+  return ret;
+}
+
+#if defined (ARRAY_VARS)
+/* Return non-zero if the variable VAR is visible and an array. */
+static int
+visible_array_vars (var)
+     SHELL_VAR *var;
+{
+  return (invisible_p (var) == 0 && array_p (var));
+}
+
+SHELL_VAR **
+all_array_variables ()
+{
+  return (vapply (visible_array_vars));
+}
+#endif /* ARRAY_VARS */
+
+char **
+all_variables_matching_prefix (prefix)
+     const char *prefix;
+{
+  SHELL_VAR **varlist;
+  char **rlist;
+  int vind, rind, plen;
+
+  plen = STRLEN (prefix);
+  varlist = all_visible_variables ();
+  for (vind = 0; varlist && varlist[vind]; vind++)
+    ;
+  if (varlist == 0 || vind == 0)
+    return ((char **)NULL);
+  rlist = strvec_create (vind + 1);
+  for (vind = rind = 0; varlist[vind]; vind++)
+    {
+      if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen))
+       rlist[rind++] = savestring (varlist[vind]->name);
+    }
+  rlist[rind] = (char *)0;
+  free (varlist);
+
+  return rlist;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*              Managing temporary variable scopes                 */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Make variable NAME have VALUE in the temporary environment. */
+static SHELL_VAR *
+bind_tempenv_variable (name, value)
+     const char *name;
+     char *value;
+{
+  SHELL_VAR *var;
+
+  var = temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL;
+
+  if (var)
+    {
+      FREE (value_cell (var));
+      var_setvalue (var, savestring (value));
+      INVALIDATE_EXPORTSTR (var);
+    }
+
+  return (var);
+}
+
+/* Find a variable in the temporary environment that is named NAME.
+   Return the SHELL_VAR *, or NULL if not found. */
+SHELL_VAR *
+find_tempenv_variable (name)
+     const char *name;
+{
+  return (temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL);
+}
+
+char **tempvar_list;
+int tvlist_ind;
+
+/* Push the variable described by (SHELL_VAR *)DATA down to the next
+   variable context from the temporary environment. */
+static void
+push_temp_var (data)
+     PTR_T data;
+{
+  SHELL_VAR *var, *v;
+  HASH_TABLE *binding_table;
+
+  var = (SHELL_VAR *)data;
+
+  binding_table = shell_variables->table;
+  if (binding_table == 0)
+    {
+      if (shell_variables == global_variables)
+       /* shouldn't happen */
+       binding_table = shell_variables->table = global_variables->table = hash_create (0);
+      else
+       binding_table = shell_variables->table = hash_create (TEMPENV_HASH_BUCKETS);
+    }
+
+  v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, 0);
+
+  /* XXX - should we set the context here?  It shouldn't matter because of how
+     assign_in_env works, but might want to check. */
+  if (binding_table == global_variables->table)                /* XXX */
+    var->attributes &= ~(att_tempvar|att_propagate);
+  else
+    {
+      var->attributes |= att_propagate;
+      if  (binding_table == shell_variables->table)
+       shell_variables->flags |= VC_HASTMPVAR;
+    }
+  v->attributes |= var->attributes;
+
+  if (find_special_var (var->name) >= 0)
+    tempvar_list[tvlist_ind++] = savestring (var->name);
+
+  dispose_variable (var);
+}
+
+static void
+propagate_temp_var (data)
+     PTR_T data;
+{
+  SHELL_VAR *var;
+
+  var = (SHELL_VAR *)data;
+  if (tempvar_p (var) && (var->attributes & att_propagate))
+    push_temp_var (data);
+  else
+    {
+      if (find_special_var (var->name) >= 0)
+       tempvar_list[tvlist_ind++] = savestring (var->name);
+      dispose_variable (var);
+    }
+}
+
+/* Free the storage used in the hash table for temporary
+   environment variables.  PUSHF is a function to be called
+   to free each hash table entry.  It takes care of pushing variables
+   to previous scopes if appropriate.  PUSHF stores names of variables
+   that require special handling (e.g., IFS) on tempvar_list, so this
+   function can call stupidly_hack_special_variables on all the
+   variables in the list when the temporary hash table is destroyed. */
+static void
+dispose_temporary_env (pushf)
+     sh_free_func_t *pushf;
+{
+  int i;
+
+  tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1);
+  tempvar_list[tvlist_ind = 0] = 0;
+    
+  hash_flush (temporary_env, pushf);
+  hash_dispose (temporary_env);
+  temporary_env = (HASH_TABLE *)NULL;
+
+  tempvar_list[tvlist_ind] = 0;
+
+  array_needs_making = 1;
+
+#if 0
+  sv_ifs ("IFS");              /* XXX here for now -- check setifs in assign_in_env */  
+#endif
+  for (i = 0; i < tvlist_ind; i++)
+    stupidly_hack_special_variables (tempvar_list[i]);
+
+  strvec_dispose (tempvar_list);
+  tempvar_list = 0;
+  tvlist_ind = 0;
+}
+
+void
+dispose_used_env_vars ()
+{
+  if (temporary_env)
+    {
+      dispose_temporary_env (propagate_temp_var);
+      maybe_make_export_env ();
+    }
+}
+
+/* Take all of the shell variables in the temporary environment HASH_TABLE
+   and make shell variables from them at the current variable context. */
+void
+merge_temporary_env ()
+{
+  if (temporary_env)
+    dispose_temporary_env (push_temp_var);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*          Creating and manipulating the environment              */
+/*                                                                 */
+/* **************************************************************** */
+
+static inline char *
+mk_env_string (name, value)
+     const char *name, *value;
+{
+  int name_len, value_len;
+  char *p;
+
+  name_len = strlen (name);
+  value_len = STRLEN (value);
+  p = (char *)xmalloc (2 + name_len + value_len);
+  strcpy (p, name);
+  p[name_len] = '=';
+  if (value && *value)
+    strcpy (p + name_len + 1, value);
+  else
+    p[name_len + 1] = '\0';
+  return (p);
+}
+
+#ifdef DEBUG
+/* Debugging */
+static int
+valid_exportstr (v)
+     SHELL_VAR *v;
+{
+  char *s;
+
+  s = v->exportstr;
+  if (s == 0)
+    {
+      internal_error (_("%s has null exportstr"), v->name);
+      return (0);
+    }
+  if (legal_variable_starter ((unsigned char)*s) == 0)
+    {
+      internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
+      return (0);
+    }
+  for (s = v->exportstr + 1; s && *s; s++)
+    {
+      if (*s == '=')
+       break;
+      if (legal_variable_char ((unsigned char)*s) == 0)
+       {
+         internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
+         return (0);
+       }
+    }
+  if (*s != '=')
+    {
+      internal_error (_("no `=' in exportstr for %s"), v->name);
+      return (0);
+    }
+  return (1);
+}
+#endif
+
+static char **
+make_env_array_from_var_list (vars)
+     SHELL_VAR **vars;
+{
+  register int i, list_index;
+  register SHELL_VAR *var;
+  char **list, *value;
+
+  list = strvec_create ((1 + strvec_len ((char **)vars)));
+
+#define USE_EXPORTSTR (value == var->exportstr)
+
+  for (i = 0, list_index = 0; var = vars[i]; i++)
+    {
+#if defined (__CYGWIN__)
+      /* We don't use the exportstr stuff on Cygwin at all. */
+      INVALIDATE_EXPORTSTR (var);
+#endif
+      if (var->exportstr)
+       value = var->exportstr;
+      else if (function_p (var))
+       value = named_function_string ((char *)NULL, function_cell (var), 0);
+#if defined (ARRAY_VARS)
+      else if (array_p (var))
+#  if ARRAY_EXPORT
+       value = array_to_assignment_string (array_cell (var));
+#  else
+       continue;       /* XXX array vars cannot yet be exported */
+#  endif /* ARRAY_EXPORT */
+      else if (assoc_p (var))
+#  if 0
+       value = assoc_to_assignment_string (assoc_cell (var));
+#  else
+       continue;       /* XXX associative array vars cannot yet be exported */
+#  endif
+#endif
+      else
+       value = value_cell (var);
+
+      if (value)
+       {
+         /* Gee, I'd like to get away with not using savestring() if we're
+            using the cached exportstr... */
+         list[list_index] = USE_EXPORTSTR ? savestring (value)
+                                          : mk_env_string (var->name, value);
+
+         if (USE_EXPORTSTR == 0)
+           SAVE_EXPORTSTR (var, list[list_index]);
+
+         list_index++;
+#undef USE_EXPORTSTR
+
+#if 0  /* not yet */
+#if defined (ARRAY_VARS)
+         if (array_p (var) || assoc_p (var))
+           free (value);
+#endif
+#endif
+       }
+    }
+
+  list[list_index] = (char *)NULL;
+  return (list);
+}
+
+/* Make an array of assignment statements from the hash table
+   HASHED_VARS which contains SHELL_VARs.  Only visible, exported
+   variables are eligible. */
+static char **
+make_var_export_array (vcxt)
+     VAR_CONTEXT *vcxt;
+{
+  char **list;
+  SHELL_VAR **vars;
+
+#if 0
+  vars = map_over (visible_and_exported, vcxt);
+#else
+  vars = map_over (export_environment_candidate, vcxt);
+#endif
+
+  if (vars == 0)
+    return (char **)NULL;
+
+  list = make_env_array_from_var_list (vars);
+
+  free (vars);
+  return (list);
+}
+
+static char **
+make_func_export_array ()
+{
+  char **list;
+  SHELL_VAR **vars;
+
+  vars = map_over_funcs (visible_and_exported);
+  if (vars == 0)
+    return (char **)NULL;
+
+  list = make_env_array_from_var_list (vars);
+
+  free (vars);
+  return (list);
+}
+
+/* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
+#define add_to_export_env(envstr,do_alloc) \
+do \
+  { \
+    if (export_env_index >= (export_env_size - 1)) \
+      { \
+       export_env_size += 16; \
+       export_env = strvec_resize (export_env, export_env_size); \
+       environ = export_env; \
+      } \
+    export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
+    export_env[export_env_index] = (char *)NULL; \
+  } while (0)
+
+/* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
+   array with the same left-hand side.  Return the new EXPORT_ENV. */
+char **
+add_or_supercede_exported_var (assign, do_alloc)
+     char *assign;
+     int do_alloc;
+{
+  register int i;
+  int equal_offset;
+
+  equal_offset = assignment (assign, 0);
+  if (equal_offset == 0)
+    return (export_env);
+
+  /* If this is a function, then only supersede the function definition.
+     We do this by including the `=() {' in the comparison, like
+     initialize_shell_variables does. */
+  if (assign[equal_offset + 1] == '(' &&
+     strncmp (assign + equal_offset + 2, ") {", 3) == 0)               /* } */
+    equal_offset += 4;
+
+  for (i = 0; i < export_env_index; i++)
+    {
+      if (STREQN (assign, export_env[i], equal_offset + 1))
+       {
+         free (export_env[i]);
+         export_env[i] = do_alloc ? savestring (assign) : assign;
+         return (export_env);
+       }
+    }
+  add_to_export_env (assign, do_alloc);
+  return (export_env);
+}
+
+static void
+add_temp_array_to_env (temp_array, do_alloc, do_supercede)
+     char **temp_array;
+     int do_alloc, do_supercede;
+{
+  register int i;
+
+  if (temp_array == 0)
+    return;
+
+  for (i = 0; temp_array[i]; i++)
+    {
+      if (do_supercede)
+       export_env = add_or_supercede_exported_var (temp_array[i], do_alloc);
+      else
+       add_to_export_env (temp_array[i], do_alloc);
+    }
+
+  free (temp_array);
+}
+
+/* Make the environment array for the command about to be executed, if the
+   array needs making.  Otherwise, do nothing.  If a shell action could
+   change the array that commands receive for their environment, then the
+   code should `array_needs_making++'.
+
+   The order to add to the array is:
+       temporary_env
+       list of var contexts whose head is shell_variables
+       shell_functions
+
+  This is the shell variable lookup order.  We add only new variable
+  names at each step, which allows local variables and variables in
+  the temporary environments to shadow variables in the global (or
+  any previous) scope.
+*/
+
+static int
+n_shell_variables ()
+{
+  VAR_CONTEXT *vc;
+  int n;
+
+  for (n = 0, vc = shell_variables; vc; vc = vc->down)
+    n += HASH_ENTRIES (vc->table);
+  return n;
+}
+
+int
+chkexport (name)
+     char *name;
+{
+  SHELL_VAR *v;
+
+  v = find_variable (name);
+  if (v && exported_p (v))
+    {
+      array_needs_making = 1;
+      maybe_make_export_env ();
+      return 1;
+    }
+  return 0;
+}
+
+void
+maybe_make_export_env ()
+{
+  register char **temp_array;
+  int new_size;
+  VAR_CONTEXT *tcxt;
+
+  if (array_needs_making)
+    {
+      if (export_env)
+       strvec_flush (export_env);
+
+      /* Make a guess based on how many shell variables and functions we
+        have.  Since there will always be array variables, and array
+        variables are not (yet) exported, this will always be big enough
+        for the exported variables and functions. */
+      new_size = n_shell_variables () + HASH_ENTRIES (shell_functions) + 1 +
+                HASH_ENTRIES (temporary_env);
+      if (new_size > export_env_size)
+       {
+         export_env_size = new_size;
+         export_env = strvec_resize (export_env, export_env_size);
+         environ = export_env;
+       }
+      export_env[export_env_index = 0] = (char *)NULL;
+
+      /* Make a dummy variable context from the temporary_env, stick it on
+        the front of shell_variables, call make_var_export_array on the
+        whole thing to flatten it, and convert the list of SHELL_VAR *s
+        to the form needed by the environment. */
+      if (temporary_env)
+       {
+         tcxt = new_var_context ((char *)NULL, 0);
+         tcxt->table = temporary_env;
+         tcxt->down = shell_variables;
+       }
+      else
+       tcxt = shell_variables;
+      
+      temp_array = make_var_export_array (tcxt);
+      if (temp_array)
+       add_temp_array_to_env (temp_array, 0, 0);
+
+      if (tcxt != shell_variables)
+       free (tcxt);
+
+#if defined (RESTRICTED_SHELL)
+      /* Restricted shells may not export shell functions. */
+      temp_array = restricted ? (char **)0 : make_func_export_array ();
+#else
+      temp_array = make_func_export_array ();
+#endif
+      if (temp_array)
+       add_temp_array_to_env (temp_array, 0, 0);
+
+      array_needs_making = 0;
+    }
+}
+
+/* This is an efficiency hack.  PWD and OLDPWD are auto-exported, so
+   we will need to remake the exported environment every time we
+   change directories.  `_' is always put into the environment for
+   every external command, so without special treatment it will always
+   cause the environment to be remade.
+
+   If there is no other reason to make the exported environment, we can
+   just update the variables in place and mark the exported environment
+   as no longer needing a remake. */
+void
+update_export_env_inplace (env_prefix, preflen, value)
+     char *env_prefix;
+     int preflen;
+     char *value;
+{
+  char *evar;
+
+  evar = (char *)xmalloc (STRLEN (value) + preflen + 1);
+  strcpy (evar, env_prefix);
+  if (value)
+    strcpy (evar + preflen, value);
+  export_env = add_or_supercede_exported_var (evar, 0);
+}
+
+/* We always put _ in the environment as the name of this command. */
+void
+put_command_name_into_env (command_name)
+     char *command_name;
+{
+  update_export_env_inplace ("_=", 2, command_name);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                   Managing variable contexts                    */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Allocate and return a new variable context with NAME and FLAGS.
+   NAME can be NULL. */
+
+VAR_CONTEXT *
+new_var_context (name, flags)
+     char *name;
+     int flags;
+{
+  VAR_CONTEXT *vc;
+
+  vc = (VAR_CONTEXT *)xmalloc (sizeof (VAR_CONTEXT));
+  vc->name = name ? savestring (name) : (char *)NULL;
+  vc->scope = variable_context;
+  vc->flags = flags;
+
+  vc->up = vc->down = (VAR_CONTEXT *)NULL;
+  vc->table = (HASH_TABLE *)NULL;
+
+  return vc;
+}
+
+/* Free a variable context and its data, including the hash table.  Dispose
+   all of the variables. */
+void
+dispose_var_context (vc)
+     VAR_CONTEXT *vc;
+{
+  FREE (vc->name);
+
+  if (vc->table)
+    {
+      delete_all_variables (vc->table);
+      hash_dispose (vc->table);
+    }
+
+  free (vc);
+}
+
+/* Set VAR's scope level to the current variable context. */
+static int
+set_context (var)
+     SHELL_VAR *var;
+{
+  return (var->context = variable_context);
+}
+
+/* Make a new variable context with NAME and FLAGS and a HASH_TABLE of
+   temporary variables, and push it onto shell_variables.  This is
+   for shell functions. */
+VAR_CONTEXT *
+push_var_context (name, flags, tempvars)
+     char *name;
+     int flags;
+     HASH_TABLE *tempvars;
+{
+  VAR_CONTEXT *vc;
+
+  vc = new_var_context (name, flags);
+  vc->table = tempvars;
+  if (tempvars)
+    {
+      /* Have to do this because the temp environment was created before
+        variable_context was incremented. */
+      flatten (tempvars, set_context, (VARLIST *)NULL, 0);
+      vc->flags |= VC_HASTMPVAR;
+    }
+  vc->down = shell_variables;
+  shell_variables->up = vc;
+
+  return (shell_variables = vc);
+}
+
+static void
+push_func_var (data)
+     PTR_T data;
+{
+  SHELL_VAR *var, *v;
+
+  var = (SHELL_VAR *)data;
+
+  if (tempvar_p (var) && (posixly_correct || (var->attributes & att_propagate)))
+    {
+      /* Make sure we have a hash table to store the variable in while it is
+        being propagated down to the global variables table.  Create one if
+        we have to */
+      if ((vc_isfuncenv (shell_variables) || vc_istempenv (shell_variables)) && shell_variables->table == 0)
+       shell_variables->table = hash_create (0);
+      /* XXX - should we set v->context here? */
+      v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
+      if (shell_variables == global_variables)
+       var->attributes &= ~(att_tempvar|att_propagate);
+      else
+       shell_variables->flags |= VC_HASTMPVAR;
+      v->attributes |= var->attributes;
+    }
+  else
+    stupidly_hack_special_variables (var->name);       /* XXX */
+
+  dispose_variable (var);
+}
+
+/* Pop the top context off of VCXT and dispose of it, returning the rest of
+   the stack. */
+void
+pop_var_context ()
+{
+  VAR_CONTEXT *ret, *vcxt;
+
+  vcxt = shell_variables;
+  if (vc_isfuncenv (vcxt) == 0)
+    {
+      internal_error (_("pop_var_context: head of shell_variables not a function context"));
+      return;
+    }
+
+  if (ret = vcxt->down)
+    {
+      ret->up = (VAR_CONTEXT *)NULL;
+      shell_variables = ret;
+      if (vcxt->table)
+       hash_flush (vcxt->table, push_func_var);
+      dispose_var_context (vcxt);
+    }
+  else
+    internal_error (_("pop_var_context: no global_variables context"));
+}
+
+/* Delete the HASH_TABLEs for all variable contexts beginning at VCXT, and
+   all of the VAR_CONTEXTs except GLOBAL_VARIABLES. */
+void
+delete_all_contexts (vcxt)
+     VAR_CONTEXT *vcxt;
+{
+  VAR_CONTEXT *v, *t;
+
+  for (v = vcxt; v != global_variables; v = t)
+    {
+      t = v->down;
+      dispose_var_context (v);
+    }    
+
+  delete_all_variables (global_variables->table);
+  shell_variables = global_variables;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*        Pushing and Popping temporary variable scopes            */
+/*                                                                 */
+/* **************************************************************** */
+
+VAR_CONTEXT *
+push_scope (flags, tmpvars)
+     int flags;
+     HASH_TABLE *tmpvars;
+{
+  return (push_var_context ((char *)NULL, flags, tmpvars));
+}
+
+static void
+push_exported_var (data)
+     PTR_T data;
+{
+  SHELL_VAR *var, *v;
+
+  var = (SHELL_VAR *)data;
+
+  /* If a temp var had its export attribute set, or it's marked to be
+     propagated, bind it in the previous scope before disposing it. */
+  /* XXX - This isn't exactly right, because all tempenv variables have the
+    export attribute set. */
+#if 0
+  if (exported_p (var) || (var->attributes & att_propagate))
+#else
+  if (tempvar_p (var) && exported_p (var) && (var->attributes & att_propagate))
+#endif
+    {
+      var->attributes &= ~att_tempvar;         /* XXX */
+      v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
+      if (shell_variables == global_variables)
+       var->attributes &= ~att_propagate;
+      v->attributes |= var->attributes;
+    }
+  else
+    stupidly_hack_special_variables (var->name);       /* XXX */
+
+  dispose_variable (var);
+}
+
+void
+pop_scope (is_special)
+     int is_special;
+{
+  VAR_CONTEXT *vcxt, *ret;
+
+  vcxt = shell_variables;
+  if (vc_istempscope (vcxt) == 0)
+    {
+      internal_error (_("pop_scope: head of shell_variables not a temporary environment scope"));
+      return;
+    }
+
+  ret = vcxt->down;
+  if (ret)
+    ret->up = (VAR_CONTEXT *)NULL;
+
+  shell_variables = ret;
+
+  /* Now we can take care of merging variables in VCXT into set of scopes
+     whose head is RET (shell_variables). */
+  FREE (vcxt->name);
+  if (vcxt->table)
+    {
+      if (is_special)
+       hash_flush (vcxt->table, push_func_var);
+      else
+       hash_flush (vcxt->table, push_exported_var);
+      hash_dispose (vcxt->table);
+    }
+  free (vcxt);
+
+  sv_ifs ("IFS");      /* XXX here for now */
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*              Pushing and Popping function contexts              */
+/*                                                                 */
+/* **************************************************************** */
+
+static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
+static int dollar_arg_stack_slots;
+static int dollar_arg_stack_index;
+
+/* XXX - we might want to consider pushing and popping the `getopts' state
+   when we modify the positional parameters. */
+void
+push_context (name, is_subshell, tempvars)
+     char *name;       /* function name */
+     int is_subshell;
+     HASH_TABLE *tempvars;
+{
+  if (is_subshell == 0)
+    push_dollar_vars ();
+  variable_context++;
+  push_var_context (name, VC_FUNCENV, tempvars);
+}
+
+/* Only called when subshell == 0, so we don't need to check, and can
+   unconditionally pop the dollar vars off the stack. */
+void
+pop_context ()
+{
+  pop_dollar_vars ();
+  variable_context--;
+  pop_var_context ();
+
+  sv_ifs ("IFS");              /* XXX here for now */
+}
+
+/* Save the existing positional parameters on a stack. */
+void
+push_dollar_vars ()
+{
+  if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
+    {
+      dollar_arg_stack = (WORD_LIST **)
+       xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
+                 * sizeof (WORD_LIST *));
+    }
+  dollar_arg_stack[dollar_arg_stack_index++] = list_rest_of_args ();
+  dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
+}
+
+/* Restore the positional parameters from our stack. */
+void
+pop_dollar_vars ()
+{
+  if (!dollar_arg_stack || dollar_arg_stack_index == 0)
+    return;
+
+  remember_args (dollar_arg_stack[--dollar_arg_stack_index], 1);
+  dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
+  dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
+  set_dollar_vars_unchanged ();
+}
+
+void
+dispose_saved_dollar_vars ()
+{
+  if (!dollar_arg_stack || dollar_arg_stack_index == 0)
+    return;
+
+  dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
+  dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
+}
+
+/* Manipulate the special BASH_ARGV and BASH_ARGC variables. */
+
+void
+push_args (list)
+     WORD_LIST *list;
+{
+#if defined (ARRAY_VARS) && defined (DEBUGGER)
+  SHELL_VAR *bash_argv_v, *bash_argc_v;
+  ARRAY *bash_argv_a, *bash_argc_a;
+  WORD_LIST *l;
+  arrayind_t i;
+  char *t;
+
+  GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
+  GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
+
+  for (l = list, i = 0; l; l = l->next, i++)
+    array_push (bash_argv_a, l->word->word);
+
+  t = itos (i);
+  array_push (bash_argc_a, t);
+  free (t);
+#endif /* ARRAY_VARS && DEBUGGER */
+}
+
+/* Remove arguments from BASH_ARGV array.  Pop top element off BASH_ARGC
+   array and use that value as the count of elements to remove from
+   BASH_ARGV. */
+void
+pop_args ()
+{
+#if defined (ARRAY_VARS) && defined (DEBUGGER)
+  SHELL_VAR *bash_argv_v, *bash_argc_v;
+  ARRAY *bash_argv_a, *bash_argc_a;
+  ARRAY_ELEMENT *ce;
+  intmax_t i;
+
+  GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
+  GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
+
+  ce = array_shift (bash_argc_a, 1, 0);
+  if (ce == 0 || legal_number (element_value (ce), &i) == 0)
+    i = 0;
+
+  for ( ; i > 0; i--)
+    array_pop (bash_argv_a);
+  array_dispose_element (ce);
+#endif /* ARRAY_VARS && DEBUGGER */
+}
+
+/*************************************************
+ *                                              *
+ *     Functions to manage special variables    *
+ *                                              *
+ *************************************************/
+
+/* Extern declarations for variables this code has to manage. */
+extern int eof_encountered, eof_encountered_limit, ignoreeof;
+
+#if defined (READLINE)
+extern int hostname_list_initialized;
+#endif
+
+/* An alist of name.function for each special variable.  Most of the
+   functions don't do much, and in fact, this would be faster with a
+   switch statement, but by the end of this file, I am sick of switch
+   statements. */
+
+#define SET_INT_VAR(name, intvar)  intvar = find_variable (name) != 0
+
+/* This table will be sorted with qsort() the first time it's accessed. */
+struct name_and_function {
+  char *name;
+  sh_sv_func_t *function;
+};
+
+static struct name_and_function special_vars[] = {
+  { "BASH_COMPAT", sv_shcompat },
+  { "BASH_XTRACEFD", sv_xtracefd },
+
+#if defined (JOB_CONTROL)
+  { "CHILD_MAX", sv_childmax },
+#endif
+
+#if defined (READLINE)
+#  if defined (STRICT_POSIX)
+  { "COLUMNS", sv_winsize },
+#  endif
+  { "COMP_WORDBREAKS", sv_comp_wordbreaks },
+#endif
+
+  { "FUNCNEST", sv_funcnest },
+
+  { "GLOBIGNORE", sv_globignore },
+
+#if defined (HISTORY)
+  { "HISTCONTROL", sv_history_control },
+  { "HISTFILESIZE", sv_histsize },
+  { "HISTIGNORE", sv_histignore },
+  { "HISTSIZE", sv_histsize },
+  { "HISTTIMEFORMAT", sv_histtimefmt },
+#endif
+
+#if defined (__CYGWIN__)
+  { "HOME", sv_home },
+#endif
+
+#if defined (READLINE)
+  { "HOSTFILE", sv_hostfile },
+#endif
+
+  { "IFS", sv_ifs },
+  { "IGNOREEOF", sv_ignoreeof },
+
+  { "LANG", sv_locale },
+  { "LC_ALL", sv_locale },
+  { "LC_COLLATE", sv_locale },
+  { "LC_CTYPE", sv_locale },
+  { "LC_MESSAGES", sv_locale },
+  { "LC_NUMERIC", sv_locale },
+  { "LC_TIME", sv_locale },
+
+#if defined (READLINE) && defined (STRICT_POSIX)
+  { "LINES", sv_winsize },
+#endif
+
+  { "MAIL", sv_mail },
+  { "MAILCHECK", sv_mail },
+  { "MAILPATH", sv_mail },
+
+  { "OPTERR", sv_opterr },
+  { "OPTIND", sv_optind },
+
+  { "PATH", sv_path },
+  { "POSIXLY_CORRECT", sv_strict_posix },
+
+#if defined (READLINE)
+  { "TERM", sv_terminal },
+  { "TERMCAP", sv_terminal },
+  { "TERMINFO", sv_terminal },
+#endif /* READLINE */
+
+  { "TEXTDOMAIN", sv_locale },
+  { "TEXTDOMAINDIR", sv_locale },
+
+#if defined (HAVE_TZSET)
+  { "TZ", sv_tz },
+#endif
+
+#if defined (HISTORY) && defined (BANG_HISTORY)
+  { "histchars", sv_histchars },
+#endif /* HISTORY && BANG_HISTORY */
+
+  { "ignoreeof", sv_ignoreeof },
+
+  { (char *)0, (sh_sv_func_t *)0 }
+};
+
+#define N_SPECIAL_VARS (sizeof (special_vars) / sizeof (special_vars[0]) - 1)
+
+static int
+sv_compare (sv1, sv2)
+     struct name_and_function *sv1, *sv2;
+{
+  int r;
+
+  if ((r = sv1->name[0] - sv2->name[0]) == 0)
+    r = strcmp (sv1->name, sv2->name);
+  return r;
+}
+
+static inline int
+find_special_var (name)
+     const char *name;
+{
+  register int i, r;
+
+  for (i = 0; special_vars[i].name; i++)
+    {
+      r = special_vars[i].name[0] - name[0];
+      if (r == 0)
+       r = strcmp (special_vars[i].name, name);
+      if (r == 0)
+       return i;
+      else if (r > 0)
+       /* Can't match any of rest of elements in sorted list.  Take this out
+          if it causes problems in certain environments. */
+       break;
+    }
+  return -1;
+}
+
+/* The variable in NAME has just had its state changed.  Check to see if it
+   is one of the special ones where something special happens. */
+void
+stupidly_hack_special_variables (name)
+     char *name;
+{
+  static int sv_sorted = 0;
+  int i;
+
+  if (sv_sorted == 0)  /* shouldn't need, but it's fairly cheap. */
+    {
+      qsort (special_vars, N_SPECIAL_VARS, sizeof (special_vars[0]),
+               (QSFUNC *)sv_compare);
+      sv_sorted = 1;
+    }
+
+  i = find_special_var (name);
+  if (i != -1)
+    (*(special_vars[i].function)) (name);
+}
+
+/* Special variables that need hooks to be run when they are unset as part
+   of shell reinitialization should have their sv_ functions run here. */
+void
+reinit_special_variables ()
+{
+#if defined (READLINE)
+  sv_comp_wordbreaks ("COMP_WORDBREAKS");
+#endif
+  sv_globignore ("GLOBIGNORE");
+  sv_opterr ("OPTERR");
+}
+
+void
+sv_ifs (name)
+     char *name;
+{
+  SHELL_VAR *v;
+
+  v = find_variable ("IFS");
+  setifs (v);
+}
+
+/* What to do just after the PATH variable has changed. */
+void
+sv_path (name)
+     char *name;
+{
+  /* hash -r */
+  phash_flush ();
+}
+
+/* What to do just after one of the MAILxxxx variables has changed.  NAME
+   is the name of the variable.  This is called with NAME set to one of
+   MAIL, MAILCHECK, or MAILPATH.  */
+void
+sv_mail (name)
+     char *name;
+{
+  /* If the time interval for checking the files has changed, then
+     reset the mail timer.  Otherwise, one of the pathname vars
+     to the users mailbox has changed, so rebuild the array of
+     filenames. */
+  if (name[4] == 'C')  /* if (strcmp (name, "MAILCHECK") == 0) */
+    reset_mail_timer ();
+  else
+    {
+      free_mail_files ();
+      remember_mail_dates ();
+    }
+}
+
+void
+sv_funcnest (name)
+     char *name;
+{
+  SHELL_VAR *v;
+  intmax_t num;
+
+  v = find_variable (name);
+  if (v == 0)
+    funcnest_max = 0;
+  else if (legal_number (value_cell (v), &num) == 0)
+    funcnest_max = 0;
+  else
+    funcnest_max = num;
+}
+
+/* What to do when GLOBIGNORE changes. */
+void
+sv_globignore (name)
+     char *name;
+{
+  if (privileged_mode == 0)
+    setup_glob_ignore (name);
+}
+
+#if defined (READLINE)
+void
+sv_comp_wordbreaks (name)
+     char *name;
+{
+  SHELL_VAR *sv;
+
+  sv = find_variable (name);
+  if (sv == 0)
+    reset_completer_word_break_chars ();
+}
+
+/* What to do just after one of the TERMxxx variables has changed.
+   If we are an interactive shell, then try to reset the terminal
+   information in readline. */
+void
+sv_terminal (name)
+     char *name;
+{
+  if (interactive_shell && no_line_editing == 0)
+    rl_reset_terminal (get_string_value ("TERM"));
+}
+
+void
+sv_hostfile (name)
+     char *name;
+{
+  SHELL_VAR *v;
+
+  v = find_variable (name);
+  if (v == 0)
+    clear_hostname_list ();
+  else
+    hostname_list_initialized = 0;
+}
+
+#if defined (STRICT_POSIX)
+/* In strict posix mode, we allow assignments to LINES and COLUMNS (and values
+   found in the initial environment) to override the terminal size reported by
+   the kernel. */
+void
+sv_winsize (name)
+     char *name;
+{
+  SHELL_VAR *v;
+  intmax_t xd;
+  int d;
+
+  if (posixly_correct == 0 || interactive_shell == 0 || no_line_editing)
+    return;
+
+  v = find_variable (name);
+  if (v == 0 || var_isnull (v))
+    rl_reset_screen_size ();
+  else
+    {
+      if (legal_number (value_cell (v), &xd) == 0)
+       return;
+      winsize_assignment = 1;
+      d = xd;                  /* truncate */
+      if (name[0] == 'L')      /* LINES */
+       rl_set_screen_size (d, -1);
+      else                     /* COLUMNS */
+       rl_set_screen_size (-1, d);
+      winsize_assignment = 0;
+    }
+}
+#endif /* STRICT_POSIX */
+#endif /* READLINE */
+
+/* Update the value of HOME in the export environment so tilde expansion will
+   work on cygwin. */
+#if defined (__CYGWIN__)
+sv_home (name)
+     char *name;
+{
+  array_needs_making = 1;
+  maybe_make_export_env ();
+}
+#endif
+
+#if defined (HISTORY)
+/* What to do after the HISTSIZE or HISTFILESIZE variables change.
+   If there is a value for this HISTSIZE (and it is numeric), then stifle
+   the history.  Otherwise, if there is NO value for this variable,
+   unstifle the history.  If name is HISTFILESIZE, and its value is
+   numeric, truncate the history file to hold no more than that many
+   lines. */
+void
+sv_histsize (name)
+     char *name;
+{
+  char *temp;
+  intmax_t num;
+  int hmax;
+
+  temp = get_string_value (name);
+
+  if (temp && *temp)
+    {
+      if (legal_number (temp, &num))
+       {
+         hmax = num;
+         if (hmax < 0 && name[4] == 'S')
+           unstifle_history ();        /* unstifle history if HISTSIZE < 0 */
+         else if (name[4] == 'S')
+           {
+             stifle_history (hmax);
+             hmax = where_history ();
+             if (history_lines_this_session > hmax)
+               history_lines_this_session = hmax;
+           }
+         else if (hmax >= 0)   /* truncate HISTFILE if HISTFILESIZE >= 0 */
+           {
+             history_truncate_file (get_string_value ("HISTFILE"), hmax);
+             if (hmax <= history_lines_in_file)
+               history_lines_in_file = hmax;
+           }
+       }
+    }
+  else if (name[4] == 'S')
+    unstifle_history ();
+}
+
+/* What to do after the HISTIGNORE variable changes. */
+void
+sv_histignore (name)
+     char *name;
+{
+  setup_history_ignore (name);
+}
+
+/* What to do after the HISTCONTROL variable changes. */
+void
+sv_history_control (name)
+     char *name;
+{
+  char *temp;
+  char *val;
+  int tptr;
+
+  history_control = 0;
+  temp = get_string_value (name);
+
+  if (temp == 0 || *temp == 0)
+    return;
+
+  tptr = 0;
+  while (val = extract_colon_unit (temp, &tptr))
+    {
+      if (STREQ (val, "ignorespace"))
+       history_control |= HC_IGNSPACE;
+      else if (STREQ (val, "ignoredups"))
+       history_control |= HC_IGNDUPS;
+      else if (STREQ (val, "ignoreboth"))
+       history_control |= HC_IGNBOTH;
+      else if (STREQ (val, "erasedups"))
+       history_control |= HC_ERASEDUPS;
+
+      free (val);
+    }
+}
+
+#if defined (BANG_HISTORY)
+/* Setting/unsetting of the history expansion character. */
+void
+sv_histchars (name)
+     char *name;
+{
+  char *temp;
+
+  temp = get_string_value (name);
+  if (temp)
+    {
+      history_expansion_char = *temp;
+      if (temp[0] && temp[1])
+       {
+         history_subst_char = temp[1];
+         if (temp[2])
+             history_comment_char = temp[2];
+       }
+    }
+  else
+    {
+      history_expansion_char = '!';
+      history_subst_char = '^';
+      history_comment_char = '#';
+    }
+}
+#endif /* BANG_HISTORY */
+
+void
+sv_histtimefmt (name)
+     char *name;
+{
+  SHELL_VAR *v;
+
+  if (v = find_variable (name))
+    {
+      if (history_comment_char == 0)
+       history_comment_char = '#';
+    }
+  history_write_timestamps = (v != 0);
+}
+#endif /* HISTORY */
+
+#if defined (HAVE_TZSET)
+void
+sv_tz (name)
+     char *name;
+{
+  if (chkexport (name))
+    tzset ();
+}
+#endif
+
+/* If the variable exists, then the value of it can be the number
+   of times we actually ignore the EOF.  The default is small,
+   (smaller than csh, anyway). */
+void
+sv_ignoreeof (name)
+     char *name;
+{
+  SHELL_VAR *tmp_var;
+  char *temp;
+
+  eof_encountered = 0;
+
+  tmp_var = find_variable (name);
+  ignoreeof = tmp_var != 0;
+  temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
+  if (temp)
+    eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
+  set_shellopts ();    /* make sure `ignoreeof' is/is not in $SHELLOPTS */
+}
+
+void
+sv_optind (name)
+     char *name;
+{
+  char *tt;
+  int s;
+
+  tt = get_string_value ("OPTIND");
+  if (tt && *tt)
+    {
+      s = atoi (tt);
+
+      /* According to POSIX, setting OPTIND=1 resets the internal state
+        of getopt (). */
+      if (s < 0 || s == 1)
+       s = 0;
+    }
+  else
+    s = 0;
+  getopts_reset (s);
+}
+
+void
+sv_opterr (name)
+     char *name;
+{
+  char *tt;
+
+  tt = get_string_value ("OPTERR");
+  sh_opterr = (tt && *tt) ? atoi (tt) : 1;
+}
+
+void
+sv_strict_posix (name)
+     char *name;
+{
+  SET_INT_VAR (name, posixly_correct);
+  posix_initialize (posixly_correct);
+#if defined (READLINE)
+  if (interactive_shell)
+    posix_readline_initialize (posixly_correct);
+#endif /* READLINE */
+  set_shellopts ();    /* make sure `posix' is/is not in $SHELLOPTS */
+}
+
+void
+sv_locale (name)
+     char *name;
+{
+  char *v;
+  int r;
+
+  v = get_string_value (name);
+  if (name[0] == 'L' && name[1] == 'A')        /* LANG */
+    r = set_lang (name, v);
+  else
+    r = set_locale_var (name, v);              /* LC_*, TEXTDOMAIN* */
+
+#if 1
+  if (r == 0 && posixly_correct)
+    last_command_exit_value = 1;
+#endif
+}
+
+#if defined (ARRAY_VARS)
+void
+set_pipestatus_array (ps, nproc)
+     int *ps;
+     int nproc;
+{
+  SHELL_VAR *v;
+  ARRAY *a;
+  ARRAY_ELEMENT *ae;
+  register int i;
+  char *t, tbuf[INT_STRLEN_BOUND(int) + 1];
+
+  v = find_variable ("PIPESTATUS");
+  if (v == 0)
+    v = make_new_array_variable ("PIPESTATUS");
+  if (array_p (v) == 0)
+    return;            /* Do nothing if not an array variable. */
+  a = array_cell (v);
+
+  if (a == 0 || array_num_elements (a) == 0)
+    {
+      for (i = 0; i < nproc; i++)      /* was ps[i] != -1, not i < nproc */
+       {
+         t = inttostr (ps[i], tbuf, sizeof (tbuf));
+         array_insert (a, i, t);
+       }
+      return;
+    }
+
+  /* Fast case */
+  if (array_num_elements (a) == nproc && nproc == 1)
+    {
+      ae = element_forw (a->head);
+      free (element_value (ae));
+      ae->value = itos (ps[0]);
+    }
+  else if (array_num_elements (a) <= nproc)
+    {
+      /* modify in array_num_elements members in place, then add */
+      ae = a->head;
+      for (i = 0; i < array_num_elements (a); i++)
+       {
+         ae = element_forw (ae);
+         free (element_value (ae));
+         ae->value = itos (ps[i]);
+       }
+      /* add any more */
+      for ( ; i < nproc; i++)
+       {
+         t = inttostr (ps[i], tbuf, sizeof (tbuf));
+         array_insert (a, i, t);
+       }
+    }
+  else
+    {
+      /* deleting elements.  it's faster to rebuild the array. */        
+      array_flush (a);
+      for (i = 0; ps[i] != -1; i++)
+       {
+         t = inttostr (ps[i], tbuf, sizeof (tbuf));
+         array_insert (a, i, t);
+       }
+    }
+}
+
+ARRAY *
+save_pipestatus_array ()
+{
+  SHELL_VAR *v;
+  ARRAY *a, *a2;
+
+  v = find_variable ("PIPESTATUS");
+  if (v == 0 || array_p (v) == 0 || array_cell (v) == 0)
+    return ((ARRAY *)NULL);
+    
+  a = array_cell (v);
+  a2 = array_copy (array_cell (v));
+
+  return a2;
+}
+
+void
+restore_pipestatus_array (a)
+     ARRAY *a;
+{
+  SHELL_VAR *v;
+  ARRAY *a2;
+
+  v = find_variable ("PIPESTATUS");
+  /* XXX - should we still assign even if existing value is NULL? */
+  if (v == 0 || array_p (v) == 0 || array_cell (v) == 0)
+    return;
+
+  a2 = array_cell (v);
+  var_setarray (v, a); 
+
+  array_dispose (a2);
+}
+#endif
+
+void
+set_pipestatus_from_exit (s)
+     int s;
+{
+#if defined (ARRAY_VARS)
+  static int v[2] = { 0, -1 };
+
+  v[0] = s;
+  set_pipestatus_array (v, 1);
+#endif
+}
+
+void
+sv_xtracefd (name)
+     char *name;
+{
+  SHELL_VAR *v;
+  char *t, *e;
+  int fd;
+  FILE *fp;
+
+  v = find_variable (name);
+  if (v == 0)
+    {
+      xtrace_reset ();
+      return;
+    }
+
+  t = value_cell (v);
+  if (t == 0 || *t == 0)
+    xtrace_reset ();
+  else
+    {
+      fd = (int)strtol (t, &e, 10);
+      if (e != t && *e == '\0' && sh_validfd (fd))
+       {
+         fp = fdopen (fd, "w");
+         if (fp == 0)
+           internal_error (_("%s: %s: cannot open as FILE"), name, value_cell (v));
+         else
+           xtrace_set (fd, fp);
+       }
+      else
+       internal_error (_("%s: %s: invalid value for trace file descriptor"), name, value_cell (v));
+    }
+}
+
+#define MIN_COMPAT_LEVEL 31
+
+void
+sv_shcompat (name)
+     char *name;
+{
+  SHELL_VAR *v;
+  char *val;
+  int tens, ones, compatval;
+
+  v = find_variable (name);
+  if (v == 0)
+    {
+      shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
+      set_compatibility_opts ();
+      return;
+    }
+  val = value_cell (v);
+  if (val == 0 || *val == '\0')
+    {
+      shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
+      set_compatibility_opts ();
+      return;
+    }
+  /* Handle decimal-like compatibility version specifications: 4.2 */
+  if (isdigit (val[0]) && val[1] == '.' && isdigit (val[2]) && val[3] == 0)
+    {
+      tens = val[0] - '0';
+      ones = val[2] - '0';
+      compatval = tens*10 + ones;
+    }
+  /* Handle integer-like compatibility version specifications: 42 */
+  else if (isdigit (val[0]) && isdigit (val[1]) && val[2] == 0)
+    {
+      tens = val[0] - '0';
+      ones = val[1] - '0';
+      compatval = tens*10 + ones;
+    }
+  else
+    {
+compat_error:
+      internal_error (_("%s: %s: compatibility value out of range"), name, val);
+      shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
+      set_compatibility_opts ();
+      return;
+    }
+
+  if (compatval < MIN_COMPAT_LEVEL || compatval > DEFAULT_COMPAT_LEVEL)
+    goto compat_error;
+
+  shell_compatibility_level = compatval;
+  set_compatibility_opts ();
+}
+
+#if defined (JOB_CONTROL)
+void
+sv_childmax (name)
+     char *name;
+{
+  char *tt;
+  int s;
+
+  tt = get_string_value (name);
+  s = (tt && *tt) ? atoi (tt) : 0;
+  set_maxchild (s);
+}
+#endif