]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
bash-20130222 remove leftover and stray files
authorChet Ramey <chet@caleb.ins.cwru.edu>
Mon, 4 Mar 2013 13:11:33 +0000 (08:11 -0500)
committerChet Ramey <chet@caleb.ins.cwru.edu>
Mon, 4 Mar 2013 13:11:33 +0000 (08:11 -0500)
22 files changed:
CWRU/CWRU.chlog~ [deleted file]
CWRU/POSIX.NOTES.old [deleted file]
CWRU/old/set.def.save [deleted file]
CWRU/save/unwind_prot.h.save [deleted file]
builtins/read.def~ [deleted file]
cross-build/cygwin32.cache.old [deleted file]
doc/FAQ.orig [deleted file]
eval.c~ [deleted file]
examples/loadables/Makefile.in.save [deleted file]
examples/scripts/adventure.sh.save1 [deleted file]
lib/readline/display.c~ [deleted file]
lib/readline/doc/Makefile.old [deleted file]
quit.h~ [deleted file]
sig.c~ [deleted file]
sig.h~ [deleted file]
subst.c~ [deleted file]
tests/misc/regress/log.orig [deleted file]
tests/misc/regress/shx.orig [deleted file]
trap.c~ [deleted file]
trap.h~ [deleted file]
unwind_prot.c~ [deleted file]
variables.c~ [deleted file]

diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~
deleted file mode 100644 (file)
index 53f67c3..0000000
+++ /dev/null
@@ -1,4649 +0,0 @@
-                                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-big/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
diff --git a/CWRU/POSIX.NOTES.old b/CWRU/POSIX.NOTES.old
deleted file mode 100644 (file)
index 1707ab1..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-Starting bash with the `--posix' command-line option or executing
-`set -o posix' while bash is running will cause bash to conform more
-closely to the Posix.2 standard by changing the behavior to match that
-specified by Posix.2 in areas where the bash default differs.
-
-The following list is what's changed when `posix mode' is in effect:
-
-1.  When a command in the hash table no longer exists, bash will re-search
-    $PATH to find the new location.  This is also available with
-    `shopt -s checkhash'.
-
-2.  The >& redirection does not redirect stdout and stderr.
-
-3.  The message printed by the job control code and builtins when a job
-    exits with a non-zero status is `Done(status)'.
-
-4.  Reserved words may not be aliased.
-
-5.  The Posix.2 PS1 and PS2 expansions of `!' -> history number and
-    `!!' -> `!' are enabled, and parameter expansion is performed on
-    the value regardless of the setting of the `promptvars' option.
-
-6.  Interactive comments are enabled by default.  (Note that bash has
-    them on by default anyway.)
-
-7.  The Posix.2 startup files are executed ($ENV) rather than the normal
-    bash files.
-
-8.  Tilde expansion is only performed on assignments preceding a command
-    name, rather than on all assignment statements on the line.
-
-9.  The default history file is ~/.sh_history (default value of $HISTFILE).
-
-10. The output of `kill -l' prints all the signal names on a single line,
-    separated by spaces.
-
-11. Non-interactive shells exit if `file' in `. file' is not found.
-
-12. Redirection operators do not perform pathname expansion on the word
-    in the redirection unless the shell is interactive
-
-13. Function names must be valid shell identifiers.  That is, they may not
-    contain characters other than letters, digits, and underscores, and
-    may not start with a digit.  Declaring a function with an illegal name
-    causes a fatal syntax error in non-interactive shells.
-
-14. Posix.2 `special' builtins are found before shell functions during command
-    lookup.
-
-15. If a Posix.2 special builtin returns an error status, a non-interactive
-    shell exits.  The fatal errors are those listed in the POSIX.2 standard,
-    and include things like passing incorrect options, redirection errors,
-    variable assignment errors for assignments preceding the command name,
-    and so on.
-
-16. The environment passed to executed commands is not sorted.  Neither is
-    the output of `set'.  This is not strictly Posix.2 behavior, but sh
-    does it this way.  Ksh does not.  It's not necessary to sort the
-    environment; no program should rely on it being sorted.
-
-17. If the `cd' builtin finds a directory to change to using $CDPATH, the
-    value it assigns to $PWD does not contain any symbolic links, as if
-    `cd -P' had been executed.
-
-18. A non-interactive shell exits with an error status if a variable
-    assignment error occurs when no command name follows the assignment
-    statements.  A variable assignment error occurs, for example, when
-    trying to assign a value to a read-only variable.
-
-19. A non-interactive shell exits with an error status if the iteration
-    variable in a for statement or the selection variable in a select
-    statement is a read-only variable.
-
-20. Process substitution is not available.
-
-21. Assignment statements preceding POSIX.2 `special' builtins persist in
-    the shell environment after the builtin completes.
-
-There is other Posix.2 behavior that bash does not implement.  Specifically:
-
-1.  Assignment statements affect the execution environment of all builtins,
-    not just special ones.
diff --git a/CWRU/old/set.def.save b/CWRU/old/set.def.save
deleted file mode 100644 (file)
index 87b78d7..0000000
+++ /dev/null
@@ -1,544 +0,0 @@
-This file is set.def, from which is created set.c.
-It implements the "set" and "unset" builtins in Bash.
-
-Copyright (C) 1987, 1989, 1991 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 1, 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; see the file COPYING.  If not, write to the Free Software
-Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-$PRODUCES set.c
-
-#include <stdio.h>
-#include "../shell.h"
-#include "../flags.h"
-
-#include "bashgetopt.h"
-
-extern int interactive;
-extern int noclobber, posixly_correct;
-#if defined (READLINE)
-extern int rl_editing_mode, no_line_editing;
-#endif /* READLINE */
-
-$BUILTIN set
-$FUNCTION set_builtin
-$SHORT_DOC set [--abefhkmnptuvxldBCHP] [-o option] [arg ...]
-    -a  Mark variables which are modified or created for export.
-    -b  Notify of job termination immediately.
-    -e  Exit immediately if a command exits with a non-zero status.
-    -f  Disable file name generation (globbing).
-    -h  Locate and remember function commands as functions are
-        defined.  Function commands are normally looked up when
-        the function is executed.
-    -i  Force the shell to be an "interactive" one.  Interactive shells
-        always read `~/.bashrc' on startup.
-    -k  All keyword arguments are placed in the environment for a
-        command, not just those that precede the command name.
-    -m  Job control is enabled.
-    -n  Read commands but do not execute them.
-    -o option-name
-        Set the variable corresponding to option-name:
-            allexport    same as -a
-            braceexpand  same as -B
-#if defined (READLINE)
-            emacs        use an emacs-style line editing interface
-#endif /* READLINE */
-            errexit      same as -e
-            histexpand   same as -H
-            ignoreeof    the shell will not exit upon reading EOF
-            interactive-comments
-                         allow comments to appear in interactive commands
-            monitor      same as -m
-            noclobber    disallow redirection to existing files
-            noexec       same as -n
-            noglob       same as -f
-            nohash       same as -d
-            notify       save as -b
-            nounset      same as -u
-           physical     same as -P
-           posix        change the behavior of bash where the default
-                        operation differs from the 1003.2 standard to
-                        match the standard
-           privileged   same as -p
-            verbose      same as -v
-#if defined (READLINE)
-            vi           use a vi-style line editing interface
-#endif /* READLINE */
-            xtrace       same as -x
-    -p  Turned on whenever the real and effective user ids do not match.
-        Disables processing of the $ENV file and importing of shell
-        functions.  Turning this option off causes the effective uid and
-       gid to be set to the real uid and gid.
-    -t  Exit after reading and executing one command.
-    -u  Treat unset variables as an error when substituting.
-    -v  Print shell input lines as they are read.
-    -x  Print commands and their arguments as they are executed.
-    -l  Save and restore the binding of the NAME in a FOR command.
-    -d  Disable the hashing of commands that are looked up for execution.
-        Normally, commands are remembered in a hash table, and once
-        found, do not have to be looked up again.
-#if defined (BRACE_EXPANSION)
-    -B  the shell will perform brace expansion
-#endif /* BRACE_EXPANSION */
-#if defined (BANG_HISTORY)
-    -H  Enable ! style history substitution.  This flag is on
-        by default.
-#endif /* BANG_HISTORY */
-    -C  If set, disallow existing regular files to be overwritten
-        by redirection of output.
-    -P  If set, do not follow symbolic links when executing commands
-        such as cd which change the current directory.
-
-Using + rather than - causes these flags to be turned off.  The
-flags can also be used upon invocation of the shell.  The current
-set of flags may be found in $-.  The remaining n ARGs are positional
-parameters and are assigned, in order, to $1, $2, .. $n.  If no
-ARGs are given, all shell variables are printed.
-$END
-
-/* An a-list used to match long options for set -o to the corresponding
-   option letter. */
-struct {
-  char *name;
-  int letter;
-} o_options[] = {
-  { "allexport",  'a' },
-#if defined (BRACE_EXPANSION)
-  { "braceexpand",'B' },
-#endif
-  { "errexit",   'e' },
-  { "histexpand", 'H' },
-  { "monitor",   'm' },
-  { "noexec",    'n' },
-  { "noglob",    'f' },
-  { "nohash",    'd' },
-#if defined (JOB_CONTROL)
-  { "notify",    'b' },
-#endif /* JOB_CONTROL */
-  {"nounset",    'u' },
-  {"physical",    'P' },
-  {"privileged",  'p' },
-  {"verbose",    'v' },
-  {"xtrace",     'x' },
-  {(char *)NULL, 0},
-};
-
-#define MINUS_O_FORMAT "%-15s\t%s\n"
-
-void
-list_minus_o_opts ()
-{
-  register int i;
-  char *on = "on", *off = "off";
-
-  printf (MINUS_O_FORMAT, "noclobber", (noclobber == 1) ? on : off);
-
-  if (find_variable ("ignoreeof") || find_variable ("IGNOREEOF"))
-    printf (MINUS_O_FORMAT, "ignoreeof", on);
-  else
-    printf (MINUS_O_FORMAT, "ignoreeof", off);
-
-  printf (MINUS_O_FORMAT, "interactive-comments",
-         interactive_comments ? on : off);
-
-  printf (MINUS_O_FORMAT, "posix", posixly_correct ? on : off);
-
-#if defined (READLINE)
-  if (no_line_editing)
-    {
-      printf (MINUS_O_FORMAT, "emacs", off);
-      printf (MINUS_O_FORMAT, "vi", off);
-    }
-  else
-    {
-      /* Magic.  This code `knows' how readline handles rl_editing_mode. */
-      printf (MINUS_O_FORMAT, "emacs", (rl_editing_mode == 1) ? on : off);
-      printf (MINUS_O_FORMAT, "vi", (rl_editing_mode == 0) ? on : off);
-    }
-#endif /* READLINE */
-
-  for (i = 0; o_options[i].name; i++)
-    {
-      int *on_or_off, zero = 0;
-
-      on_or_off = find_flag (o_options[i].letter);
-      if (on_or_off == FLAG_UNKNOWN)
-       on_or_off = &zero;
-      printf (MINUS_O_FORMAT, o_options[i].name, (*on_or_off == 1) ? on : off);
-    }
-}
-
-set_minus_o_option (on_or_off, option_name)
-     int on_or_off;
-     char *option_name;
-{
-  int option_char = -1;
-
-  if (STREQ (option_name, "noclobber"))
-    {
-      if (on_or_off == FLAG_ON)
-       bind_variable ("noclobber", "");
-      else
-       unbind_variable ("noclobber");
-      stupidly_hack_special_variables ("noclobber");
-    }
-  else if (STREQ (option_name, "ignoreeof"))
-    {
-      unbind_variable ("ignoreeof");
-      unbind_variable ("IGNOREEOF");
-      if (on_or_off == FLAG_ON)
-       bind_variable ("IGNOREEOF", "10");
-      stupidly_hack_special_variables ("IGNOREEOF");
-    }
-  
-#if defined (READLINE)
-  else if ((STREQ (option_name, "emacs")) || (STREQ (option_name, "vi")))
-    {
-      if (on_or_off == FLAG_ON)
-       {
-         rl_variable_bind ("editing-mode", option_name);
-
-         if (interactive)
-           with_input_from_stdin ();
-         no_line_editing = 0;
-       }
-      else
-       {
-         int isemacs = (rl_editing_mode == 1);
-         if ((isemacs && STREQ (option_name, "emacs")) ||
-             (!isemacs && STREQ (option_name, "vi")))
-           {
-             if (interactive)
-               with_input_from_stream (stdin, "stdin");
-             no_line_editing = 1;
-           }
-         else
-           builtin_error ("not in %s editing mode", option_name);
-       }
-    }
-#endif /* READLINE */
-  else if (STREQ (option_name, "interactive-comments"))
-    interactive_comments = (on_or_off == FLAG_ON);
-  else if (STREQ (option_name, "posix"))
-    {
-      posixly_correct = (on_or_off == FLAG_ON);
-      unbind_variable ("POSIXLY_CORRECT");
-      unbind_variable ("POSIX_PEDANTIC");
-      if (on_or_off == FLAG_ON)
-       {
-         bind_variable ("POSIXLY_CORRECT", "");
-         stupidly_hack_special_variables ("POSIXLY_CORRECT");
-       }
-    }
-  else
-    {
-      register int i;
-      for (i = 0; o_options[i].name; i++)
-       {
-         if (STREQ (option_name, o_options[i].name))
-           {
-             option_char = o_options[i].letter;
-             break;
-           }
-       }
-      if (option_char == -1)
-       {
-         builtin_error ("%s: unknown option name", option_name);
-         return (EXECUTION_FAILURE);
-       }
-      if (change_flag (option_char, on_or_off) == FLAG_ERROR)
-       {
-         bad_option (option_name);
-         return (EXECUTION_FAILURE);
-       }
-    }
-  return (EXECUTION_SUCCESS);
-}
-
-/* Set some flags from the word values in the input list.  If LIST is empty,
-   then print out the values of the variables instead.  If LIST contains
-   non-flags, then set $1 - $9 to the successive words of LIST. */
-set_builtin (list)
-     WORD_LIST *list;
-{
-  int on_or_off, flag_name, force_assignment = 0;
-
-  if (!list)
-    {
-      SHELL_VAR **vars;
-
-      vars = all_shell_variables ();
-      if (vars)
-       {
-         print_var_list (vars);
-         free (vars);
-       }
-
-      vars = all_shell_functions ();
-      if (vars)
-       {
-         print_var_list (vars);
-         free (vars);
-       }
-
-      return (EXECUTION_SUCCESS);
-    }
-
-  /* Check validity of flag arguments. */
-  if (*list->word->word == '-' || *list->word->word == '+')
-    {
-      register char *arg;
-      WORD_LIST *save_list = list;
-
-      while (list && (arg = list->word->word))
-       {
-         char c;
-
-         if (arg[0] != '-' && arg[0] != '+')
-           break;
-
-         /* `-' or `--' signifies end of flag arguments. */
-         if (arg[0] == '-' &&
-             (!arg[1] || (arg[1] == '-' && !arg[2])))
-           break;
-
-         while (c = *++arg)
-           {
-             if (find_flag (c) == FLAG_UNKNOWN && c != 'o')
-               {
-                 char s[2];
-                 s[0] = c; s[1] = '\0';
-                 bad_option (s);
-                 if (c == '?')
-                   builtin_usage ();
-                 return (c == '?' ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
-               }
-           }
-         list = list->next;
-       }
-      list = save_list;
-    }
-
-  /* Do the set command.  While the list consists of words starting with
-     '-' or '+' treat them as flags, otherwise, start assigning them to
-     $1 ... $n. */
-  while (list)
-    {
-      char *string = list->word->word;
-
-      /* If the argument is `--' or `-' then signal the end of the list
-        and remember the remaining arguments. */
-      if (string[0] == '-' && (!string[1] || (string[1] == '-' && !string[2])))
-       {
-         list = list->next;
-
-         /* `set --' unsets the positional parameters. */
-         if (string[1] == '-')
-           force_assignment = 1;
-
-         /* Until told differently, the old shell behaviour of
-            `set - [arg ...]' being equivalent to `set +xv [arg ...]'
-            stands.  Posix.2 says the behaviour is marked as obsolescent. */
-         else
-           {
-             change_flag ('x', '+');
-             change_flag ('v', '+');
-           }
-
-         break;
-       }
-
-      if ((on_or_off = *string) &&
-         (on_or_off == '-' || on_or_off == '+'))
-       {
-         int i = 1;
-         while (flag_name = string[i++])
-           {
-             if (flag_name == '?')
-               {
-                 builtin_usage ();
-                 return (EXECUTION_SUCCESS);
-               }
-             else if (flag_name == 'o') /* -+o option-name */
-               {
-                 char *option_name;
-                 WORD_LIST *opt;
-
-                 opt = list->next;
-
-                 if (!opt)
-                   {
-                     list_minus_o_opts ();
-                     continue;
-                   }
-
-                 option_name = opt->word->word;
-
-                 if (!option_name || !*option_name || (*option_name == '-'))
-                   {
-                     list_minus_o_opts ();
-                     continue;
-                   }
-                 list = list->next; /* Skip over option name. */
-
-                 if (set_minus_o_option (on_or_off, option_name) != EXECUTION_SUCCESS)
-                   return (EXECUTION_FAILURE);
-               }
-             else
-               {
-                 if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
-                   {
-                     char opt[3];
-                     opt[0] = on_or_off;
-                     opt[1] = flag_name;
-                     opt[2] = '\0';
-                     bad_option (opt);
-                     builtin_usage ();
-                     return (EXECUTION_FAILURE);
-                   }
-               }
-           }
-       }
-      else
-       {
-         break;
-       }
-      list = list->next;
-    }
-
-  /* Assigning $1 ... $n */
-  if (list || force_assignment)
-    remember_args (list, 1);
-  return (EXECUTION_SUCCESS);
-}
-
-$BUILTIN unset
-$FUNCTION unset_builtin
-$SHORT_DOC unset [-f] [-v] [name ...]
-For each NAME, remove the corresponding variable or function.  Given
-the `-v', unset will only act on variables.  Given the `-f' flag,
-unset will only act on functions.  With neither flag, unset first
-tries to unset a variable, and if that fails, then tries to unset a
-function.  Some variables (such as PATH and IFS) cannot be unset; also
-see readonly.
-$END
-
-#define NEXT_VARIABLE()        any_failed++; list = list->next; continue;
-
-unset_builtin (list)
-  WORD_LIST *list;
-{
-  int unset_function, unset_variable, unset_array, opt, any_failed;
-  char *name;
-
-  unset_function = unset_variable = unset_array = any_failed = 0;
-
-  reset_internal_getopt ();
-  while ((opt = internal_getopt (list, "fv")) != -1)
-    {
-      switch (opt)
-       {
-       case 'f':
-         unset_function = 1;
-         break;
-       case 'v':
-         unset_variable = 1;
-         break;
-       default:
-         builtin_usage ();
-         return (EXECUTION_FAILURE);
-       }
-    }
-
-  list = loptend;
-
-  if (unset_function && unset_variable)
-    {
-      builtin_error ("cannot simultaneously unset a function and a variable");
-      return (EXECUTION_FAILURE);
-    }
-
-  while (list)
-    {
-      SHELL_VAR *var;
-      int tem;
-#if defined (ARRAY_VARS)
-      char *t;
-#endif
-
-      name = list->word->word;
-
-#if defined (ARRAY_VARS)
-      if (!unset_function && valid_array_reference (name))
-       {
-         t = strchr (name, '[');
-         *t++ = '\0';
-         unset_array++;
-       }
-#endif
-
-      var = unset_function ? find_function (name) : find_variable (name);
-
-      if (var && !unset_function && non_unsettable_p (var))
-       {
-         builtin_error ("%s: cannot unset", name);
-         NEXT_VARIABLE ();
-       }
-
-      /* Posix.2 says that unsetting readonly variables is an error. */
-      if (var && readonly_p (var))
-       {
-         builtin_error ("%s: cannot unset: readonly %s",
-                        name, unset_function ? "function" : "variable");
-         NEXT_VARIABLE ();
-       }
-
-      /* Unless the -f option is supplied, the name refers to a variable. */
-#if defined (ARRAY_VARS)
-      if (var && unset_array)
-       {
-         if (array_p (var) == 0)
-           {
-             builtin_error ("%s: not an array variable", name);
-             NEXT_VARIABLE ();
-           }
-         else
-           tem = unbind_array_element (var, t);
-       }
-      else
-#endif /* ARRAY_VARS */
-      tem = makunbound (name, unset_function ? shell_functions : shell_variables);
-
-      /* This is what Posix.2 draft 11+ says.  ``If neither -f nor -v
-        is specified, the name refers to a variable; if a variable by
-        that name does not exist, a function by that name, if any,
-        shall be unset.'' */
-      if ((tem == -1) && !unset_function && !unset_variable)
-       tem = makunbound (name, shell_functions);
-
-      if (tem == -1)
-       any_failed++;
-      else if (!unset_function)
-       stupidly_hack_special_variables (name);
-
-      list = list->next;
-    }
-
-  if (any_failed)
-    return (EXECUTION_FAILURE);
-  else
-    return (EXECUTION_SUCCESS);
-}
diff --git a/CWRU/save/unwind_prot.h.save b/CWRU/save/unwind_prot.h.save
deleted file mode 100644 (file)
index 998fd72..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/* unwind_prot.h - Macros and functions for hacking unwind protection. */
-
-/* Copyright (C) 1993 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 2, 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; see the file COPYING.  If not, write to the Free Software
-   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if !defined (_UNWIND_PROT_H)
-#define _UNWIND_PROT_H
-
-/* Run a function without interrupts. */
-extern void begin_unwind_frame ();
-extern void discard_unwind_frame ();
-extern void run_unwind_frame ();
-extern void add_unwind_protect ();
-extern void remove_unwind_protect ();
-extern void run_unwind_protects ();
-extern void unwind_protect_var ();
-
-/* Define for people who like their code to look a certain way. */
-#define end_unwind_frame()
-
-/* How to protect an integer. */
-#define unwind_protect_int(X) unwind_protect_var (&(X), (char *)(X), sizeof (int))
-
-/* How to protect a pointer to a string. */
-#define unwind_protect_string(X) \
-  unwind_protect_var ((int *)&(X), (X), sizeof (char *))
-
-/* How to protect any old pointer. */
-#define unwind_protect_pointer(X) unwind_protect_string (X)
-
-/* How to protect the contents of a jmp_buf. */
-#define unwind_protect_jmp_buf(X) \
-  unwind_protect_var ((int *)(X), (char *)(X), sizeof (procenv_t))
-
-#endif /* _UNWIND_PROT_H */
diff --git a/builtins/read.def~ b/builtins/read.def~
deleted file mode 100644 (file)
index a7a54a7..0000000
+++ /dev/null
@@ -1,1084 +0,0 @@
-This file is read.def, from which is created read.c.
-It implements the builtin "read" 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 read.c
-
-$BUILTIN read
-$FUNCTION read_builtin
-$SHORT_DOC read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
-Read a line from the standard input and split it into fields.
-
-Reads a single line from the standard input, or from file descriptor FD
-if the -u option is supplied.  The line is split into fields as with word
-splitting, and the first word is assigned to the first NAME, the second
-word to the second NAME, and so on, with any leftover words assigned to
-the last NAME.  Only the characters found in $IFS are recognized as word
-delimiters.
-
-If no NAMEs are supplied, the line read is stored in the REPLY variable.
-
-Options:
-  -a array     assign the words read to sequential indices of the array
-               variable ARRAY, starting at zero
-  -d delim     continue until the first character of DELIM is read, rather
-               than newline
-  -e           use Readline to obtain the line in an interactive shell
-  -i text      Use TEXT as the initial text for Readline
-  -n nchars    return after reading NCHARS characters rather than waiting
-               for a newline, but honor a delimiter if fewer than NCHARS
-               characters are read before the delimiter
-  -N nchars    return only after reading exactly NCHARS characters, unless
-               EOF is encountered or read times out, ignoring any delimiter
-  -p prompt    output the string PROMPT without a trailing newline before
-               attempting to read
-  -r           do not allow backslashes to escape any characters
-  -s           do not echo input coming from a terminal
-  -t timeout   time out and return failure if a complete line of input is
-               not read within TIMEOUT seconds.  The value of the TMOUT
-               variable is the default timeout.  TIMEOUT may be a
-               fractional number.  If TIMEOUT is 0, read returns immediately,
-               without trying to read any data, returning success only if
-               input is available on the specified file descriptor.  The
-               exit status is greater than 128 if the timeout is exceeded
-  -u fd                read from file descriptor FD instead of the standard input
-
-Exit Status:
-The return code is zero, unless end-of-file is encountered, read times out
-(in which case it's greater than 128), a variable assignment error occurs,
-or an invalid file descriptor is supplied as the argument to -u.
-$END
-
-#include <config.h>
-
-#include "bashtypes.h"
-#include "posixstat.h"
-
-#include <stdio.h>
-
-#include "bashansi.h"
-
-#if defined (HAVE_UNISTD_H)
-#  include <unistd.h>
-#endif
-
-#include <signal.h>
-#include <errno.h>
-
-#ifdef __CYGWIN__
-#  include <fcntl.h>
-#  include <io.h>
-#endif
-
-#include "../bashintl.h"
-
-#include "../shell.h"
-#include "common.h"
-#include "bashgetopt.h"
-
-#include <shtty.h>
-
-#if defined (READLINE)
-#include "../bashline.h"
-#include <readline/readline.h>
-#endif
-
-#if defined (BUFFERED_INPUT)
-#  include "input.h"
-#endif
-
-#include "shmbutil.h"
-
-#if !defined(errno)
-extern int errno;
-#endif
-
-extern void run_pending_traps __P((void));
-
-extern int posixly_correct;
-extern int trapped_signal_received;
-
-struct ttsave
-{
-  int fd;
-  TTYSTRUCT *attrs;
-};
-
-#if defined (READLINE)
-static void reset_attempted_completion_function __P((char *));
-static int set_itext __P((void));
-static char *edit_line __P((char *, char *));
-static void set_eol_delim __P((int));
-static void reset_eol_delim __P((char *));
-#endif
-static SHELL_VAR *bind_read_variable __P((char *, char *));
-#if defined (HANDLE_MULTIBYTE)
-static int read_mbchar __P((int, char *, int, int, int));
-#endif
-static void ttyrestore __P((struct ttsave *));
-
-static sighandler sigalrm __P((int));
-static void reset_alarm __P((void));
-
-/* Try this to see what the rest of the shell can do with the information. */
-procenv_t alrmbuf;
-int sigalrm_seen;
-
-static int reading;
-static SigHandler *old_alrm;
-static unsigned char delim;
-
-/* In all cases, SIGALRM just sets a flag that we check periodically.  This
-   avoids problems with the semi-tricky stuff we do with the xfree of
-   input_string at the top of the unwind-protect list (see below). */
-
-/* Set a flag that CHECK_ALRM can check.  This relies on zread calling
-   trap.c:check_signals_and_traps(), which knows about sigalrm_seen and
-   alrmbuf. */
-static sighandler
-sigalrm (s)
-     int s;
-{
-itrace("sigalrm: reading = %d", reading);
-  sigalrm_seen = 1;
-}
-
-static void
-reset_alarm ()
-{
-itrace("reset_alarm: resetting SIGALRM handler to %p", old_alrm);
-  set_signal_handler (SIGALRM, old_alrm);
-  falarm (0, 0);
-}
-
-/* Read the value of the shell variables whose names follow.
-   The reading is done from the current input stream, whatever
-   that may be.  Successive words of the input line are assigned
-   to the variables mentioned in LIST.  The last variable in LIST
-   gets the remainder of the words on the line.  If no variables
-   are mentioned in LIST, then the default variable is $REPLY. */
-int
-read_builtin (list)
-     WORD_LIST *list;
-{
-  register char *varname;
-  int size, i, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
-  int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul;
-  int raw, edit, nchars, silent, have_timeout, ignore_delim, fd, lastsig, t_errno;
-  unsigned int tmsec, tmusec;
-  long ival, uval;
-  intmax_t intval;
-  char c;
-  char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
-  char *e, *t, *t1, *ps2, *tofree;
-  struct stat tsb;
-  SHELL_VAR *var;
-  TTYSTRUCT ttattrs, ttset;
-  struct ttsave termsave;
-#if defined (ARRAY_VARS)
-  WORD_LIST *alist;
-#endif
-#if defined (READLINE)
-  char *rlbuf, *itext;
-  int rlind;
-#endif
-
-  USE_VAR(size);
-  USE_VAR(i);
-  USE_VAR(pass_next);
-  USE_VAR(print_ps2);
-  USE_VAR(saw_escape);
-  USE_VAR(input_is_pipe);
-/*  USE_VAR(raw); */
-  USE_VAR(edit);
-  USE_VAR(tmsec);
-  USE_VAR(tmusec);
-  USE_VAR(nchars);
-  USE_VAR(silent);
-  USE_VAR(ifs_chars);
-  USE_VAR(prompt);
-  USE_VAR(arrayname);
-#if defined (READLINE)
-  USE_VAR(rlbuf);
-  USE_VAR(rlind);
-  USE_VAR(itext);
-#endif
-  USE_VAR(list);
-  USE_VAR(ps2);
-  USE_VAR(lastsig);
-
-  sigalrm_seen = reading = 0;
-
-  i = 0;               /* Index into the string that we are reading. */
-  raw = edit = 0;      /* Not reading raw input by default. */
-  silent = 0;
-  arrayname = prompt = (char *)NULL;
-  fd = 0;              /* file descriptor to read from */
-
-#if defined (READLINE)
-  rlbuf = itext = (char *)0;
-  rlind = 0;
-#endif
-
-  tmsec = tmusec = 0;          /* no timeout */
-  nr = nchars = input_is_tty = input_is_pipe = unbuffered_read = have_timeout = 0;
-  delim = '\n';                /* read until newline */
-  ignore_delim = 0;
-
-  reset_internal_getopt ();
-  while ((opt = internal_getopt (list, "ersa:d:i:n:p:t:u:N:")) != -1)
-    {
-      switch (opt)
-       {
-       case 'r':
-         raw = 1;
-         break;
-       case 'p':
-         prompt = list_optarg;
-         break;
-       case 's':
-         silent = 1;
-         break;
-       case 'e':
-#if defined (READLINE)
-         edit = 1;
-#endif
-         break;
-       case 'i':
-#if defined (READLINE)
-         itext = list_optarg;
-#endif
-         break;
-#if defined (ARRAY_VARS)
-       case 'a':
-         arrayname = list_optarg;
-         break;
-#endif
-       case 't':
-         code = uconvert (list_optarg, &ival, &uval);
-         if (code == 0 || ival < 0 || uval < 0)
-           {
-             builtin_error (_("%s: invalid timeout specification"), list_optarg);
-             return (EXECUTION_FAILURE);
-           }
-         else
-           {
-             have_timeout = 1;
-             tmsec = ival;
-             tmusec = uval;
-           }
-         break;
-       case 'N':
-         ignore_delim = 1;
-         delim = -1;
-       case 'n':
-         code = legal_number (list_optarg, &intval);
-         if (code == 0 || intval < 0 || intval != (int)intval)
-           {
-             sh_invalidnum (list_optarg);
-             return (EXECUTION_FAILURE);
-           }
-         else
-           nchars = intval;
-         break;
-       case 'u':
-         code = legal_number (list_optarg, &intval);
-         if (code == 0 || intval < 0 || intval != (int)intval)
-           {
-             builtin_error (_("%s: invalid file descriptor specification"), list_optarg);
-             return (EXECUTION_FAILURE);
-           }
-         else
-           fd = intval;
-         if (sh_validfd (fd) == 0)
-           {
-             builtin_error (_("%d: invalid file descriptor: %s"), fd, strerror (errno));
-             return (EXECUTION_FAILURE);
-           }
-         break;
-       case 'd':
-         delim = *list_optarg;
-         break;
-       default:
-         builtin_usage ();
-         return (EX_USAGE);
-       }
-    }
-  list = loptend;
-
-  /* `read -t 0 var' tests whether input is available with select/FIONREAD,
-     and fails if those are unavailable */
-  if (have_timeout && tmsec == 0 && tmusec == 0)
-#if 0
-    return (EXECUTION_FAILURE);
-#else
-    return (input_avail (fd) ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
-#endif
-
-  /* If we're asked to ignore the delimiter, make sure we do. */
-  if (ignore_delim)
-    delim = -1;
-
-  /* IF IFS is unset, we use the default of " \t\n". */
-  ifs_chars = getifs ();
-  if (ifs_chars == 0)          /* XXX - shouldn't happen */
-    ifs_chars = "";
-  /* If we want to read exactly NCHARS chars, don't split on IFS */
-  if (ignore_delim)
-    ifs_chars = "";
-  for (skip_ctlesc = skip_ctlnul = 0, e = ifs_chars; *e; e++)
-    skip_ctlesc |= *e == CTLESC, skip_ctlnul |= *e == CTLNUL;
-
-  input_string = (char *)xmalloc (size = 112); /* XXX was 128 */
-  input_string[0] = '\0';
-
-  /* $TMOUT, if set, is the default timeout for read. */
-  if (have_timeout == 0 && (e = get_string_value ("TMOUT")))
-    {
-      code = uconvert (e, &ival, &uval);
-      if (code == 0 || ival < 0 || uval < 0)
-       tmsec = tmusec = 0;
-      else
-       {
-         tmsec = ival;
-         tmusec = uval;
-       }
-    }
-
-  begin_unwind_frame ("read_builtin");
-
-#if defined (BUFFERED_INPUT)
-  if (interactive == 0 && default_buffered_input >= 0 && fd_is_bash_input (fd))
-    sync_buffered_stream (default_buffered_input);
-#endif
-
-  input_is_tty = isatty (fd);
-  if (input_is_tty == 0)
-#ifndef __CYGWIN__
-    input_is_pipe = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE);
-#else
-    input_is_pipe = 1;
-#endif
-
-  /* If the -p, -e or -s flags were given, but input is not coming from the
-     terminal, turn them off. */
-  if ((prompt || edit || silent) && input_is_tty == 0)
-    {
-      prompt = (char *)NULL;
-#if defined (READLINE)
-      itext = (char *)NULL;
-#endif
-      edit = silent = 0;
-    }
-
-#if defined (READLINE)
-  if (edit)
-    add_unwind_protect (xfree, rlbuf);
-#endif
-
-  pass_next = 0;       /* Non-zero signifies last char was backslash. */
-  saw_escape = 0;      /* Non-zero signifies that we saw an escape char */
-
-  if (tmsec > 0 || tmusec > 0)
-    {
-      /* Turn off the timeout if stdin is a regular file (e.g. from
-        input redirection). */
-      if ((fstat (fd, &tsb) < 0) || S_ISREG (tsb.st_mode))
-       tmsec = tmusec = 0;
-    }
-
-  if (tmsec > 0 || tmusec > 0)
-    {
-      code = setjmp_nosigs (alrmbuf);
-      if (code)
-       {
-itrace("read_builtin: longjmp to alrmbuf code = %d", code);
-         sigalrm_seen = 0;
-         /* Tricky.  The top of the unwind-protect stack is the free of
-            input_string.  We want to run all the rest and use input_string,
-            so we have to save input_string temporarily, run the unwind-
-            protects, then restore input_string so we can use it later */
-         orig_input_string = 0;
-         input_string[i] = '\0';       /* make sure it's terminated */
-         if (i == 0)
-           {
-             t = (char *)xmalloc (1);
-             t[0] = 0;
-           }
-         else
-           t = savestring (input_string);
-
-         run_unwind_frame ("read_builtin");
-         input_string = t;
-         retval = 128+SIGALRM;
-         goto assign_vars;
-       }
-      old_alrm = set_signal_handler (SIGALRM, sigalrm);
-itrace("read_builtin: set_signal_handler for SIGALRM to sigalrm");
-      add_unwind_protect (reset_alarm, (char *)NULL);
-#if defined (READLINE)
-      if (edit)
-       add_unwind_protect (reset_attempted_completion_function, (char *)NULL);
-#endif
-      falarm (tmsec, tmusec);
-itrace("read_builtin: set falarm %d %d", tmsec, tmusec);
-    }
-
-  /* If we've been asked to read only NCHARS chars, or we're using some
-     character other than newline to terminate the line, do the right
-     thing to readline or the tty. */
-  if (nchars > 0 || delim != '\n')
-    {
-#if defined (READLINE)
-      if (edit)
-       {
-         if (nchars > 0)
-           {
-             unwind_protect_int (rl_num_chars_to_read);
-             rl_num_chars_to_read = nchars;
-           }
-         if (delim != '\n')
-           {
-             set_eol_delim (delim);
-             add_unwind_protect (reset_eol_delim, (char *)NULL);
-           }
-       }
-      else
-#endif
-      if (input_is_tty)
-       {
-         /* ttsave() */
-         termsave.fd = fd;
-         ttgetattr (fd, &ttattrs);
-         termsave.attrs = &ttattrs;
-
-         ttset = ttattrs;        
-         i = silent ? ttfd_cbreak (fd, &ttset) : ttfd_onechar (fd, &ttset);
-         if (i < 0)
-           sh_ttyerror (1);
-         add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
-       }
-    }
-  else if (silent)     /* turn off echo but leave term in canonical mode */
-    {
-      /* ttsave (); */
-      termsave.fd = fd;
-      ttgetattr (fd, &ttattrs);
-      termsave.attrs = &ttattrs;
-
-      ttset = ttattrs;
-      i = ttfd_noecho (fd, &ttset);                    /* ttnoecho (); */
-      if (i < 0)
-       sh_ttyerror (1);
-
-      add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
-    }
-
-  /* This *must* be the top unwind-protect on the stack, so the manipulation
-     of the unwind-protect stack after the realloc() works right. */
-  add_unwind_protect (xfree, input_string);
-
-  CHECK_ALRM;
-  if ((nchars > 0) && (input_is_tty == 0) && ignore_delim)     /* read -N */
-    unbuffered_read = 2;
-  else if ((nchars > 0) || (delim != '\n') || input_is_pipe)
-    unbuffered_read = 1;
-
-  if (prompt && edit == 0)
-    {
-      fprintf (stderr, "%s", prompt);
-      fflush (stderr);
-    }
-
-#if defined (__CYGWIN__) && defined (O_TEXT)
-  setmode (0, O_TEXT);
-#endif
-
-  ps2 = 0;
-  for (print_ps2 = eof = retval = 0;;)
-    {
-      CHECK_ALRM;
-
-#if defined (READLINE)
-      if (edit)
-       {
-         if (rlbuf && rlbuf[rlind] == '\0')
-           {
-             xfree (rlbuf);
-             rlbuf = (char *)0;
-           }
-         if (rlbuf == 0)
-           {
-             reading = 1;
-             rlbuf = edit_line (prompt ? prompt : "", itext);
-             reading = 0;
-             rlind = 0;
-           }
-         if (rlbuf == 0)
-           {
-             eof = 1;
-             break;
-           }
-         c = rlbuf[rlind++];
-       }
-      else
-       {
-#endif
-
-      if (print_ps2)
-       {
-         if (ps2 == 0)
-           ps2 = get_string_value ("PS2");
-         fprintf (stderr, "%s", ps2 ? ps2 : "");
-         fflush (stderr);
-         print_ps2 = 0;
-       }
-
-#if 0
-      if (posixly_correct == 0)
-       interrupt_immediately++;
-#endif
-      reading = 1;
-      if (unbuffered_read == 2)
-       retval = posixly_correct ? zreadintr (fd, &c, 1) : zreadn (fd, &c, nchars - nr);
-      else if (unbuffered_read)
-       retval = posixly_correct ? zreadintr (fd, &c, 1) : zread (fd, &c, 1);
-      else
-       retval = posixly_correct ? zreadcintr (fd, &c) : zreadc (fd, &c);
-      reading = 0;
-#if 0
-      if (posixly_correct == 0)
-       interrupt_immediately--;
-#endif
-
-      if (retval <= 0)
-       {
-         if (retval < 0 && errno == EINTR)
-           {
-             lastsig = LASTSIG();
-             if (lastsig == 0)
-               lastsig = trapped_signal_received;
-             run_pending_traps ();     /* because interrupt_immediately is not set */
-           }
-         else
-           lastsig = 0;
-         CHECK_TERMSIG;
-         eof = 1;
-         break;
-       }
-
-      CHECK_ALRM;
-
-#if defined (READLINE)
-       }
-#endif
-
-      CHECK_ALRM;
-      if (i + 4 >= size)       /* XXX was i + 2; use i + 4 for multibyte/read_mbchar */
-       {
-         char *t;
-         t = (char *)xrealloc (input_string, size += 128);
-
-         /* Only need to change unwind-protect if input_string changes */
-         if (t != input_string)
-           {
-             input_string = t;
-             remove_unwind_protect ();
-             add_unwind_protect (xfree, input_string);
-           }
-       }
-
-      /* If the next character is to be accepted verbatim, a backslash
-        newline pair still disappears from the input. */
-      if (pass_next)
-       {
-         pass_next = 0;
-         if (c == '\n')
-           {
-             i--;              /* back up over the CTLESC */
-             if (interactive && input_is_tty && raw == 0)
-               print_ps2 = 1;
-           }
-         else
-           goto add_char;
-         continue;
-       }
-
-      /* This may cause problems if IFS contains CTLESC */
-      if (c == '\\' && raw == 0)
-       {
-         pass_next++;
-         if (skip_ctlesc == 0)
-           {
-             saw_escape++;
-             input_string[i++] = CTLESC;
-           }
-         continue;
-       }
-
-      if ((unsigned char)c == delim)
-       break;
-
-      if (c == '\0' && delim != '\0')
-       continue;               /* skip NUL bytes in input */
-
-      if ((skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL))
-       {
-         saw_escape++;
-         input_string[i++] = CTLESC;
-       }
-
-add_char:
-      input_string[i++] = c;
-      CHECK_ALRM;
-
-#if defined (HANDLE_MULTIBYTE)
-      if (nchars > 0 && MB_CUR_MAX > 1 && is_basic (c) == 0)
-       {
-         input_string[i] = '\0';       /* for simplicity and debugging */
-         i += read_mbchar (fd, input_string, i, c, unbuffered_read);
-       }
-#endif
-
-      nr++;
-
-      if (nchars > 0 && nr >= nchars)
-       break;
-    }
-  input_string[i] = '\0';
-  CHECK_ALRM;
-
-  if (retval < 0)
-    {
-      t_errno = errno;
-      if (errno != EINTR)
-       builtin_error (_("read error: %d: %s"), fd, strerror (errno));
-      run_unwind_frame ("read_builtin");
-      return ((t_errno != EINTR) ? EXECUTION_FAILURE : 128+lastsig);
-    }
-
-  if (tmsec > 0 || tmusec > 0)
-    reset_alarm ();
-
-  if (nchars > 0 || delim != '\n')
-    {
-#if defined (READLINE)
-      if (edit)
-       {
-         if (nchars > 0)
-           rl_num_chars_to_read = 0;
-         if (delim != '\n')
-           reset_eol_delim ((char *)NULL);
-       }
-      else
-#endif
-      if (input_is_tty)
-       ttyrestore (&termsave);
-    }
-  else if (silent)
-    ttyrestore (&termsave);
-
-  if (unbuffered_read == 0)
-    zsyncfd (fd);
-
-  discard_unwind_frame ("read_builtin");
-
-  retval = eof ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
-
-assign_vars:
-
-#if defined (ARRAY_VARS)
-  /* If -a was given, take the string read, break it into a list of words,
-     an assign them to `arrayname' in turn. */
-  if (arrayname)
-    {
-      if (legal_identifier (arrayname) == 0)
-       {
-         sh_invalidid (arrayname);
-         xfree (input_string);
-         return (EXECUTION_FAILURE);
-       }
-
-      var = find_or_make_array_variable (arrayname, 1);
-      if (var == 0)
-       {
-         xfree (input_string);
-         return EXECUTION_FAILURE;     /* readonly or noassign */
-       }
-      if (assoc_p (var))
-       {
-          builtin_error (_("%s: cannot convert associative to indexed array"), arrayname);
-         xfree (input_string);
-         return EXECUTION_FAILURE;     /* existing associative array */
-       }
-      else if (invisible_p (var))
-       VUNSETATTR (var, att_invisible);
-      array_flush (array_cell (var));
-
-      alist = list_string (input_string, ifs_chars, 0);
-      if (alist)
-       {
-         if (saw_escape)
-           dequote_list (alist);
-         else
-           word_list_remove_quoted_nulls (alist);
-         assign_array_var_from_word_list (var, alist, 0);
-         dispose_words (alist);
-       }
-      xfree (input_string);
-      return (retval);
-    }
-#endif /* ARRAY_VARS */ 
-
-  /* If there are no variables, save the text of the line read to the
-     variable $REPLY.  ksh93 strips leading and trailing IFS whitespace,
-     so that `read x ; echo "$x"' and `read ; echo "$REPLY"' behave the
-     same way, but I believe that the difference in behaviors is useful
-     enough to not do it.  Without the bash behavior, there is no way
-     to read a line completely without interpretation or modification
-     unless you mess with $IFS (e.g., setting it to the empty string).
-     If you disagree, change the occurrences of `#if 0' to `#if 1' below. */
-  if (list == 0)
-    {
-#if 0
-      orig_input_string = input_string;
-      for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++)
-       ;
-      input_string = t;
-      input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
-#endif
-
-      if (saw_escape)
-       {
-         t = dequote_string (input_string);
-         var = bind_variable ("REPLY", t, 0);
-         free (t);
-       }
-      else
-       var = bind_variable ("REPLY", input_string, 0);
-      VUNSETATTR (var, att_invisible);
-
-      xfree (input_string);
-      return (retval);
-    }
-
-  /* This code implements the Posix.2 spec for splitting the words
-     read and assigning them to variables. */
-  orig_input_string = input_string;
-
-  /* Remove IFS white space at the beginning of the input string.  If
-     $IFS is null, no field splitting is performed. */
-  for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++)
-    ;
-  input_string = t;
-  for (; list->next; list = list->next)
-    {
-      varname = list->word->word;
-#if defined (ARRAY_VARS)
-      if (legal_identifier (varname) == 0 && valid_array_reference (varname) == 0)
-#else
-      if (legal_identifier (varname) == 0)
-#endif
-       {
-         sh_invalidid (varname);
-         xfree (orig_input_string);
-         return (EXECUTION_FAILURE);
-       }
-
-      /* If there are more variables than words read from the input,
-        the remaining variables are set to the empty string. */
-      if (*input_string)
-       {
-         /* This call updates INPUT_STRING. */
-         t = get_word_from_string (&input_string, ifs_chars, &e);
-         if (t)
-           *e = '\0';
-         /* Don't bother to remove the CTLESC unless we added one
-            somewhere while reading the string. */
-         if (t && saw_escape)
-           {
-             t1 = dequote_string (t);
-             var = bind_read_variable (varname, t1);
-             xfree (t1);
-           }
-         else
-           var = bind_read_variable (varname, t ? t : "");
-       }
-      else
-       {
-         t = (char *)0;
-         var = bind_read_variable (varname, "");
-       }
-
-      FREE (t);
-      if (var == 0)
-       {
-         xfree (orig_input_string);
-         return (EXECUTION_FAILURE);
-       }
-
-      stupidly_hack_special_variables (varname);
-      VUNSETATTR (var, att_invisible);
-    }
-
-  /* Now assign the rest of the line to the last variable argument. */
-#if defined (ARRAY_VARS)
-  if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word) == 0)
-#else
-  if (legal_identifier (list->word->word) == 0)
-#endif
-    {
-      sh_invalidid (list->word->word);
-      xfree (orig_input_string);
-      return (EXECUTION_FAILURE);
-    }
-
-#if 0
-  /* This has to be done this way rather than using string_list
-     and list_string because Posix.2 says that the last variable gets the
-     remaining words and their intervening separators. */
-  input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
-#else
-  /* Check whether or not the number of fields is exactly the same as the
-     number of variables. */
-  tofree = NULL;
-  if (*input_string)
-    {
-      t1 = input_string;
-      t = get_word_from_string (&input_string, ifs_chars, &e);
-      if (*input_string == 0)
-       tofree = input_string = t;
-      else
-       {
-         input_string = strip_trailing_ifs_whitespace (t1, ifs_chars, saw_escape);
-         tofree = t;
-       }
-    }
-#endif
-
-  if (saw_escape && input_string && *input_string)
-    {
-      t = dequote_string (input_string);
-      var = bind_read_variable (list->word->word, t);
-      xfree (t);
-    }
-  else
-    var = bind_read_variable (list->word->word, input_string ? input_string : "");
-
-  if (var)
-    {
-      stupidly_hack_special_variables (list->word->word);
-      VUNSETATTR (var, att_invisible);
-    }
-  else
-    retval = EXECUTION_FAILURE;
-
-  FREE (tofree);
-  xfree (orig_input_string);
-
-  return (retval);
-}
-
-static SHELL_VAR *
-bind_read_variable (name, value)
-     char *name, *value;
-{
-  SHELL_VAR *v;
-
-#if defined (ARRAY_VARS)
-  if (valid_array_reference (name) == 0)
-    v = bind_variable (name, value, 0);
-  else
-    v = assign_array_element (name, value, 0);
-#else /* !ARRAY_VARS */
-  v = bind_variable (name, value, 0);
-#endif /* !ARRAY_VARS */
-  return (v == 0 ? v
-                : ((readonly_p (v) || noassign_p (v)) ? (SHELL_VAR *)NULL : v));
-}
-
-#if defined (HANDLE_MULTIBYTE)
-static int
-read_mbchar (fd, string, ind, ch, unbuffered)
-     int fd;
-     char *string;
-     int ind, ch, unbuffered;
-{
-  char mbchar[MB_LEN_MAX + 1];
-  int i, n, r;
-  char c;
-  size_t ret;
-  mbstate_t ps, ps_back;
-  wchar_t wc;
-
-  memset (&ps, '\0', sizeof (mbstate_t));
-  memset (&ps_back, '\0', sizeof (mbstate_t));
-  
-  mbchar[0] = ch;
-  i = 1;
-  for (n = 0; n <= MB_LEN_MAX; n++)
-    {
-      ps_back = ps;
-      ret = mbrtowc (&wc, mbchar, i, &ps);
-      if (ret == (size_t)-2)
-       {
-         ps = ps_back;
-         /* We don't want to be interrupted during a multibyte char read */
-         if (unbuffered)
-           r = zread (fd, &c, 1);
-         else
-           r = zreadc (fd, &c);
-         if (r < 0)
-           goto mbchar_return;
-         mbchar[i++] = c;      
-         continue;
-       }
-      else if (ret == (size_t)-1 || ret == (size_t)0 || ret > (size_t)0)
-       break;
-    }
-
-mbchar_return:
-  if (i > 1)   /* read a multibyte char */
-    /* mbchar[0] is already string[ind-1] */
-    for (r = 1; r < i; r++)
-      string[ind+r-1] = mbchar[r];
-  return i - 1;
-}
-#endif
-
-
-static void
-ttyrestore (ttp)
-     struct ttsave *ttp;
-{
-  ttsetattr (ttp->fd, ttp->attrs);
-}
-
-#if defined (READLINE)
-static rl_completion_func_t *old_attempted_completion_function = 0;
-static rl_hook_func_t *old_startup_hook;
-static char *deftext;
-
-static void
-reset_attempted_completion_function (cp)
-     char *cp;
-{
-  if (rl_attempted_completion_function == 0 && old_attempted_completion_function)
-    rl_attempted_completion_function = old_attempted_completion_function;
-}
-
-static int
-set_itext ()
-{
-  int r1, r2;
-
-  r1 = r2 = 0;
-  if (old_startup_hook)
-    r1 = (*old_startup_hook) ();
-  if (deftext)
-    {
-      r2 = rl_insert_text (deftext);
-      deftext = (char *)NULL;
-      rl_startup_hook = old_startup_hook;
-      old_startup_hook = (rl_hook_func_t *)NULL;
-    }
-  return (r1 || r2);
-}
-
-static char *
-edit_line (p, itext)
-     char *p;
-     char *itext;
-{
-  char *ret;
-  int len;
-
-  if (bash_readline_initialized == 0)
-    initialize_readline ();
-
-  old_attempted_completion_function = rl_attempted_completion_function;
-  rl_attempted_completion_function = (rl_completion_func_t *)NULL;
-  if (itext)
-    {
-      old_startup_hook = rl_startup_hook;
-      rl_startup_hook = set_itext;
-      deftext = itext;
-    }
-
-  ret = readline (p);
-
-  rl_attempted_completion_function = old_attempted_completion_function;
-  old_attempted_completion_function = (rl_completion_func_t *)NULL;
-
-  if (ret == 0)
-    return ret;
-  len = strlen (ret);
-  ret = (char *)xrealloc (ret, len + 2);
-  ret[len++] = delim;
-  ret[len] = '\0';
-  return ret;
-}
-
-static int old_delim_ctype;
-static rl_command_func_t *old_delim_func;
-static int old_newline_ctype;
-static rl_command_func_t *old_newline_func;
-
-static unsigned char delim_char;
-
-static void
-set_eol_delim (c)
-     int c;
-{
-  Keymap cmap;
-
-  if (bash_readline_initialized == 0)
-    initialize_readline ();
-  cmap = rl_get_keymap ();
-
-  /* Change newline to self-insert */
-  old_newline_ctype = cmap[RETURN].type;
-  old_newline_func =  cmap[RETURN].function;
-  cmap[RETURN].type = ISFUNC;
-  cmap[RETURN].function = rl_insert;
-
-  /* Bind the delimiter character to accept-line. */
-  old_delim_ctype = cmap[c].type;
-  old_delim_func = cmap[c].function;
-  cmap[c].type = ISFUNC;
-  cmap[c].function = rl_newline;
-
-  delim_char = c;
-}
-
-static void
-reset_eol_delim (cp)
-     char *cp;
-{
-  Keymap cmap;
-
-  cmap = rl_get_keymap ();
-
-  cmap[RETURN].type = old_newline_ctype;
-  cmap[RETURN].function = old_newline_func;
-
-  cmap[delim_char].type = old_delim_ctype;
-  cmap[delim_char].function = old_delim_func;
-}
-#endif
diff --git a/cross-build/cygwin32.cache.old b/cross-build/cygwin32.cache.old
deleted file mode 100644 (file)
index 640390f..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-# This file is a shell script that caches the results of configure
-# tests for CYGWIN32 so they don't need to be done when cross-compiling.
-
-# AC_FUNC_GETPGRP should also define GETPGRP_VOID
-ac_cv_func_getpgrp_void=${ac_cv_func_getpgrp_void='yes'}
-# AC_FUNC_SETVBUF_REVERSED should not define anything else
-ac_cv_func_setvbuf_reversed=${ac_cv_func_setvbuf_reversed='no'}
-# on CYGWIN32, system calls do not restart
-ac_cv_sys_restartable_syscalls=${ac_cv_sys_restartable_syscalls='no'}
-bash_cv_sys_restartable_syscalls=${bash_cv_sys_restartable_syscalls='no'}
-
-# these may be necessary, but they are currently commented out
-#ac_cv_c_bigendian=${ac_cv_c_bigendian='no'}
-ac_cv_sizeof_char_p=${ac_cv_sizeof_char_p='4'}
-ac_cv_sizeof_int=${ac_cv_sizeof_int='4'}
-ac_cv_sizeof_long=${ac_cv_sizeof_long='4'}
-ac_cv_sizeof_double=${ac_cv_sizeof_double='8'}
-
-bash_cv_dup2_broken=${bash_cv_dup2_broken='no'}
-bash_cv_pgrp_pipe=${bash_cv_pgrp_pipe='no'}
-bash_cv_type_rlimit=${bash_cv_type_rlimit='long'}
-bash_cv_decl_under_sys_siglist=${bash_cv_decl_under_sys_siglist='no'}
-bash_cv_under_sys_siglist=${bash_cv_under_sys_siglist='no'}
-bash_cv_sys_siglist=${bash_cv_sys_siglist='no'}
-bash_cv_opendir_not_robust=${bash_cv_opendir_not_robust='no'}
-bash_cv_getenv_redef=${bash_cv_getenv_redef='yes'}
-bash_cv_printf_declared=${bash_cv_printf_declared='yes'}
-bash_cv_ulimit_maxfds=${bash_cv_ulimit_maxfds='no'}
-bash_cv_getcwd_calls_popen=${bash_cv_getcwd_calls_popen='no'}
-bash_cv_must_reinstall_sighandlers=${bash_cv_must_reinstall_sighandlers='no'}
-bash_cv_job_control_missing=${bash_cv_job_control_missing='present'}
-bash_cv_sys_named_pipes=${bash_cv_sys_named_pipes='missing'}
-bash_cv_func_sigsetjmp=${bash_cv_func_sigsetjmp='missing'}
-bash_cv_mail_dir=${bash_cv_mail_dir='unknown'}
-bash_cv_func_strcoll_broken=${bash_cv_func_strcoll_broken='no'}
-
-bash_cv_type_int32_t=${bash_cv_type_int32_t='int'}
-bash_cv_type_u_int32_t=${bash_cv_type_u_int32_t='int'}
-
-ac_cv_type_bits64_t=${ac_cv_type_bits64_t='no'}
-
-# end of cross-build/cygwin32.cache
diff --git a/doc/FAQ.orig b/doc/FAQ.orig
deleted file mode 100644 (file)
index 1cff3c8..0000000
+++ /dev/null
@@ -1,1745 +0,0 @@
-This is the Bash FAQ, version 3.24, for Bash version 2.05b.
-
-This document contains a set of frequently-asked questions concerning
-Bash, the GNU Bourne-Again Shell.  Bash is a freely-available command
-interpreter with advanced features for both interactive use and shell
-programming.
-
-Another good source of basic information about shells is the collection
-of FAQ articles periodically posted to comp.unix.shell.
-
-Questions and comments concerning this document should be sent to
-chet@po.cwru.edu.
-
-This document is available for anonymous FTP with the URL
-
-ftp://ftp.cwru.edu/pub/bash/FAQ
-
-The Bash home page is http://cnswww.cns.cwru.edu/~chet/bash/bashtop.html
-
-----------
-Contents:
-
-Section A:  The Basics
-
-A1) What is it?
-A2) What's the latest version?
-A3) Where can I get it?
-A4) On what machines will bash run?
-A5) Will bash run on operating systems other than Unix?
-A6) How can I build bash with gcc?
-A7) How can I make bash my login shell?
-A8) I just changed my login shell to bash, and now I can't FTP into my
-    machine.  Why not?
-A9) What's the `POSIX 1003.2 standard'?
-A10) What is the bash `posix mode'?
-
-Section B:  The latest version
-
-B1) What's new in version 2.05b?
-B2) Are there any user-visible incompatibilities between bash-2.05b and
-    bash-1.14.7?
-
-Section C:  Differences from other Unix shells
-
-C1) How does bash differ from sh, the Bourne shell?
-C2) How does bash differ from the Korn shell, version ksh88?
-C3) Which new features in ksh-93 are not in bash, and which are?
-
-Section D:  Why does bash do some things differently than other Unix shells?
-
-D1) Why does bash run a different version of `command' than
-    `which command' says it will?
-D2) Why doesn't bash treat brace expansions exactly like csh?
-D3) Why doesn't bash have csh variable modifiers?
-D4) How can I make my csh aliases work when I convert to bash?
-D5) How can I pipe standard output and standard error from one command to
-    another, like csh does with `|&'?
-D6) Now that I've converted from ksh to bash, are there equivalents to
-    ksh features like autoloaded functions and the `whence' command?
-
-Section E:  Why does bash do certain things the way it does?
-
-E1) Why is the bash builtin `test' slightly different from /bin/test?
-E2) Why does bash sometimes say `Broken pipe'?
-E3) When I have terminal escape sequences in my prompt, why does bash
-    wrap lines at the wrong column?
-E4) If I pipe the output of a command into `read variable', why doesn't
-    the output show up in $variable when the read command finishes?
-E5) I have a bunch of shell scripts that use backslash-escaped characters
-    in arguments to `echo'.  Bash doesn't interpret these characters.  Why
-    not, and how can I make it understand them?
-E6) Why doesn't a while or for loop get suspended when I type ^Z?
-E7) What about empty for loops in Makefiles?
-E8) Why does the arithmetic evaluation code complain about `08'?
-E9) Why does the pattern matching expression [A-Z]* match files beginning
-    with every letter except `z'?
-E10) Why does `cd //' leave $PWD as `//'?
-E11) If I resize my xterm while another program is running, why doesn't bash
-     notice the change?
-
-Section F:  Things to watch out for on certain Unix versions
-
-F1) Why can't I use command line editing in my `cmdtool'?
-F2) I built bash on Solaris 2.  Why do globbing expansions and filename
-    completion chop off the first few characters of each filename?
-F3) Why does bash dump core after I interrupt username completion or
-    `~user' tilde expansion on a machine running NIS?
-F4) I'm running SVR4.2.  Why is the line erased every time I type `@'?
-F5) Why does bash report syntax errors when my C News scripts use a
-    redirection before a subshell command?
-F6) Why can't I use vi-mode editing on Red Hat Linux 6.1?
-F7) Why do bash-2.05a and  bash-2.05b fail to compile `printf.def' on
-    HP/UX 11.x?
-
-Section G:  How can I get bash to do certain common things?
-
-G1) How can I get bash to read and display eight-bit characters?
-G2) How do I write a function `x' to replace builtin command `x', but
-    still invoke the command from within the function?
-G3) How can I find the value of a shell variable whose name is the value
-    of another shell variable?
-G4) How can I make the bash `time' reserved word print timing output that
-    looks like the output from my system's /usr/bin/time?
-G5) How do I get the current directory into my prompt?
-G6) How can I rename "*.foo" to "*.bar"?
-G7) How can I translate a filename from uppercase to lowercase?
-G8) How can I write a filename expansion (globbing) pattern that will match
-    all files in the current directory except "." and ".."?
-
-Section H:  Where do I go from here?
-
-H1) How do I report bugs in bash, and where should I look for fixes and
-    advice?
-H2) What kind of bash documentation is there?
-H3) What's coming in future versions?
-H4) What's on the bash `wish list'?
-H5) When will the next release appear?
-
-----------
-Section A:  The Basics
-
-A1)  What is it?
-
-Bash is a Unix command interpreter (shell).  It is an implementation of
-the Posix 1003.2 shell standard, and resembles the Korn and System V
-shells.
-
-Bash contains a number of enhancements over those shells, both
-for interactive use and shell programming.  Features geared
-toward interactive use include command line editing, command
-history, job control, aliases, and prompt expansion.  Programming
-features include additional variable expansions, shell
-arithmetic, and a number of variables and options to control
-shell behavior.
-
-Bash was originally written by Brian Fox of the Free Software
-Foundation.  The current developer and maintainer is Chet Ramey
-of Case Western Reserve University.
-
-A2)  What's the latest version?
-
-The latest version is 2.05b, first made available on Wednesday, 17
-July, 2002.
-
-A3)  Where can I get it?
-
-Bash is the GNU project's shell, and so is available from the
-master GNU archive site, ftp.gnu.org, and its mirrors.  The
-latest version is also available for FTP from ftp.cwru.edu.
-The following URLs tell how to get version 2.05b:
-
-ftp://ftp.gnu.org/pub/gnu/bash/bash-2.05b.tar.gz
-ftp://ftp.cwru.edu/pub/bash/bash-2.05b.tar.gz
-
-Formatted versions of the documentation are available with the URLs:
-
-ftp://ftp.gnu.org/pub/gnu/bash/bash-doc-2.05b.tar.gz
-ftp://ftp.cwru.edu/pub/bash/bash-doc-2.05b.tar.gz
-
-A4)  On what machines will bash run?
-
-Bash has been ported to nearly every version of UNIX.  All you
-should have to do to build it on a machine for which a port
-exists is to type `configure' and then `make'.  The build process
-will attempt to discover the version of UNIX you have and tailor
-itself accordingly, using a script created by GNU autoconf.
-
-More information appears in the file `INSTALL' in the distribution.
-
-The Bash web page (http://cnswww.cns.cwru.edu/~chet/bash/bashtop.html)
-explains how to obtain binary versions of bash for most of the major
-commercial Unix systems.
-
-A5) Will bash run on operating systems other than Unix?
-
-Configuration specifics for Unix-like systems such as QNX and
-LynxOS are included in the distribution.  Bash-2.05 and later
-versions should compile and run on Minix 2.0 (patches were
-contributed), but I don't believe anyone has built bash-2.x on
-earlier Minix versions yet. 
-
-Bash has been ported to versions of Windows implementing the Win32
-programming interface.  This includes Windows 95 and Windows NT.
-The port was done by Cygnus Solutions as part of their CYGWIN
-project.  For more information about the project, look at the URLs
-
-http://www.cygwin.com/
-http://sourceware.cygnus.com/cygwin
-
-Cygnus originally ported bash-1.14.7, and that port was part of their
-early GNU-Win32 (the original name) releases.  Cygnus has also done a
-port of bash-2.05 to the CYGWIN environment, and it is available as
-part of their current release.
-
-Bash-2.05b should require no local Cygnus changes to build and run under
-CYGWIN.
-
-The Cygnus port works only on Intel machines.  There is a port of bash
-(I don't know which version) to the alpha/NT environment available from
-
-ftp://ftp.gnustep.org//pub/win32/bash-alpha-nt-1.01.tar.gz
-
-DJ Delorie has a port of bash-2.x which runs under MS-DOS, as part
-of the DJGPP project.  For more information on the project, see
-
-http://www.delorie.com/djgpp/
-
-I have been told that the original DJGPP port was done by Daisuke Aoyama.
-
-Mark Elbrecht <snowball3@bigfoot.com> has sent me notice that bash-2.04
-is available for DJGPP V2.  The files are available as:
-
-ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsh204b.zip binary
-ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsh204d.zip documentation
-ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsh204s.zip source
-
-Mark has begun to work with bash-2.05, but I don't know the status.
-
-Ports of bash-1.12 and bash-2.0 are available for OS/2 from
-
-ftp://hobbes.nmsu.edu/pub/os2/util/shell/bash_112.zip
-ftp://hobbes.nmsu.edu/pub/os2/util/shell/bash-2.0(253).zip
-
-I haven't looked at either, but the second appears to be a binary-only
-distribution.  Beware.
-
-I have received word that Bash (I'm not sure which version, but I
-believe that it's at least bash-2.02.1) is the standard shell on
-BeOS.
-
-A6) How can I build bash with gcc? 
-
-Bash configures to use gcc by default if it is available.  Read the
-file INSTALL in the distribution for more information.
-
-A7)  How can I make bash my login shell?
-
-Some machines let you use `chsh' to change your login shell.  Other
-systems use `passwd -s' or `passwd -e'.  If one of these works for
-you, that's all you need.  Note that many systems require the full
-pathname to a shell to appear in /etc/shells before you can make it
-your login shell.  For this, you may need the assistance of your
-friendly local system administrator. 
-
-If you cannot do this, you can still use bash as your login shell, but
-you need to perform some tricks.  The basic idea is to add a command
-to your login shell's startup file to replace your login shell with
-bash.
-
-For example, if your login shell is csh or tcsh, and you have installed
-bash in /usr/gnu/bin/bash, add the following line to ~/.login:
-
-       if ( -f /usr/gnu/bin/bash ) exec /usr/gnu/bin/bash --login
-
-(the `--login' tells bash that it is a login shell).
-
-It's not a good idea to put this command into ~/.cshrc, because every
-csh you run without the `-f' option, even ones started to run csh scripts,
-reads that file.  If you must put the command in ~/.cshrc, use something
-like
-
-       if ( $?prompt ) exec /usr/gnu/bin/bash --login
-
-to ensure that bash is exec'd only when the csh is interactive.
-
-If your login shell is sh or ksh, you have to do two things.
-
-First, create an empty file in your home directory named `.bash_profile'.
-The existence of this file will prevent the exec'd bash from trying to
-read ~/.profile, and re-execing itself over and over again.  ~/.bash_profile
-is the first file bash tries to read initialization commands from when
-it is invoked as a login shell.
-
-Next, add a line similar to the above to ~/.profile:
-
-       [ -f /usr/gnu/bin/bash ] && [ -x /usr/gnu/bin/bash ] && \
-               exec /usr/gnu/bin/bash --login
-
-This will cause login shells to replace themselves with bash running as
-a login shell.  Once you have this working, you can copy your initialization
-code from ~/.profile to ~/.bash_profile.
-
-I have received word that the recipe supplied above is insufficient for
-machines running CDE.  CDE has a maze of twisty little startup files, all
-slightly different.
-
-If you cannot change your login shell in the password file to bash, you
-will have to (apparently) live with CDE using the shell in the password
-file to run its startup scripts.  If you have changed your shell to bash,
-there is code in the CDE startup files (on Solaris, at least) that attempts
-to do the right thing.  It is, however, often broken, and may require that
-you use the $BASH_ENV trick described below.
-
-`dtterm' claims to use $SHELL as the default program to start, so if you
-can change $SHELL in the CDE startup files, you should be able to use bash
-in your terminal windows.
-
-Setting DTSOURCEPROFILE in ~/.dtprofile will cause the `Xsession' program
-to read your login shell's startup files.  You may be able to use bash for
-the rest of the CDE programs by setting SHELL to bash in ~/.dtprofile as
-well, but I have not tried this.
-
-You can use the above `exec' recipe to start bash when not logging in with
-CDE by testing the value of the DT variable:
-
-       if [ -n "$DT" ]; then
-               [ -f /usr/gnu/bin/bash ] && exec /usr/gnu/bin/bash --login
-       fi
-
-If CDE starts its shells non-interactively during login, the login shell
-startup files (~/.profile, ~/.bash_profile) will not be sourced at login.
-To get around this problem, append a line similar to the following to your
-~/.dtprofile:
-
-       BASH_ENV=${HOME}/.bash_profile ; export BASH_ENV
-
-and add the following line to the beginning of ~/.bash_profile:
-
-       unset BASH_ENV
-
-A8) I just changed my login shell to bash, and now I can't FTP into my
-   machine.  Why not?
-
-You must add the full pathname to bash to the file /etc/shells.  As
-noted in the answer to the previous question, many systems require
-this before you can make bash your login shell. 
-
-Most versions of ftpd use this file to prohibit `special' users
-such as `uucp' and `news' from using FTP. 
-
-A9)  What's the `POSIX 1003.2 standard'?
-
-POSIX is a name originally coined by Richard Stallman for a
-family of open system standards based on UNIX.  There are a
-number of aspects of UNIX under consideration for
-standardization, from the basic system services at the system
-call and C library level to applications and tools to system
-administration and management.  Each area of standardization is
-assigned to a working group in the 1003 series. 
-
-The POSIX Shell and Utilities standard has been developed by IEEE
-Working Group 1003.2 (POSIX.2).  It concentrates on the command
-interpreter interface and utility programs commonly executed from
-the command line or by other programs.  An initial version of the
-standard has been approved and published by the IEEE, and work is
-currently underway to update it. 
-
-Bash is concerned with the aspects of the shell's behavior
-defined by POSIX.2.  The shell command language has of course
-been standardized, including the basic flow control and program
-execution constructs, I/O redirection and pipelining, argument
-handling, variable expansion, and quoting. 
-
-The `special' builtins, which must be implemented as part of the
-shell to provide the desired functionality, are specified as
-being part of the shell; examples of these are `eval' and
-`export'.  Other utilities appear in the sections of POSIX.2 not
-devoted to the shell which are commonly (and in some cases must
-be) implemented as builtin commands, such as `read' and `test'. 
-POSIX.2 also specifies aspects of the shell's interactive
-behavior as part of the UPE, including job control and command
-line editing.  Only vi-style line editing commands have been
-standardized; emacs editing commands were left out due to
-objections.
-
-The Open Group has made an older version of its Single Unix
-Specification (version 2), which is very similar to POSIX.2,
-available on the web at
-
-http://www.opengroup.org/onlinepubs/007908799/
-
-The Single Unix Specification, version 3, is available on the web at
-
-http://www.opengroup.org/onlinepubs/007904975/
-
-A10)  What is the bash `posix mode'?
-
-Although bash is an implementation of the POSIX.2 shell
-specification, there are areas where the bash default behavior
-differs from that spec.  The bash `posix mode' changes the bash
-behavior in these areas so that it obeys the spec more closely. 
-
-Posix mode is entered by starting bash with the --posix or
-'-o posix' option or executing `set -o posix' after bash is running.
-
-The specific aspects of bash which change when posix mode is
-active are listed in the file POSIX in the bash distribution.
-They are also listed in a section in the Bash Reference Manual
-(from which that file is generated).
-
-Section B:  The latest version
-
-B1) What's new in version 2.05b?
-
-The raison d'etre for bash-2.05b is to make a second intermediate
-release containing the first of the new features to be available
-in bash-3.0 and get feedback on those features before proceeding.
-The major new feature is multibyte character support in both Bash
-and Readline.
-
-Bash-2.05b contains the following new features (see the manual page for
-complete descriptions and the CHANGES and NEWS files in the bash-2.05b
-distribution):
-
-o support for multibyte characters has been added to both bash and readline
-
-o the DEBUG trap is now run *before* simple commands, ((...)) commands,
-  [[...]] conditional commands, and for ((...)) loops
-
-o the shell now performs arithmetic in the largest integer size the machine
-  supports (intmax_t)
-
-o there is a new \D{...} prompt expansion; passes the `...' to strftime(3)
-  and inserts the result into the expanded prompt
-
-o there is a new `here-string' redirection operator:  <<< word
-
-o when displaying variables, function attributes and definitions are shown
-  separately, allowing them to be re-used as input (attempting to re-use
-  the old output would result in syntax errors).
-
-o `read' has a new `-u fd' option to read from a specified file descriptor
-
-o the bash debugger in examples/bashdb has been modified to work with the
-  new DEBUG trap semantics, the command set has been made more gdb-like,
-  and the changes to $LINENO make debugging functions work better
-
-o the expansion of $LINENO inside a shell function is only relative to the
-  function start if the shell is interactive -- if the shell is running a
-  script, $LINENO expands to the line number in the script.  This is as
-  POSIX-2001 requires
-
-
-A short feature history dating from Bash-2.0:
-
-Bash-2.05a introduced the following new features:
-
-o The `printf' builtin has undergone major work
-
-o There is a new read-only `shopt' option: login_shell, which is set by
-  login shells and unset otherwise
-
-o New `\A' prompt string escape sequence; expanding to time in 24-hour
-  HH:MM format
-
-o New `-A group/-g' option to complete and compgen; goes group name
-  completion
-
-o New [+-]O invocation option to set and unset `shopt' options at startup
-
-o ksh-like `ERR' trap
-
-o `for' loops now allow empty word lists after the `in' reserved word
-
-o new `hard' and `soft' arguments for the `ulimit' builtin
-
-o Readline can be configured to place the user at the same point on the line
-  when retrieving commands from the history list
-
-o Readline can be configured to skip `hidden' files (filenames with a leading
-  `.' on Unix) when performing completion
-
-Bash-2.05 introduced the following new features:
-
-o This version has once again reverted to using locales and strcoll(3) when
-  processing pattern matching bracket expressions, as POSIX requires. 
-o Added a new `--init-file' invocation argument as a synonym for `--rcfile',
-  per the new GNU coding standards.
-o The /dev/tcp and /dev/udp redirections now accept service names as well as
-  port numbers.
-o `complete' and `compgen' now take a `-o value' option, which controls some
-   of the aspects of that compspec.  Valid values are:
-
-        default - perform bash default completion if programmable
-                  completion produces no matches
-        dirnames - perform directory name completion if programmable
-                   completion produces no matches
-        filenames - tell readline that the compspec produces filenames,
-                    so it can do things like append slashes to
-                    directory names and suppress trailing spaces
-o A new loadable builtin, realpath, which canonicalizes and expands symlinks
-  in pathname arguments.
-o When `set' is called without options, it prints function defintions in a
-  way that allows them to be reused as input.  This affects `declare' and 
-  `declare -p' as well.  This only happens when the shell is not in POSIX
-   mode, since POSIX.2 forbids this behavior.
-
-Bash-2.04 introduced the following new features:
-
-o Programmable word completion with the new `complete' and `compgen' builtins;
-  examples are provided in examples/complete/complete-examples
-o `history' has a new `-d' option to delete a history entry
-o `bind' has a new `-x' option to bind key sequences to shell commands
-o The prompt expansion code has new `\j' and `\l' escape sequences
-o The `no_empty_cmd_completion' shell option, if enabled, inhibits
-  command completion when TAB is typed on an empty line
-o `help' has a new `-s' option to print a usage synopsis
-o New arithmetic operators: var++, var--, ++var, --var, expr1,expr2 (comma)
-o New ksh93-style arithmetic for command:
-       for ((expr1 ; expr2; expr3 )); do list; done
-o `read' has new options: `-t', `-n', `-d', `-s'
-o The redirection code handles several filenames specially:  /dev/fd/N,
-  /dev/stdin, /dev/stdout, /dev/stderr
-o The redirection code now recognizes /dev/tcp/HOST/PORT and
-  /dev/udp/HOST/PORT and tries to open a TCP or UDP socket, respectively,
-  to the specified port on the specified host
-o The ${!prefix*} expansion has been implemented
-o A new FUNCNAME variable, which expands to the name of a currently-executing
-  function
-o The GROUPS variable is no longer readonly
-o A new shopt `xpg_echo' variable, to control the behavior of echo with
-  respect to backslash-escape sequences at runtime
-o The NON_INTERACTIVE_LOGIN_SHELLS #define has returned
-
-The version of Readline released with Bash-2.04, Readline-4.1, had several
-new features as well:
-
-o Parentheses matching is always compiled into readline, and controllable
-  with the new `blink-matching-paren' variable
-o The history-search-forward and history-search-backward functions now leave
-  point at the end of the line when the search string is empty, like
-  reverse-search-history, and forward-search-history
-o A new function for applications:  rl_on_new_line_with_prompt()
-o New variables for applications:  rl_already_prompted, and rl_gnu_readline_p
-
-
-Bash-2.03 had very few new features, in keeping with the convention
-that odd-numbered releases provide mainly bug fixes.  A number of new
-features were added to Readline, mostly at the request of the Cygnus
-folks.
-
-A new shopt option, `restricted_shell', so that startup files can test
-       whether or not the shell was started in restricted mode
-Filename generation is now performed on the words between ( and ) in
-       compound array assignments (this is really a bug fix)
-OLDPWD is now auto-exported, as POSIX.2 requires
-ENV and BASH_ENV are read-only variables in a restricted shell
-Bash may now be linked against an already-installed Readline library,
-       as long as the Readline library is version 4 or newer
-All shells begun with the `--login' option will source the login shell
-       startup files, even if the shell is not interactive
-
-There were lots of changes to the version of the Readline library released
-along with Bash-2.03.  For a complete list of the changes, read the file
-CHANGES in the Bash-2.03 distribution.
-
-Bash-2.02 contained the following new features:
-
-a new version of malloc (based on the old GNU malloc code in previous
-       bash versions) that is more page-oriented, more conservative
-       with memory usage, does not `orphan' large blocks when they
-       are freed, is usable on 64-bit machines, and has allocation
-       checking turned on unconditionally
-POSIX.2-style globbing character classes ([:alpha:], [:alnum:], etc.)
-POSIX.2-style globbing equivalence classes
-POSIX.2-style globbing collating symbols
-the ksh [[...]] extended conditional command
-the ksh egrep-style extended pattern matching operators
-a new `printf' builtin
-the ksh-like $(<filename) command substitution, which is equivalent to
-       $(cat filename)
-new tilde prefixes that expand to directories from the directory stack
-new `**' arithmetic operator to do exponentiation
-case-insensitive globbing (filename expansion)
-menu completion a la tcsh
-`magic-space' history expansion function like tcsh
-the readline inputrc `language' has a new file inclusion directive ($include)
-
-Bash-2.01 contained only a few new features:
-
-new `GROUPS' builtin array variable containing the user's group list
-new bindable readline commands: history-and-alias-expand-line and
-       alias-expand-line
-
-Bash-2.0 contained extensive changes and new features from bash-1.14.7.
-Here's a short list:
-
-new `time' reserved word to time pipelines, shell builtins, and
-       shell functions
-one-dimensional arrays with a new compound assignment statement,
-        appropriate expansion constructs and modifications to some
-       of the builtins (read, declare, etc.) to use them
-new quoting syntaxes for ANSI-C string expansion and locale-specific
-       string translation
-new expansions to do substring extraction, pattern replacement, and
-       indirect variable expansion
-new builtins: `disown' and `shopt'
-new variables: HISTIGNORE, SHELLOPTS, PIPESTATUS, DIRSTACK, GLOBIGNORE,
-              MACHTYPE, BASH_VERSINFO
-special handling of many unused or redundant variables removed
-       (e.g., $notify, $glob_dot_filenames, $no_exit_on_failed_exec)
-dynamic loading of new builtin commands; many loadable examples provided
-new prompt expansions: \a, \e, \n, \H, \T, \@, \v, \V
-history and aliases available in shell scripts
-new readline variables: enable-keypad, mark-directories, input-meta,
-       visible-stats, disable-completion, comment-begin
-new readline commands to manipulate the mark and operate on the region
-new readline emacs mode commands and bindings for ksh-88 compatibility
-updated and extended builtins
-new DEBUG trap
-expanded (and now documented) restricted shell mode
-
-implementation stuff:  
-autoconf-based configuration
-nearly all of the bugs reported since version 1.14 have been fixed
-most builtins converted to use builtin `getopt' for consistency
-most builtins use -p option to display output in a reusable form
-       (for consistency)
-grammar tighter and smaller (66 reduce-reduce conflicts gone)
-lots of code now smaller and faster
-test suite greatly expanded
-
-B2) Are there any user-visible incompatibilities between bash-2.05b and
-    bash-1.14.7?
-
-There are a few incompatibilities between version 1.14.7 and version 2.05b.
-They are detailed in the file COMPAT in the bash distribution.  That file
-is not meant to be all-encompassing; send mail to bash-maintainers@gnu.org
-if if you find something that's not mentioned there.
-
-Section C:  Differences from other Unix shells
-
-C1) How does bash differ from sh, the Bourne shell?
-
-This is a non-comprehensive list of features that differentiate bash
-from the SVR4.2 shell.  The bash manual page explains these more
-completely.
-
-Things bash has that sh does not:
-       long invocation options
-       [+-]O invocation option
-       -l invocation option
-       `!' reserved word to invert pipeline return value
-       `time' reserved word to time pipelines and shell builtins
-       the `function' reserved word
-       the `select' compound command and reserved word
-       arithmetic for command: for ((expr1 ; expr2; expr3 )); do list; done
-       new $'...' and $"..." quoting
-       the $(...) form of command substitution
-       the $(<filename) form of command substitution, equivalent to
-               $(cat filename)
-       the ${#param} parameter value length operator
-       the ${!param} indirect parameter expansion operator
-       the ${!param*} prefix expansion operator
-       the ${param:offset[:length]} parameter substring operator
-       the ${param/pat[/string]} parameter pattern substitution operator
-       expansions to perform substring removal (${p%[%]w}, ${p#[#]w})
-       expansion of positional parameters beyond $9 with ${num}
-       variables: BASH, BASH_VERSION, BASH_VERSINFO, UID, EUID, REPLY,
-                  TIMEFORMAT, PPID, PWD, OLDPWD, SHLVL, RANDOM, SECONDS,
-                  LINENO, HISTCMD, HOSTTYPE, OSTYPE, MACHTYPE, HOSTNAME,
-                  ENV, PS3, PS4, DIRSTACK, PIPESTATUS, HISTSIZE, HISTFILE,
-                  HISTFILESIZE, HISTCONTROL, HISTIGNORE, GLOBIGNORE, GROUPS,
-                  PROMPT_COMMAND, FCEDIT, FIGNORE, IGNOREEOF, INPUTRC,
-                  SHELLOPTS, OPTERR, HOSTFILE, TMOUT, FUNCNAME, histchars,
-                  auto_resume
-       DEBUG trap
-       ERR trap
-       variable arrays with new compound assignment syntax
-       redirections: <>, &>, >|, <<<, [n]<&word-, [n]>&word-
-       prompt string special char translation and variable expansion
-       auto-export of variables in initial environment
-       command search finds functions before builtins
-       bash return builtin will exit a file sourced with `.'
-       builtins: cd -/-L/-P, exec -l/-c/-a, echo -e/-E, hash -d/-l/-p/-t.
-                 export -n/-f/-p/name=value, pwd -L/-P,
-                 read -e/-p/-a/-t/-n/-d/-s/-u,
-                 readonly -a/-f/name=value, trap -l, set +o,
-                 set -b/-m/-o option/-h/-p/-B/-C/-H/-P,
-                 unset -f/-v, ulimit -m/-p/-u,
-                 type -a/-p/-t/-f/-P, suspend -f, kill -n,
-                 test -o optname/s1 == s2/s1 < s2/s1 > s2/-nt/-ot/-ef/-O/-G/-S
-       bash reads ~/.bashrc for interactive shells, $ENV for non-interactive
-       bash restricted shell mode is more extensive
-       bash allows functions and variables with the same name
-       brace expansion
-       tilde expansion
-       arithmetic expansion with $((...)) and `let' builtin
-       the `[[...]]' extended conditional command
-       process substitution
-       aliases and alias/unalias builtins
-       local variables in functions and `local' builtin
-       readline and command-line editing with programmable completion
-       command history and history/fc builtins
-       csh-like history expansion
-       other new bash builtins: bind, command, compgen, complete, builtin,
-                                declare/typeset, dirs, enable, fc, help,
-                                history, logout, popd, pushd, disown, shopt,
-                                printf
-       exported functions
-       filename generation when using output redirection (command >a*)
-       POSIX.2-style globbing character classes
-       POSIX.2-style globbing equivalence classes
-       POSIX.2-style globbing collating symbols
-       egrep-like extended pattern matching operators
-       case-insensitive pattern matching and globbing
-       variable assignments preceding commands affect only that command,
-               even for builtins and functions
-       posix mode
-       redirection to /dev/fd/N, /dev/stdin, /dev/stdout, /dev/stderr,
-               /dev/tcp/host/port, /dev/udp/host/port
-
-Things sh has that bash does not:
-       uses variable SHACCT to do shell accounting
-       includes `stop' builtin (bash can use alias stop='kill -s STOP')
-       `newgrp' builtin
-       turns on job control if called as `jsh'
-       $TIMEOUT (like bash $TMOUT)
-       `^' is a synonym for `|'
-       new SVR4.2 sh builtins: mldmode, priv
-
-Implementation differences:
-       redirection to/from compound commands causes sh to create a subshell
-       bash does not allow unbalanced quotes; sh silently inserts them at EOF
-       bash does not mess with signal 11
-       sh sets (euid, egid) to (uid, gid) if -p not supplied and uid < 100
-       bash splits only the results of expansions on IFS, using POSIX.2
-               field splitting rules; sh splits all words on IFS
-       sh does not allow MAILCHECK to be unset (?)
-       sh does not allow traps on SIGALRM or SIGCHLD
-       bash allows multiple option arguments when invoked (e.g. -x -v);
-               sh allows only a single option argument (`sh -x -v' attempts
-               to open a file named `-v', and, on SunOS 4.1.4, dumps core.
-               On Solaris 2.4 and earlier versions, sh goes into an infinite
-               loop.)
-       sh exits a script if any builtin fails; bash exits only if one of
-               the POSIX.2 `special' builtins fails
-
-C2)  How does bash differ from the Korn shell, version ksh88?
-
-Things bash has or uses that ksh88 does not:
-       long invocation options
-       [-+]O invocation option
-       -l invocation option
-       `!' reserved word
-       arithmetic for command: for ((expr1 ; expr2; expr3 )); do list; done
-       arithmetic in largest machine-supported size (intmax_t)
-       posix mode and posix conformance
-       command hashing
-       tilde expansion for assignment statements that look like $PATH
-       process substitution with named pipes if /dev/fd is not available
-       the ${!param} indirect parameter expansion operator
-       the ${!param*} prefix expansion operator
-       the ${param:offset[:length]} parameter substring operator
-       the ${param/pat[/string]} parameter pattern substitution operator
-       variables: BASH, BASH_VERSION, BASH_VERSINFO, UID, EUID, SHLVL,
-                  TIMEFORMAT, HISTCMD, HOSTTYPE, OSTYPE, MACHTYPE,
-                  HISTFILESIZE, HISTIGNORE, HISTCONTROL, PROMPT_COMMAND,
-                  IGNOREEOF, FIGNORE, INPUTRC, HOSTFILE, DIRSTACK,
-                  PIPESTATUS, HOSTNAME, OPTERR, SHELLOPTS, GLOBIGNORE,
-                  GROUPS, FUNCNAME, histchars, auto_resume
-       prompt expansion with backslash escapes and command substitution
-       redirection: &> (stdout and stderr), <<<, [n]<&word-, [n]>&word-
-       more extensive and extensible editing and programmable completion
-       builtins: bind, builtin, command, declare, dirs, echo -e/-E, enable,
-                 exec -l/-c/-a, fc -s, export -n/-f/-p, hash, help, history,
-                 jobs -x/-r/-s, kill -s/-n/-l, local, logout, popd, pushd,
-                 read -e/-p/-a/-t/-n/-d/-s, readonly -a/-n/-f/-p,
-                 set -o braceexpand/-o histexpand/-o interactive-comments/
-                 -o notify/-o physical/-o posix/-o hashall/-o onecmd/
-                 -h/-B/-C/-b/-H/-P, set +o, suspend, trap -l, type,
-                 typeset -a/-F/-p, ulimit -u, umask -S, alias -p, shopt,
-                 disown, printf, complete, compgen
-       `!' csh-style history expansion
-       POSIX.2-style globbing character classes
-       POSIX.2-style globbing equivalence classes
-       POSIX.2-style globbing collating symbols
-       egrep-like extended pattern matching operators
-       case-insensitive pattern matching and globbing
-       `**' arithmetic operator to do exponentiation
-       redirection to /dev/fd/N, /dev/stdin, /dev/stdout, /dev/stderr
-       arrays of unlimited size
-       TMOUT is default timeout for `read' and `select'
-
-Things ksh88 has or uses that bash does not:
-       tracked aliases (alias -t)
-       variables: ERRNO, FPATH, EDITOR, VISUAL
-       co-processes (|&, >&p, <&p)
-       weirdly-scoped functions
-       typeset +f to list all function names without definitions
-       text of command history kept in a file, not memory
-       builtins: alias -x, cd old new, fc -e -, newgrp, print,
-                 read -p/-s/var?prompt, set -A/-o gmacs/
-                 -o bgnice/-o markdirs/-o nolog/-o trackall/-o viraw/-s,
-                 typeset -H/-L/-R/-Z/-A/-ft/-fu/-fx/-l/-u/-t, whence
-       using environment to pass attributes of exported variables
-       arithmetic evaluation done on arguments to some builtins
-       reads .profile from $PWD when invoked as login shell
-
-Implementation differences:
-       ksh runs last command of a pipeline in parent shell context
-       bash has brace expansion by default (ksh88 compile-time option)
-       bash has fixed startup file for all interactive shells; ksh reads $ENV
-       bash has exported functions
-       bash command search finds functions before builtins
-       bash waits for all commands in pipeline to exit before returning status
-       emacs-mode editing has some slightly different key bindings
-
-C3)  Which new features in ksh-93 are not in bash, and which are?
-
-New things in ksh-93 not in bash-2.05b:
-       associative arrays
-       floating point arithmetic and variables
-       math library functions
-       ${!name[sub]} name of subscript for associative array
-       `.' is allowed in variable names to create a hierarchical namespace
-       more extensive compound assignment syntax
-       discipline functions
-       `sleep' and `getconf' builtins (bash has loadable versions)
-       typeset -n and `nameref' variables
-       KEYBD trap
-       variables: .sh.edchar, .sh.edmode, .sh.edcol, .sh.edtext, .sh.version,
-                  .sh.name, .sh.subscript, .sh.value, .sh.match, HISTEDIT
-       backreferences in pattern matching (\N)
-       `&' operator in pattern lists for matching
-       print -f (bash uses printf)
-       `fc' has been renamed to `hist'
-       `.' can execute shell functions
-       exit statuses between 0 and 255
-       set -o pipefail
-       `+=' variable assignment operator
-       FPATH and PATH mixing
-       getopts -a
-       -I invocation option
-       DEBUG trap now executed before each simple command, instead of after
-       printf %H, %P, %T, %Z modifiers, output base for %d
-       lexical scoping for local variables in `ksh' functions
-       no scoping for local variables in `POSIX' functions
-
-New things in ksh-93 present in bash-2.05b:
-       [n]<&word- and [n]>&word- redirections (combination dup and close)
-        for (( expr1; expr2; expr3 )) ; do list; done - arithmetic for command
-        ?:, ++, --, `expr1 , expr2' arithmetic operators
-       expansions: ${!param}, ${param:offset[:len]}, ${param/pat[/str]},
-                   ${!param*}
-       compound array assignment
-       the `!' reserved word
-       loadable builtins -- but ksh uses `builtin' while bash uses `enable'
-       `command', `builtin', `disown' builtins
-       new $'...' and $"..." quoting
-       FIGNORE (but bash uses GLOBIGNORE), HISTCMD
-       set -o notify/-C
-       changes to kill builtin
-       read -A (bash uses read -a)
-        read -t/-d
-       trap -p
-       exec -c/-a
-       `.' restores the positional parameters when it completes
-       POSIX.2 `test'
-       umask -S
-       unalias -a
-       command and arithmetic substitution performed on PS1, PS4, and ENV
-       command name completion
-       ENV processed only for interactive shells
-
-Section D:  Why does bash do some things differently than other Unix shells?
-
-D1) Why does bash run a different version of `command' than
-    `which command' says it will?
-
-On many systems, `which' is actually a csh script that assumes
-you're running csh.  In tcsh, `which' and its cousin `where'
-are builtins.  On other Unix systems, `which' is a perl script
-that uses the PATH environment variable.
-
-The csh script version reads the csh startup files from your
-home directory and uses those to determine which `command' will
-be invoked.  Since bash doesn't use any of those startup files,
-there's a good chance that your bash environment differs from
-your csh environment.  The bash `type' builtin does everything
-`which' does, and will report correct results for the running
-shell.  If you're really wedded to the name `which', try adding
-the following function definition to your .bashrc:
-
-       which()
-       {
-               builtin type "$@"
-       }
-
-If you're moving from tcsh and would like to bring `where' along
-as well, use this function:
-
-       where()
-       {
-               builtin type -a "$@"
-       }
-
-D2) Why doesn't bash treat brace expansions exactly like csh?
-
-The only difference between bash and csh brace expansion is that
-bash requires a brace expression to contain at least one unquoted
-comma if it is to be expanded.  Any brace-surrounded word not
-containing an unquoted comma is left unchanged by the brace
-expansion code.  This affords the greatest degree of sh
-compatibility. 
-
-Bash, ksh, zsh, and pd-ksh all implement brace expansion this way. 
-
-D3) Why doesn't bash have csh variable modifiers?
-
-Posix has specified a more powerful, albeit somewhat more cryptic,
-mechanism cribbed from ksh, and bash implements it.
-
-${parameter%word}
-        Remove smallest suffix pattern.  The WORD is expanded to produce
-        a pattern.  It then expands to the value of PARAMETER, with the
-        smallest portion of the suffix matched by the pattern deleted.
-
-        x=file.c
-        echo ${x%.c}.o
-        -->file.o
-
-${parameter%%word}
-
-        Remove largest suffix pattern.  The WORD is expanded to produce
-        a pattern.  It then expands to the value of PARAMETER, with the
-        largest portion of the suffix matched by the pattern deleted.
-
-        x=posix/src/std
-        echo ${x%%/*}
-        -->posix
-
-${parameter#word}
-        Remove smallest prefix pattern.  The WORD is expanded to produce
-        a pattern.  It then expands to the value of PARAMETER, with the
-        smallest portion of the prefix matched by the pattern deleted.
-
-        x=$HOME/src/cmd
-        echo ${x#$HOME}
-        -->/src/cmd
-
-${parameter##word}
-        Remove largest prefix pattern.  The WORD is expanded to produce
-        a pattern.  It then expands to the value of PARAMETER, with the
-        largest portion of the prefix matched by the pattern deleted.
-
-        x=/one/two/three
-        echo ${x##*/}
-        -->three
-
-
-Given
-       a=/a/b/c/d
-       b=b.xxx
-
-       csh                     bash            result
-       ---                     ----            ------
-       $a:h                    ${a%/*}            /a/b/c
-       $a:t                    ${a##*/}           d
-       $b:r                    ${b%.*}            b
-       $b:e                    ${b##*.}           xxx
-
-
-D4) How can I make my csh aliases work when I convert to bash?
-
-Bash uses a different syntax to support aliases than csh does. 
-The details can be found in the documentation.  We have provided
-a shell script which does most of the work of conversion for you;
-this script can be found in ./examples/misc/aliasconv.sh.  Here is
-how you use it:
-  
-Start csh in the normal way for you.  (e.g., `csh')
-  
-Pipe the output of `alias' through `aliasconv.sh', saving the
-results into `bash_aliases':
-  
-       alias | bash aliasconv.sh >bash_aliases
-  
-Edit `bash_aliases', carefully reading through any created
-functions.  You will need to change the names of some csh specific
-variables to the bash equivalents.  The script converts $cwd to
-$PWD, $term to $TERM, $home to $HOME, $user to $USER, and $prompt
-to $PS1.  You may also have to add quotes to avoid unwanted
-expansion.
-
-For example, the csh alias:
-  
-       alias cd 'cd \!*; echo $cwd'
-  
-is converted to the bash function:
-
-       cd () { command cd "$@"; echo $PWD ; }
-
-The only thing that needs to be done is to quote $PWD:
-  
-       cd () { command cd "$@"; echo "$PWD" ; }
-  
-Merge the edited file into your ~/.bashrc.
-
-There is an additional, more ambitious, script in
-examples/misc/cshtobash that attempts to convert your entire csh
-environment to its bash equivalent.  This script can be run as
-simply `cshtobash' to convert your normal interactive
-environment, or as `cshtobash ~/.login' to convert your login
-environment. 
-
-D5) How can I pipe standard output and standard error from one command to
-    another, like csh does with `|&'?
-
-Use
-       command 2>&1 | command2
-
-The key is to remember that piping is performed before redirection, so
-file descriptor 1 points to the pipe when it is duplicated onto file
-descriptor 2.
-
-D6) Now that I've converted from ksh to bash, are there equivalents to
-    ksh features like autoloaded functions and the `whence' command?
-
-There are features in ksh-88 and ksh-93 that do not have direct bash
-equivalents.  Most, however, can be emulated with very little trouble.
-
-ksh-88 feature         Bash equivalent
---------------         ---------------
-compiled-in aliases    set up aliases in .bashrc; some ksh aliases are
-                       bash builtins (hash, history, type)
-coprocesses            named pipe pairs (one for read, one for write)
-typeset +f             declare -F
-cd, print, whence      function substitutes in examples/functions/kshenv
-autoloaded functions   examples/functions/autoload is the same as typeset -fu
-read var?prompt                read -p prompt var
-
-ksh-93 feature         Bash equivalent
---------------         ---------------
-sleep, getconf         Bash has loadable versions in examples/loadables
-${.sh.version}         $BASH_VERSION
-print -f               printf
-hist                   alias hist=fc
-$HISTEDIT              $FCEDIT
-
-Section E:  How can I get bash to do certain things, and why does bash do
-           things the way it does?
-
-E1) Why is the bash builtin `test' slightly different from /bin/test?
-
-The specific example used here is [ ! x -o x ], which is false.
-
-Bash's builtin `test' implements the Posix.2 spec, which can be
-summarized as follows (the wording is due to David Korn):
-   
-Here is the set of rules for processing test arguments.
-  
-    0 Args: False
-    1 Arg:  True iff argument is not null.
-    2 Args: If first arg is !, True iff second argument is null.
-           If first argument is unary, then true if unary test is true
-           Otherwise error.
-    3 Args: If second argument is a binary operator, do binary test of $1 $3
-           If first argument is !, negate two argument test of $2 $3
-           If first argument is `(' and third argument is `)', do the
-           one-argument test of the second argument.
-           Otherwise error.
-    4 Args: If first argument is !, negate three argument test of $2 $3 $4.
-           Otherwise unspecified
-    5 or more Args: unspecified.  (Historical shells would use their
-    current algorithm).
-   
-The operators -a and -o are considered binary operators for the purpose
-of the 3 Arg case.
-   
-As you can see, the test becomes (not (x or x)), which is false.
-
-E2) Why does bash sometimes say `Broken pipe'?
-
-If a sequence of commands appears in a pipeline, and one of the
-reading commands finishes before the writer has finished, the
-writer receives a SIGPIPE signal.  Many other shells special-case
-SIGPIPE as an exit status in the pipeline and do not report it. 
-For example, in:
-  
-      ps -aux | head
-  
-`head' can finish before `ps' writes all of its output, and ps
-will try to write on a pipe without a reader.  In that case, bash
-will print `Broken pipe' to stderr when ps is killed by a
-SIGPIPE. 
-
-You can build a version of bash that will not report SIGPIPE errors
-by uncommenting the definition of DONT_REPORT_SIGPIPE in the file
-config-top.h.
-
-E3) When I have terminal escape sequences in my prompt, why does bash
-    wrap lines at the wrong column?
-
-Readline, the line editing library that bash uses, does not know
-that the terminal escape sequences do not take up space on the
-screen.  The redisplay code assumes, unless told otherwise, that
-each character in the prompt is a `printable' character that
-takes up one character position on the screen. 
-
-You can use the bash prompt expansion facility (see the PROMPTING
-section in the manual page) to tell readline that sequences of
-characters in the prompt strings take up no screen space. 
-
-Use the \[ escape to begin a sequence of non-printing characters,
-and the \] escape to signal the end of such a sequence. 
-
-E4) If I pipe the output of a command into `read variable', why doesn't
-    the output show up in $variable when the read command finishes?
-
-This has to do with the parent-child relationship between Unix
-processes.  It affects all commands run in pipelines, not just
-simple calls to `read'.  For example, piping a command's output
-into a `while' loop that repeatedly calls `read' will result in
-the same behavior.
-
-Each element of a pipeline runs in a separate process, a child of
-the shell running the pipeline.  A subprocess cannot affect its
-parent's environment.  When the `read' command sets the variable
-to the input, that variable is set only in the subshell, not the
-parent shell.  When the subshell exits, the value of the variable
-is lost. 
-
-Many pipelines that end with `read variable' can be converted
-into command substitutions, which will capture the output of
-a specified command.  The output can then be assigned to a
-variable:
-
-       grep ^gnu /usr/lib/news/active | wc -l | read ngroup
-
-can be converted into
-
-       ngroup=$(grep ^gnu /usr/lib/news/active | wc -l)
-
-This does not, unfortunately, work to split the text among
-multiple variables, as read does when given multiple variable
-arguments.  If you need to do this, you can either use the
-command substitution above to read the output into a variable
-and chop up the variable using the bash pattern removal
-expansion operators or use some variant of the following
-approach.
-
-Say /usr/local/bin/ipaddr is the following shell script:
-
-#! /bin/sh
-host `hostname` | awk '/address/ {print $NF}'
-
-Instead of using
-
-       /usr/local/bin/ipaddr | read A B C D
-
-to break the local machine's IP address into separate octets, use
-
-       OIFS="$IFS"
-       IFS=.
-       set -- $(/usr/local/bin/ipaddr)
-       IFS="$OIFS"
-       A="$1" B="$2" C="$3" D="$4"
-
-Beware, however, that this will change the shell's positional
-parameters.  If you need them, you should save them before doing
-this.
-
-This is the general approach -- in most cases you will not need to
-set $IFS to a different value.
-
-Some other user-supplied alternatives include:
-
-read A B C D << HERE
-    $(IFS=.; echo $(/usr/local/bin/ipaddr))
-HERE
-
-and, where process substitution is available,
-
-read A B C D < <(IFS=.; echo $(/usr/local/bin/ipaddr))
-
-E5) I have a bunch of shell scripts that use backslash-escaped characters
-    in arguments to `echo'.  Bash doesn't interpret these characters.  Why
-    not, and how can I make it understand them?
-
-This is the behavior of echo on most Unix System V machines.
-
-The bash builtin `echo' is modeled after the 9th Edition
-Research Unix version of `echo'.  It does not interpret
-backslash-escaped characters in its argument strings by default;
-it requires the use of the -e option to enable the
-interpretation.  The System V echo provides no way to disable the
-special characters; the bash echo has a -E option to disable
-them. 
-
-There is a configuration option that will make bash behave like
-the System V echo and interpret things like `\t' by default.  Run
-configure with the --enable-xpg-echo-default option to turn this
-on.  Be aware that this will cause some of the tests run when you
-type `make tests' to fail.
-
-There is a shell option, `xpg_echo', settable with `shopt', that will
-change the behavior of echo at runtime.  Enabling this option turns
-on expansion of backslash-escape sequences.
-
-E6) Why doesn't a while or for loop get suspended when I type ^Z?
-
-This is a consequence of how job control works on Unix.  The only
-thing that can be suspended is the process group.  This is a single
-command or pipeline of commands that the shell forks and executes.
-
-When you run a while or for loop, the only thing that the shell forks
-and executes are any commands in the while loop test and commands in
-the loop bodies.  These, therefore, are the only things that can be
-suspended when you type ^Z.
-
-If you want to be able to stop the entire loop, you need to put it
-within parentheses, which will force the loop into a subshell that
-may be stopped (and subsequently restarted) as a single unit.
-
-E7) What about empty for loops in Makefiles?
-
-It's fairly common to see constructs like this in automatically-generated
-Makefiles:
-
-SUBDIRS = @SUBDIRS@
-
-       ...
-
-subdirs-clean:
-       for d in ${SUBDIRS}; do \
-               ( cd $$d && ${MAKE} ${MFLAGS} clean ) \
-       done
-
-When SUBDIRS is empty, this results in a command like this being passed to
-bash:
-
-       for d in ; do
-               ( cd $d && ${MAKE} ${MFLAGS} clean )
-       done
-
-In versions of bash before bash-2.05a, this was a syntax error.  If the
-reserved word `in' was present, a word must follow it before the semicolon
-or newline.  The language in the manual page referring to the list of words
-being empty referred to the list after it is expanded.  These versions of
-bash required that there be at least one word following the `in' when the
-construct was parsed.
-
-The idiomatic Makefile solution is something like:
-
-SUBDIRS = @SUBDIRS@
-
-subdirs-clean:
-       subdirs=$SUBDIRS ; for d in $$subdirs; do \
-               ( cd $$d && ${MAKE} ${MFLAGS} clean ) \
-       done
-
-The latest drafts of the updated POSIX standard have changed this:  the
-word list is no longer required.  Bash versions 2.05a and later accept
-the new syntax.
-
-E8) Why does the arithmetic evaluation code complain about `08'?
-
-The bash arithmetic evaluation code (used for `let', $(()), (()), and in
-other places), interprets a leading `0' in numeric constants as denoting
-an octal number, and a leading `0x' as denoting hexadecimal.  This is
-in accordance with the POSIX.2 spec, section 2.9.2.1, which states that
-arithmetic constants should be handled as signed long integers as defined
-by the ANSI/ISO C standard.
-
-The POSIX.2 interpretation committee has confirmed this:
-
-http://www.pasc.org/interps/unofficial/db/p1003.2/pasc-1003.2-173.html
-
-E9) Why does the pattern matching expression [A-Z]* match files beginning
-    with every letter except `z'?
-
-Bash-2.03, Bash-2.05 and later versions honor the current locale setting
-when processing ranges within pattern matching bracket expressions ([A-Z]). 
-This is what POSIX.2 and SUSv3/XPG6 specify. 
-
-The behavior of the matcher in bash-2.05 and later versions depends on the
-current LC_COLLATE setting.  Setting this variable to `C' or `POSIX' will
-result in the traditional behavior ([A-Z] matches all uppercase ASCII
-characters).  Many other locales, including the en_US locale (the default
-on many US versions of Linux) collate the upper and lower case letters like
-this:
-
-       AaBb...Zz
-
-which means that [A-Z] matches every letter except `z'.  Others collate like
-
-       aAbBcC...zZ
-
-which means that [A-Z] matches every letter except `a'.
-
-The portable way to specify upper case letters is [:upper:] instead of
-A-Z; lower case may be specified as [:lower:] instead of a-z.
-
-Look at the manual pages for setlocale(3), strcoll(3), and, if it is
-present, locale(1).  If you have locale(1), you can use it to find
-your current locale information even if you do not have any of the
-LC_ variables set.
-
-My advice is to put
-
-       export LC_COLLATE=C
-
-into /etc/profile and inspect any shell scripts run from cron for
-constructs like [A-Z].  This will prevent things like
-
-       rm [A-Z]*
-
-from removing every file in the current directory except those beginning
-with `z' and still allow individual users to change the collation order.
-Users may put the above command into their own profiles as well, of course.
-
-E10) Why does `cd //' leave $PWD as `//'?
-
-POSIX.2, in its description of `cd', says that *three* or more leading
-slashes may be replaced with a single slash when canonicalizing the
-current working directory.
-
-This is, I presume, for historical compatibility.  Certain versions of
-Unix, and early network file systems, used paths of the form
-//hostname/path to access `path' on server `hostname'.
-
-E11) If I resize my xterm while another program is running, why doesn't bash
-     notice the change?
-
-This is another issue that deals with job control.
-
-The kernel maintains a notion of a current terminal process group.  Members
-of this process group (processes whose process group ID is equal to the
-current terminal process group ID) receive terminal-generated signals like
-SIGWINCH.  (For more details, see the JOB CONTROL section of the bash
-man page.)
-
-If a terminal is resized, the kernel sends SIGWINCH to each member of
-the terminal's current process group (the `foreground' process group).
-
-When bash is running with job control enabled, each pipeline (which may be
-a single command) is run in its own process group, different from bash's
-process group.  This foreground process group receives the SIGWINCH; bash
-does not.  Bash has no way of knowing that the terminal has been resized.
-
-There is a `checkwinsize' option, settable with the `shopt' builtin, that
-will cause bash to check the window size and adjust its idea of the
-terminal's dimensions each time a process stops or exits and returns control
-of the terminal to bash.  Enable it with `shopt -s checkwinsize'.
-
-Section F:  Things to watch out for on certain Unix versions
-
-F1) Why can't I use command line editing in my `cmdtool'?
-
-The problem is `cmdtool' and bash fighting over the input.  When
-scrolling is enabled in a cmdtool window, cmdtool puts the tty in
-`raw mode' to permit command-line editing using the mouse for
-applications that cannot do it themselves.  As a result, bash and
-cmdtool each try to read keyboard input immediately, with neither
-getting enough of it to be useful.
-
-This mode also causes cmdtool to not implement many of the
-terminal functions and control sequences appearing in the
-`sun-cmd' termcap entry.  For a more complete explanation, see
-that file examples/suncmd.termcap in the bash distribution. 
-
-`xterm' is a better choice, and gets along with bash much more
-smoothly.
-
-If you must use cmdtool, you can use the termcap description in
-examples/suncmd.termcap.  Set the TERMCAP variable to the terminal
-description contained in that file, i.e.
-
-TERMCAP='Mu|sun-cmd:am:bs:km:pt:li#34:co#80:cl=^L:ce=\E[K:cd=\E[J:rs=\E[s:'
-
-Then export TERMCAP and start a new cmdtool window from that shell.
-The bash command-line editing should behave better in the new
-cmdtool.  If this works, you can put the assignment to TERMCAP
-in your bashrc file.
-
-F2) I built bash on Solaris 2.  Why do globbing expansions and filename
-    completion chop off the first few characters of each filename?
-
-This is the consequence of building bash on SunOS 5 and linking
-with the libraries in /usr/ucblib, but using the definitions
-and structures from files in /usr/include. 
-
-The actual conflict is between the dirent structure in
-/usr/include/dirent.h and the struct returned by the version of
-`readdir' in libucb.a (a 4.3-BSD style `struct direct'). 
-
-Make sure you've got /usr/ccs/bin ahead of /usr/ucb in your $PATH
-when configuring and building bash.  This will ensure that you
-use /usr/ccs/bin/cc or acc instead of /usr/ucb/cc and that you
-link with libc before libucb. 
-
-If you have installed the Sun C compiler, you may also need to
-put /usr/ccs/bin and /opt/SUNWspro/bin into your $PATH before
-/usr/ucb.
-
-F3) Why does bash dump core after I interrupt username completion or
-    `~user' tilde expansion on a machine running NIS?
-
-This is a famous and long-standing bug in the SunOS YP (sorry, NIS)
-client library, which is part of libc.
-
-The YP library code keeps static state -- a pointer into the data
-returned from the server.  When YP initializes itself (setpwent),
-it looks at this pointer and calls free on it if it's non-null. 
-So far, so good. 
-
-If one of the YP functions is interrupted during getpwent (the
-exact function is interpretwithsave()), and returns NULL, the
-pointer is freed without being reset to NULL, and the function
-returns.  The next time getpwent is called, it sees that this
-pointer is non-null, calls free, and the bash free() blows up
-because it's being asked to free freed memory. 
-
-The traditional Unix mallocs allow memory to be freed multiple
-times; that's probably why this has never been fixed.  You can
-run configure with the `--without-gnu-malloc' option to use
-the C library malloc and avoid the problem.
-
-F4) I'm running SVR4.2.  Why is the line erased every time I type `@'?
-
-The `@' character is the default `line kill' character in most
-versions of System V, including SVR4.2.  You can change this
-character to whatever you want using `stty'.  For example, to
-change the line kill character to control-u, type
-
-       stty kill ^U
-
-where the `^' and `U' can be two separate characters.
-
-F5) Why does bash report syntax errors when my C News scripts use a
-    redirection before a subshell command?
-
-The actual command in question is something like
-
-       < file ( command )
-
-According to the grammar given in the POSIX.2 standard, this construct
-is, in fact, a syntax error.  Redirections may only precede `simple
-commands'.  A subshell construct such as the above is one of the shell's
-`compound commands'.  A redirection may only follow a compound command.
-
-This affects the mechanical transformation of commands that use `cat'
-to pipe a file into a command (a favorite Useless-Use-Of-Cat topic on
-comp.unix.shell).  While most commands of the form
-
-       cat file | command
-
-can be converted to `< file command', shell control structures such as
-loops and subshells require `command < file'.
-
-The file CWRU/sh-redir-hack in the bash-2.05a distribution is an
-(unofficial) patch to parse.y that will modify the grammar to
-support this construct.  It will not apply with `patch'; you must
-modify parse.y by hand.  Note that if you apply this, you must
-recompile with -DREDIRECTION_HACK.  This introduces a large
-number of reduce/reduce conflicts into the shell grammar. 
-
-F6) Why can't I use vi-mode editing on Red Hat Linux 6.1?
-
-The short answer is that Red Hat screwed up.
-
-The long answer is that they shipped an /etc/inputrc that only works
-for emacs mode editing, and then screwed all the vi users by setting
-INPUTRC to /etc/inputrc in /etc/profile.
-
-The short fix is to do one of the following: remove or rename
-/etc/inputrc, set INPUTRC=~/.inputrc in ~/.bashrc (or .bash_profile,
-but make sure you export it if you do), remove the assignment to
-INPUTRC from /etc/profile, add
-
-        set keymap emacs
-
-to the beginning of /etc/inputrc, or bracket the key bindings in
-/etc/inputrc with these lines
-
-       $if mode=emacs
-               [...]
-       $endif
-
-F7) Why do bash-2.05a and bash-2.05b fail to compile `printf.def' on
-    HP/UX 11.x?
-
-HP/UX's support for long double is imperfect at best.
-
-GCC will support it without problems, but the HP C library functions
-like strtold(3) and printf(3) don't actually work with long doubles.
-HP implemented a `long_double' type as a 4-element array of 32-bit
-ints, and that is what the library functions use.  The ANSI C
-`long double' type is a 128-bit floating point scalar.
-
-The easiest fix, until HP fixes things up, is to edit the generated
-config.h and #undef the HAVE_LONG_DOUBLE line.  After doing that,
-the compilation should complete successfully.
-
-Section G:  How can I get bash to do certain common things?
-
-G1) How can I get bash to read and display eight-bit characters?
-
-This is a process requiring several steps.
-
-First, you must ensure that the `physical' data path is a full eight
-bits.  For xterms, for example, the `vt100' resources `eightBitInput'
-and `eightBitOutput' should be set to `true'.
-
-Once you have set up an eight-bit path, you must tell the kernel and
-tty driver to leave the eighth bit of characters alone when processing
-keyboard input.  Use `stty' to do this:
-
-       stty cs8 -istrip -parenb
-
-For old BSD-style systems, you can use
-
-       stty pass8
-
-You may also need
-
-       stty even odd
-
-Finally, you need to tell readline that you will be inputting and
-displaying eight-bit characters.  You use readline variables to do
-this.  These variables can be set in your .inputrc or using the bash
-`bind' builtin.  Here's an example using `bind':
-
-       bash$ bind 'set convert-meta off'
-       bash$ bind 'set meta-flag on'
-       bash$ bind 'set output-meta on'
-
-The `set' commands between the single quotes may also be placed
-in ~/.inputrc.
-
-G2) How do I write a function `x' to replace builtin command `x', but
-    still invoke the command from within the function?
-
-This is why the `command' and `builtin' builtins exist.  The
-`command' builtin executes the command supplied as its first
-argument, skipping over any function defined with that name.  The
-`builtin' builtin executes the builtin command given as its first
-argument directly. 
-
-For example, to write a function to replace `cd' that writes the
-hostname and current directory to an xterm title bar, use
-something like the following:
-
-       cd()
-       {
-               builtin cd "$@" && xtitle "$HOST: $PWD"
-       }
-
-This could also be written using `command' instead of `builtin';
-the version above is marginally more efficient. 
-
-G3) How can I find the value of a shell variable whose name is the value
-    of another shell variable?
-
-Versions of Bash newer than Bash-2.0 support this directly.  You can use 
-
-       ${!var}
-
-For example, the following sequence of commands will echo `z':
-
-       var1=var2
-       var2=z
-       echo ${!var1}
-
-For sh compatibility, use the `eval' builtin.  The important
-thing to remember is that `eval' expands the arguments you give
-it again, so you need to quote the parts of the arguments that
-you want `eval' to act on. 
-
-For example, this expression prints the value of the last positional
-parameter:
-
-       eval echo \"\$\{$#\}\"
-
-The expansion of the quoted portions of this expression will be
-deferred until `eval' runs, while the `$#' will be expanded
-before `eval' is executed.  In versions of bash later than bash-2.0,
-
-       echo ${!#}
-
-does the same thing.
-
-This is not the same thing as ksh93 `nameref' variables, though the syntax
-is similar.  I may add namerefs in a future bash version.
-
-G4) How can I make the bash `time' reserved word print timing output that
-     looks like the output from my system's /usr/bin/time?
-
-The bash command timing code looks for a variable `TIMEFORMAT' and
-uses its value as a format string to decide how to display the
-timing statistics.
-
-The value of TIMEFORMAT is a string with `%' escapes expanded in a
-fashion similar in spirit to printf(3).  The manual page explains
-the meanings of the escape sequences in the format string.
-
-If TIMEFORMAT is not set, bash acts as if the following assignment had
-been performed:
-
-       TIMEFORMAT=$'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS'
-
-The POSIX.2 default time format (used by `time -p command') is
-
-       TIMEFORMAT=$'real %2R\nuser %2U\nsys %2S'
-
-The BSD /usr/bin/time format can be emulated with:
-
-       TIMEFORMAT=$'\t%1R real\t%1U user\t%1S sys'
-
-The System V /usr/bin/time format can be emulated with:
-
-       TIMEFORMAT=$'\nreal\t%1R\nuser\t%1U\nsys\t%1S'
-
-The ksh format can be emulated with:
-
-       TIMEFORMAT=$'\nreal\t%2lR\nuser\t%2lU\nsys\t%2lS'
-
-G5) How do I get the current directory into my prompt?
-
-Bash provides a number of backslash-escape sequences which are expanded
-when the prompt string (PS1 or PS2) is displayed.  The full list is in
-the manual page.
-
-The \w expansion gives the full pathname of the current directory, with
-a tilde (`~') substituted for the current value of $HOME.  The \W
-expansion gives the basename of the current directory.  To put the full
-pathname of the current directory into the path without any tilde
-subsitution, use $PWD.  Here are some examples:
-
-       PS1='\w$ '      # current directory with tilde
-       PS1='\W$ '      # basename of current directory
-       PS1='$PWD$ '    # full pathname of current directory
-
-The single quotes are important in the final example to prevent $PWD from
-being expanded when the assignment to PS1 is performed.
-
-G6) How can I rename "*.foo" to "*.bar"?
-
-Use the pattern removal functionality described in D3.  The following `for'
-loop will do the trick:
-
-       for f in *.foo; do
-               mv $f ${f%foo}bar
-       done
-
-G7) How can I translate a filename from uppercase to lowercase?
-
-The script examples/functions/lowercase, originally written by John DuBois,
-will do the trick.  The converse is left as an exercise.
-
-G8) How can I write a filename expansion (globbing) pattern that will match
-    all files in the current directory except "." and ".."?
-
-You must have set the `extglob' shell option using `shopt -s extglob' to use
-this:
-
-       echo .!(.|) *
-
-A solution that works without extended globbing is given in the Unix Shell
-FAQ, posted periodically to comp.unix.shell.
-
-Section H:  Where do I go from here?
-
-H1) How do I report bugs in bash, and where should I look for fixes and
-    advice?
-
-Use the `bashbug' script to report bugs.  It is built and
-installed at the same time as bash.  It provides a standard
-template for reporting a problem and automatically includes
-information about your configuration and build environment. 
-
-`bashbug' sends its reports to bug-bash@gnu.org, which
-is a large mailing list gatewayed to the usenet newsgroup gnu.bash.bug. 
-
-Bug fixes, answers to questions, and announcements of new releases
-are all posted to gnu.bash.bug.  Discussions concerning bash features
-and problems also take place there.
-
-To reach the bash maintainers directly, send mail to
-bash-maintainers@gnu.org.
-
-H2) What kind of bash documentation is there?
-
-First, look in the doc directory in the bash distribution.  It should
-contain at least the following files:
-
-bash.1         an extensive, thorough Unix-style manual page
-builtins.1     a manual page covering just bash builtin commands
-bashref.texi   a reference manual in GNU tex`info format
-bashref.info   an info version of the reference manual
-FAQ            this file
-article.ms     text of an article written for The Linux Journal
-readline.3     a man page describing readline
-
-Postscript, HTML, and ASCII files created from the above source are
-available in the documentation distribution.
-
-There is additional documentation available for anonymous FTP from host
-ftp.cwru.edu in the `pub/bash' directory.
-
-Cameron Newham and Bill Rosenblatt have written a book on bash, published
-by O'Reilly and Associates.  The book is based on Bill Rosenblatt's Korn
-Shell book.  The title is ``Learning the Bash Shell'', and the ISBN number
-is 1-56592-147-X.  Look for it in fine bookstores near you.  This book
-covers bash-1.14, but has an appendix describing some of the new features
-in bash-2.0.  
-
-A second edition of this book is available, published in January, 1998.
-The ISBN number is 1-56592-347-2.  Look for it in the same fine bookstores
-or on the web.
-
-The GNU Bash Reference Manual has been published as a printed book by
-Network Theory Ltd (Paperback, ISBN: 0-9541617-7-7, Feb 2003).  It covers
-bash-2.0 and is available from most online bookstores (see
-http://www.network-theory.co.uk/bash/manual/ for details).  The publisher
-will donate $1 to the Free Software Foundation for each copy sold. 
-
-H3) What's coming in future versions?
-
-These are features I hope to include in a future version of bash.
-
-a better bash debugger (a minimally-tested version is included with bash-2.05b)
-associative arrays
-co-processes, but with a new-style syntax that looks like function declaration
-
-H4) What's on the bash `wish list' for future versions?
-
-These are features that may or may not appear in a future version of bash.
-
-breaking some of the shell functionality into embeddable libraries
-a module system like zsh's, using dynamic loading like builtins
-better internationalization using GNU `gettext'
-date-stamped command history
-a bash programmer's guide with a chapter on creating loadable builtins
-a better loadable interface to perl with access to the shell builtins and
-       variables (contributions gratefully accepted)
-ksh93-like `nameref' variables
-ksh93-like `+=' variable assignment operator
-ksh93-like `xx.yy' variables (including some of the .sh.* variables) and
-       associated disipline functions
-Some of the new ksh93 pattern matching operators, like backreferencing
-
-H5) When will the next release appear?
-
-The next version will appear sometime in 2002.  Never make predictions. 
-
-
-This document is Copyright 1995-2003 by Chester Ramey.
-
-Permission is hereby granted, without written agreement and
-without license or royalty fees, to use, copy, and distribute
-this document for any purpose, provided that the above copyright
-notice appears in all copies of this document and that the
-contents of this document remain unaltered.
diff --git a/eval.c~ b/eval.c~
deleted file mode 100644 (file)
index 2f96a06..0000000
--- a/eval.c~
+++ /dev/null
@@ -1,292 +0,0 @@
-/* eval.c -- reading and evaluating commands. */
-
-/* Copyright (C) 1996-2011 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 (HAVE_UNISTD_H)
-#  ifdef _MINIX
-#    include <sys/types.h>
-#  endif
-#  include <unistd.h>
-#endif
-
-#include "bashansi.h"
-#include <stdio.h>
-
-#include "bashintl.h"
-
-
-#include "shell.h"
-#include "flags.h"
-#include "trap.h"
-
-#include "builtins/common.h"
-
-#include "input.h"
-#include "execute_cmd.h"
-
-#if defined (HISTORY)
-#  include "bashhist.h"
-#endif
-
-extern int EOF_reached;
-extern int indirection_level;
-extern int posixly_correct;
-extern int subshell_environment, running_under_emacs;
-extern int last_command_exit_value, stdin_redir;
-extern int need_here_doc;
-extern int current_command_number, current_command_line_count, line_number;
-extern int expand_aliases;
-
-#if defined (HAVE_POSIX_SIGNALS)
-extern sigset_t top_level_mask;
-#endif
-
-static void send_pwd_to_eterm __P((void));
-static sighandler alrm_catcher __P((int));
-
-/* Read and execute commands until EOF is reached.  This assumes that
-   the input source has already been initialized. */
-int
-reader_loop ()
-{
-  int our_indirection_level;
-  COMMAND * volatile current_command;
-
-  USE_VAR(current_command);
-
-  current_command = (COMMAND *)NULL;
-
-  our_indirection_level = ++indirection_level;
-
-  while (EOF_Reached == 0)
-    {
-      int code;
-
-      code = setjmp_nosigs (top_level);
-
-#if defined (PROCESS_SUBSTITUTION)
-      unlink_fifo_list ();
-#endif /* PROCESS_SUBSTITUTION */
-
-      /* XXX - why do we set this every time through the loop? */
-      if (interactive_shell && signal_is_ignored (SIGINT) == 0)
-       set_signal_handler (SIGINT, sigint_sighandler);
-
-      if (code != NOT_JUMPED)
-       {
-         indirection_level = our_indirection_level;
-
-         switch (code)
-           {
-             /* Some kind of throw to top_level has occured. */
-           case FORCE_EOF:
-           case ERREXIT:
-           case EXITPROG:
-             current_command = (COMMAND *)NULL;
-             if (exit_immediately_on_error)
-               variable_context = 0;   /* not in a function */
-             EOF_Reached = EOF;
-             goto exec_done;
-
-           case DISCARD:
-             /* Make sure the exit status is reset to a non-zero value, but
-                leave existing non-zero values (e.g., > 128 on signal)
-                alone. */
-             if (last_command_exit_value == 0)
-               last_command_exit_value = EXECUTION_FAILURE;
-             if (subshell_environment)
-               {
-                 current_command = (COMMAND *)NULL;
-                 EOF_Reached = EOF;
-                 goto exec_done;
-               }
-             /* Obstack free command elements, etc. */
-             if (current_command)
-               {
-                 dispose_command (current_command);
-                 current_command = (COMMAND *)NULL;
-               }
-#if defined (HAVE_POSIX_SIGNALS)
-             sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
-#endif
-             break;
-
-           default:
-             command_error ("reader_loop", CMDERR_BADJUMP, code, 0);
-           }
-       }
-
-      executing = 0;
-      if (temporary_env)
-       dispose_used_env_vars ();
-
-#if (defined (ultrix) && defined (mips)) || defined (C_ALLOCA)
-      /* Attempt to reclaim memory allocated with alloca (). */
-      (void) alloca (0);
-#endif
-
-      if (read_command () == 0)
-       {
-         if (interactive_shell == 0 && read_but_dont_execute)
-           {
-             last_command_exit_value = EXECUTION_SUCCESS;
-             dispose_command (global_command);
-             global_command = (COMMAND *)NULL;
-           }
-         else if (current_command = global_command)
-           {
-             global_command = (COMMAND *)NULL;
-             current_command_number++;
-
-             executing = 1;
-             stdin_redir = 0;
-             execute_command (current_command);
-
-           exec_done:
-             QUIT;
-
-             if (current_command)
-               {
-                 dispose_command (current_command);
-                 current_command = (COMMAND *)NULL;
-               }
-           }
-       }
-      else
-       {
-         /* Parse error, maybe discard rest of stream if not interactive. */
-         if (interactive == 0)
-           EOF_Reached = EOF;
-       }
-      if (just_one_command)
-       EOF_Reached = EOF;
-    }
-  indirection_level--;
-  return (last_command_exit_value);
-}
-
-static sighandler
-alrm_catcher(i)
-     int i;
-{
-  printf (_("\007timed out waiting for input: auto-logout\n"));
-  fflush (stdout);
-  bash_logout ();      /* run ~/.bash_logout if this is a login shell */
-  jump_to_top_level (EXITPROG);
-  SIGRETURN (0);
-}
-
-/* Send an escape sequence to emacs term mode to tell it the
-   current working directory. */
-static void
-send_pwd_to_eterm ()
-{
-  char *pwd, *f;
-
-  f = 0;
-  pwd = get_string_value ("PWD");
-  if (pwd == 0)
-    f = pwd = get_working_directory ("eterm");
-  fprintf (stderr, "\032/%s\n", pwd);
-  free (f);
-}
-
-/* Call the YACC-generated parser and return the status of the parse.
-   Input is read from the current input stream (bash_input).  yyparse
-   leaves the parsed command in the global variable GLOBAL_COMMAND.
-   This is where PROMPT_COMMAND is executed. */
-int
-parse_command ()
-{
-  int r;
-  char *command_to_execute;
-
-  need_here_doc = 0;
-  run_pending_traps ();
-
-  /* Allow the execution of a random command just before the printing
-     of each primary prompt.  If the shell variable PROMPT_COMMAND
-     is set then the value of it is the command to execute. */
-  if (interactive && bash_input.type != st_string)
-    {
-      command_to_execute = get_string_value ("PROMPT_COMMAND");
-      if (command_to_execute)
-       execute_variable_command (command_to_execute, "PROMPT_COMMAND");
-
-      if (running_under_emacs == 2)
-       send_pwd_to_eterm ();   /* Yuck */
-    }
-
-  current_command_line_count = 0;
-  r = yyparse ();
-
-  if (need_here_doc)
-    gather_here_documents ();
-
-  return (r);
-}
-
-/* Read and parse a command, returning the status of the parse.  The command
-   is left in the globval variable GLOBAL_COMMAND for use by reader_loop.
-   This is where the shell timeout code is executed. */
-int
-read_command ()
-{
-  SHELL_VAR *tmout_var;
-  int tmout_len, result;
-  SigHandler *old_alrm;
-
-  set_current_prompt_level (1);
-  global_command = (COMMAND *)NULL;
-
-  /* Only do timeouts if interactive. */
-  tmout_var = (SHELL_VAR *)NULL;
-  tmout_len = 0;
-  old_alrm = (SigHandler *)NULL;
-
-  if (interactive)
-    {
-      tmout_var = find_variable ("TMOUT");
-
-      if (tmout_var && var_isset (tmout_var))
-       {
-         tmout_len = atoi (value_cell (tmout_var));
-         if (tmout_len > 0)
-           {
-             old_alrm = set_signal_handler (SIGALRM, alrm_catcher);
-             alarm (tmout_len);
-           }
-       }
-    }
-
-  QUIT;
-
-  current_command_line_count = 0;
-  result = parse_command ();
-
-  if (interactive && tmout_var && (tmout_len > 0))
-    {
-      alarm(0);
-      set_signal_handler (SIGALRM, old_alrm);
-    }
-
-  return (result);
-}
diff --git a/examples/loadables/Makefile.in.save b/examples/loadables/Makefile.in.save
deleted file mode 100644 (file)
index f6208f5..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-#
-# Simple makefile for the sample loadable builtins
-#
-# Copyright (C) 1996 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 2, 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
-
-# Include some boilerplate Gnu makefile definitions.
-prefix = @prefix@
-
-exec_prefix = @exec_prefix@
-bindir = @bindir@
-libdir = @libdir@
-infodir = @infodir@
-includedir = @includedir@
-
-topdir = @top_srcdir@
-BUILD_DIR = @BUILD_DIR@
-srcdir = @srcdir@
-VPATH = .:@srcdir@
-
-@SET_MAKE@
-CC = @CC@
-RM = rm -f
-
-SHELL = @MAKE_SHELL@
-
-host_os = @host_os@
-host_cpu = @host_cpu@
-host_vendor = @host_vendor@
-
-CFLAGS = @CFLAGS@
-LOCAL_CFLAGS = @LOCAL_CFLAGS@
-DEFS = @DEFS@
-LOCAL_DEFS = @LOCAL_DEFS@
-
-CPPFLAGS = @CPPFLAGS@
-
-BASHINCDIR = ${topdir}/include
-
-LIBBUILD = ${BUILD_DIR}/lib
-
-INTL_LIBSRC = ${topdir}/lib/intl
-INTL_BUILDDIR = ${LIBBUILD}/intl
-INTL_INC = @INTL_INC@
-LIBINTL_H = @LIBINTL_H@
-
-CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) $(CFLAGS)
-
-#
-# These values are generated for configure by ${topdir}/support/shobj-conf.
-# If your system is not supported by that script, but includes facilities for
-# dynamic loading of shared objects, please update the script and send the
-# changes to bash-maintainers@gnu.org.
-#
-SHOBJ_CC = @SHOBJ_CC@
-SHOBJ_CFLAGS = @SHOBJ_CFLAGS@
-SHOBJ_LD = @SHOBJ_LD@
-SHOBJ_LDFLAGS = @SHOBJ_LDFLAGS@
-SHOBJ_XLDFLAGS = @SHOBJ_XLDFLAGS@
-SHOBJ_LIBS = @SHOBJ_LIBS@
-SHOBJ_STATUS = @SHOBJ_STATUS@
-
-INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins \
-      -I$(BASHINCDIR) -I$(BUILD_DIR) -I$(LIBBUILD) \
-      -I$(BUILD_DIR)/builtins $(INTL_INC)
-
-.c.o:
-       $(SHOBJ_CC) $(SHOBJ_CFLAGS) $(CCFLAGS) $(INC) -c -o $@ $<
-
-
-ALLPROG = print truefalse sleep pushd finfo logname basename dirname \
-         tty pathchk tee head mkdir rmdir printenv id whoami \
-         uname sync push ln unlink cut realpath getconf strftime
-OTHERPROG = necho hello cat
-
-all:   $(SHOBJ_STATUS)
-
-supported:     $(ALLPROG)
-others:                $(OTHERPROG)
-
-unsupported:
-       @echo "Your system (${host_os}) is not supported by the"
-       @echo "${topdir}/support/shobj-conf script."
-       @echo "If your operating system provides facilities for dynamic"
-       @echo "loading of shared objects using the dlopen(3) interface,"
-       @echo "please update the script and re-run configure.
-       @echo "Please send the changes you made to bash-maintainers@gnu.org"
-       @echo "for inclusion in future bash releases."
-
-everything: supported others
-
-print: print.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ print.o $(SHOBJ_LIBS)
-
-necho: necho.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ necho.o $(SHOBJ_LIBS)
-
-getconf: getconf.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ getconf.o $(SHOBJ_LIBS)
-
-hello: hello.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ hello.o $(SHOBJ_LIBS)
-
-truefalse: truefalse.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ truefalse.o $(SHOBJ_LIBS)
-
-sleep: sleep.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sleep.o $(SHOBJ_LIBS)
-
-finfo: finfo.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ finfo.o $(SHOBJ_LIBS)
-
-cat:   cat.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cat.o $(SHOBJ_LIBS)
-
-logname:       logname.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ logname.o $(SHOBJ_LIBS)
-
-basename:      basename.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ basename.o $(SHOBJ_LIBS)
-
-dirname:       dirname.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ dirname.o $(SHOBJ_LIBS)
-
-tty:   tty.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tty.o $(SHOBJ_LIBS)
-
-pathchk:       pathchk.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pathchk.o $(SHOBJ_LIBS)
-
-tee:   tee.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tee.o $(SHOBJ_LIBS)
-
-mkdir: mkdir.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ mkdir.o $(SHOBJ_LIBS)
-
-rmdir: rmdir.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ rmdir.o $(SHOBJ_LIBS)
-
-head:  head.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ head.o $(SHOBJ_LIBS)
-
-printenv:      printenv.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ printenv.o $(SHOBJ_LIBS)
-
-id:    id.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ id.o $(SHOBJ_LIBS)
-
-whoami:        whoami.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ whoami.o $(SHOBJ_LIBS)
-
-uname: uname.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ uname.o $(SHOBJ_LIBS)
-
-sync:  sync.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sync.o $(SHOBJ_LIBS)
-
-push:  push.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ push.o $(SHOBJ_LIBS)
-
-ln:    ln.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ ln.o $(SHOBJ_LIBS)
-
-unlink:        unlink.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ unlink.o $(SHOBJ_LIBS)
-
-cut:   cut.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cut.o $(SHOBJ_LIBS)
-
-realpath:      realpath.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ realpath.o $(SHOBJ_LIBS)
-
-strftime:      strftime.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ strftime.o $(SHOBJ_LIBS)
-
-# pushd is a special case.  We use the same source that the builtin version
-# uses, with special compilation options.
-#
-pushd.c:       ${topdir}/builtins/pushd.def
-       $(RM) $@
-       ${BUILD_DIR}/builtins/mkbuiltins -D ${topdir}/builtins ${topdir}/builtins/pushd.def
-
-pushd.o:       pushd.c
-       $(RM) $@
-       $(SHOBJ_CC) -DHAVE_CONFIG_H -DPUSHD_AND_POPD -DLOADABLE_BUILTIN $(SHOBJ_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(INC) -c -o $@ $<
-
-pushd: pushd.o
-       $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pushd.o $(SHOBJ_LIBS)
-
-clean:
-       $(RM) $(ALLPROG) $(OTHERPROG) *.o
-       -( cd perl && ${MAKE} ${MFLAGS} $@ )
-
-mostlyclean:   clean
-       -( cd perl && ${MAKE} ${MFLAGS} $@ )
-
-distclean maintainer-clean: clean
-       $(RM) Makefile pushd.c
-       -( cd perl && ${MAKE} ${MFLAGS} $@ )
-
-print.o: print.c
-truefalse.o: truefalse.c
-sleep.o: sleep.c
-finfo.o: finfo.c
-logname.o: logname.c
-basename.o: basename.c
-dirname.o: dirname.c
-tty.o: tty.c
-pathchk.o: pathchk.c
-tee.o: tee.c
-head.o: head.c
-rmdir.o: rmdir.c
-necho.o: necho.c
-getconf.o: getconf.c
-hello.o: hello.c
-cat.o: cat.c
-printenv.o: printenv.c
-id.o: id.c
-whoami.o: whoami.c
-uname.o: uname.c
-sync.o: sync.c
-push.o: push.c
-mkdir.o: mkdir.c
-realpath.o: realpath.c
-strftime.o: strftime.c
diff --git a/examples/scripts/adventure.sh.save1 b/examples/scripts/adventure.sh.save1
deleted file mode 100755 (executable)
index 4e22393..0000000
+++ /dev/null
@@ -1,549 +0,0 @@
-#!/bin/bash
-#      ash -- "Adventure shell"
-#      last edit:      86/04/21        D A Gwyn
-#      SCCS ID:        @(#)ash.sh      1.4
-
-OPATH=$PATH
-
-ask()
-{
-       echo -n "$@" '[y/n] '
-       read ans
-
-       case "$ans" in
-       y*|Y*)
-               return 0
-               ;;
-       *)
-               return 1
-               ;;
-       esac
-}
-       
-CAT=${PAGER:-more}
-
-ash_inst()
-{
-       cat <<- EOF
-
-                       Instructions for the Adventure shell
-
-       Welcome to the Adventure shell!  In this exploration of the UNIX file
-       system, I will act as your eyes and hands.  As you move around, I will
-       describe whatever is visible and will carry out your commands.  The
-       general form of a command is
-               Verb Object Extra_stuff.
-       Most commands pay no attention to the "Extra_stuff", and many do not
-       need an "Object".  A typical command is
-               get all
-       which picks up all files in the current "room" (directory).  You can
-       find out what you are carrying by typing the command
-               inventory
-       The command "help" results in a full description of all commands that I
-       understand.  To quit the Adventure shell, type
-               quit
-
-       There are UNIX monsters lurking in the background.  These are also
-       known as "commands with arguments".
-
-       Good luck!
-       EOF
-}
-
-ash_help()
-{
-echo "I understand the following commands (synonyms in parentheses):"
-echo ""
-
-echo "change OBJECT to NEW_NAME       changes the name of the object"
-echo "clone OBJECT as NEW_NAME        duplicates the object"
-echo "drop OBJECTS                    leaves the objects in the room"
-echo "enter (go) PASSAGE              takes the labeled passage"
-echo "examine OBJECTS                 describes the objects in detail"
-echo "feed OBJECT to MONSTER          stuffs the object into a UNIX monster"
-echo "get (take) OBJECTS              picks up the specified objects"
-echo "gripe (bug)                     report a problem with the Adventure shell"
-echo "help                            prints this summary"
-echo "inventory (i)                   tells what you are carrying"
-echo "kill (destroy) OBJECTS          destroys the objects"
-echo "look (l)                        describes the room, including hidden objects"
-echo "open (read) OBJECT              shows the contents of an object"
-echo "quit (exit)                     leaves the Adventure shell"
-echo "resurrect OBJECTS               attempts to restore dead objects"
-echo "steal OBJECT from MONSTER       obtains the object from a UNIX monster"
-echo "throw OBJECT at daemon          feeds the object to the printer daemon"
-echo "up                              takes the overhead passage"
-echo "wake MONSTER                    awakens a UNIX monster"
-echo "where (w)                       tells you where you are"
-echo "xyzzy                           moves you to your home"
-}
-       
-MAINT=chet@ins.cwru.edu
-
-PATH=/usr/ucb:/bin:/usr/bin:/usr/local/bin:.
-export PATH
-
-trap 'echo Ouch!' 2 3
-#trap '' 18                    # disable Berkeley job control
-
-ash_lk(){ echo " $1 " | fgrep " $2 " >&- 2>&-; }
-ash_pr(){ echo $* | tr ' ' '\012' | pr -5 -t -w75 -l$[ ( $# + 4 ) / 5 ]; }
-ash_rm(){ echo " $1 " | sed -e "s/ $2 / /" -e 's/^ //' -e 's/ $//'; }
-
-# enable history, bang history expansion, and emacs editing
-set -o history
-set -o histexpand
-set -o emacs
-
-cd
-LIM=.limbo                     # $HOME/$LIM contains "destroyed" objects
-mkdir $LIM >&- 2>&-
-KNAP=.knapsack                 # $HOME/$KNAP contains objects being "carried"
-if [ ! -d $KNAP ]
-then   mkdir $KNAP >&- 2>&-
-       if [ $? = 0 ]
-       then    echo 'You found a discarded empty knapsack.'
-       else    echo 'You have no knapsack to carry things in.'
-               exit 1
-       fi
-else   echo 'One moment while I peek in your old knapsack...'
-fi
-
-kn=`echo \`ls -a $KNAP | sed -e '/^\.$/d' -e '/^\.\.$/d'\``
-
-if ask 'Welcome to the Adventure shell!  Do you need instructions?'
-then
-       ash_inst
-       echo -n 'Type a newline to continue: '
-       read
-fi
-
-wiz=false
-cha=false
-prev=$LIM
-while :
-do     room=`pwd`
-       if [ $room != $prev ]
-       then    if [ $room = $HOME ]
-               then    echo 'You are in your own home.'
-               else    echo "You have entered $room."
-               fi
-               exs=
-               obs=
-               hexs=
-               hobs=
-               f=false
-               for i in `ls -a`
-               do      case $i in
-                       .|..)   ;;
-                       .*)     if [ -f $i ]
-                               then    hobs="$hobs $i"
-                               elif [ -d $i ]
-                               then    hexs="$hexs $i"
-                               else    f=true
-                               fi
-                               ;;
-                       *)      if [ -f $i ]
-                               then    obs="$obs $i"
-                               elif [ -d $i ]
-                               then    exs="$exs $i"
-                               else    f=true
-                               fi
-                               ;;
-                       esac
-               done
-               if [ "$obs" ]
-               then    echo 'This room contains:'
-                       ash_pr $obs
-               else    echo 'The room looks empty.'
-               fi
-               if [ "$exs" ]
-               then    echo 'There are exits labeled:'
-                       ash_pr $exs
-                       echo 'as well as a passage overhead.'
-               else    echo 'There is a passage overhead.'
-               fi
-               if sh -c $f
-               then    echo 'There are shadowy figures in the corner.'
-               fi
-               prev=$room
-       fi
-
-       read -e -p '-advsh> ' verb obj x        # prompt is '-advsh> '
-       if [ $? != 0 ]
-       then    verb=quit               # EOF
-       fi
-
-       case $verb in
-       change)         if [ "$obj" ]
-                       then    if ash_lk "$obs $hobs" "$obj"
-                               then    set -- $x
-                                       case "$1" in
-                                       to)     if [ "$2" ]
-                                               then    if [ -f $2 ]
-                                                       then    echo "You must destroy $2 first."
-                                                               set --
-                                                       fi
-                                                       if [ "$2" ]
-                                                       then    if mv $obj $2 >&- 2>&-
-                                                               then    echo "The $obj shimmers and turns into $2."
-                                                                       obs=`ash_rm "$2 $obs" "$obj"`
-                                                               else    echo "There is a cloud of smoke but the $obj is unchanged."
-                                                               fi
-                                                       fi
-                                               else    echo 'To what?'
-                                               fi
-                                               ;;
-                                       *)      echo "Change $obj to what?"
-                                               ;;
-                                       esac
-                               else    if ash_lk "$kn" "$obj"
-                                       then    echo 'You must drop it first.'
-                                       else    echo "I see no $obj here."
-                                       fi
-                               fi
-                       else    echo 'Change what?'
-                       fi
-                       ;;
-       clone)          if [ "$obj" ]
-                       then    if ash_lk "$obs $hobs" "$obj"
-                               then    if [ ! -r $obj ]
-                                       then    echo "The $obj does not wish to be cloned."
-                                       else    set -- $x
-                                               case "$1" in
-                                               as)     if [ "$2" ]
-                                                       then    if [ -f $2 ]
-                                                               then    echo "You must destroy $2 first."
-                                                               else    if cp $obj $2 >&- 2>&-
-                                                                       then    echo "Poof!  When the smoke clears, you see the new $2."
-                                                                               obs="$obs $2"
-                                                                       else    echo 'You hear a dull thud but no clone appears.'
-                                                                       fi
-                                                               fi
-                                                       else    echo 'As what?'
-                                                       fi
-                                                       ;;
-                                               *)      echo "Clone $obj as what?"
-                                                       ;;
-                                               esac
-                                       fi
-                               else    if ash_lk "$kn" "$obj"
-                                       then    echo 'You must drop it first.'
-                                       else    echo "I see no $obj here."
-                                       fi
-                               fi
-                       else    echo 'Clone what?'
-                       fi
-                       ;;
-       drop)           if [ "$obj" ]
-                       then    for it in $obj $x
-                               do      if ash_lk "$kn" "$it"
-                                       then    if [ -w $it ]
-                                               then    echo "You must destroy $it first."
-                                               else    if mv $HOME/$KNAP/$it $it >&- 2>&-
-                                                       then    echo "$it: dropped."
-                                                               kn=`ash_rm "$kn" "$it"`
-                                                               obs=`echo $it $obs`
-                                                       else    echo "The $it is caught in your knapsack."
-                                                       fi
-                                               fi
-                                       else    echo "You're not carrying the $it!"
-                                       fi
-                               done
-                       else    echo 'Drop what?'
-                       fi
-                       ;;
-       enter|go)       if [ "$obj" ]
-                       then    if [ $obj != up ]
-                               then    if ash_lk "$exs $hexs" "$obj"
-                                       then    if [ -x $obj ]
-                                               then    if cd $obj
-                                                       then    echo 'You squeeze through the passage.'
-                                                       else    echo "You can't go that direction."
-                                                       fi
-                                               else    echo 'An invisible force blocks your way.'
-                                               fi
-                                       else    echo 'I see no such passage.'
-                                       fi
-                               else    if cd ..
-                                       then    echo 'You struggle upwards.'
-                                       else    echo "You can't reach that high."
-                                       fi
-                               fi
-                       else    echo 'Which passage?'
-                       fi
-                       ;;
-       examine)        if [ "$obj" ]
-                       then    if [ $obj = all ]
-                               then    $obj=`echo $obs $exs`
-                                       x=
-                               fi
-                               for it in $obj $x
-                               do      if ash_lk "$obs $hobs $exs $hexs" "$it"
-                                       then    echo "Upon close inspection of the $it, you see:"
-                                               ls -ld $it 2>&-
-                                               if [ $? != 0 ]
-                                               then    echo "-- when you look directly at the $it, it vanishes."
-                                               fi
-                                       else    if ash_lk "$kn" "$it"
-                                               then    echo 'You must drop it first.'
-                                               else    echo "I see no $it here."
-                                               fi
-                                       fi
-                               done
-                       else    echo 'Examine what?'
-                       fi
-                       ;;
-       feed)           if [ "$obj" ]
-                       then    if ash_lk "$obs $hobs" "$obj"
-                               then    set -- $x
-                                       case "$1" in
-                                       to)     if [ "$2" ]
-                                               then    shift
-                                                       if PATH=$OPATH $* <$obj 2>&-
-                                                       then    echo "The $1 monster devours your $obj."
-                                                               if rm -f $obj >&- 2>&-
-                                                               then    obs=`ash_rm "$obs" "$obj"`
-                                                               else    echo 'But he spits it back up.'
-                                                               fi
-                                                       else    echo "The $1 monster holds his nose in disdain."
-                                                       fi
-                                               else    echo 'To what?'
-                                               fi
-                                               ;;
-                                       *)      echo "Feed $obj to what?"
-                                               ;;
-                                       esac
-                               else    if ash_lk "$kn" "$obj"
-                                       then    echo 'You must drop it first.'
-                                       else    echo "I see no $obj here."
-                                       fi
-                               fi
-                       else    echo 'Feed what?'
-                       fi
-                       ;;
-       get|take)       if [ "$obj" ]
-                       then    if [ $obj = all ]
-                               then    obj="$obs"
-                                       x=
-                               fi
-                               for it in $obj $x
-                               do      if ash_lk "$obs $hobs" "$it"
-                                       then    if ash_lk "$kn" "$it"
-                                               then    echo 'You already have one.'
-                                               else    if mv $it $HOME/$KNAP/$it >&- 2>&-
-                                                       then    echo "$it: taken."
-                                                               kn="$it $kn"
-                                                               obs=`ash_rm "$obs" "$it"`
-                                                       else    echo "The $it is too heavy."
-                                                       fi
-                                               fi
-                                       else    echo "I see no $it here."
-                                       fi
-                               done
-                       else    echo 'Get what?'
-                       fi
-                       ;;
-       gripe|bug)      echo 'Please describe the problem and your situation at the time it failed.\nEnd the bug report with a line containing just a Ctrl-D.'
-                       cat | mail $MAINT -s 'ash bug'
-                       echo 'Thank you!'
-                       ;;
-       help)           ash_help
-                       ;;
-       inventory|i)    if [ "$kn" ]
-                       then    echo 'Your knapsack contains:'
-                               ash_pr $kn
-                       else    echo 'You are poverty-stricken.'
-                       fi
-                       ;;
-       kill|destroy)   if [ "$obj" ]
-                       then    if [ $obj = all ]
-                               then    x=
-                                       if ask "Do you really want to attempt to $verb them all?"
-                                       then    obj=`echo $obs`
-                                       else    echo 'Chicken!'
-                                               obj=
-                                       fi
-                               fi
-                               for it in $obj $x
-                               do      if ash_lk "$obs $hobs" "$it"
-                                       then    if mv $it $HOME/$LIM <&- >&- 2>&-
-                                               then    if [ $verb = kill ]
-                                                       then    echo "The $it cannot defend himself; he dies."
-                                                       else    echo "You have destroyed the $it; it vanishes."
-                                                       fi
-                                                       obs=`ash_rm "$obs" "$it"`
-                                               else    if [ $verb = kill ]
-                                                       then    echo "Your feeble blows are no match for the $it."
-                                                       else    echo "The $it is indestructible."
-                                                       fi
-                                               fi
-                                       else    if ash_lk "$kn" "$it"
-                                               then    echo "You must drop the $it first."
-                                                       found=false
-                                               else    echo "I see no $it here."
-                                               fi
-                                       fi
-                               done
-                       else    echo 'Kill what?'
-                       fi
-                       ;;
-       look|l)         obs=`echo $obs $hobs`
-                       hobs=
-                       if [ "$obs" ]
-                       then    echo 'The room contains:'
-                               ash_pr $obs
-                       else    echo 'The room is empty.'
-                       fi
-                       exs=`echo $exs $hexs`
-                       hexs=
-                       if [ "$exs" ]
-                       then    echo 'There are exits plainly labeled:'
-                               ash_pr $exs
-                               echo 'and a passage directly overhead.'
-                       else    echo 'The only exit is directly overhead.'
-                       fi
-                       ;;
-       magic)          if [ "$obj" = mode ]
-                       then    if sh -c $cha
-                               then    echo 'You had your chance and you blew it.'
-                               else    if ask 'Are you a wizard?'
-                                       then    echo -n 'Prove it!  Say the magic word: '
-                                               read obj
-                                               if [ "$obj" = armadillo ]
-                                               then    echo 'Yes, master!!'
-                                                       wiz=true
-                                               else    echo "Homie says: I don't think so"
-                                                       cha=true
-                                               fi
-                                       else    echo "I didn't think so."
-                                       fi
-                               fi
-                       else    echo 'Nice try.'
-                       fi
-                       ;;
-       open|read)      if [ "$obj" ]
-                       then    if ash_lk "$obs $hobs" "$obj"
-                               then    if [ -r $obj ]
-                                       then    if [ -s $obj ]
-                                               then    echo "Opening the $obj reveals:"
-                                                       $CAT < $obj
-                                                       if [ $? != 0 ]
-                                                       then    echo '-- oops, you lost the contents!'
-                                                       fi
-                                               else    echo "There is nothing inside the $obj."
-                                               fi
-                                       else    echo "You do not have the proper tools to open the $obj."
-                                       fi
-                               else    if ash_lk "$kn" "$obj"
-                                       then    echo 'You must drop it first.'
-                                               found=false
-                                       else    echo "I see no $obj here."
-                                       fi
-                               fi
-                       else    echo 'Open what?'
-                       fi
-                       ;;
-       quit|exit)      if ask 'Do you really want to quit now?'
-                       then    if [ "$kn" ]
-                               then    echo 'The contents of your knapsack will still be there next time.'
-                               fi
-                               rm -rf $HOME/$LIM
-                               echo 'See you later!'
-                               exit 0
-                       fi
-                       ;;
-       resurrect)      if [ "$obj" ]
-                       then    for it in $obj $x
-                               do      if ash_lk "$obs $hobs" "$it"
-                                       then    echo "The $it is already alive and well."
-                                       else    if mv $HOME/$LIM/$it $it <&- >&- 2>&-
-                                               then    echo "The $it staggers to his feet."
-                                                       obs=`echo $it $obs`
-                                               else    echo "There are sparks but no $it appears."
-                                               fi
-                                       fi
-                               done
-                       else    echo 'Resurrect what?'
-                       fi
-                       ;;
-       steal)          if [ "$obj" ]
-                       then    if ash_lk "$obs $hobs" "$obj"
-                               then    echo 'There is already one here.'
-                               else    set -- $x
-                                       case "$1" in
-                                       from)   if [ "$2" ]
-                                               then    shift
-                                                       if PATH=$OPATH $* >$obj 2>&-
-                                                       then    echo "The $1 monster drops the $obj."
-                                                               obs=`echo $obj $obs`
-                                                       else    echo "The $1 monster runs away as you approach."
-                                                               rm -f $obj >&- 2>&-
-                                                       fi
-                                               else    echo 'From what?'
-                                               fi
-                                               ;;
-                                       *)      echo "Steal $obj from what?"
-                                               ;;
-                                       esac
-                               fi
-                       else    echo 'Steal what?'
-                       fi
-                       ;;
-       throw)          if [ "$obj" ]
-                       then    if ash_lk "$obs $hobs" "$obj"
-                               then    set -- $x
-                                       case "$1" in
-                                       at)     case "$2" in
-                                               daemon) if sh -c "lpr -r $obj"
-                                                       then    echo "The daemon catches the $obj, turns it into paper,\nand leaves it in the basket."
-                                                               obs=`ash_rm "$obs" "$obj"`
-                                                       else    echo "The daemon is nowhere to be found."
-                                                       fi
-                                                       ;;
-                                               *)      echo 'At what?'
-                                                       ;;
-                                               esac
-                                               ;;
-                                       *)      echo "Throw $obj at what?"
-                                               ;;
-                                       esac
-                               else    if ash_lk "$kn" "$obj"
-                                       then    echo 'It is in your knapsack.'
-                                               found=false
-                                       else    echo "I see no $obj here."
-                                       fi
-                               fi
-                       else    echo 'Throw what?'
-                       fi
-                       ;;
-       u|up)           if cd ..
-                       then    echo 'You pull yourself up a level.'
-                       else    echo "You can't reach that high."
-                       fi
-                       ;;
-       wake)           if [ "$obj" ]
-                       then    echo "You awaken the $obj monster:"
-                               PATH=$OPATH $obj $x
-                               echo 'The monster slithers back into the darkness.'
-                       else    echo 'Wake what?'
-                       fi
-                       ;;
-       w|where)        echo "You are in $room."
-                       ;;
-       xyzzy)          if cd
-                       then    echo 'A strange feeling comes over you.'
-                       else    echo 'Your spell fizzles out.'
-                       fi
-                       ;;
-       *)              if [ "$verb" ]
-                       then    if sh -c $wiz
-                               then    PATH=$OPATH $verb $obj $x
-                               else    echo "I don't know how to \"$verb\"."
-                                       echo 'Type "help" for assistance.'
-                               fi
-                       else    echo 'Say something!'
-                       fi
-                       ;;
-       esac
-done
diff --git a/lib/readline/display.c~ b/lib/readline/display.c~
deleted file mode 100644 (file)
index ba7e8cc..0000000
+++ /dev/null
@@ -1,2819 +0,0 @@
-/* display.c -- readline redisplay facility. */
-
-/* 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
-
-#if defined (HAVE_CONFIG_H)
-#  include <config.h>
-#endif
-
-#include <sys/types.h>
-
-#if defined (HAVE_UNISTD_H)
-#  include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#include "posixstat.h"
-
-#if defined (HAVE_STDLIB_H)
-#  include <stdlib.h>
-#else
-#  include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#include <stdio.h>
-
-#ifdef __MSDOS__
-#  include <pc.h>
-#endif
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-#include "rlmbutil.h"
-
-/* Termcap library stuff. */
-#include "tcap.h"
-
-/* Some standard library routines. */
-#include "readline.h"
-#include "history.h"
-
-#include "rlprivate.h"
-#include "xmalloc.h"
-
-#if !defined (strchr) && !defined (__STDC__)
-extern char *strchr (), *strrchr ();
-#endif /* !strchr && !__STDC__ */
-
-static void update_line PARAMS((char *, char *, int, int, int, int));
-static void space_to_eol PARAMS((int));
-static void delete_chars PARAMS((int));
-static void insert_some_chars PARAMS((char *, int, int));
-static void open_some_spaces PARAMS((int));
-static void cr PARAMS((void));
-
-/* State of visible and invisible lines. */
-struct line_state
-  {
-    char *line;
-    int *lbreaks;
-    int lbsize;
-#if defined (HANDLE_MULTIBYTE)
-    int *wrapped_line;
-    int wbsize;
-#endif
-  };
-
-/* The line display buffers.  One is the line currently displayed on
-   the screen.  The other is the line about to be displayed. */
-static struct line_state line_state_array[2];
-static struct line_state *line_state_visible = &line_state_array[0];
-static struct line_state *line_state_invisible = &line_state_array[1];
-static int line_structures_initialized = 0;
-
-/* Backwards-compatible names. */
-#define inv_lbreaks    (line_state_invisible->lbreaks)
-#define inv_lbsize     (line_state_invisible->lbsize)
-#define vis_lbreaks    (line_state_visible->lbreaks)
-#define vis_lbsize     (line_state_visible->lbsize)
-
-#define visible_line   (line_state_visible->line)
-#define invisible_line (line_state_invisible->line)
-
-#if defined (HANDLE_MULTIBYTE)
-static int _rl_col_width PARAMS((const char *, int, int, int));
-#else
-#  define _rl_col_width(l, s, e, f)    (((e) <= (s)) ? 0 : (e) - (s))
-#endif
-
-/* Heuristic used to decide whether it is faster to move from CUR to NEW
-   by backing up or outputting a carriage return and moving forward.  CUR
-   and NEW are either both buffer positions or absolute screen positions. */
-#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
-
-/* _rl_last_c_pos is an absolute cursor position in multibyte locales and a
-   buffer index in others.  This macro is used when deciding whether the
-   current cursor position is in the middle of a prompt string containing
-   invisible characters.  XXX - might need to take `modmark' into account. */
-#define PROMPT_ENDING_INDEX \
-  ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1)
-  
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Display stuff                               */
-/*                                                                 */
-/* **************************************************************** */
-
-/* This is the stuff that is hard for me.  I never seem to write good
-   display routines in C.  Let's see how I do this time. */
-
-/* (PWP) Well... Good for a simple line updater, but totally ignores
-   the problems of input lines longer than the screen width.
-
-   update_line and the code that calls it makes a multiple line,
-   automatically wrapping line update.  Careful attention needs
-   to be paid to the vertical position variables. */
-
-/* Keep two buffers; one which reflects the current contents of the
-   screen, and the other to draw what we think the new contents should
-   be.  Then compare the buffers, and make whatever changes to the
-   screen itself that we should.  Finally, make the buffer that we
-   just drew into be the one which reflects the current contents of the
-   screen, and place the cursor where it belongs.
-
-   Commands that want to can fix the display themselves, and then let
-   this function know that the display has been fixed by setting the
-   RL_DISPLAY_FIXED variable.  This is good for efficiency. */
-
-/* Application-specific redisplay function. */
-rl_voidfunc_t *rl_redisplay_function = rl_redisplay;
-
-/* Global variables declared here. */
-/* What YOU turn on when you have handled all redisplay yourself. */
-int rl_display_fixed = 0;
-
-int _rl_suppress_redisplay = 0;
-int _rl_want_redisplay = 0;
-
-/* The stuff that gets printed out before the actual text of the line.
-   This is usually pointing to rl_prompt. */
-char *rl_display_prompt = (char *)NULL;
-
-/* Pseudo-global variables declared here. */
-
-/* The visible cursor position.  If you print some text, adjust this. */
-/* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale
-   supporting multibyte characters, and an absolute cursor position when
-   in such a locale.  This is an artifact of the donated multibyte support.
-   Care must be taken when modifying its value. */
-int _rl_last_c_pos = 0;
-int _rl_last_v_pos = 0;
-
-static int cpos_adjusted;
-static int cpos_buffer_position;
-static int displaying_prompt_first_line;
-static int prompt_multibyte_chars;
-
-/* Number of lines currently on screen minus 1. */
-int _rl_vis_botlin = 0;
-
-/* Variables used only in this file. */
-/* The last left edge of text that was displayed.  This is used when
-   doing horizontal scrolling.  It shifts in thirds of a screenwidth. */
-static int last_lmargin;
-
-/* A buffer for `modeline' messages. */
-static char *msg_buf = 0;
-static int msg_bufsiz = 0;
-
-/* Non-zero forces the redisplay even if we thought it was unnecessary. */
-static int forced_display;
-
-/* Default and initial buffer size.  Can grow. */
-static int line_size = 1024;
-
-/* Variables to keep track of the expanded prompt string, which may
-   include invisible characters. */
-
-static char *local_prompt, *local_prompt_prefix;
-static int local_prompt_len;
-static int prompt_visible_length, prompt_prefix_length;
-
-/* The number of invisible characters in the line currently being
-   displayed on the screen. */
-static int visible_wrap_offset;
-
-/* The number of invisible characters in the prompt string.  Static so it
-   can be shared between rl_redisplay and update_line */
-static int wrap_offset;
-
-/* The index of the last invisible character in the prompt string. */
-static int prompt_last_invisible;
-
-/* The length (buffer offset) of the first line of the last (possibly
-   multi-line) buffer displayed on the screen. */
-static int visible_first_line_len;
-
-/* Number of invisible characters on the first physical line of the prompt.
-   Only valid when the number of physical characters in the prompt exceeds
-   (or is equal to) _rl_screenwidth. */
-static int prompt_invis_chars_first_line;
-
-static int prompt_last_screen_line;
-
-static int prompt_physical_chars;
-
-/* set to a non-zero value by rl_redisplay if we are marking modified history
-   lines and the current line is so marked. */
-static int modmark;
-
-/* Variables to save and restore prompt and display information. */
-
-/* These are getting numerous enough that it's time to create a struct. */
-
-static char *saved_local_prompt;
-static char *saved_local_prefix;
-static int saved_last_invisible;
-static int saved_visible_length;
-static int saved_prefix_length;
-static int saved_local_length;
-static int saved_invis_chars_first_line;
-static int saved_physical_chars;
-
-/* Return a character indicating the editing mode, for use in the prompt. */
-static int
-prompt_modechar ()
-{
-  if (rl_editing_mode == emacs_mode)
-    return '@';
-  else if (_rl_keymap == vi_insertion_keymap)
-    return '+';                /* vi insert mode */
-  else
-    return ':';                /* vi command mode */
-}
-
-/* Expand the prompt string S and return the number of visible
-   characters in *LP, if LP is not null.  This is currently more-or-less
-   a placeholder for expansion.  LIP, if non-null is a place to store the
-   index of the last invisible character in the returned string. NIFLP,
-   if non-zero, is a place to store the number of invisible characters in
-   the first prompt line.  The previous are used as byte counts -- indexes
-   into a character buffer. */
-
-/* Current implementation:
-       \001 (^A) start non-visible characters
-       \002 (^B) end non-visible characters
-   all characters except \001 and \002 (following a \001) are copied to
-   the returned string; all characters except those between \001 and
-   \002 are assumed to be `visible'. */        
-
-static char *
-expand_prompt (pmt, lp, lip, niflp, vlp)
-     char *pmt;
-     int *lp, *lip, *niflp, *vlp;
-{
-  char *r, *ret, *p, *igstart;
-  int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
-
-  /* Short-circuit if we can. */
-  if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
-    {
-      if (pmt == rl_prompt && _rl_show_mode_in_prompt)
-        {
-          l = strlen (pmt);
-          r = (char *)xmalloc (l + 2);
-          r[0] = prompt_modechar ();
-          strcpy (r + 1, pmt);
-        }
-      else
-       r = savestring (pmt);
-
-      if (lp)
-       *lp = strlen (r);
-      if (lip)
-       *lip = 0;
-      if (niflp)
-       *niflp = 0;
-      if (vlp)
-       *vlp = lp ? *lp : strlen (r);
-      return r;
-    }
-
-  l = strlen (pmt);
-  r = ret = (char *)xmalloc (l + 2);
-
-  rl = physchars = 0;  /* move up here so mode show can set them */
-  if (pmt == rl_prompt && _rl_show_mode_in_prompt)
-    {
-      *r++ = prompt_modechar ();
-      rl = physchars = 1;
-    }
-
-  invfl = 0;   /* invisible chars in first line of prompt */
-  invflset = 0;        /* we only want to set invfl once */
-
-  igstart = 0;
-  for (ignoring = last = ninvis = 0, p = pmt; p && *p; p++)
-    {
-      /* This code strips the invisible character string markers
-        RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
-      if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE)               /* XXX - check ignoring? */
-       {
-         ignoring = 1;
-         igstart = p;
-         continue;
-       }
-      else if (ignoring && *p == RL_PROMPT_END_IGNORE)
-       {
-         ignoring = 0;
-         if (p != (igstart + 1))
-           last = r - ret - 1;
-         continue;
-       }
-      else
-       {
-#if defined (HANDLE_MULTIBYTE)
-         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-           {
-             pind = p - pmt;
-             ind = _rl_find_next_mbchar (pmt, pind, 1, MB_FIND_NONZERO);
-             l = ind - pind;
-             while (l--)
-               *r++ = *p++;
-             if (!ignoring)
-               {
-                 /* rl ends up being assigned to prompt_visible_length,
-                    which is the number of characters in the buffer that
-                    contribute to characters on the screen, which might
-                    not be the same as the number of physical characters
-                    on the screen in the presence of multibyte characters */
-                 rl += ind - pind;
-                 physchars += _rl_col_width (pmt, pind, ind, 0);
-               }
-             else
-               ninvis += ind - pind;
-             p--;                      /* compensate for later increment */
-           }
-         else
-#endif
-           {
-             *r++ = *p;
-             if (!ignoring)
-               {
-                 rl++;                 /* visible length byte counter */
-                 physchars++;
-               }
-             else
-               ninvis++;               /* invisible chars byte counter */
-           }
-
-         if (invflset == 0 && rl >= _rl_screenwidth)
-           {
-             invfl = ninvis;
-             invflset = 1;
-           }
-       }
-    }
-
-  if (rl < _rl_screenwidth)
-    invfl = ninvis;
-
-  *r = '\0';
-  if (lp)
-    *lp = rl;
-  if (lip)
-    *lip = last;
-  if (niflp)
-    *niflp = invfl;
-  if  (vlp)
-    *vlp = physchars;
-  return ret;
-}
-
-/* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
-   PMT and return the rest of PMT. */
-char *
-_rl_strip_prompt (pmt)
-     char *pmt;
-{
-  char *ret;
-
-  ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL);
-  return ret;
-}
-
-void
-_rl_reset_prompt ()
-{
-  rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
-}
-
-/*
- * Expand the prompt string into the various display components, if
- * necessary.
- *
- * local_prompt = expanded last line of string in rl_display_prompt
- *               (portion after the final newline)
- * local_prompt_prefix = portion before last newline of rl_display_prompt,
- *                      expanded via expand_prompt
- * prompt_visible_length = number of visible characters in local_prompt
- * prompt_prefix_length = number of visible characters in local_prompt_prefix
- *
- * This function is called once per call to readline().  It may also be
- * called arbitrarily to expand the primary prompt.
- *
- * The return value is the number of visible characters on the last line
- * of the (possibly multi-line) prompt.
- */
-int
-rl_expand_prompt (prompt)
-     char *prompt;
-{
-  char *p, *t;
-  int c;
-
-  /* Clear out any saved values. */
-  FREE (local_prompt);
-  FREE (local_prompt_prefix);
-
-  local_prompt = local_prompt_prefix = (char *)0;
-  local_prompt_len = 0;
-  prompt_last_invisible = prompt_invis_chars_first_line = 0;
-  prompt_visible_length = prompt_physical_chars = 0;
-
-  if (prompt == 0 || *prompt == 0)
-    return (0);
-
-  p = strrchr (prompt, '\n');
-  if (!p)
-    {
-      /* The prompt is only one logical line, though it might wrap. */
-      local_prompt = expand_prompt (prompt, &prompt_visible_length,
-                                           &prompt_last_invisible,
-                                           &prompt_invis_chars_first_line,
-                                           &prompt_physical_chars);
-      local_prompt_prefix = (char *)0;
-      local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
-      return (prompt_visible_length);
-    }
-  else
-    {
-      /* The prompt spans multiple lines. */
-      t = ++p;
-      local_prompt = expand_prompt (p, &prompt_visible_length,
-                                      &prompt_last_invisible,
-                                      &prompt_invis_chars_first_line,
-                                      &prompt_physical_chars);
-      c = *t; *t = '\0';
-      /* The portion of the prompt string up to and including the
-        final newline is now null-terminated. */
-      local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
-                                                  (int *)NULL,
-                                                  (int *)NULL,
-                                                  (int *)NULL);
-      *t = c;
-      local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
-      return (prompt_prefix_length);
-    }
-}
-
-/* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
-   arrays of line break markers.  MINSIZE is the minimum size of VISIBLE_LINE
-   and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
-   increased.  If the lines have already been allocated, this ensures that
-   they can hold at least MINSIZE characters. */
-static void
-init_line_structures (minsize)
-      int minsize;
-{
-  register int n;
-
-  if (invisible_line == 0)     /* initialize it */
-    {
-      if (line_size < minsize)
-       line_size = minsize;
-      visible_line = (char *)xmalloc (line_size);
-      invisible_line = (char *)xmalloc (line_size);
-    }
-  else if (line_size < minsize)        /* ensure it can hold MINSIZE chars */
-    {
-      line_size *= 2;
-      if (line_size < minsize)
-       line_size = minsize;
-      visible_line = (char *)xrealloc (visible_line, line_size);
-      invisible_line = (char *)xrealloc (invisible_line, line_size);
-    }
-
-  for (n = minsize; n < line_size; n++)
-    {
-      visible_line[n] = 0;
-      invisible_line[n] = 1;
-    }
-
-  if (vis_lbreaks == 0)
-    {
-      /* should be enough. */
-      inv_lbsize = vis_lbsize = 256;
-
-#if defined (HANDLE_MULTIBYTE)
-      line_state_visible->wbsize = vis_lbsize;
-      line_state_visible->wrapped_line = (int *)xmalloc (line_state_visible->wbsize * sizeof (int));
-
-      line_state_invisible->wbsize = inv_lbsize;
-      line_state_invisible->wrapped_line = (int *)xmalloc (line_state_invisible->wbsize * sizeof (int));
-#endif
-
-      inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
-      vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
-      inv_lbreaks[0] = vis_lbreaks[0] = 0;
-    }
-
-  line_structures_initialized = 1;
-}
-  
-/* Basic redisplay algorithm. */
-void
-rl_redisplay ()
-{
-  register int in, out, c, linenum, cursor_linenum;
-  register char *line;
-  int inv_botlin, lb_botlin, lb_linenum, o_cpos;
-  int newlines, lpos, temp, n0, num, prompt_lines_estimate;
-  char *prompt_this_line;
-#if defined (HANDLE_MULTIBYTE)
-  wchar_t wc;
-  size_t wc_bytes;
-  int wc_width;
-  mbstate_t ps;
-  int _rl_wrapped_multicolumn = 0;
-#endif
-
-  if (_rl_echoing_p == 0)
-    return;
-
-  /* Block keyboard interrupts because this function manipulates global
-     data structures. */
-  _rl_block_sigint ();  
-  RL_SETSTATE (RL_STATE_REDISPLAYING);
-
-  if (!rl_display_prompt)
-    rl_display_prompt = "";
-
-  if (line_structures_initialized == 0)
-    {
-      init_line_structures (0);
-      rl_on_new_line ();
-    }
-
-  /* Draw the line into the buffer. */
-  cpos_buffer_position = -1;
-
-  prompt_multibyte_chars = prompt_visible_length - prompt_physical_chars;
-
-  line = invisible_line;
-  out = inv_botlin = 0;
-
-  /* Mark the line as modified or not.  We only do this for history
-     lines. */
-  modmark = 0;
-  if (_rl_mark_modified_lines && current_history () && rl_undo_list)
-    {
-      line[out++] = '*';
-      line[out] = '\0';
-      modmark = 1;
-    }
-
-  /* If someone thought that the redisplay was handled, but the currently
-     visible line has a different modification state than the one about
-     to become visible, then correct the caller's misconception. */
-  if (visible_line[0] != invisible_line[0])
-    rl_display_fixed = 0;
-
-  /* If the prompt to be displayed is the `primary' readline prompt (the
-     one passed to readline()), use the values we have already expanded.
-     If not, use what's already in rl_display_prompt.  WRAP_OFFSET is the
-     number of non-visible characters in the prompt string. */
-  if (rl_display_prompt == rl_prompt || local_prompt)
-    {
-      if (local_prompt_prefix && forced_display)
-       _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
-
-      if (local_prompt_len > 0)
-       {
-         temp = local_prompt_len + out + 2;
-         if (temp >= line_size)
-           {
-             line_size = (temp + 1024) - (temp % 1024);
-             visible_line = (char *)xrealloc (visible_line, line_size);
-             line = invisible_line = (char *)xrealloc (invisible_line, line_size);
-           }
-         strncpy (line + out, local_prompt, local_prompt_len);
-         out += local_prompt_len;
-       }
-      line[out] = '\0';
-      wrap_offset = local_prompt_len - prompt_visible_length;
-    }
-  else
-    {
-      int pmtlen;
-      prompt_this_line = strrchr (rl_display_prompt, '\n');
-      if (!prompt_this_line)
-       prompt_this_line = rl_display_prompt;
-      else
-       {
-         prompt_this_line++;
-         pmtlen = prompt_this_line - rl_display_prompt;        /* temp var */
-         if (forced_display)
-           {
-             _rl_output_some_chars (rl_display_prompt, pmtlen);
-             /* Make sure we are at column zero even after a newline,
-                regardless of the state of terminal output processing. */
-             if (pmtlen < 2 || prompt_this_line[-2] != '\r')
-               cr ();
-           }
-       }
-
-      prompt_physical_chars = pmtlen = strlen (prompt_this_line);
-      temp = pmtlen + out + 2;
-      if (temp >= line_size)
-       {
-         line_size = (temp + 1024) - (temp % 1024);
-         visible_line = (char *)xrealloc (visible_line, line_size);
-         line = invisible_line = (char *)xrealloc (invisible_line, line_size);
-       }
-      strncpy (line + out,  prompt_this_line, pmtlen);
-      out += pmtlen;
-      line[out] = '\0';
-      wrap_offset = prompt_invis_chars_first_line = 0;
-    }
-
-#define CHECK_INV_LBREAKS() \
-      do { \
-       if (newlines >= (inv_lbsize - 2)) \
-         { \
-           inv_lbsize *= 2; \
-           inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
-         } \
-      } while (0)
-
-#if defined (HANDLE_MULTIBYTE)   
-#define CHECK_LPOS() \
-      do { \
-       lpos++; \
-       if (lpos >= _rl_screenwidth) \
-         { \
-           if (newlines >= (inv_lbsize - 2)) \
-             { \
-               inv_lbsize *= 2; \
-               inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
-             } \
-           inv_lbreaks[++newlines] = out; \
-           if (newlines >= (line_state_invisible->wbsize - 1)) \
-             { \
-               line_state_invisible->wbsize *= 2; \
-               line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \
-             } \
-           line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn; \
-           lpos = 0; \
-         } \
-      } while (0)
-#else
-#define CHECK_LPOS() \
-      do { \
-       lpos++; \
-       if (lpos >= _rl_screenwidth) \
-         { \
-           if (newlines >= (inv_lbsize - 2)) \
-             { \
-               inv_lbsize *= 2; \
-               inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
-             } \
-           inv_lbreaks[++newlines] = out; \
-           lpos = 0; \
-         } \
-      } while (0)
-#endif
-
-  /* inv_lbreaks[i] is where line i starts in the buffer. */
-  inv_lbreaks[newlines = 0] = 0;
-  lpos = prompt_physical_chars + modmark;
-
-#if defined (HANDLE_MULTIBYTE)
-  memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wbsize * sizeof (int));
-  num = 0;
-#endif
-
-  /* prompt_invis_chars_first_line is the number of invisible characters in
-     the first physical line of the prompt.
-     wrap_offset - prompt_invis_chars_first_line is the number of invis
-     chars on the second (or, more generally, last) line. */
-
-  /* This is zero-based, used to set the newlines */
-  prompt_lines_estimate = lpos / _rl_screenwidth;
-
-  /* what if lpos is already >= _rl_screenwidth before we start drawing the
-     contents of the command line? */
-  while (lpos >= _rl_screenwidth)
-    {
-      int z;
-      /* fix from Darin Johnson <darin@acuson.com> for prompt string with
-         invisible characters that is longer than the screen width.  The
-         prompt_invis_chars_first_line variable could be made into an array
-         saying how many invisible characters there are per line, but that's
-         probably too much work for the benefit gained.  How many people have
-         prompts that exceed two physical lines?
-         Additional logic fix from Edward Catmur <ed@catmur.co.uk> */
-#if defined (HANDLE_MULTIBYTE)
-      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
-       {
-         n0 = num;
-          temp = local_prompt_len;
-          while (num < temp)
-           {
-             z = _rl_col_width  (local_prompt, n0, num, 1);
-             if (z > _rl_screenwidth)
-               {
-                 num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY);
-                 break;
-               }
-             else if (z == _rl_screenwidth)
-               break;
-             num++;
-           }
-          temp = num;
-       }
-      else
-#endif /* !HANDLE_MULTIBYTE */
-       temp = ((newlines + 1) * _rl_screenwidth);
-
-      /* Now account for invisible characters in the current line. */
-      /* XXX - this assumes that the invisible characters may be split, but only
-        between the first and the last lines. */
-      temp += ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line
-                                                            : ((newlines == prompt_lines_estimate) ? wrap_offset : prompt_invis_chars_first_line))
-                                         : ((newlines == 0) ? wrap_offset : 0));
-             
-      inv_lbreaks[++newlines] = temp;
-#if defined (HANDLE_MULTIBYTE)
-      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
-       lpos -= _rl_col_width (local_prompt, n0, num, 1);
-      else
-#endif
-       lpos -= _rl_screenwidth;
-    }
-
-  prompt_last_screen_line = newlines;
-
-  /* Draw the rest of the line (after the prompt) into invisible_line, keeping
-     track of where the cursor is (cpos_buffer_position), the number of the line containing
-     the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin).
-     It maintains an array of line breaks for display (inv_lbreaks).
-     This handles expanding tabs for display and displaying meta characters. */
-  lb_linenum = 0;
-#if defined (HANDLE_MULTIBYTE)
-  in = 0;
-  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-    {
-      memset (&ps, 0, sizeof (mbstate_t));
-      /* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */
-      wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
-    }
-  else
-    wc_bytes = 1;
-  while (in < rl_end)
-#else
-  for (in = 0; in < rl_end; in++)
-#endif
-    {
-      c = (unsigned char)rl_line_buffer[in];
-
-#if defined (HANDLE_MULTIBYTE)
-      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-       {
-         if (MB_INVALIDCH (wc_bytes))
-           {
-             /* Byte sequence is invalid or shortened.  Assume that the
-                first byte represents a character. */
-             wc_bytes = 1;
-             /* Assume that a character occupies a single column. */
-             wc_width = 1;
-             memset (&ps, 0, sizeof (mbstate_t));
-           }
-         else if (MB_NULLWCH (wc_bytes))
-           break;                      /* Found '\0' */
-         else
-           {
-             temp = WCWIDTH (wc);
-             wc_width = (temp >= 0) ? temp : 1;
-           }
-       }
-#endif
-
-      if (out + 8 >= line_size)                /* XXX - 8 for \t */
-       {
-         line_size *= 2;
-         visible_line = (char *)xrealloc (visible_line, line_size);
-         invisible_line = (char *)xrealloc (invisible_line, line_size);
-         line = invisible_line;
-       }
-
-      if (in == rl_point)
-       {
-         cpos_buffer_position = out;
-         lb_linenum = newlines;
-       }
-
-#if defined (HANDLE_MULTIBYTE)
-      if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */
-#else
-      if (META_CHAR (c))
-#endif
-       {
-         if (_rl_output_meta_chars == 0)
-           {
-             sprintf (line + out, "\\%o", c);
-
-             if (lpos + 4 >= _rl_screenwidth)
-               {
-                 temp = _rl_screenwidth - lpos;
-                 CHECK_INV_LBREAKS ();
-                 inv_lbreaks[++newlines] = out + temp;
-                 lpos = 4 - temp;
-               }
-             else
-               lpos += 4;
-
-             out += 4;
-           }
-         else
-           {
-             line[out++] = c;
-             CHECK_LPOS();
-           }
-       }
-#if defined (DISPLAY_TABS)
-      else if (c == '\t')
-       {
-         register int newout;
-
-#if 0
-         newout = (out | (int)7) + 1;
-#else
-         newout = out + 8 - lpos % 8;
-#endif
-         temp = newout - out;
-         if (lpos + temp >= _rl_screenwidth)
-           {
-             register int temp2;
-             temp2 = _rl_screenwidth - lpos;
-             CHECK_INV_LBREAKS ();
-             inv_lbreaks[++newlines] = out + temp2;
-             lpos = temp - temp2;
-             while (out < newout)
-               line[out++] = ' ';
-           }
-         else
-           {
-             while (out < newout)
-               line[out++] = ' ';
-             lpos += temp;
-           }
-       }
-#endif
-      else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
-       {
-         line[out++] = '\0';   /* XXX - sentinel */
-         CHECK_INV_LBREAKS ();
-         inv_lbreaks[++newlines] = out;
-         lpos = 0;
-       }
-      else if (CTRL_CHAR (c) || c == RUBOUT)
-       {
-         line[out++] = '^';
-         CHECK_LPOS();
-         line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
-         CHECK_LPOS();
-       }
-      else
-       {
-#if defined (HANDLE_MULTIBYTE)
-         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-           {
-             register int i;
-
-             _rl_wrapped_multicolumn = 0;
-
-             if (_rl_screenwidth < lpos + wc_width)
-               for (i = lpos; i < _rl_screenwidth; i++)
-                 {
-                   /* The space will be removed in update_line() */
-                   line[out++] = ' ';
-                   _rl_wrapped_multicolumn++;
-                   CHECK_LPOS();
-                 }
-             if (in == rl_point)
-               {
-                 cpos_buffer_position = out;
-                 lb_linenum = newlines;
-               }
-             for (i = in; i < in+wc_bytes; i++)
-               line[out++] = rl_line_buffer[i];
-             for (i = 0; i < wc_width; i++)
-               CHECK_LPOS();
-           }
-         else
-           {
-             line[out++] = c;
-             CHECK_LPOS();
-           }
-#else
-         line[out++] = c;
-         CHECK_LPOS();
-#endif
-       }
-
-#if defined (HANDLE_MULTIBYTE)
-      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-       {
-         in += wc_bytes;
-         /* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */
-         wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
-       }
-      else
-        in++;
-#endif
-
-    }
-  line[out] = '\0';
-  if (cpos_buffer_position < 0)
-    {
-      cpos_buffer_position = out;
-      lb_linenum = newlines;
-    }
-
-  inv_botlin = lb_botlin = newlines;
-  CHECK_INV_LBREAKS ();
-  inv_lbreaks[newlines+1] = out;
-  cursor_linenum = lb_linenum;
-
-  /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed.
-     CURSOR_LINENUM == line number where the cursor should be placed. */
-
-  /* PWP: now is when things get a bit hairy.  The visible and invisible
-     line buffers are really multiple lines, which would wrap every
-     (screenwidth - 1) characters.  Go through each in turn, finding
-     the changed region and updating it.  The line order is top to bottom. */
-
-  /* If we can move the cursor up and down, then use multiple lines,
-     otherwise, let long lines display in a single terminal line, and
-     horizontally scroll it. */
-  displaying_prompt_first_line = 1;
-  if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
-    {
-      int nleft, pos, changed_screen_line, tx;
-
-      if (!rl_display_fixed || forced_display)
-       {
-         forced_display = 0;
-
-         /* If we have more than a screenful of material to display, then
-            only display a screenful.  We should display the last screen,
-            not the first.  */
-         if (out >= _rl_screenchars)
-           {
-             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-               out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY);
-             else
-               out = _rl_screenchars - 1;
-           }
-
-         /* The first line is at character position 0 in the buffer.  The
-            second and subsequent lines start at inv_lbreaks[N], offset by
-            OFFSET (which has already been calculated above).  */
-
-#define INVIS_FIRST()  (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
-#define WRAP_OFFSET(line, offset)  ((line == 0) \
-                                       ? (offset ? INVIS_FIRST() : 0) \
-                                       : ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
-#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
-#define VIS_LLEN(l)    ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
-#define INV_LLEN(l)    (inv_lbreaks[l+1] - inv_lbreaks[l])
-#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
-#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
-#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
-
-#define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \
-                       _rl_last_c_pos != o_cpos && \
-                       _rl_last_c_pos > wrap_offset && \
-                       o_cpos < prompt_last_invisible)
-
-         /* For each line in the buffer, do the updating display. */
-         for (linenum = 0; linenum <= inv_botlin; linenum++)
-           {
-             /* This can lead us astray if we execute a program that changes
-                the locale from a non-multibyte to a multibyte one. */
-             o_cpos = _rl_last_c_pos;
-             cpos_adjusted = 0;
-             update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
-                          VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
-
-             /* update_line potentially changes _rl_last_c_pos, but doesn't
-                take invisible characters into account, since _rl_last_c_pos
-                is an absolute cursor position in a multibyte locale.  See
-                if compensating here is the right thing, or if we have to
-                change update_line itself.  There are several cases in which
-                update_line adjusts _rl_last_c_pos itself (so it can pass
-                _rl_move_cursor_relative accurate values); it communicates
-                this back by setting cpos_adjusted.  If we assume that
-                _rl_last_c_pos is correct (an absolute cursor position) each
-                time update_line is called, then we can assume in our
-                calculations that o_cpos does not need to be adjusted by
-                wrap_offset. */
-             if (linenum == 0 && (MB_CUR_MAX > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT())
-               _rl_last_c_pos -= prompt_invis_chars_first_line;        /* XXX - was wrap_offset */
-             else if (linenum == prompt_last_screen_line && prompt_physical_chars > _rl_screenwidth &&
-                       (MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
-                       cpos_adjusted == 0 &&
-                       _rl_last_c_pos != o_cpos &&
-                       _rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line))
-               _rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
-                 
-             /* If this is the line with the prompt, we might need to
-                compensate for invisible characters in the new line. Do
-                this only if there is not more than one new line (which
-                implies that we completely overwrite the old visible line)
-                and the new line is shorter than the old.  Make sure we are
-                at the end of the new line before clearing. */
-             if (linenum == 0 &&
-                 inv_botlin == 0 && _rl_last_c_pos == out &&
-                 (wrap_offset > visible_wrap_offset) &&
-                 (_rl_last_c_pos < visible_first_line_len))
-               {
-                 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-                   nleft = _rl_screenwidth - _rl_last_c_pos;
-                 else
-                   nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
-                 if (nleft)
-                   _rl_clear_to_eol (nleft);
-               }
-#if 0
-             /* This segment is intended to handle the case where the prompt
-                has invisible characters on the second line and the new line
-                to be displayed needs to clear the rest of the old characters
-                out (e.g., when printing the i-search prompt).  In general,
-                the case of the new line being shorter than the old.
-                Incomplete */
-             else if (linenum == prompt_last_screen_line &&
-                      prompt_physical_chars > _rl_screenwidth &&
-                      wrap_offset != prompt_invis_chars_first_line &&
-                      _rl_last_c_pos == out &&
-#endif
-
-
-             /* Since the new first line is now visible, save its length. */
-             if (linenum == 0)
-               visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
-           }
-
-         /* We may have deleted some lines.  If so, clear the left over
-            blank ones at the bottom out. */
-         if (_rl_vis_botlin > inv_botlin)
-           {
-             char *tt;
-             for (; linenum <= _rl_vis_botlin; linenum++)
-               {
-                 tt = VIS_CHARS (linenum);
-                 _rl_move_vert (linenum);
-                 _rl_move_cursor_relative (0, tt);
-                 _rl_clear_to_eol
-                   ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
-               }
-           }
-         _rl_vis_botlin = inv_botlin;
-
-         /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
-            different screen line during this redisplay. */
-         changed_screen_line = _rl_last_v_pos != cursor_linenum;
-         if (changed_screen_line)
-           {
-             _rl_move_vert (cursor_linenum);
-             /* If we moved up to the line with the prompt using _rl_term_up,
-                the physical cursor position on the screen stays the same,
-                but the buffer position needs to be adjusted to account
-                for invisible characters. */
-             if ((MB_CUR_MAX == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset)
-               _rl_last_c_pos += wrap_offset;
-           }
-
-         /* We have to reprint the prompt if it contains invisible
-            characters, since it's not generally OK to just reprint
-            the characters from the current cursor position.  But we
-            only need to reprint it if the cursor is before the last
-            invisible character in the prompt string. */
-         nleft = prompt_visible_length + wrap_offset;
-         if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
-#if 0
-             _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt)
-#else
-             _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
-#endif
-           {
-#if defined (__MSDOS__)
-             putc ('\r', rl_outstream);
-#else
-             if (_rl_term_cr)
-               tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
-             if (modmark)
-               _rl_output_some_chars ("*", 1);
-
-             _rl_output_some_chars (local_prompt, nleft);
-             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-               _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft, 1) - wrap_offset + modmark;
-             else
-               _rl_last_c_pos = nleft + modmark;
-           }
-
-         /* Where on that line?  And where does that line start
-            in the buffer? */
-         pos = inv_lbreaks[cursor_linenum];
-         /* nleft == number of characters in the line buffer between the
-            start of the line and the desired cursor position. */
-         nleft = cpos_buffer_position - pos;
-
-         /* NLEFT is now a number of characters in a buffer.  When in a
-            multibyte locale, however, _rl_last_c_pos is an absolute cursor
-            position that doesn't take invisible characters in the prompt
-            into account.  We use a fudge factor to compensate. */
-
-         /* Since _rl_backspace() doesn't know about invisible characters in the
-            prompt, and there's no good way to tell it, we compensate for
-            those characters here and call _rl_backspace() directly. */
-         if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
-           {
-             /* TX == new physical cursor position in multibyte locale. */
-             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-               tx = _rl_col_width (&visible_line[pos], 0, nleft, 1) - visible_wrap_offset;
-             else
-               tx = nleft;
-             if (tx >= 0 && _rl_last_c_pos > tx)
-               {
-                 _rl_backspace (_rl_last_c_pos - tx);  /* XXX */
-                 _rl_last_c_pos = tx;
-               }
-           }
-
-         /* We need to note that in a multibyte locale we are dealing with
-            _rl_last_c_pos as an absolute cursor position, but moving to a
-            point specified by a buffer position (NLEFT) that doesn't take
-            invisible characters into account. */
-         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-           _rl_move_cursor_relative (nleft, &invisible_line[pos]);
-         else if (nleft != _rl_last_c_pos)
-           _rl_move_cursor_relative (nleft, &invisible_line[pos]);
-       }
-    }
-  else                         /* Do horizontal scrolling. */
-    {
-#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
-      int lmargin, ndisp, nleft, phys_c_pos, t;
-
-      /* Always at top line. */
-      _rl_last_v_pos = 0;
-
-      /* Compute where in the buffer the displayed line should start.  This
-        will be LMARGIN. */
-
-      /* The number of characters that will be displayed before the cursor. */
-      ndisp = cpos_buffer_position - wrap_offset;
-      nleft  = prompt_visible_length + wrap_offset;
-      /* Where the new cursor position will be on the screen.  This can be
-        longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
-      phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset);
-      t = _rl_screenwidth / 3;
-
-      /* If the number of characters had already exceeded the screenwidth,
-        last_lmargin will be > 0. */
-
-      /* If the number of characters to be displayed is more than the screen
-        width, compute the starting offset so that the cursor is about
-        two-thirds of the way across the screen. */
-      if (phys_c_pos > _rl_screenwidth - 2)
-       {
-         lmargin = cpos_buffer_position - (2 * t);
-         if (lmargin < 0)
-           lmargin = 0;
-         /* If the left margin would be in the middle of a prompt with
-            invisible characters, don't display the prompt at all. */
-         if (wrap_offset && lmargin > 0 && lmargin < nleft)
-           lmargin = nleft;
-       }
-      else if (ndisp < _rl_screenwidth - 2)            /* XXX - was -1 */
-       lmargin = 0;
-      else if (phys_c_pos < 1)
-       {
-         /* If we are moving back towards the beginning of the line and
-            the last margin is no longer correct, compute a new one. */
-         lmargin = ((cpos_buffer_position - 1) / t) * t;       /* XXX */
-         if (wrap_offset && lmargin > 0 && lmargin < nleft)
-           lmargin = nleft;
-       }
-      else
-       lmargin = last_lmargin;
-
-      displaying_prompt_first_line = lmargin < nleft;
-
-      /* If the first character on the screen isn't the first character
-        in the display line, indicate this with a special character. */
-      if (lmargin > 0)
-       line[lmargin] = '<';
-
-      /* If SCREENWIDTH characters starting at LMARGIN do not encompass
-        the whole line, indicate that with a special character at the
-        right edge of the screen.  If LMARGIN is 0, we need to take the
-        wrap offset into account. */
-      t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
-      if (t < out)
-       line[t - 1] = '>';
-
-      if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
-       {
-         forced_display = 0;
-         o_cpos = _rl_last_c_pos;
-         cpos_adjusted = 0;
-         update_line (&visible_line[last_lmargin],
-                      &invisible_line[lmargin],
-                      0,
-                      _rl_screenwidth + visible_wrap_offset,
-                      _rl_screenwidth + (lmargin ? 0 : wrap_offset),
-                      0);
-
-         if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
-               displaying_prompt_first_line && OLD_CPOS_IN_PROMPT())
-           _rl_last_c_pos -= prompt_invis_chars_first_line;    /* XXX - was wrap_offset */
-
-         /* If the visible new line is shorter than the old, but the number
-            of invisible characters is greater, and we are at the end of
-            the new line, we need to clear to eol. */
-         t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
-         if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
-             (_rl_last_c_pos == out) && displaying_prompt_first_line &&
-             t < visible_first_line_len)
-           {
-             nleft = _rl_screenwidth - t;
-             _rl_clear_to_eol (nleft);
-           }
-         visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
-         if (visible_first_line_len > _rl_screenwidth)
-           visible_first_line_len = _rl_screenwidth;
-
-         _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin]);
-         last_lmargin = lmargin;
-       }
-    }
-  fflush (rl_outstream);
-
-  /* Swap visible and non-visible lines. */
-  {
-    struct line_state *vtemp = line_state_visible;
-
-    line_state_visible = line_state_invisible;
-    line_state_invisible = vtemp;
-
-    rl_display_fixed = 0;
-    /* If we are displaying on a single line, and last_lmargin is > 0, we
-       are not displaying any invisible characters, so set visible_wrap_offset
-       to 0. */
-    if (_rl_horizontal_scroll_mode && last_lmargin)
-      visible_wrap_offset = 0;
-    else
-      visible_wrap_offset = wrap_offset;
-  }
-
-  RL_UNSETSTATE (RL_STATE_REDISPLAYING);
-  _rl_release_sigint ();
-}
-
-/* PWP: update_line() is based on finding the middle difference of each
-   line on the screen; vis:
-
-                            /old first difference
-       /beginning of line   |        /old last same       /old EOL
-       v                    v        v             v
-old:   eddie> Oh, my little gruntle-buggy is to me, as lurgid as
-new:   eddie> Oh, my little buggy says to me, as lurgid as
-       ^                    ^  ^                          ^
-       \beginning of line   |  \new last same     \new end of line
-                            \new first difference
-
-   All are character pointers for the sake of speed.  Special cases for
-   no differences, as well as for end of line additions must be handled.
-
-   Could be made even smarter, but this works well enough */
-static void
-update_line (old, new, current_line, omax, nmax, inv_botlin)
-     register char *old, *new;
-     int current_line, omax, nmax, inv_botlin;
-{
-  register char *ofd, *ols, *oe, *nfd, *nls, *ne;
-  int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
-  int current_invis_chars;
-  int col_lendiff, col_temp;
-  int bytes_to_insert;
-#if defined (HANDLE_MULTIBYTE)
-  mbstate_t ps_new, ps_old;
-  int new_offset, old_offset;
-#endif
-
-  /* If we're at the right edge of a terminal that supports xn, we're
-     ready to wrap around, so do so.  This fixes problems with knowing
-     the exact cursor position and cut-and-paste with certain terminal
-     emulators.  In this calculation, TEMP is the physical screen
-     position of the cursor. */
-  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-    temp = _rl_last_c_pos;
-  else
-    temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset);
-  if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
-       && _rl_last_v_pos == current_line - 1)
-    {
-#if defined (HANDLE_MULTIBYTE)
-      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-       {
-         wchar_t wc;
-         mbstate_t ps;
-         int tempwidth, bytes;
-         size_t ret;
-
-         /* This fixes only double-column characters, but if the wrapped
-            character comsumes more than three columns, spaces will be
-            inserted in the string buffer. */
-         if (current_line < line_state_visible->wbsize && line_state_visible->wrapped_line[current_line] > 0)
-           _rl_clear_to_eol (line_state_visible->wrapped_line[current_line]);
-
-         memset (&ps, 0, sizeof (mbstate_t));
-         ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
-         if (MB_INVALIDCH (ret))
-           {
-             tempwidth = 1;
-             ret = 1;
-           }
-         else if (MB_NULLWCH (ret))
-           tempwidth = 0;
-         else
-           tempwidth = WCWIDTH (wc);
-
-         if (tempwidth > 0)
-           {
-             int count, i;
-             bytes = ret;
-             for (count = 0; count < bytes; count++)
-               putc (new[count], rl_outstream);
-             _rl_last_c_pos = tempwidth;
-             _rl_last_v_pos++;
-             memset (&ps, 0, sizeof (mbstate_t));
-             ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
-             if (ret != 0 && bytes != 0)
-               {
-                 if (MB_INVALIDCH (ret))
-                   ret = 1;
-                 memmove (old+bytes, old+ret, strlen (old+ret));
-                 memcpy (old, new, bytes);
-                 /* Fix up indices if we copy data from one line to another */
-                 omax += bytes - ret;
-                 for (i = current_line+1; i <= inv_botlin+1; i++)
-                   vis_lbreaks[i] += bytes - ret;
-               }
-           }
-         else
-           {
-             putc (' ', rl_outstream);
-             _rl_last_c_pos = 1;
-             _rl_last_v_pos++;
-             if (old[0] && new[0])
-               old[0] = new[0];
-           }
-       }
-      else
-#endif
-       {
-         if (new[0])
-           putc (new[0], rl_outstream);
-         else
-           putc (' ', rl_outstream);
-         _rl_last_c_pos = 1;
-         _rl_last_v_pos++;
-         if (old[0] && new[0])
-           old[0] = new[0];
-       }
-    }
-
-      
-  /* Find first difference. */
-#if defined (HANDLE_MULTIBYTE)
-  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-    {
-      /* See if the old line is a subset of the new line, so that the
-        only change is adding characters. */
-      temp = (omax < nmax) ? omax : nmax;
-      if (memcmp (old, new, temp) == 0)                /* adding at the end */
-       {
-         new_offset = old_offset = temp;
-         ofd = old + temp;
-         nfd = new + temp;
-       }
-      else
-       {      
-         memset (&ps_new, 0, sizeof(mbstate_t));
-         memset (&ps_old, 0, sizeof(mbstate_t));
-
-         if (omax == nmax && STREQN (new, old, omax))
-           {
-             old_offset = omax;
-             new_offset = nmax;
-             ofd = old + omax;
-             nfd = new + nmax;
-           }
-         else
-           {
-             new_offset = old_offset = 0;
-             for (ofd = old, nfd = new;
-                   (ofd - old < omax) && *ofd &&
-                   _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
-               {
-                 old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
-                 new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
-
-                 ofd = old + old_offset;
-                 nfd = new + new_offset;
-               }
-           }
-       }
-    }
-  else
-#endif
-  for (ofd = old, nfd = new;
-       (ofd - old < omax) && *ofd && (*ofd == *nfd);
-       ofd++, nfd++)
-    ;
-
-  /* Move to the end of the screen line.  ND and OD are used to keep track
-     of the distance between ne and new and oe and old, respectively, to
-     move a subtraction out of each loop. */
-  for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
-  for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
-
-  /* If no difference, continue to next line. */
-  if (ofd == oe && nfd == ne)
-    return;
-
-#if defined (HANDLE_MULTIBYTE)
-  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && _rl_utf8locale)
-    {
-      wchar_t wc;
-      mbstate_t ps = { 0 };
-      int t;
-
-      /* If the first character in the difference is a zero-width character,
-        assume it's a combining character and back one up so the two base
-        characters no longer compare equivalently. */
-      t = mbrtowc (&wc, ofd, MB_CUR_MAX, &ps);
-      if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0)
-       {
-         old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY);
-         new_offset = _rl_find_prev_mbchar (new, nfd - new, MB_FIND_ANY);
-         ofd = old + old_offset;       /* equal by definition */
-         nfd = new + new_offset;
-       }
-    }
-#endif
-
-  wsatend = 1;                 /* flag for trailing whitespace */
-
-#if defined (HANDLE_MULTIBYTE)
-  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-    {
-      ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
-      nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
-
-      while ((ols > ofd) && (nls > nfd))
-       {
-         memset (&ps_old, 0, sizeof (mbstate_t));
-         memset (&ps_new, 0, sizeof (mbstate_t));
-
-#if 0
-         /* On advice from jir@yamato.ibm.com */
-         _rl_adjust_point (old, ols - old, &ps_old);
-         _rl_adjust_point (new, nls - new, &ps_new);
-#endif
-
-         if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
-           break;
-
-         if (*ols == ' ')
-           wsatend = 0;
-
-         ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
-         nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
-       }
-    }
-  else
-    {
-#endif /* HANDLE_MULTIBYTE */
-  ols = oe - 1;                        /* find last same */
-  nls = ne - 1;
-  while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
-    {
-      if (*ols != ' ')
-       wsatend = 0;
-      ols--;
-      nls--;
-    }
-#if defined (HANDLE_MULTIBYTE)
-    }
-#endif
-
-  if (wsatend)
-    {
-      ols = oe;
-      nls = ne;
-    }
-#if defined (HANDLE_MULTIBYTE)
-  /* This may not work for stateful encoding, but who cares?  To handle
-     stateful encoding properly, we have to scan each string from the
-     beginning and compare. */
-  else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
-#else
-  else if (*ols != *nls)
-#endif
-    {
-      if (*ols)                        /* don't step past the NUL */
-       {
-         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-           ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
-         else
-           ols++;
-       }
-      if (*nls)
-       {
-         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-           nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
-         else
-           nls++;
-       }
-    }
-
-  /* count of invisible characters in the current invisible line. */
-  current_invis_chars = W_OFFSET (current_line, wrap_offset);
-  if (_rl_last_v_pos != current_line)
-    {
-      _rl_move_vert (current_line);
-      if ((MB_CUR_MAX == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
-       _rl_last_c_pos += visible_wrap_offset;
-    }
-
-  /* If this is the first line and there are invisible characters in the
-     prompt string, and the prompt string has not changed, and the current
-     cursor position is before the last invisible character in the prompt,
-     and the index of the character to move to is past the end of the prompt
-     string, then redraw the entire prompt string.  We can only do this
-     reliably if the terminal supports a `cr' capability.
-
-     This is not an efficiency hack -- there is a problem with redrawing
-     portions of the prompt string if they contain terminal escape
-     sequences (like drawing the `unbold' sequence without a corresponding
-     `bold') that manifests itself on certain terminals. */
-
-  lendiff = local_prompt_len;
-  od = ofd - old;      /* index of first difference in visible line */
-  if (current_line == 0 && !_rl_horizontal_scroll_mode &&
-      _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
-      od >= lendiff && _rl_last_c_pos < PROMPT_ENDING_INDEX)
-    {
-#if defined (__MSDOS__)
-      putc ('\r', rl_outstream);
-#else
-      tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
-      if (modmark)
-       _rl_output_some_chars ("*", 1);
-      _rl_output_some_chars (local_prompt, lendiff);
-      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-       {
-         /* We take wrap_offset into account here so we can pass correct
-            information to _rl_move_cursor_relative. */
-         _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark;
-         cpos_adjusted = 1;
-       }
-      else
-       _rl_last_c_pos = lendiff + modmark;
-    }
-
-  o_cpos = _rl_last_c_pos;
-
-  /* When this function returns, _rl_last_c_pos is correct, and an absolute
-     cursor postion in multibyte mode, but a buffer index when not in a
-     multibyte locale. */
-  _rl_move_cursor_relative (od, old);
-
-#if defined (HANDLE_MULTIBYTE)
-  /* We need to indicate that the cursor position is correct in the presence of
-     invisible characters in the prompt string.  Let's see if setting this when
-     we make sure we're at the end of the drawn prompt string works. */
-  if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 &&
-      (_rl_last_c_pos > 0 || o_cpos > 0) &&
-      _rl_last_c_pos == prompt_physical_chars)
-    cpos_adjusted = 1;
-#endif
-
-  /* if (len (new) > len (old))
-     lendiff == difference in buffer (bytes)
-     col_lendiff == difference on screen (columns)
-     When not using multibyte characters, these are equal */
-  lendiff = (nls - nfd) - (ols - ofd);
-  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-    col_lendiff = _rl_col_width (new, nfd - new, nls - new, 1) - _rl_col_width (old, ofd - old, ols - old, 1);
-  else
-    col_lendiff = lendiff;
-
-  /* If we are changing the number of invisible characters in a line, and
-     the spot of first difference is before the end of the invisible chars,
-     lendiff needs to be adjusted. */
-  if (current_line == 0 && !_rl_horizontal_scroll_mode &&
-      current_invis_chars != visible_wrap_offset)
-    {
-      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-       {
-         lendiff += visible_wrap_offset - current_invis_chars;
-         col_lendiff += visible_wrap_offset - current_invis_chars;
-       }
-      else
-       {
-         lendiff += visible_wrap_offset - current_invis_chars;
-         col_lendiff = lendiff;
-       }
-    }
-
-  /* We use temp as a count of the number of bytes from the first difference
-     to the end of the new line.  col_temp is the corresponding number of
-     screen columns.  A `dumb' update moves to the spot of first difference
-     and writes TEMP bytes. */
-  /* Insert (diff (len (old), len (new)) ch. */
-  temp = ne - nfd;
-  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-    col_temp = _rl_col_width (new, nfd - new, ne - new, 1);
-  else
-    col_temp = temp;
-
-  /* how many bytes from the new line buffer to write to the display */
-  bytes_to_insert = nls - nfd;
-
-  /* col_lendiff > 0 if we are adding characters to the line */
-  if (col_lendiff > 0) /* XXX - was lendiff */
-    {
-      /* Non-zero if we're increasing the number of lines. */
-      int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
-      /* If col_lendiff is > 0, implying that the new string takes up more
-        screen real estate than the old, but lendiff is < 0, meaning that it
-        takes fewer bytes, we need to just output the characters starting
-        from the first difference.  These will overwrite what is on the
-        display, so there's no reason to do a smart update.  This can really
-        only happen in a multibyte environment. */
-      if (lendiff < 0)
-       {
-         _rl_output_some_chars (nfd, temp);
-         _rl_last_c_pos += col_temp;   /* XXX - was _rl_col_width (nfd, 0, temp, 1); */
-         /* If nfd begins before any invisible characters in the prompt,
-            adjust _rl_last_c_pos to account for wrap_offset and set
-            cpos_adjusted to let the caller know. */
-         if (current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
-           {
-             _rl_last_c_pos -= wrap_offset;
-             cpos_adjusted = 1;
-           }
-         return;
-       }
-      /* Sometimes it is cheaper to print the characters rather than
-        use the terminal's capabilities.  If we're growing the number
-        of lines, make sure we actually cause the new line to wrap
-        around on auto-wrapping terminals. */
-      else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
-       {
-         /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
-            _rl_horizontal_scroll_mode == 1, inserting the characters with
-            _rl_term_IC or _rl_term_ic will screw up the screen because of the
-            invisible characters.  We need to just draw them. */
-         /* The same thing happens if we're trying to draw before the last
-            invisible character in the prompt string or we're increasing the
-            number of invisible characters in the line and we're not drawing
-            the entire prompt string. */
-         if (*ols && ((_rl_horizontal_scroll_mode &&
-                       _rl_last_c_pos == 0 &&
-                       lendiff > prompt_visible_length &&
-                       current_invis_chars > 0) == 0) &&
-                     (((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
-                       current_line == 0 && wrap_offset &&
-                       ((nfd - new) <= prompt_last_invisible) &&
-                       (col_lendiff < prompt_visible_length)) == 0) &&
-                     (visible_wrap_offset >= current_invis_chars))
-           {
-             open_some_spaces (col_lendiff);
-             _rl_output_some_chars (nfd, bytes_to_insert);
-             _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
-           }
-         else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
-           {
-             /* At the end of a line the characters do not have to
-                be "inserted".  They can just be placed on the screen. */
-             /* However, this screws up the rest of this block, which
-                assumes you've done the insert because you can. */
-             _rl_output_some_chars (nfd, lendiff);
-             _rl_last_c_pos += col_lendiff;
-           }
-         else  /* just write from first difference to end of new line */
-           {
-             _rl_output_some_chars (nfd, temp);
-             _rl_last_c_pos += col_temp;
-             /* If nfd begins before the last invisible character in the
-                prompt, adjust _rl_last_c_pos to account for wrap_offset
-                and set cpos_adjusted to let the caller know. */
-             if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
-               {
-                 _rl_last_c_pos -= wrap_offset;
-                 cpos_adjusted = 1;
-               }
-             return;
-           }
-
-         if (bytes_to_insert > lendiff)
-           {
-             /* If nfd begins before the last invisible character in the
-                prompt, adjust _rl_last_c_pos to account for wrap_offset
-                and set cpos_adjusted to let the caller know. */
-             if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
-               {
-                 _rl_last_c_pos -= wrap_offset;
-                 cpos_adjusted = 1;
-               }
-           }
-       }
-      else
-       {
-         /* cannot insert chars, write to EOL */
-         _rl_output_some_chars (nfd, temp);
-         _rl_last_c_pos += col_temp;
-         /* If we're in a multibyte locale and were before the last invisible
-            char in the current line (which implies we just output some invisible
-            characters) we need to adjust _rl_last_c_pos, since it represents
-            a physical character position. */
-         if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
-               current_line == prompt_last_screen_line && wrap_offset &&
-               displaying_prompt_first_line &&
-               wrap_offset != prompt_invis_chars_first_line &&
-               ((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth))))
-           {
-             _rl_last_c_pos -= wrap_offset - prompt_invis_chars_first_line;
-             cpos_adjusted = 1;
-           }
-       }
-    }
-  else                         /* Delete characters from line. */
-    {
-      /* If possible and inexpensive to use terminal deletion, then do so. */
-      if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
-       {
-         /* If all we're doing is erasing the invisible characters in the
-            prompt string, don't bother.  It screws up the assumptions
-            about what's on the screen. */
-         if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
-             displaying_prompt_first_line &&
-             -lendiff == visible_wrap_offset)
-           col_lendiff = 0;
-
-         /* If we have moved lmargin and we're shrinking the line, we've
-            already moved the cursor to the first character of the new line,
-            so deleting -col_lendiff characters will mess up the cursor
-            position calculation */
-         if (_rl_horizontal_scroll_mode && displaying_prompt_first_line == 0 &&
-               col_lendiff && _rl_last_c_pos < -col_lendiff)
-           col_lendiff = 0;
-
-         if (col_lendiff)
-           delete_chars (-col_lendiff); /* delete (diff) characters */
-
-         /* Copy (new) chars to screen from first diff to last match,
-            overwriting what is there. */
-         if (bytes_to_insert > 0)
-           {
-             /* If nfd begins at the prompt, or before the invisible
-                characters in the prompt, we need to adjust _rl_last_c_pos
-                in a multibyte locale to account for the wrap offset and
-                set cpos_adjusted accordingly. */
-             _rl_output_some_chars (nfd, bytes_to_insert);
-             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-               {
-                 _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
-                 if (current_line == 0 && wrap_offset &&
-                       displaying_prompt_first_line &&
-                       _rl_last_c_pos > wrap_offset &&
-                       ((nfd - new) <= prompt_last_invisible))
-                   {
-                     _rl_last_c_pos -= wrap_offset;
-                     cpos_adjusted = 1;
-                   }
-               }
-             else
-               _rl_last_c_pos += bytes_to_insert;
-
-             if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
-               goto clear_rest_of_line;
-           }
-       }
-      /* Otherwise, print over the existing material. */
-      else
-       {
-         if (temp > 0)
-           {
-             /* If nfd begins at the prompt, or before the invisible
-                characters in the prompt, we need to adjust _rl_last_c_pos
-                in a multibyte locale to account for the wrap offset and
-                set cpos_adjusted accordingly. */
-             _rl_output_some_chars (nfd, temp);
-             _rl_last_c_pos += col_temp;               /* XXX */
-             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-               {
-                 if (current_line == 0 && wrap_offset &&
-                       displaying_prompt_first_line &&
-                       _rl_last_c_pos > wrap_offset &&
-                       ((nfd - new) <= prompt_last_invisible))
-                   {
-                     _rl_last_c_pos -= wrap_offset;
-                     cpos_adjusted = 1;
-                   }
-               }
-           }
-clear_rest_of_line:
-         lendiff = (oe - old) - (ne - new);
-         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-           col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
-         else
-           col_lendiff = lendiff;
-
-         /* If we've already printed over the entire width of the screen,
-            including the old material, then col_lendiff doesn't matter and
-            space_to_eol will insert too many spaces.  XXX - maybe we should
-            adjust col_lendiff based on the difference between _rl_last_c_pos
-            and _rl_screenwidth */
-         if (col_lendiff && ((MB_CUR_MAX == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
-           {     
-             if (_rl_term_autowrap && current_line < inv_botlin)
-               space_to_eol (col_lendiff);
-             else
-               _rl_clear_to_eol (col_lendiff);
-           }
-       }
-    }
-}
-
-/* Tell the update routines that we have moved onto a new (empty) line. */
-int
-rl_on_new_line ()
-{
-  if (visible_line)
-    visible_line[0] = '\0';
-
-  _rl_last_c_pos = _rl_last_v_pos = 0;
-  _rl_vis_botlin = last_lmargin = 0;
-  if (vis_lbreaks)
-    vis_lbreaks[0] = vis_lbreaks[1] = 0;
-  visible_wrap_offset = 0;
-  return 0;
-}
-
-/* Tell the update routines that we have moved onto a new line with the
-   prompt already displayed.  Code originally from the version of readline
-   distributed with CLISP.  rl_expand_prompt must have already been called
-   (explicitly or implicitly).  This still doesn't work exactly right. */
-int
-rl_on_new_line_with_prompt ()
-{
-  int prompt_size, i, l, real_screenwidth, newlines;
-  char *prompt_last_line, *lprompt;
-
-  /* Initialize visible_line and invisible_line to ensure that they can hold
-     the already-displayed prompt. */
-  prompt_size = strlen (rl_prompt) + 1;
-  init_line_structures (prompt_size);
-
-  /* Make sure the line structures hold the already-displayed prompt for
-     redisplay. */
-  lprompt = local_prompt ? local_prompt : rl_prompt;
-  strcpy (visible_line, lprompt);
-  strcpy (invisible_line, lprompt);
-
-  /* If the prompt contains newlines, take the last tail. */
-  prompt_last_line = strrchr (rl_prompt, '\n');
-  if (!prompt_last_line)
-    prompt_last_line = rl_prompt;
-
-  l = strlen (prompt_last_line);
-  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-    _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1);        /* XXX */
-  else
-    _rl_last_c_pos = l;
-
-  /* Dissect prompt_last_line into screen lines. Note that here we have
-     to use the real screenwidth. Readline's notion of screenwidth might be
-     one less, see terminal.c. */
-  real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
-  _rl_last_v_pos = l / real_screenwidth;
-  /* If the prompt length is a multiple of real_screenwidth, we don't know
-     whether the cursor is at the end of the last line, or already at the
-     beginning of the next line. Output a newline just to be safe. */
-  if (l > 0 && (l % real_screenwidth) == 0)
-    _rl_output_some_chars ("\n", 1);
-  last_lmargin = 0;
-
-  newlines = 0; i = 0;
-  while (i <= l)
-    {
-      _rl_vis_botlin = newlines;
-      vis_lbreaks[newlines++] = i;
-      i += real_screenwidth;
-    }
-  vis_lbreaks[newlines] = l;
-  visible_wrap_offset = 0;
-
-  rl_display_prompt = rl_prompt;       /* XXX - make sure it's set */
-
-  return 0;
-}
-
-/* Actually update the display, period. */
-int
-rl_forced_update_display ()
-{
-  register char *temp;
-
-  if (visible_line)
-    {
-      temp = visible_line;
-      while (*temp)
-       *temp++ = '\0';
-    }
-  rl_on_new_line ();
-  forced_display++;
-  (*rl_redisplay_function) ();
-  return 0;
-}
-
-/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
-   (Well, when we don't have multibyte characters, _rl_last_c_pos is a
-   buffer index.)
-   DATA is the contents of the screen line of interest; i.e., where
-   the movement is being done. */
-void
-_rl_move_cursor_relative (new, data)
-     int new;
-     const char *data;
-{
-  register int i;
-  int woff;                    /* number of invisible chars on current line */
-  int cpos, dpos;              /* current and desired cursor positions */
-  int adjust;
-
-  woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
-  cpos = _rl_last_c_pos;
-
-  if (cpos == 0 && cpos == new)
-    return;
-
-#if defined (HANDLE_MULTIBYTE)
-  /* If we have multibyte characters, NEW is indexed by the buffer point in
-     a multibyte string, but _rl_last_c_pos is the display position.  In
-     this case, NEW's display position is not obvious and must be
-     calculated.  We need to account for invisible characters in this line,
-     as long as we are past them and they are counted by _rl_col_width. */
-  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-    {
-      adjust = 1;
-      /* Try to short-circuit common cases and eliminate a bunch of multibyte
-        character function calls. */
-      /* 1.  prompt string */
-      if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0)
-       {
-         dpos = prompt_physical_chars;
-         cpos_adjusted = 1;
-         adjust = 0;
-       }
-      /* 2.  prompt_string + line contents */
-      else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0)
-       {
-         dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1);
-         cpos_adjusted = 1;
-         adjust = 0;
-       }
-      else
-        dpos = _rl_col_width (data, 0, new, 1);
-
-      if (displaying_prompt_first_line == 0)
-       adjust = 0;
-
-      /* Use NEW when comparing against the last invisible character in the
-        prompt string, since they're both buffer indices and DPOS is a
-        desired display position. */
-      if (adjust && ((new > prompt_last_invisible) ||          /* XXX - don't use woff here */
-         (prompt_physical_chars >= _rl_screenwidth &&
-          _rl_last_v_pos == prompt_last_screen_line &&
-          wrap_offset >= woff && dpos >= woff &&
-          new > (prompt_last_invisible-(_rl_screenwidth*_rl_last_v_pos)-wrap_offset))))
-          /* XXX last comparison might need to be >= */
-       {
-         dpos -= woff;
-         /* Since this will be assigned to _rl_last_c_pos at the end (more
-            precisely, _rl_last_c_pos == dpos when this function returns),
-            let the caller know. */
-         cpos_adjusted = 1;
-       }
-    }
-  else
-#endif
-    dpos = new;
-
-  /* If we don't have to do anything, then return. */
-  if (cpos == dpos)
-    return;
-
-  /* It may be faster to output a CR, and then move forwards instead
-     of moving backwards. */
-  /* i == current physical cursor position. */
-#if defined (HANDLE_MULTIBYTE)
-  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-    i = _rl_last_c_pos;
-  else
-#endif
-  i = _rl_last_c_pos - woff;
-  if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
-      (_rl_term_autowrap && i == _rl_screenwidth))
-    {
-#if defined (__MSDOS__)
-      putc ('\r', rl_outstream);
-#else
-      tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif /* !__MSDOS__ */
-      cpos = _rl_last_c_pos = 0;
-    }
-
-  if (cpos < dpos)
-    {
-      /* Move the cursor forward.  We do it by printing the command
-        to move the cursor forward if there is one, else print that
-        portion of the output buffer again.  Which is cheaper? */
-
-      /* The above comment is left here for posterity.  It is faster
-        to print one character (non-control) than to print a control
-        sequence telling the terminal to move forward one character.
-        That kind of control is for people who don't know what the
-        data is underneath the cursor. */
-
-      /* However, we need a handle on where the current display position is
-        in the buffer for the immediately preceding comment to be true.
-        In multibyte locales, we don't currently have that info available.
-        Without it, we don't know where the data we have to display begins
-        in the buffer and we have to go back to the beginning of the screen
-        line.  In this case, we can use the terminal sequence to move forward
-        if it's available. */
-      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-       {
-         if (_rl_term_forward_char)
-           {
-             for (i = cpos; i < dpos; i++)
-               tputs (_rl_term_forward_char, 1, _rl_output_character_function);
-           }
-         else
-           {
-             tputs (_rl_term_cr, 1, _rl_output_character_function);
-             for (i = 0; i < new; i++)
-               putc (data[i], rl_outstream);
-           }
-       }
-      else
-       for (i = cpos; i < new; i++)
-         putc (data[i], rl_outstream);
-    }
-
-#if defined (HANDLE_MULTIBYTE)
-  /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
-     The byte length of the string is probably bigger than the column width
-     of the string, which means that if NEW == _rl_last_c_pos, then NEW's
-     display point is less than _rl_last_c_pos. */
-#endif
-  else if (cpos > dpos)
-    _rl_backspace (cpos - dpos);
-
-  _rl_last_c_pos = dpos;
-}
-
-/* PWP: move the cursor up or down. */
-void
-_rl_move_vert (to)
-     int to;
-{
-  register int delta, i;
-
-  if (_rl_last_v_pos == to || to > _rl_screenheight)
-    return;
-
-  if ((delta = to - _rl_last_v_pos) > 0)
-    {
-      for (i = 0; i < delta; i++)
-       putc ('\n', rl_outstream);
-#if defined (__MSDOS__)
-      putc ('\r', rl_outstream);
-#else
-      tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
-      _rl_last_c_pos = 0;
-    }
-  else
-    {                  /* delta < 0 */
-#ifdef __DJGPP__
-      int row, col;
-
-      fflush (rl_outstream);
-      ScreenGetCursor (&row, &col);
-      ScreenSetCursor (row + delta, col);
-      i = -delta;
-#else
-      if (_rl_term_up && *_rl_term_up)
-       for (i = 0; i < -delta; i++)
-         tputs (_rl_term_up, 1, _rl_output_character_function);
-#endif /* !__DJGPP__ */
-    }
-
-  _rl_last_v_pos = to;         /* Now TO is here */
-}
-
-/* Physically print C on rl_outstream.  This is for functions which know
-   how to optimize the display.  Return the number of characters output. */
-int
-rl_show_char (c)
-     int c;
-{
-  int n = 1;
-  if (META_CHAR (c) && (_rl_output_meta_chars == 0))
-    {
-      fprintf (rl_outstream, "M-");
-      n += 2;
-      c = UNMETA (c);
-    }
-
-#if defined (DISPLAY_TABS)
-  if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
-#else
-  if (CTRL_CHAR (c) || c == RUBOUT)
-#endif /* !DISPLAY_TABS */
-    {
-      fprintf (rl_outstream, "C-");
-      n += 2;
-      c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
-    }
-
-  putc (c, rl_outstream);
-  fflush (rl_outstream);
-  return n;
-}
-
-int
-rl_character_len (c, pos)
-     register int c, pos;
-{
-  unsigned char uc;
-
-  uc = (unsigned char)c;
-
-  if (META_CHAR (uc))
-    return ((_rl_output_meta_chars == 0) ? 4 : 1);
-
-  if (uc == '\t')
-    {
-#if defined (DISPLAY_TABS)
-      return (((pos | 7) + 1) - pos);
-#else
-      return (2);
-#endif /* !DISPLAY_TABS */
-    }
-
-  if (CTRL_CHAR (c) || c == RUBOUT)
-    return (2);
-
-  return ((ISPRINT (uc)) ? 1 : 2);
-}
-/* How to print things in the "echo-area".  The prompt is treated as a
-   mini-modeline. */
-static int msg_saved_prompt = 0;
-
-#if defined (USE_VARARGS)
-int
-#if defined (PREFER_STDARG)
-rl_message (const char *format, ...)
-#else
-rl_message (va_alist)
-     va_dcl
-#endif
-{
-  va_list args;
-#if defined (PREFER_VARARGS)
-  char *format;
-#endif
-#if defined (HAVE_VSNPRINTF)
-  int bneed;
-#endif
-
-#if defined (PREFER_STDARG)
-  va_start (args, format);
-#else
-  va_start (args);
-  format = va_arg (args, char *);
-#endif
-
-  if (msg_buf == 0)
-    msg_buf = xmalloc (msg_bufsiz = 128);
-
-#if defined (HAVE_VSNPRINTF)
-  bneed = vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
-  if (bneed >= msg_bufsiz - 1)
-    {
-      msg_bufsiz = bneed + 1;
-      msg_buf = xrealloc (msg_buf, msg_bufsiz);
-      va_end (args);
-
-#if defined (PREFER_STDARG)
-      va_start (args, format);
-#else
-      va_start (args);
-      format = va_arg (args, char *);
-#endif
-      vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
-    }
-#else
-  vsprintf (msg_buf, format, args);
-  msg_buf[msg_bufsiz - 1] = '\0';      /* overflow? */
-#endif
-  va_end (args);
-
-  if (saved_local_prompt == 0)
-    {
-      rl_save_prompt ();
-      msg_saved_prompt = 1;
-    }
-  else if (local_prompt != saved_local_prompt)
-    {
-      FREE (local_prompt);
-      FREE (local_prompt_prefix);
-      local_prompt = (char *)NULL;
-    }
-  rl_display_prompt = msg_buf;
-  local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
-                                        &prompt_last_invisible,
-                                        &prompt_invis_chars_first_line,
-                                        &prompt_physical_chars);
-  local_prompt_prefix = (char *)NULL;
-  local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
-  (*rl_redisplay_function) ();
-
-  return 0;
-}
-#else /* !USE_VARARGS */
-int
-rl_message (format, arg1, arg2)
-     char *format;
-{
-  if (msg_buf == 0)
-    msg_buf = xmalloc (msg_bufsiz = 128);
-
-  sprintf (msg_buf, format, arg1, arg2);
-  msg_buf[msg_bufsiz - 1] = '\0';      /* overflow? */
-
-  rl_display_prompt = msg_buf;
-  if (saved_local_prompt == 0)
-    {
-      rl_save_prompt ();
-      msg_saved_prompt = 1;
-    }
-  else if (local_prompt != saved_local_prompt)
-    {
-      FREE (local_prompt);
-      FREE (local_prompt_prefix);
-      local_prompt = (char *)NULL;
-    }
-  local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
-                                        &prompt_last_invisible,
-                                        &prompt_invis_chars_first_line,
-                                        &prompt_physical_chars);
-  local_prompt_prefix = (char *)NULL;
-  local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
-  (*rl_redisplay_function) ();
-      
-  return 0;
-}
-#endif /* !USE_VARARGS */
-
-/* How to clear things from the "echo-area". */
-int
-rl_clear_message ()
-{
-  rl_display_prompt = rl_prompt;
-  if (msg_saved_prompt)
-    {
-      rl_restore_prompt ();
-      msg_saved_prompt = 0;
-    }
-  (*rl_redisplay_function) ();
-  return 0;
-}
-
-int
-rl_reset_line_state ()
-{
-  rl_on_new_line ();
-
-  rl_display_prompt = rl_prompt ? rl_prompt : "";
-  forced_display = 1;
-  return 0;
-}
-
-void
-rl_save_prompt ()
-{
-  saved_local_prompt = local_prompt;
-  saved_local_prefix = local_prompt_prefix;
-  saved_prefix_length = prompt_prefix_length;
-  saved_local_length = local_prompt_len;
-  saved_last_invisible = prompt_last_invisible;
-  saved_visible_length = prompt_visible_length;
-  saved_invis_chars_first_line = prompt_invis_chars_first_line;
-  saved_physical_chars = prompt_physical_chars;
-
-  local_prompt = local_prompt_prefix = (char *)0;
-  local_prompt_len = 0;
-  prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
-  prompt_invis_chars_first_line = prompt_physical_chars = 0;
-}
-
-void
-rl_restore_prompt ()
-{
-  FREE (local_prompt);
-  FREE (local_prompt_prefix);
-
-  local_prompt = saved_local_prompt;
-  local_prompt_prefix = saved_local_prefix;
-  local_prompt_len = saved_local_length;
-  prompt_prefix_length = saved_prefix_length;
-  prompt_last_invisible = saved_last_invisible;
-  prompt_visible_length = saved_visible_length;
-  prompt_invis_chars_first_line = saved_invis_chars_first_line;
-  prompt_physical_chars = saved_physical_chars;
-
-  /* can test saved_local_prompt to see if prompt info has been saved. */
-  saved_local_prompt = saved_local_prefix = (char *)0;
-  saved_local_length = 0;
-  saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
-  saved_invis_chars_first_line = saved_physical_chars = 0;
-}
-
-char *
-_rl_make_prompt_for_search (pchar)
-     int pchar;
-{
-  int len;
-  char *pmt, *p;
-
-  rl_save_prompt ();
-
-  /* We've saved the prompt, and can do anything with the various prompt
-     strings we need before they're restored.  We want the unexpanded
-     portion of the prompt string after any final newline. */
-  p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
-  if (p == 0)
-    {
-      len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
-      pmt = (char *)xmalloc (len + 2);
-      if (len)
-       strcpy (pmt, rl_prompt);
-      pmt[len] = pchar;
-      pmt[len+1] = '\0';
-    }
-  else
-    {
-      p++;
-      len = strlen (p);
-      pmt = (char *)xmalloc (len + 2);
-      if (len)
-       strcpy (pmt, p);
-      pmt[len] = pchar;
-      pmt[len+1] = '\0';
-    }  
-
-  /* will be overwritten by expand_prompt, called from rl_message */
-  prompt_physical_chars = saved_physical_chars + 1;
-  return pmt;
-}
-
-/* Quick redisplay hack when erasing characters at the end of the line. */
-void
-_rl_erase_at_end_of_line (l)
-     int l;
-{
-  register int i;
-
-  _rl_backspace (l);
-  for (i = 0; i < l; i++)
-    putc (' ', rl_outstream);
-  _rl_backspace (l);
-  for (i = 0; i < l; i++)
-    visible_line[--_rl_last_c_pos] = '\0';
-  rl_display_fixed++;
-}
-
-/* Clear to the end of the line.  COUNT is the minimum
-   number of character spaces to clear, */
-void
-_rl_clear_to_eol (count)
-     int count;
-{
-#ifndef __MSDOS__
-  if (_rl_term_clreol)
-    tputs (_rl_term_clreol, 1, _rl_output_character_function);
-  else
-#endif
-    if (count)
-      space_to_eol (count);
-}
-
-/* Clear to the end of the line using spaces.  COUNT is the minimum
-   number of character spaces to clear, */
-static void
-space_to_eol (count)
-     int count;
-{
-  register int i;
-
-  for (i = 0; i < count; i++)
-   putc (' ', rl_outstream);
-
-  _rl_last_c_pos += count;
-}
-
-void
-_rl_clear_screen ()
-{
-#ifndef __DJGPP__
-  if (_rl_term_clrpag)
-    tputs (_rl_term_clrpag, 1, _rl_output_character_function);
-  else
-    rl_crlf ();
-#else
-  ScreenClear ();
-  ScreenSetCursor (0, 0);
-#endif /* __DJGPP__ */
-}
-
-/* Insert COUNT characters from STRING to the output stream at column COL. */
-static void
-insert_some_chars (string, count, col)
-     char *string;
-     int count, col;
-{
-  open_some_spaces (col);
-  _rl_output_some_chars (string, count);
-}
-
-/* Insert COL spaces, keeping the cursor at the same position.  We follow the
-   ncurses documentation and use either im/ei with explicit spaces, or IC/ic
-   by itself.  We assume there will either be ei or we don't need to use it. */
-static void
-open_some_spaces (col)
-     int col;
-{
-#if !defined (__MSDOS__) && !defined (__MINGW32__)
-  char *buffer;
-  register int i;
-
-  /* If IC is defined, then we do not have to "enter" insert mode. */
-  if (_rl_term_IC)
-    {
-      buffer = tgoto (_rl_term_IC, 0, col);
-      tputs (buffer, 1, _rl_output_character_function);
-    }
-  else if (_rl_term_im && *_rl_term_im)
-    {
-      tputs (_rl_term_im, 1, _rl_output_character_function);
-      /* just output the desired number of spaces */
-      for (i = col; i--; )
-       _rl_output_character_function (' ');
-      /* If there is a string to turn off insert mode, use it now. */
-      if (_rl_term_ei && *_rl_term_ei)
-       tputs (_rl_term_ei, 1, _rl_output_character_function);
-      /* and move back the right number of spaces */
-      _rl_backspace (col);
-    }
-  else if (_rl_term_ic && *_rl_term_ic)
-    {
-      /* If there is a special command for inserting characters, then
-        use that first to open up the space. */
-      for (i = col; i--; )
-       tputs (_rl_term_ic, 1, _rl_output_character_function);
-    }
-#endif /* !__MSDOS__ && !__MINGW32__ */
-}
-
-/* Delete COUNT characters from the display line. */
-static void
-delete_chars (count)
-     int count;
-{
-  if (count > _rl_screenwidth) /* XXX */
-    return;
-
-#if !defined (__MSDOS__) && !defined (__MINGW32__)
-  if (_rl_term_DC && *_rl_term_DC)
-    {
-      char *buffer;
-      buffer = tgoto (_rl_term_DC, count, count);
-      tputs (buffer, count, _rl_output_character_function);
-    }
-  else
-    {
-      if (_rl_term_dc && *_rl_term_dc)
-       while (count--)
-         tputs (_rl_term_dc, 1, _rl_output_character_function);
-    }
-#endif /* !__MSDOS__ && !__MINGW32__ */
-}
-
-void
-_rl_update_final ()
-{
-  int full_lines;
-
-  full_lines = 0;
-  /* If the cursor is the only thing on an otherwise-blank last line,
-     compensate so we don't print an extra CRLF. */
-  if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
-       visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
-    {
-      _rl_vis_botlin--;
-      full_lines = 1;
-    }
-  _rl_move_vert (_rl_vis_botlin);
-  /* If we've wrapped lines, remove the final xterm line-wrap flag. */
-  if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
-    {
-      char *last_line;
-
-      last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
-      cpos_buffer_position = -1;       /* don't know where we are in buffer */
-      _rl_move_cursor_relative (_rl_screenwidth - 1, last_line);       /* XXX */
-      _rl_clear_to_eol (0);
-      putc (last_line[_rl_screenwidth - 1], rl_outstream);
-    }
-  _rl_vis_botlin = 0;
-  rl_crlf ();
-  fflush (rl_outstream);
-  rl_display_fixed++;
-}
-
-/* Move to the start of the current line. */
-static void
-cr ()
-{
-  if (_rl_term_cr)
-    {
-#if defined (__MSDOS__)
-      putc ('\r', rl_outstream);
-#else
-      tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
-      _rl_last_c_pos = 0;
-    }
-}
-
-/* Redraw the last line of a multi-line prompt that may possibly contain
-   terminal escape sequences.  Called with the cursor at column 0 of the
-   line to draw the prompt on. */
-static void
-redraw_prompt (t)
-     char *t;
-{
-  char *oldp;
-
-  oldp = rl_display_prompt;
-  rl_save_prompt ();
-
-  rl_display_prompt = t;
-  local_prompt = expand_prompt (t, &prompt_visible_length,
-                                  &prompt_last_invisible,
-                                  &prompt_invis_chars_first_line,
-                                  &prompt_physical_chars);
-  local_prompt_prefix = (char *)NULL;
-  local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
-
-  rl_forced_update_display ();
-
-  rl_display_prompt = oldp;
-  rl_restore_prompt();
-}
-      
-/* Redisplay the current line after a SIGWINCH is received. */
-void
-_rl_redisplay_after_sigwinch ()
-{
-  char *t;
-
-  /* Clear the last line (assuming that the screen size change will result in
-     either more or fewer characters on that line only) and put the cursor at
-     column 0.  Make sure the right thing happens if we have wrapped to a new
-     screen line. */
-  if (_rl_term_cr)
-    {
-      _rl_move_vert (_rl_vis_botlin);
-
-#if defined (__MSDOS__)
-      putc ('\r', rl_outstream);
-#else
-      tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
-      _rl_last_c_pos = 0;
-#if defined (__MSDOS__)
-      space_to_eol (_rl_screenwidth);
-      putc ('\r', rl_outstream);
-#else
-      if (_rl_term_clreol)
-       tputs (_rl_term_clreol, 1, _rl_output_character_function);
-      else
-       {
-         space_to_eol (_rl_screenwidth);
-         tputs (_rl_term_cr, 1, _rl_output_character_function);
-       }
-#endif
-      if (_rl_last_v_pos > 0)
-       _rl_move_vert (0);
-    }
-  else
-    rl_crlf ();
-
-  /* Redraw only the last line of a multi-line prompt. */
-  t = strrchr (rl_display_prompt, '\n');
-  if (t)
-    redraw_prompt (++t);
-  else
-    rl_forced_update_display ();
-}
-
-void
-_rl_clean_up_for_exit ()
-{
-  if (_rl_echoing_p)
-    {
-      _rl_move_vert (_rl_vis_botlin);
-      _rl_vis_botlin = 0;
-      fflush (rl_outstream);
-      rl_restart_output (1, 0);
-    }
-}
-
-void
-_rl_erase_entire_line ()
-{
-  cr ();
-  _rl_clear_to_eol (0);
-  cr ();
-  fflush (rl_outstream);
-}
-
-/* return the `current display line' of the cursor -- the number of lines to
-   move up to get to the first screen line of the current readline line. */
-int
-_rl_current_display_line ()
-{
-  int ret, nleft;
-
-  /* Find out whether or not there might be invisible characters in the
-     editing buffer. */
-  if (rl_display_prompt == rl_prompt)
-    nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
-  else
-    nleft = _rl_last_c_pos - _rl_screenwidth;
-
-  if (nleft > 0)
-    ret = 1 + nleft / _rl_screenwidth;
-  else
-    ret = 0;
-
-  return ret;
-}
-
-#if defined (HANDLE_MULTIBYTE)
-/* Calculate the number of screen columns occupied by STR from START to END.
-   In the case of multibyte characters with stateful encoding, we have to
-   scan from the beginning of the string to take the state into account. */
-static int
-_rl_col_width (str, start, end, flags)
-     const char *str;
-     int start, end, flags;
-{
-  wchar_t wc;
-  mbstate_t ps;
-  int tmp, point, width, max;
-
-  if (end <= start)
-    return 0;
-  if (MB_CUR_MAX == 1 || rl_byte_oriented)
-{
-_rl_ttymsg ("_rl_col_width: called with MB_CUR_MAX == 1");
-    return (end - start);
-}
-
-  memset (&ps, 0, sizeof (mbstate_t));
-
-  point = 0;
-  max = end;
-
-  /* Try to short-circuit common cases.  The adjustment to remove wrap_offset
-     is done by the caller. */
-  /* 1.  prompt string */
-  if (flags && start == 0 && end == local_prompt_len && memcmp (str, local_prompt, local_prompt_len) == 0)
-    return (prompt_physical_chars + wrap_offset);
-  /* 2.  prompt string + line contents */
-  else if (flags && start == 0 && local_prompt_len > 0 && end > local_prompt_len && local_prompt && memcmp (str, local_prompt, local_prompt_len) == 0)
-    {
-      tmp = prompt_physical_chars + wrap_offset;
-      /* XXX - try to call ourselves recursively with non-prompt portion */
-      tmp += _rl_col_width (str, local_prompt_len, end, flags);
-      return (tmp);
-    }
-
-  while (point < start)
-    {
-      tmp = mbrlen (str + point, max, &ps);
-      if (MB_INVALIDCH ((size_t)tmp))
-       {
-         /* In this case, the bytes are invalid or too short to compose a
-            multibyte character, so we assume that the first byte represents
-            a single character. */
-         point++;
-         max--;
-
-         /* 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 (MB_NULLWCH (tmp))
-       break;          /* Found '\0' */
-      else
-       {
-         point += tmp;
-         max -= tmp;
-       }
-    }
-
-  /* If START is not a byte that starts a character, then POINT will be
-     greater than START.  In this case, assume that (POINT - START) gives
-     a byte count that is the number of columns of difference. */
-  width = point - start;
-
-  while (point < end)
-    {
-      tmp = mbrtowc (&wc, str + point, max, &ps);
-      if (MB_INVALIDCH ((size_t)tmp))
-       {
-         /* In this case, the bytes are invalid or too short to compose a
-            multibyte character, so we assume that the first byte represents
-            a single character. */
-         point++;
-         max--;
-
-         /* and assume that the byte occupies a single column. */
-         width++;
-
-         /* 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 (MB_NULLWCH (tmp))
-       break;                  /* Found '\0' */
-      else
-       {
-         point += tmp;
-         max -= tmp;
-         tmp = WCWIDTH(wc);
-         width += (tmp >= 0) ? tmp : 1;
-       }
-    }
-
-  width += point - end;
-
-  return width;
-}
-#endif /* HANDLE_MULTIBYTE */
diff --git a/lib/readline/doc/Makefile.old b/lib/readline/doc/Makefile.old
deleted file mode 100644 (file)
index 58d4dd7..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-# This makefile for Readline library documentation is in -*- text -*- mode.
-# Emacs likes it that way.
-RM = rm -f
-
-MAKEINFO    = makeinfo
-TEXI2DVI    = texi2dvi
-TEXI2HTML   = texi2html
-QUIETPS     = #set this to -q to shut up dvips
-DVIPS       = dvips -D 300 $(QUIETPS) -o $@     # tricky
-
-INSTALL_DATA = cp
-infodir = /usr/local/info
-
-RLSRC = rlman.texinfo rluser.texinfo rltech.texinfo
-HISTSRC = hist.texinfo hsuser.texinfo hstech.texinfo
-
-DVIOBJ = readline.dvi history.dvi
-INFOOBJ = readline.info history.info
-PSOBJ = readline.ps history.ps
-HTMLOBJ = readline.html history.html
-
-all: info dvi html ps
-nodvi: info html
-
-readline.dvi: $(RLSRC)
-       $(TEXI2DVI) rlman.texinfo
-       mv rlman.dvi readline.dvi
-
-readline.info: $(RLSRC)
-       $(MAKEINFO) --no-split -o $@ rlman.texinfo
-
-history.dvi: ${HISTSRC}
-       $(TEXI2DVI) hist.texinfo
-       mv hist.dvi history.dvi
-
-history.info: ${HISTSRC}
-       $(MAKEINFO) --no-split -o $@ hist.texinfo
-
-readline.ps:   readline.dvi
-       $(RM) $@
-       $(DVIPS) readline.dvi
-
-history.ps:    history.dvi
-       $(RM) $@
-       $(DVIPS) history.dvi
-
-readline.html: ${RLSRC}
-       $(TEXI2HTML) rlman.texinfo
-       sed -e 's:rlman.html:readline.html:' -e 's:rlman_toc.html:readline_toc.html:' rlman.html > readline.html
-       sed -e 's:rlman.html:readline.html:' -e 's:rlman_toc.html:readline_toc.html:' rlman_toc.html > readline_toc.html
-       $(RM) rlman.html rlman_toc.html
-
-history.html:  ${HISTSRC}
-       $(TEXI2HTML) hist.texinfo
-       sed -e 's:hist.html:history.html:' -e 's:hist_toc.html:history_toc.html:' hist.html > history.html
-       sed -e 's:hist.html:history.html:' -e 's:hist_toc.html:history_toc.html:' hist_toc.html > history_toc.html
-       $(RM) hist.html hist_toc.html
-
-info:  $(INFOOBJ)
-dvi:   $(DVIOBJ)
-ps:    $(PSOBJ)
-html:  $(HTMLOBJ)
-
-clean:
-       $(RM) *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr *.cps *.pgs \
-             *.fns *.kys *.tps *.vrs *.o core
-
-distclean: clean
-mostlyclean: clean
-
-maintainer-clean: clean
-       $(RM) *.dvi *.info *.info-* *.ps *.html
-
-install:       info
-       ${INSTALL_DATA} readline.info $(infodir)/readline.info
-       ${INSTALL_DATA} history.info $(infodir)/history.info
diff --git a/quit.h~ b/quit.h~
deleted file mode 100644 (file)
index adfb3eb..0000000
--- a/quit.h~
+++ /dev/null
@@ -1,79 +0,0 @@
-/* quit.h -- How to handle SIGINT gracefully. */
-
-/* Copyright (C) 1993-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/>.
-*/
-
-#if !defined (_QUIT_H_)
-#define _QUIT_H_
-
-/* Non-zero means SIGINT has already ocurred. */
-extern volatile int interrupt_state;
-extern volatile int terminating_signal;
-
-extern sig_atomic_t sigterm_received;
-
-/* Macro to call a great deal.  SIGINT just sets the interrupt_state variable.
-   When it is safe, put QUIT in the code, and the "interrupt" will take
-   place.  The same scheme is used for terminating signals (e.g., SIGHUP)
-   and the terminating_signal variable.  That calls a function which will
-   end up exiting the shell. */
-#define QUIT \
-  do { \
-    if (terminating_signal) termsig_handler (terminating_signal); \
-    if (interrupt_state) throw_to_top_level (); \
-  } while (0)
-
-#define CHECK_ALRM \
-  do { \
-    if (sigalrm_seen) \
-      longjmp (alrmbuf, 1); \
-  } while (0)
-
-#define SETINTERRUPT interrupt_state = 1
-#define CLRINTERRUPT interrupt_state = 0
-
-#define ADDINTERRUPT interrupt_state++
-#define DELINTERRUPT interrupt_state--
-
-/* The same sort of thing, this time just for signals that would ordinarily
-   cause the shell to terminate. */
-
-#define CHECK_TERMSIG \
-  do { \
-    if (terminating_signal) termsig_handler (terminating_signal); \
-  } while (0)
-
-#define LASTSIG() \
-  (terminating_signal ? terminating_signal : (interrupt_state ? SIGINT : 0))
-
-#define CHECK_WAIT_INTR \
-  do { \
-    if (wait_signal_received && this_shell_builtin && (this_shell_builtin == wait_builtin)) \
-      longjmp (wait_intr_buf, 1); \
-  } while (0)
-
-#define RESET_SIGTERM \
-  do { \
-    sigterm_received = 0; \
-  } while (0)
-
-#define CHECK_SIGTERM \
-  do { \
-    if (sigterm_received) termsig_handler (SIGTERM); \
-  } while (0)
-#endif /* _QUIT_H_ */
diff --git a/sig.c~ b/sig.c~
deleted file mode 100644 (file)
index 539a1ff..0000000
--- a/sig.c~
+++ /dev/null
@@ -1,722 +0,0 @@
-/* sig.c - interface for shell signal handlers and signal initialization. */
-
-/* Copyright (C) 1994-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"
-
-#if defined (HAVE_UNISTD_H)
-#  ifdef _MINIX
-#    include <sys/types.h>
-#  endif
-#  include <unistd.h>
-#endif
-
-#include <stdio.h>
-#include <signal.h>
-
-#include "bashintl.h"
-
-#include "shell.h"
-#if defined (JOB_CONTROL)
-#include "jobs.h"
-#endif /* JOB_CONTROL */
-#include "siglist.h"
-#include "sig.h"
-#include "trap.h"
-
-#include "builtins/common.h"
-
-#if defined (READLINE)
-#  include "bashline.h"
-#  include <readline/readline.h>
-#endif
-
-#if defined (HISTORY)
-#  include "bashhist.h"
-#endif
-
-extern int last_command_exit_value;
-extern int last_command_exit_signal;
-extern int return_catch_flag;
-extern int loop_level, continuing, breaking, funcnest;
-extern int executing_list;
-extern int comsub_ignore_return;
-extern int parse_and_execute_level, shell_initialized;
-#if defined (HISTORY)
-extern int history_lines_this_session;
-#endif
-extern int no_line_editing;
-
-extern void initialize_siglist ();
-
-/* Non-zero after SIGINT. */
-volatile int interrupt_state = 0;
-
-/* Non-zero after SIGWINCH */
-volatile int sigwinch_received = 0;
-
-/* Set to the value of any terminating signal received. */
-volatile int terminating_signal = 0;
-
-sig_atomic_t sigterm_received = 0;
-
-/* The environment at the top-level R-E loop.  We use this in
-   the case of error return. */
-procenv_t top_level;
-
-#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
-/* The signal masks that this shell runs with. */
-sigset_t top_level_mask;
-#endif /* JOB_CONTROL */
-
-/* When non-zero, we throw_to_top_level (). */
-int interrupt_immediately = 0;
-
-/* When non-zero, we call the terminating signal handler immediately. */
-int terminate_immediately = 0;
-
-#if defined (SIGWINCH)
-static SigHandler *old_winch = (SigHandler *)SIG_DFL;
-#endif
-
-static void initialize_shell_signals __P((void));
-
-void
-initialize_signals (reinit)
-     int reinit;
-{
-  initialize_shell_signals ();
-  initialize_job_signals ();
-#if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
-  if (reinit == 0)
-    initialize_siglist ();
-#endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
-}
-
-/* A structure describing a signal that terminates the shell if not
-   caught.  The orig_handler member is present so children can reset
-   these signals back to their original handlers. */
-struct termsig {
-     int signum;
-     SigHandler *orig_handler;
-     int orig_flags;
-};
-
-#define NULL_HANDLER (SigHandler *)SIG_DFL
-
-/* The list of signals that would terminate the shell if not caught.
-   We catch them, but just so that we can write the history file,
-   and so forth. */
-static struct termsig terminating_signals[] = {
-#ifdef SIGHUP
-{  SIGHUP, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGINT
-{  SIGINT, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGILL
-{  SIGILL, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGTRAP
-{  SIGTRAP, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGIOT
-{  SIGIOT, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGDANGER
-{  SIGDANGER, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGEMT
-{  SIGEMT, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGFPE
-{  SIGFPE, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGBUS
-{  SIGBUS, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGSEGV
-{  SIGSEGV, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGSYS
-{  SIGSYS, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGPIPE
-{  SIGPIPE, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGALRM
-{  SIGALRM, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGTERM
-{  SIGTERM, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGXCPU
-{  SIGXCPU, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGXFSZ
-{  SIGXFSZ, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGVTALRM
-{  SIGVTALRM, NULL_HANDLER, 0 },
-#endif
-
-#if 0
-#ifdef SIGPROF
-{  SIGPROF, NULL_HANDLER, 0 },
-#endif
-#endif
-
-#ifdef SIGLOST
-{  SIGLOST, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGUSR1
-{  SIGUSR1, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGUSR2
-{  SIGUSR2, NULL_HANDLER, 0 },
-#endif
-};
-
-#define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
-
-#define XSIG(x) (terminating_signals[x].signum)
-#define XHANDLER(x) (terminating_signals[x].orig_handler)
-#define XSAFLAGS(x) (terminating_signals[x].orig_flags)
-
-static int termsigs_initialized = 0;
-
-/* Initialize signals that will terminate the shell to do some
-   unwind protection.  For non-interactive shells, we only call
-   this when a trap is defined for EXIT (0) or when trap is run
-   to display signal dispositions. */
-void
-initialize_terminating_signals ()
-{
-  register int i;
-#if defined (HAVE_POSIX_SIGNALS)
-  struct sigaction act, oact;
-#endif
-
-  if (termsigs_initialized)
-    return;
-
-  /* The following code is to avoid an expensive call to
-     set_signal_handler () for each terminating_signals.  Fortunately,
-     this is possible in Posix.  Unfortunately, we have to call signal ()
-     on non-Posix systems for each signal in terminating_signals. */
-#if defined (HAVE_POSIX_SIGNALS)
-  act.sa_handler = termsig_sighandler;
-  act.sa_flags = 0;
-  sigemptyset (&act.sa_mask);
-  sigemptyset (&oact.sa_mask);
-  for (i = 0; i < TERMSIGS_LENGTH; i++)
-    sigaddset (&act.sa_mask, XSIG (i));
-  for (i = 0; i < TERMSIGS_LENGTH; i++)
-    {
-      /* If we've already trapped it, don't do anything. */
-      if (signal_is_trapped (XSIG (i)))
-       continue;
-
-      sigaction (XSIG (i), &act, &oact);
-      XHANDLER(i) = oact.sa_handler;
-      XSAFLAGS(i) = oact.sa_flags;
-      /* Don't do anything with signals that are ignored at shell entry
-        if the shell is not interactive. */
-      /* XXX - should we do this for interactive shells, too? */
-      if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
-       {
-         sigaction (XSIG (i), &oact, &act);
-         set_signal_ignored (XSIG (i));
-       }
-#if defined (SIGPROF) && !defined (_MINIX)
-      if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
-       sigaction (XSIG (i), &oact, (struct sigaction *)NULL);
-#endif /* SIGPROF && !_MINIX */
-    }
-
-#else /* !HAVE_POSIX_SIGNALS */
-
-  for (i = 0; i < TERMSIGS_LENGTH; i++)
-    {
-      /* If we've already trapped it, don't do anything. */
-      if (signal_is_trapped (XSIG (i)))
-       continue;
-
-      XHANDLER(i) = signal (XSIG (i), termsig_sighandler);
-      XSAFLAGS(i) = 0;
-      /* Don't do anything with signals that are ignored at shell entry
-        if the shell is not interactive. */
-      /* XXX - should we do this for interactive shells, too? */
-      if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
-       {
-         signal (XSIG (i), SIG_IGN);
-         set_signal_ignored (XSIG (i));
-       }
-#ifdef SIGPROF
-      if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
-       signal (XSIG (i), XHANDLER (i));
-#endif
-    }
-
-#endif /* !HAVE_POSIX_SIGNALS */
-
-  termsigs_initialized = 1;
-}
-
-static void
-initialize_shell_signals ()
-{
-  if (interactive)
-    initialize_terminating_signals ();
-
-#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
-  /* All shells use the signal mask they inherit, and pass it along
-     to child processes.  Children will never block SIGCHLD, though. */
-  sigemptyset (&top_level_mask);
-  sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
-#  if defined (SIGCHLD)
-  sigdelset (&top_level_mask, SIGCHLD);
-#  endif
-#endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
-
-  /* And, some signals that are specifically ignored by the shell. */
-  set_signal_handler (SIGQUIT, SIG_IGN);
-
-  if (interactive)
-    {
-      set_signal_handler (SIGINT, sigint_sighandler);
-      get_original_signal (SIGTERM);
-      if (signal_is_hard_ignored (SIGTERM) == 0)
-       set_signal_handler (SIGTERM, sigterm_sighandler);
-      set_sigwinch_handler ();
-    }
-}
-
-void
-reset_terminating_signals ()
-{
-  register int i;
-#if defined (HAVE_POSIX_SIGNALS)
-  struct sigaction act;
-#endif
-
-  if (termsigs_initialized == 0)
-    return;
-
-#if defined (HAVE_POSIX_SIGNALS)
-  act.sa_flags = 0;
-  sigemptyset (&act.sa_mask);
-  for (i = 0; i < TERMSIGS_LENGTH; i++)
-    {
-      /* Skip a signal if it's trapped or handled specially, because the
-        trap code will restore the correct value. */
-      if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
-       continue;
-
-      act.sa_handler = XHANDLER (i);
-      act.sa_flags = XSAFLAGS (i);
-      sigaction (XSIG (i), &act, (struct sigaction *) NULL);
-    }
-#else /* !HAVE_POSIX_SIGNALS */
-  for (i = 0; i < TERMSIGS_LENGTH; i++)
-    {
-      if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
-       continue;
-
-      signal (XSIG (i), XHANDLER (i));
-    }
-#endif /* !HAVE_POSIX_SIGNALS */
-
-  termsigs_initialized = 0;
-}
-#undef XSIG
-#undef XHANDLER
-
-/* Run some of the cleanups that should be performed when we run
-   jump_to_top_level from a builtin command context.  XXX - might want to
-   also call reset_parser here. */
-void
-top_level_cleanup ()
-{
-  /* Clean up string parser environment. */
-  while (parse_and_execute_level)
-    parse_and_execute_cleanup ();
-
-#if defined (PROCESS_SUBSTITUTION)
-  unlink_fifo_list ();
-#endif /* PROCESS_SUBSTITUTION */
-
-  run_unwind_protects ();
-  loop_level = continuing = breaking = funcnest = 0;
-  executing_list = comsub_ignore_return = return_catch_flag = 0;
-}
-
-/* What to do when we've been interrupted, and it is safe to handle it. */
-void
-throw_to_top_level ()
-{
-  int print_newline = 0;
-
-  if (interrupt_state)
-    {
-      if (last_command_exit_value < 128)
-       last_command_exit_value = 128 + SIGINT;
-      print_newline = 1;
-      DELINTERRUPT;
-    }
-
-  if (interrupt_state)
-    return;
-
-  last_command_exit_signal = (last_command_exit_value > 128) ?
-                               (last_command_exit_value - 128) : 0;
-  last_command_exit_value |= 128;
-
-  /* Run any traps set on SIGINT. */
-  run_interrupt_trap ();
-
-  /* Clean up string parser environment. */
-  while (parse_and_execute_level)
-    parse_and_execute_cleanup ();
-
-#if defined (JOB_CONTROL)
-  give_terminal_to (shell_pgrp, 0);
-#endif /* JOB_CONTROL */
-
-#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
-  /* This needs to stay because jobs.c:make_child() uses it without resetting
-     the signal mask. */
-  sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
-#endif
-
-  reset_parser ();
-
-#if defined (READLINE)
-  if (interactive)
-    bashline_reset ();
-#endif /* READLINE */
-
-#if defined (PROCESS_SUBSTITUTION)
-  unlink_fifo_list ();
-#endif /* PROCESS_SUBSTITUTION */
-
-  run_unwind_protects ();
-  loop_level = continuing = breaking = funcnest = 0;
-  executing_list = comsub_ignore_return = return_catch_flag = 0;
-
-  if (interactive && print_newline)
-    {
-      fflush (stdout);
-      fprintf (stderr, "\n");
-      fflush (stderr);
-    }
-
-  /* An interrupted `wait' command in a script does not exit the script. */
-  if (interactive || (interactive_shell && !shell_initialized) ||
-      (print_newline && signal_is_trapped (SIGINT)))
-    jump_to_top_level (DISCARD);
-  else
-    jump_to_top_level (EXITPROG);
-}
-
-/* This is just here to isolate the longjmp calls. */
-void
-jump_to_top_level (value)
-     int value;
-{
-  longjmp (top_level, value);
-}
-
-sighandler
-termsig_sighandler (sig)
-     int sig;
-{
-  /* If we get called twice with the same signal before handling it,
-     terminate right away. */
-  if (
-#ifdef SIGHUP
-    sig != SIGHUP &&
-#endif
-#ifdef SIGINT
-    sig != SIGINT &&
-#endif
-#ifdef SIGDANGER
-    sig != SIGDANGER &&
-#endif
-#ifdef SIGPIPE
-    sig != SIGPIPE &&
-#endif
-#ifdef SIGALRM
-    sig != SIGALRM &&
-#endif
-#ifdef SIGTERM
-    sig != SIGTERM &&
-#endif
-#ifdef SIGXCPU
-    sig != SIGXCPU &&
-#endif
-#ifdef SIGXFSZ
-    sig != SIGXFSZ &&
-#endif
-#ifdef SIGVTALRM
-    sig != SIGVTALRM &&
-#endif
-#ifdef SIGLOST
-    sig != SIGLOST &&
-#endif
-#ifdef SIGUSR1
-    sig != SIGUSR1 &&
-#endif
-#ifdef SIGUSR2
-   sig != SIGUSR2 &&
-#endif
-   sig == terminating_signal)
-    terminate_immediately = 1;
-
-  terminating_signal = sig;
-
-  /* XXX - should this also trigger when interrupt_immediately is set? */
-  if (terminate_immediately)
-    {
-#if defined (HISTORY)
-      /* XXX - will inhibit history file being written */
-#  if defined (READLINE)
-      if (interactive_shell == 0 || interactive == 0 || (sig != SIGHUP && sig != SIGTERM) || no_line_editing || (RL_ISSTATE (RL_STATE_READCMD) == 0))
-#  endif
-        history_lines_this_session = 0;
-#endif
-      terminate_immediately = 0;
-      termsig_handler (sig);
-    }
-
-#if defined (READLINE)
-  /* Set the event hook so readline will call it after the signal handlers
-     finish executing, so if this interrupted character input we can get
-     quick response. */
-  if (interactive_shell && interactive && no_line_editing == 0)
-    bashline_set_event_hook ();
-#endif
-
-  SIGRETURN (0);
-}
-
-void
-termsig_handler (sig)
-     int sig;
-{
-  static int handling_termsig = 0;
-
-  /* Simple semaphore to keep this function from being executed multiple
-     times.  Since we no longer are running as a signal handler, we don't
-     block multiple occurrences of the terminating signals while running. */
-  if (handling_termsig)
-    return;
-  handling_termsig = 1;
-  terminating_signal = 0;      /* keep macro from re-testing true. */
-
-  /* I don't believe this condition ever tests true. */
-  if (sig == SIGINT && signal_is_trapped (SIGINT))
-    run_interrupt_trap ();
-
-#if defined (HISTORY)
-  /* If we don't do something like this, the history will not be saved when
-     an interactive shell is running in a terminal window that gets closed
-     with the `close' button.  We can't test for RL_STATE_READCMD because
-     readline no longer handles SIGTERM synchronously.  */
-  if (interactive_shell && interactive && sig == SIGHUP && remember_on_history)
-    maybe_save_shell_history ();
-#endif /* HISTORY */
-
-#if defined (JOB_CONTROL)
-  if (sig == SIGHUP && (interactive || (subshell_environment & (SUBSHELL_COMSUB|SUBSHELL_PROCSUB))))
-    hangup_all_jobs ();
-  end_job_control ();
-#endif /* JOB_CONTROL */
-
-#if defined (PROCESS_SUBSTITUTION)
-  unlink_fifo_list ();
-#endif /* PROCESS_SUBSTITUTION */
-
-  /* Reset execution context */
-  loop_level = continuing = breaking = funcnest = 0;
-  executing_list = comsub_ignore_return = return_catch_flag = 0;
-
-  run_exit_trap ();
-  set_signal_handler (sig, SIG_DFL);
-  kill (getpid (), sig);
-}
-
-/* What we really do when SIGINT occurs. */
-sighandler
-sigint_sighandler (sig)
-     int sig;
-{
-#if defined (MUST_REINSTALL_SIGHANDLERS)
-  signal (sig, sigint_sighandler);
-#endif
-
-  /* interrupt_state needs to be set for the stack of interrupts to work
-     right.  Should it be set unconditionally? */
-  if (interrupt_state == 0)
-    ADDINTERRUPT;
-
-  if (interrupt_immediately)
-    {
-      interrupt_immediately = 0;
-      last_command_exit_value = 128 + sig;
-      throw_to_top_level ();
-    }
-#if defined (READLINE)
-  /* Set the event hook so readline will call it after the signal handlers
-     finish executing, so if this interrupted character input we can get
-     quick response. */
-  else if (RL_ISSTATE (RL_STATE_SIGHANDLER))
-    bashline_set_event_hook ();
-#endif
-
-  SIGRETURN (0);
-}
-
-#if defined (SIGWINCH)
-sighandler
-sigwinch_sighandler (sig)
-     int sig;
-{
-#if defined (MUST_REINSTALL_SIGHANDLERS)
-  set_signal_handler (SIGWINCH, sigwinch_sighandler);
-#endif /* MUST_REINSTALL_SIGHANDLERS */
-  sigwinch_received = 1;
-  SIGRETURN (0);
-}
-#endif /* SIGWINCH */
-
-void
-set_sigwinch_handler ()
-{
-#if defined (SIGWINCH)
- old_winch = set_signal_handler (SIGWINCH, sigwinch_sighandler);
-#endif
-}
-
-void
-unset_sigwinch_handler ()
-{
-#if defined (SIGWINCH)
-  set_signal_handler (SIGWINCH, old_winch);
-#endif
-}
-
-sighandler
-sigterm_sighandler (sig)
-     int sig;
-{
-  sigterm_received = 1;                /* XXX - counter? */
-  SIGRETURN (0);
-}
-
-/* Signal functions used by the rest of the code. */
-#if !defined (HAVE_POSIX_SIGNALS)
-
-/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
-sigprocmask (operation, newset, oldset)
-     int operation, *newset, *oldset;
-{
-  int old, new;
-
-  if (newset)
-    new = *newset;
-  else
-    new = 0;
-
-  switch (operation)
-    {
-    case SIG_BLOCK:
-      old = sigblock (new);
-      break;
-
-    case SIG_SETMASK:
-      old = sigsetmask (new);
-      break;
-
-    default:
-      internal_error (_("sigprocmask: %d: invalid operation"), operation);
-    }
-
-  if (oldset)
-    *oldset = old;
-}
-
-#else
-
-#if !defined (SA_INTERRUPT)
-#  define SA_INTERRUPT 0
-#endif
-
-#if !defined (SA_RESTART)
-#  define SA_RESTART 0
-#endif
-
-SigHandler *
-set_signal_handler (sig, handler)
-     int sig;
-     SigHandler *handler;
-{
-  struct sigaction act, oact;
-
-  act.sa_handler = handler;
-  act.sa_flags = 0;
-
-  /* XXX - bash-4.2 */
-  /* We don't want a child death to interrupt interruptible system calls, even
-     if we take the time to reap children */
-#if defined (SIGCHLD)
-  if (sig == SIGCHLD)
-    act.sa_flags |= SA_RESTART;                /* XXX */
-#endif
-  /* If we're installing a SIGTERM handler for interactive shells, we want
-     it to be as close to SIG_IGN as possible. */
-  if (sig == SIGTERM && handler == sigterm_sighandler)
-    act.sa_flags |= SA_RESTART;                /* XXX */
-
-  sigemptyset (&act.sa_mask);
-  sigemptyset (&oact.sa_mask);
-  sigaction (sig, &act, &oact);
-  return (oact.sa_handler);
-}
-#endif /* HAVE_POSIX_SIGNALS */
diff --git a/sig.h~ b/sig.h~
deleted file mode 100644 (file)
index fa28c72..0000000
--- a/sig.h~
+++ /dev/null
@@ -1,139 +0,0 @@
-/* sig.h -- header file for signal handler definitions. */
-
-/* Copyright (C) 1994-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/>.
-*/
-
-/* Make sure that this is included *after* config.h! */
-
-#if !defined (_SIG_H_)
-#  define _SIG_H_
-
-#include "stdc.h"
-
-#if !defined (SIG_DFL)
-#  include <signal.h>
-#endif
-
-#if !defined (SIGABRT) && defined (SIGIOT)
-#  define SIGABRT SIGIOT
-#endif
-
-#define sighandler RETSIGTYPE
-typedef RETSIGTYPE SigHandler __P((int));
-
-#if defined (VOID_SIGHANDLER)
-#  define SIGRETURN(n) return
-#else
-#  define SIGRETURN(n) return(n)
-#endif /* !VOID_SIGHANDLER */
-
-/* Here is a definition for set_signal_handler () which simply expands to
-   a call to signal () for non-Posix systems.  The code for set_signal_handler
-   in the Posix case resides in general.c. */
-#if !defined (HAVE_POSIX_SIGNALS)
-#  define set_signal_handler(sig, handler) (SigHandler *)signal (sig, handler)
-#else
-extern SigHandler *set_signal_handler __P((int, SigHandler *));        /* in sig.c */
-#endif /* _POSIX_VERSION */
-
-#if !defined (SIGCHLD) && defined (SIGCLD)
-#  define SIGCHLD SIGCLD
-#endif
-
-#if !defined (HAVE_POSIX_SIGNALS) && !defined (sigmask)
-#  define sigmask(x) (1 << ((x)-1))
-#endif /* !HAVE_POSIX_SIGNALS && !sigmask */
-
-#if !defined (HAVE_POSIX_SIGNALS)
-#  if !defined (SIG_BLOCK)
-#    define SIG_BLOCK 2
-#    define SIG_SETMASK 3
-#  endif /* SIG_BLOCK */
-
-/* sigset_t defined in config.h */
-
-/* Make sure there is nothing inside the signal set. */
-#  define sigemptyset(set) (*(set) = 0)
-
-/* Initialize the signal set to hold all signals. */
-#  define sigfillset(set) (*set) = sigmask (NSIG) - 1
-
-/* Add SIG to the contents of SET. */
-#  define sigaddset(set, sig) *(set) |= sigmask (sig)
-
-/* Delete SIG from signal set SET. */
-#  define sigdelset(set, sig) *(set) &= ~sigmask (sig)
-
-/* Is SIG a member of the signal set SET? */
-#  define sigismember(set, sig) ((*(set) & sigmask (sig)) != 0)
-
-/* Suspend the process until the reception of one of the signals
-   not present in SET. */
-#  define sigsuspend(set) sigpause (*(set))
-#endif /* !HAVE_POSIX_SIGNALS */
-
-/* These definitions are used both in POSIX and non-POSIX implementations. */
-
-#define BLOCK_SIGNAL(sig, nvar, ovar) \
-do { \
-  sigemptyset (&nvar); \
-  sigaddset (&nvar, sig); \
-  sigemptyset (&ovar); \
-  sigprocmask (SIG_BLOCK, &nvar, &ovar); \
-} while (0)
-
-#define UNBLOCK_SIGNAL(ovar) sigprocmask (SIG_SETMASK, &ovar, (sigset_t *) NULL)
-
-#if defined (HAVE_POSIX_SIGNALS)
-#  define BLOCK_CHILD(nvar, ovar) BLOCK_SIGNAL (SIGCHLD, nvar, ovar)
-#  define UNBLOCK_CHILD(ovar) UNBLOCK_SIGNAL(ovar)
-#else /* !HAVE_POSIX_SIGNALS */
-#  define BLOCK_CHILD(nvar, ovar) ovar = sigblock (sigmask (SIGCHLD))
-#  define UNBLOCK_CHILD(ovar) sigsetmask (ovar)
-#endif /* !HAVE_POSIX_SIGNALS */
-
-/* Extern variables */
-extern sig_atomic_t sigwinch_received;
-extern sig_atomic_t sigterm_received;
-
-extern int interrupt_immediately;
-extern int terminate_immediately;
-
-/* Functions from sig.c. */
-extern sighandler termsig_sighandler __P((int));
-extern void termsig_handler __P((int));
-extern sighandler sigint_sighandler __P((int));
-extern void initialize_signals __P((int));
-extern void initialize_terminating_signals __P((void));
-extern void reset_terminating_signals __P((void));
-extern void top_level_cleanup __P((void));
-extern void throw_to_top_level __P((void));
-extern void jump_to_top_level __P((int)) __attribute__((__noreturn__));
-
-extern sighandler sigwinch_sighandler __P((int));
-extern void set_sigwinch_handler __P((void));
-extern void unset_sigwinch_handler __P((void));
-
-extern sighandler sigterm_sighandler __P((int));
-
-/* Functions defined in trap.c. */
-extern SigHandler *set_sigint_handler __P((void));
-extern SigHandler *trap_to_sighandler __P((int));
-extern sighandler trap_handler __P((int));
-
-#endif /* _SIG_H_ */
diff --git a/subst.c~ b/subst.c~
deleted file mode 100644 (file)
index b56fc69..0000000
--- a/subst.c~
+++ /dev/null
@@ -1,9544 +0,0 @@
-/* subst.c -- The part of the shell that does parameter, command, arithmetic,
-   and globbing substitutions. */
-
-/* ``Have a little faith, there's magic in the night.  You ain't a
-     beauty, but, hey, you're alright.'' */
-
-/* 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 <stdio.h>
-#include "chartypes.h"
-#if defined (HAVE_PWD_H)
-#  include <pwd.h>
-#endif
-#include <signal.h>
-#include <errno.h>
-
-#if defined (HAVE_UNISTD_H)
-#  include <unistd.h>
-#endif
-
-#include "bashansi.h"
-#include "posixstat.h"
-#include "bashintl.h"
-
-#include "shell.h"
-#include "parser.h"
-#include "flags.h"
-#include "jobs.h"
-#include "execute_cmd.h"
-#include "filecntl.h"
-#include "trap.h"
-#include "pathexp.h"
-#include "mailcheck.h"
-
-#include "shmbutil.h"
-#include "typemax.h"
-
-#include "builtins/getopt.h"
-#include "builtins/common.h"
-
-#include "builtins/builtext.h"
-
-#include <tilde/tilde.h>
-#include <glob/strmatch.h>
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-/* The size that strings change by. */
-#define DEFAULT_INITIAL_ARRAY_SIZE 112
-#define DEFAULT_ARRAY_SIZE 128
-
-/* Variable types. */
-#define VT_VARIABLE    0
-#define VT_POSPARMS    1
-#define VT_ARRAYVAR    2
-#define VT_ARRAYMEMBER 3
-#define VT_ASSOCVAR    4
-
-#define VT_STARSUB     128     /* $* or ${array[*]} -- used to split */
-
-/* Flags for quoted_strchr */
-#define ST_BACKSL      0x01
-#define ST_CTLESC      0x02
-#define ST_SQUOTE      0x04    /* unused yet */
-#define ST_DQUOTE      0x08    /* unused yet */
-
-/* Flags for the `pflags' argument to param_expand() */
-#define PF_NOCOMSUB    0x01    /* Do not perform command substitution */
-#define PF_IGNUNBOUND  0x02    /* ignore unbound vars even if -u set */
-#define PF_NOSPLIT2    0x04    /* same as W_NOSPLIT2 */
-#define PF_ASSIGNRHS   0x08    /* same as W_ASSIGNRHS */
-
-/* These defs make it easier to use the editor. */
-#define LBRACE         '{'
-#define RBRACE         '}'
-#define LPAREN         '('
-#define RPAREN         ')'
-
-#if defined (HANDLE_MULTIBYTE)
-#define WLPAREN                L'('
-#define WRPAREN                L')'
-#endif
-
-/* Evaluates to 1 if C is one of the shell's special parameters whose length
-   can be taken, but is also one of the special expansion characters. */
-#define VALID_SPECIAL_LENGTH_PARAM(c) \
-  ((c) == '-' || (c) == '?' || (c) == '#')
-
-/* Evaluates to 1 if C is one of the shell's special parameters for which an
-   indirect variable reference may be made. */
-#define VALID_INDIR_PARAM(c) \
-  ((posixly_correct == 0 && (c) == '#') || (posixly_correct == 0 && (c) == '?') || (c) == '@' || (c) == '*')
-
-/* Evaluates to 1 if C is one of the OP characters that follows the parameter
-   in ${parameter[:]OPword}. */
-#define VALID_PARAM_EXPAND_CHAR(c) (sh_syntaxtab[(unsigned char)c] & CSUBSTOP)
-
-/* Evaluates to 1 if this is one of the shell's special variables. */
-#define SPECIAL_VAR(name, wi) \
- ((DIGIT (*name) && all_digits (name)) || \
-      (name[1] == '\0' && (sh_syntaxtab[(unsigned char)*name] & CSPECVAR)) || \
-      (wi && name[2] == '\0' && VALID_INDIR_PARAM (name[1])))
-
-/* An expansion function that takes a string and a quoted flag and returns
-   a WORD_LIST *.  Used as the type of the third argument to
-   expand_string_if_necessary(). */
-typedef WORD_LIST *EXPFUNC __P((char *, int));
-
-/* Process ID of the last command executed within command substitution. */
-pid_t last_command_subst_pid = NO_PID;
-pid_t current_command_subst_pid = NO_PID;
-
-/* Variables used to keep track of the characters in IFS. */
-SHELL_VAR *ifs_var;
-char *ifs_value;
-unsigned char ifs_cmap[UCHAR_MAX + 1];
-int ifs_is_set, ifs_is_null;
-
-#if defined (HANDLE_MULTIBYTE)
-unsigned char ifs_firstc[MB_LEN_MAX];
-size_t ifs_firstc_len;
-#else
-unsigned char ifs_firstc;
-#endif
-
-/* Sentinel to tell when we are performing variable assignments preceding a
-   command name and putting them into the environment.  Used to make sure
-   we use the temporary environment when looking up variable values. */
-int assigning_in_environment;
-
-/* Used to hold a list of variable assignments preceding a command.  Global
-   so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a
-   SIGCHLD trap and so it can be saved and restored by the trap handlers. */
-WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL;
-
-/* Extern functions and variables from different files. */
-extern int last_command_exit_value, last_command_exit_signal;
-extern int subshell_environment, line_number;
-extern int subshell_level, parse_and_execute_level, sourcelevel;
-extern int eof_encountered;
-extern int return_catch_flag, return_catch_value;
-extern pid_t dollar_dollar_pid;
-extern int posixly_correct;
-extern char *this_command_name;
-extern struct fd_bitmap *current_fds_to_close;
-extern int wordexp_only;
-extern int expanding_redir;
-extern int tempenv_assign_error;
-extern int builtin_ignoring_errexit;
-
-#if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
-extern wchar_t *wcsdup __P((const wchar_t *));
-#endif
-
-/* Non-zero means to allow unmatched globbed filenames to expand to
-   a null file. */
-int allow_null_glob_expansion;
-
-/* Non-zero means to throw an error when globbing fails to match anything. */
-int fail_glob_expansion;
-
-#if 0
-/* Variables to keep track of which words in an expanded word list (the
-   output of expand_word_list_internal) are the result of globbing
-   expansions.  GLOB_ARGV_FLAGS is used by execute_cmd.c.
-   (CURRENTLY UNUSED). */
-char *glob_argv_flags;
-static int glob_argv_flags_size;
-#endif
-
-static WORD_LIST expand_word_error, expand_word_fatal;
-static WORD_DESC expand_wdesc_error, expand_wdesc_fatal;
-static char expand_param_error, expand_param_fatal;
-static char extract_string_error, extract_string_fatal;
-
-/* Tell the expansion functions to not longjmp back to top_level on fatal
-   errors.  Enabled when doing completion and prompt string expansion. */
-static int no_longjmp_on_fatal_error = 0;
-
-/* Set by expand_word_unsplit; used to inhibit splitting and re-joining
-   $* on $IFS, primarily when doing assignment statements. */
-static int expand_no_split_dollar_star = 0;
-
-/* A WORD_LIST of words to be expanded by expand_word_list_internal,
-   without any leading variable assignments. */
-static WORD_LIST *garglist = (WORD_LIST *)NULL;
-
-static char *quoted_substring __P((char *, int, int));
-static int quoted_strlen __P((char *));
-static char *quoted_strchr __P((char *, int, int));
-
-static char *expand_string_if_necessary __P((char *, int, EXPFUNC *));
-static inline char *expand_string_to_string_internal __P((char *, int, EXPFUNC *));
-static WORD_LIST *call_expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
-static WORD_LIST *expand_string_internal __P((char *, int));
-static WORD_LIST *expand_string_leave_quoted __P((char *, int));
-static WORD_LIST *expand_string_for_rhs __P((char *, int, int *, int *));
-
-static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
-static char *make_quoted_char __P((int));
-static WORD_LIST *quote_list __P((WORD_LIST *));
-
-static int unquoted_substring __P((char *, char *));
-static int unquoted_member __P((int, char *));
-
-#if defined (ARRAY_VARS)
-static SHELL_VAR *do_compound_assignment __P((char *, char *, int));
-#endif
-static int do_assignment_internal __P((const WORD_DESC *, int));
-
-static char *string_extract_verbatim __P((char *, size_t, int *, char *, int));
-static char *string_extract __P((char *, int *, char *, int));
-static char *string_extract_double_quoted __P((char *, int *, int));
-static inline char *string_extract_single_quoted __P((char *, int *));
-static inline int skip_single_quoted __P((const char *, size_t, int));
-static int skip_double_quoted __P((char *, size_t, int));
-static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
-static char *extract_dollar_brace_string __P((char *, int *, int, int));
-static int skip_matched_pair __P((const char *, int, int, int, int));
-
-static char *pos_params __P((char *, int, int, int));
-
-static unsigned char *mb_getcharlens __P((char *, int));
-
-static char *remove_upattern __P((char *, char *, int));
-#if defined (HANDLE_MULTIBYTE) 
-static wchar_t *remove_wpattern __P((wchar_t *, size_t, wchar_t *, int));
-#endif
-static char *remove_pattern __P((char *, char *, int));
-
-static int match_upattern __P((char *, char *, int, char **, char **));
-#if defined (HANDLE_MULTIBYTE)
-static int match_wpattern __P((wchar_t *, char **, size_t, wchar_t *, int, char **, char **));
-#endif
-static int match_pattern __P((char *, char *, int, char **, char **));
-static int getpatspec __P((int, char *));
-static char *getpattern __P((char *, int, int));
-static char *variable_remove_pattern __P((char *, char *, int, int));
-static char *list_remove_pattern __P((WORD_LIST *, char *, int, int, int));
-static char *parameter_list_remove_pattern __P((int, char *, int, int));
-#ifdef ARRAY_VARS
-static char *array_remove_pattern __P((SHELL_VAR *, char *, int, char *, int));
-#endif
-static char *parameter_brace_remove_pattern __P((char *, char *, int, char *, int, int, int));
-
-static char *process_substitute __P((char *, int));
-
-static char *read_comsub __P((int, int, int *));
-
-#ifdef ARRAY_VARS
-static arrayind_t array_length_reference __P((char *));
-#endif
-
-static int valid_brace_expansion_word __P((char *, int));
-static int chk_atstar __P((char *, int, int *, int *));
-static int chk_arithsub __P((const char *, int));
-
-static WORD_DESC *parameter_brace_expand_word __P((char *, int, int, int, arrayind_t *));
-static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
-static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
-static void parameter_brace_expand_error __P((char *, char *));
-
-static int valid_length_expression __P((char *));
-static intmax_t parameter_brace_expand_length __P((char *));
-
-static char *skiparith __P((char *, int));
-static int verify_substring_values __P((SHELL_VAR *, char *, char *, int, intmax_t *, intmax_t *));
-static int get_var_and_type __P((char *, char *, arrayind_t, int, int, SHELL_VAR **, char **));
-static char *mb_substring __P((char *, int, int));
-static char *parameter_brace_substring __P((char *, char *, int, char *, int, int));
-
-static int shouldexp_replacement __P((char *));
-
-static char *pos_params_pat_subst __P((char *, char *, char *, int));
-
-static char *parameter_brace_patsub __P((char *, char *, int, char *, int, int));
-
-static char *pos_params_casemod __P((char *, char *, int, int));
-static char *parameter_brace_casemod __P((char *, char *, int, int, char *, int, int));
-
-static WORD_DESC *parameter_brace_expand __P((char *, int *, int, int, int *, int *));
-static WORD_DESC *param_expand __P((char *, int *, int, int *, int *, int *, int *, int));
-
-static WORD_LIST *expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
-
-static WORD_LIST *word_list_split __P((WORD_LIST *));
-
-static void exp_jump_to_top_level __P((int));
-
-static WORD_LIST *separate_out_assignments __P((WORD_LIST *));
-static WORD_LIST *glob_expand_word_list __P((WORD_LIST *, int));
-#ifdef BRACE_EXPANSION
-static WORD_LIST *brace_expand_word_list __P((WORD_LIST *, int));
-#endif
-#if defined (ARRAY_VARS)
-static int make_internal_declare __P((char *, char *));
-#endif
-static WORD_LIST *shell_expand_word_list __P((WORD_LIST *, int));
-static WORD_LIST *expand_word_list_internal __P((WORD_LIST *, int));
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Utility Functions                           */
-/*                                                                 */
-/* **************************************************************** */
-
-#if defined (DEBUG)
-void
-dump_word_flags (flags)
-     int flags;
-{
-  int f;
-
-  f = flags;
-  fprintf (stderr, "%d -> ", f);
-  if (f & W_ASSIGNASSOC)
-    {
-      f &= ~W_ASSIGNASSOC;
-      fprintf (stderr, "W_ASSIGNASSOC%s", f ? "|" : "");
-    }
-  if (f & W_ASSIGNARRAY)
-    {
-      f &= ~W_ASSIGNARRAY;
-      fprintf (stderr, "W_ASSIGNARRAY%s", f ? "|" : "");
-    }
-  if (f & W_HASCTLESC)
-    {
-      f &= ~W_HASCTLESC;
-      fprintf (stderr, "W_HASCTLESC%s", f ? "|" : "");
-    }
-  if (f & W_NOPROCSUB)
-    {
-      f &= ~W_NOPROCSUB;
-      fprintf (stderr, "W_NOPROCSUB%s", f ? "|" : "");
-    }
-  if (f & W_DQUOTE)
-    {
-      f &= ~W_DQUOTE;
-      fprintf (stderr, "W_DQUOTE%s", f ? "|" : "");
-    }
-  if (f & W_HASQUOTEDNULL)
-    {
-      f &= ~W_HASQUOTEDNULL;
-      fprintf (stderr, "W_HASQUOTEDNULL%s", f ? "|" : "");
-    }
-  if (f & W_ASSIGNARG)
-    {
-      f &= ~W_ASSIGNARG;
-      fprintf (stderr, "W_ASSIGNARG%s", f ? "|" : "");
-    }
-  if (f & W_ASSNBLTIN)
-    {
-      f &= ~W_ASSNBLTIN;
-      fprintf (stderr, "W_ASSNBLTIN%s", f ? "|" : "");
-    }
-  if (f & W_ASSNGLOBAL)
-    {
-      f &= ~W_ASSNGLOBAL;
-      fprintf (stderr, "W_ASSNGLOBAL%s", f ? "|" : "");
-    }
-  if (f & W_COMPASSIGN)
-    {
-      f &= ~W_COMPASSIGN;
-      fprintf (stderr, "W_COMPASSIGN%s", f ? "|" : "");
-    }
-  if (f & W_NOEXPAND)
-    {
-      f &= ~W_NOEXPAND;
-      fprintf (stderr, "W_NOEXPAND%s", f ? "|" : "");
-    }
-  if (f & W_ITILDE)
-    {
-      f &= ~W_ITILDE;
-      fprintf (stderr, "W_ITILDE%s", f ? "|" : "");
-    }
-  if (f & W_NOTILDE)
-    {
-      f &= ~W_NOTILDE;
-      fprintf (stderr, "W_NOTILDE%s", f ? "|" : "");
-    }
-  if (f & W_ASSIGNRHS)
-    {
-      f &= ~W_ASSIGNRHS;
-      fprintf (stderr, "W_ASSIGNRHS%s", f ? "|" : "");
-    }
-  if (f & W_NOCOMSUB)
-    {
-      f &= ~W_NOCOMSUB;
-      fprintf (stderr, "W_NOCOMSUB%s", f ? "|" : "");
-    }
-  if (f & W_DOLLARSTAR)
-    {
-      f &= ~W_DOLLARSTAR;
-      fprintf (stderr, "W_DOLLARSTAR%s", f ? "|" : "");
-    }
-  if (f & W_DOLLARAT)
-    {
-      f &= ~W_DOLLARAT;
-      fprintf (stderr, "W_DOLLARAT%s", f ? "|" : "");
-    }
-  if (f & W_TILDEEXP)
-    {
-      f &= ~W_TILDEEXP;
-      fprintf (stderr, "W_TILDEEXP%s", f ? "|" : "");
-    }
-  if (f & W_NOSPLIT2)
-    {
-      f &= ~W_NOSPLIT2;
-      fprintf (stderr, "W_NOSPLIT2%s", f ? "|" : "");
-    }
-  if (f & W_NOSPLIT)
-    {
-      f &= ~W_NOSPLIT;
-      fprintf (stderr, "W_NOSPLIT%s", f ? "|" : "");
-    }
-  if (f & W_NOBRACE)
-    {
-      f &= ~W_NOBRACE;
-      fprintf (stderr, "W_NOBRACE%s", f ? "|" : "");
-    }
-  if (f & W_NOGLOB)
-    {
-      f &= ~W_NOGLOB;
-      fprintf (stderr, "W_NOGLOB%s", f ? "|" : "");
-    }
-  if (f & W_SPLITSPACE)
-    {
-      f &= ~W_SPLITSPACE;
-      fprintf (stderr, "W_SPLITSPACE%s", f ? "|" : "");
-    }
-  if (f & W_ASSIGNMENT)
-    {
-      f &= ~W_ASSIGNMENT;
-      fprintf (stderr, "W_ASSIGNMENT%s", f ? "|" : "");
-    }
-  if (f & W_QUOTED)
-    {
-      f &= ~W_QUOTED;
-      fprintf (stderr, "W_QUOTED%s", f ? "|" : "");
-    }
-  if (f & W_HASDOLLAR)
-    {
-      f &= ~W_HASDOLLAR;
-      fprintf (stderr, "W_HASDOLLAR%s", f ? "|" : "");
-    }
-  fprintf (stderr, "\n");
-  fflush (stderr);
-}
-#endif
-
-#ifdef INCLUDE_UNUSED
-static char *
-quoted_substring (string, start, end)
-     char *string;
-     int start, end;
-{
-  register int len, l;
-  register char *result, *s, *r;
-
-  len = end - start;
-
-  /* Move to string[start], skipping quoted characters. */
-  for (s = string, l = 0; *s && l < start; )
-    {
-      if (*s == CTLESC)
-       {
-         s++;
-         continue;
-       }
-      l++;
-      if (*s == 0)
-       break;
-    }
-
-  r = result = (char *)xmalloc (2*len + 1);      /* save room for quotes */
-
-  /* Copy LEN characters, including quote characters. */
-  s = string + l;
-  for (l = 0; l < len; s++)
-    {
-      if (*s == CTLESC)
-       *r++ = *s++;
-      *r++ = *s;
-      l++;
-      if (*s == 0)
-       break;
-    }
-  *r = '\0';
-  return result;
-}
-#endif
-
-#ifdef INCLUDE_UNUSED
-/* Return the length of S, skipping over quoted characters */
-static int
-quoted_strlen (s)
-     char *s;
-{
-  register char *p;
-  int i;
-
-  i = 0;
-  for (p = s; *p; p++)
-    {
-      if (*p == CTLESC)
-       {
-         p++;
-         if (*p == 0)
-           return (i + 1);
-       }
-      i++;
-    }
-
-  return i;
-}
-#endif
-
-/* Find the first occurrence of character C in string S, obeying shell
-   quoting rules.  If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
-   characters are skipped.  If (FLAGS & ST_CTLESC) is non-zero, characters
-   escaped with CTLESC are skipped. */
-static char *
-quoted_strchr (s, c, flags)
-     char *s;
-     int c, flags;
-{
-  register char *p;
-
-  for (p = s; *p; p++)
-    {
-      if (((flags & ST_BACKSL) && *p == '\\')
-           || ((flags & ST_CTLESC) && *p == CTLESC))
-       {
-         p++;
-         if (*p == '\0')
-           return ((char *)NULL);
-         continue;
-       }
-      else if (*p == c)
-       return p;
-    }
-  return ((char *)NULL);
-}
-
-/* Return 1 if CHARACTER appears in an unquoted portion of
-   STRING.  Return 0 otherwise.  CHARACTER must be a single-byte character. */
-static int
-unquoted_member (character, string)
-     int character;
-     char *string;
-{
-  size_t slen;
-  int sindex, c;
-  DECLARE_MBSTATE;
-
-  slen = strlen (string);
-  sindex = 0;
-  while (c = string[sindex])
-    {
-      if (c == character)
-       return (1);
-
-      switch (c)
-       {
-       default:
-         ADVANCE_CHAR (string, slen, sindex);
-         break;
-
-       case '\\':
-         sindex++;
-         if (string[sindex])
-           ADVANCE_CHAR (string, slen, sindex);
-         break;
-
-       case '\'':
-         sindex = skip_single_quoted (string, slen, ++sindex);
-         break;
-
-       case '"':
-         sindex = skip_double_quoted (string, slen, ++sindex);
-         break;
-       }
-    }
-  return (0);
-}
-
-/* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
-static int
-unquoted_substring (substr, string)
-     char *substr, *string;
-{
-  size_t slen;
-  int sindex, c, sublen;
-  DECLARE_MBSTATE;
-
-  if (substr == 0 || *substr == '\0')
-    return (0);
-
-  slen = strlen (string);
-  sublen = strlen (substr);
-  for (sindex = 0; c = string[sindex]; )
-    {
-      if (STREQN (string + sindex, substr, sublen))
-       return (1);
-
-      switch (c)
-       {
-       case '\\':
-         sindex++;
-         if (string[sindex])
-           ADVANCE_CHAR (string, slen, sindex);
-         break;
-
-       case '\'':
-         sindex = skip_single_quoted (string, slen, ++sindex);
-         break;
-
-       case '"':
-         sindex = skip_double_quoted (string, slen, ++sindex);
-         break;
-
-       default:
-         ADVANCE_CHAR (string, slen, sindex);
-         break;
-       }
-    }
-  return (0);
-}
-
-/* Most of the substitutions must be done in parallel.  In order
-   to avoid using tons of unclear goto's, I have some functions
-   for manipulating malloc'ed strings.  They all take INDX, a
-   pointer to an integer which is the offset into the string
-   where manipulation is taking place.  They also take SIZE, a
-   pointer to an integer which is the current length of the
-   character array for this string. */
-
-/* Append SOURCE to TARGET at INDEX.  SIZE is the current amount
-   of space allocated to TARGET.  SOURCE can be NULL, in which
-   case nothing happens.  Gets rid of SOURCE by freeing it.
-   Returns TARGET in case the location has changed. */
-INLINE char *
-sub_append_string (source, target, indx, size)
-     char *source, *target;
-     int *indx, *size;
-{
-  if (source)
-    {
-      int srclen, n;
-
-      srclen = STRLEN (source);
-      if (srclen >= (int)(*size - *indx))
-       {
-         n = srclen + *indx;
-         n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
-         target = (char *)xrealloc (target, (*size = n));
-       }
-
-      FASTCOPY (source, target + *indx, srclen);
-      *indx += srclen;
-      target[*indx] = '\0';
-
-      free (source);
-    }
-  return (target);
-}
-
-#if 0
-/* UNUSED */
-/* Append the textual representation of NUMBER to TARGET.
-   INDX and SIZE are as in SUB_APPEND_STRING. */
-char *
-sub_append_number (number, target, indx, size)
-     intmax_t number;
-     int *indx, *size;
-     char *target;
-{
-  char *temp;
-
-  temp = itos (number);
-  return (sub_append_string (temp, target, indx, size));
-}
-#endif
-
-/* Extract a substring from STRING, starting at SINDEX and ending with
-   one of the characters in CHARLIST.  Don't make the ending character
-   part of the string.  Leave SINDEX pointing at the ending character.
-   Understand about backslashes in the string.  If (flags & SX_VARNAME)
-   is non-zero, and array variables have been compiled into the shell,
-   everything between a `[' and a corresponding `]' is skipped over.
-   If (flags & SX_NOALLOC) is non-zero, don't return the substring, just
-   update SINDEX.  If (flags & SX_REQMATCH) is non-zero, the string must
-   contain a closing character from CHARLIST. */
-static char *
-string_extract (string, sindex, charlist, flags)
-     char *string;
-     int *sindex;
-     char *charlist;
-     int flags;
-{
-  register int c, i;
-  int found;
-  size_t slen;
-  char *temp;
-  DECLARE_MBSTATE;
-
-  slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
-  i = *sindex;
-  found = 0;
-  while (c = string[i])
-    {
-      if (c == '\\')
-       {
-         if (string[i + 1])
-           i++;
-         else
-           break;
-       }
-#if defined (ARRAY_VARS)
-      else if ((flags & SX_VARNAME) && c == '[')
-       {
-         int ni;
-         /* If this is an array subscript, skip over it and continue. */
-         ni = skipsubscript (string, i, 0);
-         if (string[ni] == ']')
-           i = ni;
-       }
-#endif
-      else if (MEMBER (c, charlist))
-       {
-         found = 1;
-         break;
-       }
-
-      ADVANCE_CHAR (string, slen, i);
-    }
-
-  /* If we had to have a matching delimiter and didn't find one, return an
-     error and let the caller deal with it. */
-  if ((flags & SX_REQMATCH) && found == 0)
-    {
-      *sindex = i;
-      return (&extract_string_error);
-    }
-  
-  temp = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
-  *sindex = i;
-  
-  return (temp);
-}
-
-/* Extract the contents of STRING as if it is enclosed in double quotes.
-   SINDEX, when passed in, is the offset of the character immediately
-   following the opening double quote; on exit, SINDEX is left pointing after
-   the closing double quote.  If STRIPDQ is non-zero, unquoted double
-   quotes are stripped and the string is terminated by a null byte.
-   Backslashes between the embedded double quotes are processed.  If STRIPDQ
-   is zero, an unquoted `"' terminates the string. */
-static char *
-string_extract_double_quoted (string, sindex, stripdq)
-     char *string;
-     int *sindex, stripdq;
-{
-  size_t slen;
-  char *send;
-  int j, i, t;
-  unsigned char c;
-  char *temp, *ret;            /* The new string we return. */
-  int pass_next, backquote, si;        /* State variables for the machine. */
-  int dquote;
-  DECLARE_MBSTATE;
-
-  slen = strlen (string + *sindex) + *sindex;
-  send = string + slen;
-
-  pass_next = backquote = dquote = 0;
-  temp = (char *)xmalloc (1 + slen - *sindex);
-
-  j = 0;
-  i = *sindex;
-  while (c = string[i])
-    {
-      /* Process a character that was quoted by a backslash. */
-      if (pass_next)
-       {
-         /* XXX - take another look at this in light of Interp 221 */
-         /* Posix.2 sez:
-
-            ``The backslash shall retain its special meaning as an escape
-            character only when followed by one of the characters:
-               $       `       "       \       <newline>''.
-
-            If STRIPDQ is zero, we handle the double quotes here and let
-            expand_word_internal handle the rest.  If STRIPDQ is non-zero,
-            we have already been through one round of backslash stripping,
-            and want to strip these backslashes only if DQUOTE is non-zero,
-            indicating that we are inside an embedded double-quoted string. */
-
-            /* If we are in an embedded quoted string, then don't strip
-               backslashes before characters for which the backslash
-               retains its special meaning, but remove backslashes in
-               front of other characters.  If we are not in an
-               embedded quoted string, don't strip backslashes at all.
-               This mess is necessary because the string was already
-               surrounded by double quotes (and sh has some really weird
-               quoting rules).
-               The returned string will be run through expansion as if
-               it were double-quoted. */
-         if ((stripdq == 0 && c != '"') ||
-             (stripdq && ((dquote && (sh_syntaxtab[c] & CBSDQUOTE)) || dquote == 0)))
-           temp[j++] = '\\';
-         pass_next = 0;
-
-add_one_character:
-         COPY_CHAR_I (temp, j, string, send, i);
-         continue;
-       }
-
-      /* A backslash protects the next character.  The code just above
-        handles preserving the backslash in front of any character but
-        a double quote. */
-      if (c == '\\')
-       {
-         pass_next++;
-         i++;
-         continue;
-       }
-
-      /* Inside backquotes, ``the portion of the quoted string from the
-        initial backquote and the characters up to the next backquote
-        that is not preceded by a backslash, having escape characters
-        removed, defines that command''. */
-      if (backquote)
-       {
-         if (c == '`')
-           backquote = 0;
-         temp[j++] = c;
-         i++;
-         continue;
-       }
-
-      if (c == '`')
-       {
-         temp[j++] = c;
-         backquote++;
-         i++;
-         continue;
-       }
-
-      /* Pass everything between `$(' and the matching `)' or a quoted
-        ${ ... } pair through according to the Posix.2 specification. */
-      if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
-       {
-         int free_ret = 1;
-
-         si = i + 2;
-         if (string[i + 1] == LPAREN)
-           ret = extract_command_subst (string, &si, 0);
-         else
-           ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, 0);
-
-         temp[j++] = '$';
-         temp[j++] = string[i + 1];
-
-         /* Just paranoia; ret will not be 0 unless no_longjmp_on_fatal_error
-            is set. */
-         if (ret == 0 && no_longjmp_on_fatal_error)
-           {
-             free_ret = 0;
-             ret = string + i + 2;
-           }
-
-         for (t = 0; ret[t]; t++, j++)
-           temp[j] = ret[t];
-         temp[j] = string[si];
-
-         if (string[si])
-           {
-             j++;
-             i = si + 1;
-           }
-         else
-           i = si;
-
-         if (free_ret)
-           free (ret);
-         continue;
-       }
-
-      /* Add any character but a double quote to the quoted string we're
-        accumulating. */
-      if (c != '"')
-       goto add_one_character;
-
-      /* c == '"' */
-      if (stripdq)
-       {
-         dquote ^= 1;
-         i++;
-         continue;
-       }
-
-      break;
-    }
-  temp[j] = '\0';
-
-  /* Point to after the closing quote. */
-  if (c)
-    i++;
-  *sindex = i;
-
-  return (temp);
-}
-
-/* This should really be another option to string_extract_double_quoted. */
-static int
-skip_double_quoted (string, slen, sind)
-     char *string;
-     size_t slen;
-     int sind;
-{
-  int c, i;
-  char *ret;
-  int pass_next, backquote, si;
-  DECLARE_MBSTATE;
-
-  pass_next = backquote = 0;
-  i = sind;
-  while (c = string[i])
-    {
-      if (pass_next)
-       {
-         pass_next = 0;
-         ADVANCE_CHAR (string, slen, i);
-         continue;
-       }
-      else if (c == '\\')
-       {
-         pass_next++;
-         i++;
-         continue;
-       }
-      else if (backquote)
-       {
-         if (c == '`')
-           backquote = 0;
-         ADVANCE_CHAR (string, slen, i);
-         continue;
-       }
-      else if (c == '`')
-       {
-         backquote++;
-         i++;
-         continue;
-       }
-      else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
-       {
-         si = i + 2;
-         if (string[i + 1] == LPAREN)
-           ret = extract_command_subst (string, &si, SX_NOALLOC);
-         else
-           ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, SX_NOALLOC);
-
-         i = si + 1;
-         continue;
-       }
-      else if (c != '"')
-       {
-         ADVANCE_CHAR (string, slen, i);
-         continue;
-       }
-      else
-       break;
-    }
-
-  if (c)
-    i++;
-
-  return (i);
-}
-
-/* Extract the contents of STRING as if it is enclosed in single quotes.
-   SINDEX, when passed in, is the offset of the character immediately
-   following the opening single quote; on exit, SINDEX is left pointing after
-   the closing single quote. */
-static inline char *
-string_extract_single_quoted (string, sindex)
-     char *string;
-     int *sindex;
-{
-  register int i;
-  size_t slen;
-  char *t;
-  DECLARE_MBSTATE;
-
-  /* Don't need slen for ADVANCE_CHAR unless multibyte chars possible. */
-  slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
-  i = *sindex;
-  while (string[i] && string[i] != '\'')
-    ADVANCE_CHAR (string, slen, i);
-
-  t = substring (string, *sindex, i);
-
-  if (string[i])
-    i++;
-  *sindex = i;
-
-  return (t);
-}
-
-static inline int
-skip_single_quoted (string, slen, sind)
-     const char *string;
-     size_t slen;
-     int sind;
-{
-  register int c;
-  DECLARE_MBSTATE;
-
-  c = sind;
-  while (string[c] && string[c] != '\'')
-    ADVANCE_CHAR (string, slen, c);
-
-  if (string[c])
-    c++;
-  return c;
-}
-
-/* Just like string_extract, but doesn't hack backslashes or any of
-   that other stuff.  Obeys CTLESC quoting.  Used to do splitting on $IFS. */
-static char *
-string_extract_verbatim (string, slen, sindex, charlist, flags)
-     char *string;
-     size_t slen;
-     int *sindex;
-     char *charlist;
-     int flags;
-{
-  register int i;
-#if defined (HANDLE_MULTIBYTE)
-  size_t clen;
-  wchar_t *wcharlist;
-#endif
-  int c;
-  char *temp;
-  DECLARE_MBSTATE;
-
-  if (charlist[0] == '\'' && charlist[1] == '\0')
-    {
-      temp = string_extract_single_quoted (string, sindex);
-      --*sindex;       /* leave *sindex at separator character */
-      return temp;
-    }
-
-  i = *sindex;
-#if 0
-  /* See how the MBLEN and ADVANCE_CHAR macros work to understand why we need
-     this only if MB_CUR_MAX > 1. */
-  slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 1;
-#endif
-#if defined (HANDLE_MULTIBYTE)
-  clen = strlen (charlist);
-  wcharlist = 0;
-#endif
-  while (c = string[i])
-    {
-#if defined (HANDLE_MULTIBYTE)
-      size_t mblength;
-#endif
-      if ((flags & SX_NOCTLESC) == 0 && c == CTLESC)
-       {
-         i += 2;
-         continue;
-       }
-      /* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL
-        through, to protect the CTLNULs from later calls to
-        remove_quoted_nulls. */
-      else if ((flags & SX_NOESCCTLNUL) == 0 && c == CTLESC && string[i+1] == CTLNUL)
-       {
-         i += 2;
-         continue;
-       }
-
-#if defined (HANDLE_MULTIBYTE)
-      mblength = MBLEN (string + i, slen - i);
-      if (mblength > 1)
-       {
-         wchar_t wc;
-         mblength = mbtowc (&wc, string + i, slen - i);
-         if (MB_INVALIDCH (mblength))
-           {
-             if (MEMBER (c, charlist))
-               break;
-           }
-         else
-           {
-             if (wcharlist == 0)
-               {
-                 size_t len;
-                 len = mbstowcs (wcharlist, charlist, 0);
-                 if (len == -1)
-                   len = 0;
-                 wcharlist = (wchar_t *)xmalloc (sizeof (wchar_t) * (len + 1));
-                 mbstowcs (wcharlist, charlist, len + 1);
-               }
-
-             if (wcschr (wcharlist, wc))
-               break;
-           }
-       }
-      else             
-#endif
-      if (MEMBER (c, charlist))
-       break;
-
-      ADVANCE_CHAR (string, slen, i);
-    }
-
-#if defined (HANDLE_MULTIBYTE)
-  FREE (wcharlist);
-#endif
-
-  temp = substring (string, *sindex, i);
-  *sindex = i;
-
-  return (temp);
-}
-
-/* Extract the $( construct in STRING, and return a new string.
-   Start extracting at (SINDEX) as if we had just seen "$(".
-   Make (SINDEX) get the position of the matching ")". )
-   XFLAGS is additional flags to pass to other extraction functions. */
-char *
-extract_command_subst (string, sindex, xflags)
-     char *string;
-     int *sindex;
-     int xflags;
-{
-  if (string[*sindex] == LPAREN)
-    return (extract_delimited_string (string, sindex, "$(", "(", ")", xflags|SX_COMMAND)); /*)*/
-  else
-    {
-      xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0);
-      return (xparse_dolparen (string, string+*sindex, sindex, xflags));
-    }
-}
-
-/* Extract the $[ construct in STRING, and return a new string. (])
-   Start extracting at (SINDEX) as if we had just seen "$[".
-   Make (SINDEX) get the position of the matching "]". */
-char *
-extract_arithmetic_subst (string, sindex)
-     char *string;
-     int *sindex;
-{
-  return (extract_delimited_string (string, sindex, "$[", "[", "]", 0)); /*]*/
-}
-
-#if defined (PROCESS_SUBSTITUTION)
-/* Extract the <( or >( construct in STRING, and return a new string.
-   Start extracting at (SINDEX) as if we had just seen "<(".
-   Make (SINDEX) get the position of the matching ")". */ /*))*/
-char *
-extract_process_subst (string, starter, sindex)
-     char *string;
-     char *starter;
-     int *sindex;
-{
-  return (extract_delimited_string (string, sindex, starter, "(", ")", SX_COMMAND));
-}
-#endif /* PROCESS_SUBSTITUTION */
-
-#if defined (ARRAY_VARS)
-/* This can be fooled by unquoted right parens in the passed string. If
-   each caller verifies that the last character in STRING is a right paren,
-   we don't even need to call extract_delimited_string. */
-char *
-extract_array_assignment_list (string, sindex)
-     char *string;
-     int *sindex;
-{
-  int slen;
-  char *ret;
-
-  slen = strlen (string);      /* ( */
-  if (string[slen - 1] == ')')
-   {
-      ret = substring (string, *sindex, slen - 1);
-      *sindex = slen - 1;
-      return ret;
-    }
-  return 0;  
-}
-#endif
-
-/* Extract and create a new string from the contents of STRING, a
-   character string delimited with OPENER and CLOSER.  SINDEX is
-   the address of an int describing the current offset in STRING;
-   it should point to just after the first OPENER found.  On exit,
-   SINDEX gets the position of the last character of the matching CLOSER.
-   If OPENER is more than a single character, ALT_OPENER, if non-null,
-   contains a character string that can also match CLOSER and thus
-   needs to be skipped. */
-static char *
-extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
-     char *string;
-     int *sindex;
-     char *opener, *alt_opener, *closer;
-     int flags;
-{
-  int i, c, si;
-  size_t slen;
-  char *t, *result;
-  int pass_character, nesting_level, in_comment;
-  int len_closer, len_opener, len_alt_opener;
-  DECLARE_MBSTATE;
-
-  slen = strlen (string + *sindex) + *sindex;
-  len_opener = STRLEN (opener);
-  len_alt_opener = STRLEN (alt_opener);
-  len_closer = STRLEN (closer);
-
-  pass_character = in_comment = 0;
-
-  nesting_level = 1;
-  i = *sindex;
-
-  while (nesting_level)
-    {
-      c = string[i];
-
-      if (c == 0)
-       break;
-
-      if (in_comment)
-       {
-         if (c == '\n')
-           in_comment = 0;
-         ADVANCE_CHAR (string, slen, i);
-         continue;
-       }
-
-      if (pass_character)      /* previous char was backslash */
-       {
-         pass_character = 0;
-         ADVANCE_CHAR (string, slen, i);
-         continue;
-       }
-
-      /* Not exactly right yet; should handle shell metacharacters and
-        multibyte characters, too.  See COMMENT_BEGIN define in parse.y */
-      if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || shellblank (string[i - 1])))
-       {
-          in_comment = 1;
-          ADVANCE_CHAR (string, slen, i);
-          continue;
-       }
-        
-      if (c == CTLESC || c == '\\')
-       {
-         pass_character++;
-         i++;
-         continue;
-       }
-
-      /* Process a nested command substitution, but only if we're parsing an
-        arithmetic substitution. */
-      if ((flags & SX_COMMAND) && string[i] == '$' && string[i+1] == LPAREN)
-        {
-          si = i + 2;
-          t = extract_command_subst (string, &si, flags|SX_NOALLOC);
-          i = si + 1;
-          continue;
-        }
-
-      /* Process a nested OPENER. */
-      if (STREQN (string + i, opener, len_opener))
-       {
-         si = i + len_opener;
-         t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|SX_NOALLOC);
-         i = si + 1;
-         continue;
-       }
-
-      /* Process a nested ALT_OPENER */
-      if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
-       {
-         si = i + len_alt_opener;
-         t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|SX_NOALLOC);
-         i = si + 1;
-         continue;
-       }
-
-      /* If the current substring terminates the delimited string, decrement
-        the nesting level. */
-      if (STREQN (string + i, closer, len_closer))
-       {
-         i += len_closer - 1;  /* move to last byte of the closer */
-         nesting_level--;
-         if (nesting_level == 0)
-           break;
-       }
-
-      /* Pass old-style command substitution through verbatim. */
-      if (c == '`')
-       {
-         si = i + 1;
-         t = string_extract (string, &si, "`", flags|SX_NOALLOC);
-         i = si + 1;
-         continue;
-       }
-
-      /* Pass single-quoted and double-quoted strings through verbatim. */
-      if (c == '\'' || c == '"')
-       {
-         si = i + 1;
-         i = (c == '\'') ? skip_single_quoted (string, slen, si)
-                         : skip_double_quoted (string, slen, si);
-         continue;
-       }
-
-      /* move past this character, which was not special. */
-      ADVANCE_CHAR (string, slen, i);
-    }
-
-  if (c == 0 && nesting_level)
-    {
-      if (no_longjmp_on_fatal_error == 0)
-       {
-         last_command_exit_value = EXECUTION_FAILURE;
-         report_error (_("bad substitution: no closing `%s' in %s"), closer, string);
-         exp_jump_to_top_level (DISCARD);
-       }
-      else
-       {
-         *sindex = i;
-         return (char *)NULL;
-       }
-    }
-
-  si = i - *sindex - len_closer + 1;
-  if (flags & SX_NOALLOC)
-    result = (char *)NULL;
-  else    
-    {
-      result = (char *)xmalloc (1 + si);
-      strncpy (result, string + *sindex, si);
-      result[si] = '\0';
-    }
-  *sindex = i;
-
-  return (result);
-}
-
-/* Extract a parameter expansion expression within ${ and } from STRING.
-   Obey the Posix.2 rules for finding the ending `}': count braces while
-   skipping over enclosed quoted strings and command substitutions.
-   SINDEX is the address of an int describing the current offset in STRING;
-   it should point to just after the first `{' found.  On exit, SINDEX
-   gets the position of the matching `}'.  QUOTED is non-zero if this
-   occurs inside double quotes. */
-/* XXX -- this is very similar to extract_delimited_string -- XXX */
-static char *
-extract_dollar_brace_string (string, sindex, quoted, flags)
-     char *string;
-     int *sindex, quoted, flags;
-{
-  register int i, c;
-  size_t slen;
-  int pass_character, nesting_level, si, dolbrace_state;
-  char *result, *t;
-  DECLARE_MBSTATE;
-
-  pass_character = 0;
-  nesting_level = 1;
-  slen = strlen (string + *sindex) + *sindex;
-
-  /* The handling of dolbrace_state needs to agree with the code in parse.y:
-     parse_matched_pair().  The different initial value is to handle the
-     case where this function is called to parse the word in
-     ${param op word} (SX_WORD). */
-  dolbrace_state = (flags & SX_WORD) ? DOLBRACE_WORD : DOLBRACE_PARAM;
-  if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && (flags & SX_POSIXEXP))
-    dolbrace_state = DOLBRACE_QUOTE;
-
-  i = *sindex;
-  while (c = string[i])
-    {
-      if (pass_character)
-       {
-         pass_character = 0;
-         ADVANCE_CHAR (string, slen, i);
-         continue;
-       }
-
-      /* CTLESCs and backslashes quote the next character. */
-      if (c == CTLESC || c == '\\')
-       {
-         pass_character++;
-         i++;
-         continue;
-       }
-
-      if (string[i] == '$' && string[i+1] == LBRACE)
-       {
-         nesting_level++;
-         i += 2;
-         continue;
-       }
-
-      if (c == RBRACE)
-       {
-         nesting_level--;
-         if (nesting_level == 0)
-           break;
-         i++;
-         continue;
-       }
-
-      /* Pass the contents of old-style command substitutions through
-        verbatim. */
-      if (c == '`')
-       {
-         si = i + 1;
-         t = string_extract (string, &si, "`", flags|SX_NOALLOC);
-         i = si + 1;
-         continue;
-       }
-
-      /* Pass the contents of new-style command substitutions and
-        arithmetic substitutions through verbatim. */
-      if (string[i] == '$' && string[i+1] == LPAREN)
-       {
-         si = i + 2;
-         t = extract_command_subst (string, &si, flags|SX_NOALLOC);
-         i = si + 1;
-         continue;
-       }
-
-      /* Pass the contents of double-quoted strings through verbatim. */
-      if (c == '"')
-       {
-         si = i + 1;
-         i = skip_double_quoted (string, slen, si);
-         /* skip_XXX_quoted leaves index one past close quote */
-         continue;
-       }
-
-      if (c == '\'')
-       {
-/*itrace("extract_dollar_brace_string: c == single quote flags = %d quoted = %d dolbrace_state = %d", flags, quoted, dolbrace_state);*/
-         if (posixly_correct && shell_compatibility_level > 41 && dolbrace_state != DOLBRACE_QUOTE && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
-           ADVANCE_CHAR (string, slen, i);
-         else
-           {
-             si = i + 1;
-             i = skip_single_quoted (string, slen, si);
-           }
-
-          continue;
-       }
-
-      /* move past this character, which was not special. */
-      ADVANCE_CHAR (string, slen, i);
-
-      /* This logic must agree with parse.y:parse_matched_pair, since they
-        share the same defines. */
-      if (dolbrace_state == DOLBRACE_PARAM && c == '%' && (i - *sindex) > 1)
-       dolbrace_state = DOLBRACE_QUOTE;
-      else if (dolbrace_state == DOLBRACE_PARAM && c == '#' && (i - *sindex) > 1)
-        dolbrace_state = DOLBRACE_QUOTE;
-      else if (dolbrace_state == DOLBRACE_PARAM && c == '/' && (i - *sindex) > 1)
-        dolbrace_state = DOLBRACE_QUOTE;
-      else if (dolbrace_state == DOLBRACE_PARAM && c == '^' && (i - *sindex) > 1)
-        dolbrace_state = DOLBRACE_QUOTE;
-      else if (dolbrace_state == DOLBRACE_PARAM && c == ',' && (i - *sindex) > 1)
-        dolbrace_state = DOLBRACE_QUOTE;
-      else if (dolbrace_state == DOLBRACE_PARAM && strchr ("#%^,~:-=?+/", c) != 0)
-       dolbrace_state = DOLBRACE_OP;
-      else if (dolbrace_state == DOLBRACE_OP && strchr ("#%^,~:-=?+/", c) == 0)
-       dolbrace_state = DOLBRACE_WORD;
-    }
-
-  if (c == 0 && nesting_level)
-    {
-      if (no_longjmp_on_fatal_error == 0)
-       {                       /* { */
-         last_command_exit_value = EXECUTION_FAILURE;
-         report_error (_("bad substitution: no closing `%s' in %s"), "}", string);
-         exp_jump_to_top_level (DISCARD);
-       }
-      else
-       {
-         *sindex = i;
-         return ((char *)NULL);
-       }
-    }
-
-  result = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
-  *sindex = i;
-
-  return (result);
-}
-
-/* Remove backslashes which are quoting backquotes from STRING.  Modifies
-   STRING, and returns a pointer to it. */
-char *
-de_backslash (string)
-     char *string;
-{
-  register size_t slen;
-  register int i, j, prev_i;
-  DECLARE_MBSTATE;
-
-  slen = strlen (string);
-  i = j = 0;
-
-  /* Loop copying string[i] to string[j], i >= j. */
-  while (i < slen)
-    {
-      if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
-                             string[i + 1] == '$'))
-       i++;
-      prev_i = i;
-      ADVANCE_CHAR (string, slen, i);
-      if (j < prev_i)
-       do string[j++] = string[prev_i++]; while (prev_i < i);
-      else
-       j = i;
-    }
-  string[j] = '\0';
-
-  return (string);
-}
-
-#if 0
-/*UNUSED*/
-/* Replace instances of \! in a string with !. */
-void
-unquote_bang (string)
-     char *string;
-{
-  register int i, j;
-  register char *temp;
-
-  temp = (char *)xmalloc (1 + strlen (string));
-
-  for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
-    {
-      if (string[i] == '\\' && string[i + 1] == '!')
-       {
-         temp[j] = '!';
-         i++;
-       }
-    }
-  strcpy (string, temp);
-  free (temp);
-}
-#endif
-
-#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
-
-/* This function assumes s[i] == open; returns with s[ret] == close; used to
-   parse array subscripts.  FLAGS & 1 means to not attempt to skip over
-   matched pairs of quotes or backquotes, or skip word expansions; it is
-   intended to be used after expansion has been performed and during final
-   assignment parsing (see arrayfunc.c:assign_compound_array_list()). */
-static int
-skip_matched_pair (string, start, open, close, flags)
-     const char *string;
-     int start, open, close, flags;
-{
-  int i, pass_next, backq, si, c, count;
-  size_t slen;
-  char *temp, *ss;
-  DECLARE_MBSTATE;
-
-  slen = strlen (string + start) + start;
-  no_longjmp_on_fatal_error = 1;
-
-  i = start + 1;               /* skip over leading bracket */
-  count = 1;
-  pass_next = backq = 0;
-  ss = (char *)string;
-  while (c = string[i])
-    {
-      if (pass_next)
-       {
-         pass_next = 0;
-         if (c == 0)
-           CQ_RETURN(i);
-         ADVANCE_CHAR (string, slen, i);
-         continue;
-       }
-      else if (c == '\\')
-       {
-         pass_next = 1;
-         i++;
-         continue;
-       }
-      else if (backq)
-       {
-         if (c == '`')
-           backq = 0;
-         ADVANCE_CHAR (string, slen, i);
-         continue;
-       }
-      else if ((flags & 1) == 0 && c == '`')
-       {
-         backq = 1;
-         i++;
-         continue;
-       }
-      else if ((flags & 1) == 0 && c == open)
-       {
-         count++;
-         i++;
-         continue;
-       }
-      else if (c == close)
-       {
-         count--;
-         if (count == 0)
-           break;
-         i++;
-         continue;
-       }
-      else if ((flags & 1) == 0 && (c == '\'' || c == '"'))
-       {
-         i = (c == '\'') ? skip_single_quoted (ss, slen, ++i)
-                         : skip_double_quoted (ss, slen, ++i);
-         /* no increment, the skip functions increment past the closing quote. */
-       }
-      else if ((flags&1) == 0 && c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
-       {
-         si = i + 2;
-         if (string[si] == '\0')
-           CQ_RETURN(si);
-
-         if (string[i+1] == LPAREN)
-           temp = extract_delimited_string (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
-         else
-           temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC);
-         i = si;
-         if (string[i] == '\0')        /* don't increment i past EOS in loop */
-           break;
-         i++;
-         continue;
-       }
-      else
-       ADVANCE_CHAR (string, slen, i);
-    }
-
-  CQ_RETURN(i);
-}
-
-#if defined (ARRAY_VARS)
-int
-skipsubscript (string, start, flags)
-     const char *string;
-     int start, flags;
-{
-  return (skip_matched_pair (string, start, '[', ']', flags));
-}
-#endif
-
-/* Skip characters in STRING until we find a character in DELIMS, and return
-   the index of that character.  START is the index into string at which we
-   begin.  This is similar in spirit to strpbrk, but it returns an index into
-   STRING and takes a starting index.  This little piece of code knows quite
-   a lot of shell syntax.  It's very similar to skip_double_quoted and other
-   functions of that ilk. */
-int
-skip_to_delim (string, start, delims, flags)
-     char *string;
-     int start;
-     char *delims;
-     int flags;
-{
-  int i, pass_next, backq, si, c, invert, skipquote, skipcmd;
-  size_t slen;
-  char *temp, open[3];
-  DECLARE_MBSTATE;
-
-  slen = strlen (string + start) + start;
-  if (flags & SD_NOJMP)
-    no_longjmp_on_fatal_error = 1;
-  invert = (flags & SD_INVERT);
-  skipcmd = (flags & SD_NOSKIPCMD) == 0;
-
-  i = start;
-  pass_next = backq = 0;
-  while (c = string[i])
-    {
-      /* If this is non-zero, we should not let quote characters be delimiters
-        and the current character is a single or double quote.  We should not
-        test whether or not it's a delimiter until after we skip single- or
-        double-quoted strings. */
-      skipquote = ((flags & SD_NOQUOTEDELIM) && (c == '\'' || c =='"'));
-      if (pass_next)
-       {
-         pass_next = 0;
-         if (c == 0)
-           CQ_RETURN(i);
-         ADVANCE_CHAR (string, slen, i);
-         continue;
-       }
-      else if (c == '\\')
-       {
-         pass_next = 1;
-         i++;
-         continue;
-       }
-      else if (backq)
-       {
-         if (c == '`')
-           backq = 0;
-         ADVANCE_CHAR (string, slen, i);
-         continue;
-       }
-      else if (c == '`')
-       {
-         backq = 1;
-         i++;
-         continue;
-       }
-      else if (skipquote == 0 && invert == 0 && member (c, delims))
-       break;
-      else if (c == '\'' || c == '"')
-       {
-         i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
-                         : skip_double_quoted (string, slen, ++i);
-         /* no increment, the skip functions increment past the closing quote. */
-       }
-      else if (c == '$' && ((skipcmd && string[i+1] == LPAREN) || string[i+1] == LBRACE))
-       {
-         si = i + 2;
-         if (string[si] == '\0')
-           CQ_RETURN(si);
-
-         if (string[i+1] == LPAREN)
-           temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
-         else
-           temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
-         i = si;
-         if (string[i] == '\0')        /* don't increment i past EOS in loop */
-           break;
-         i++;
-         continue;
-       }
-#if defined (PROCESS_SUBSTITUTION)
-      else if (skipcmd && (c == '<' || c == '>') && string[i+1] == LPAREN)
-       {
-         si = i + 2;
-         if (string[si] == '\0')
-           CQ_RETURN(si);
-         temp = extract_process_subst (string, (c == '<') ? "<(" : ">(", &si);
-         free (temp);          /* no SX_ALLOC here */
-         i = si;
-         if (string[i] == '\0')
-           break;
-         i++;
-         continue;
-       }
-#endif /* PROCESS_SUBSTITUTION */
-#if defined (EXTENDED_GLOB)
-      else if ((flags & SD_EXTGLOB) && extended_glob && string[i+1] == LPAREN && member (c, "?*+!@"))
-       {
-         si = i + 2;
-         if (string[si] == '\0')
-           CQ_RETURN(si);
-
-         open[0] = c;
-         open[1] = LPAREN;
-         open[2] = '\0';
-         temp = extract_delimited_string (string, &si, open, "(", ")", SX_NOALLOC); /* ) */
-
-         i = si;
-         if (string[i] == '\0')        /* don't increment i past EOS in loop */
-           break;
-         i++;
-         continue;
-       }
-#endif
-      else if ((skipquote || invert) && (member (c, delims) == 0))
-       break;
-      else
-       ADVANCE_CHAR (string, slen, i);
-    }
-
-  CQ_RETURN(i);
-}
-
-#if defined (READLINE)
-/* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
-   an unclosed quoted string), or if the character at EINDEX is quoted
-   by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
-   single and double-quoted string parsing functions should not return an
-   error if there are unclosed quotes or braces.  The characters that this
-   recognizes need to be the same as the contents of
-   rl_completer_quote_characters. */
-
-int
-char_is_quoted (string, eindex)
-     char *string;
-     int eindex;
-{
-  int i, pass_next, c;
-  size_t slen;
-  DECLARE_MBSTATE;
-
-  slen = strlen (string);
-  no_longjmp_on_fatal_error = 1;
-  i = pass_next = 0;
-  while (i <= eindex)
-    {
-      c = string[i];
-
-      if (pass_next)
-       {
-         pass_next = 0;
-         if (i >= eindex)      /* XXX was if (i >= eindex - 1) */
-           CQ_RETURN(1);
-         ADVANCE_CHAR (string, slen, i);
-         continue;
-       }
-      else if (c == '\\')
-       {
-         pass_next = 1;
-         i++;
-         continue;
-       }
-      else if (c == '\'' || c == '"')
-       {
-         i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
-                         : skip_double_quoted (string, slen, ++i);
-         if (i > eindex)
-           CQ_RETURN(1);
-         /* no increment, the skip_xxx functions go one past end */
-       }
-      else
-       ADVANCE_CHAR (string, slen, i);
-    }
-
-  CQ_RETURN(0);
-}
-
-int
-unclosed_pair (string, eindex, openstr)
-     char *string;
-     int eindex;
-     char *openstr;
-{
-  int i, pass_next, openc, olen;
-  size_t slen;
-  DECLARE_MBSTATE;
-
-  slen = strlen (string);
-  olen = strlen (openstr);
-  i = pass_next = openc = 0;
-  while (i <= eindex)
-    {
-      if (pass_next)
-       {
-         pass_next = 0;
-         if (i >= eindex)      /* XXX was if (i >= eindex - 1) */
-           return 0;
-         ADVANCE_CHAR (string, slen, i);
-         continue;
-       }
-      else if (string[i] == '\\')
-       {
-         pass_next = 1;
-         i++;
-         continue;
-       }
-      else if (STREQN (string + i, openstr, olen))
-       {
-         openc = 1 - openc;
-         i += olen;
-       }
-      else if (string[i] == '\'' || string[i] == '"')
-       {
-         i = (string[i] == '\'') ? skip_single_quoted (string, slen, i)
-                                 : skip_double_quoted (string, slen, i);
-         if (i > eindex)
-           return 0;
-       }
-      else
-       ADVANCE_CHAR (string, slen, i);
-    }
-  return (openc);
-}
-
-/* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
-   individual words.  If DELIMS is NULL, the current value of $IFS is used
-   to split the string, and the function follows the shell field splitting
-   rules.  SENTINEL is an index to look for.  NWP, if non-NULL,
-   gets the number of words in the returned list.  CWP, if non-NULL, gets
-   the index of the word containing SENTINEL.  Non-whitespace chars in
-   DELIMS delimit separate fields. */
-WORD_LIST *
-split_at_delims (string, slen, delims, sentinel, flags, nwp, cwp)
-     char *string;
-     int slen;
-     char *delims;
-     int sentinel, flags;
-     int *nwp, *cwp;
-{
-  int ts, te, i, nw, cw, ifs_split, dflags;
-  char *token, *d, *d2;
-  WORD_LIST *ret, *tl;
-
-  if (string == 0 || *string == '\0')
-    {
-      if (nwp)
-       *nwp = 0;
-      if (cwp)
-       *cwp = 0;       
-      return ((WORD_LIST *)NULL);
-    }
-
-  d = (delims == 0) ? ifs_value : delims;
-  ifs_split = delims == 0;
-
-  /* Make d2 the non-whitespace characters in delims */
-  d2 = 0;
-  if (delims)
-    {
-      size_t slength;
-#if defined (HANDLE_MULTIBYTE)
-      size_t mblength = 1;
-#endif
-      DECLARE_MBSTATE;
-
-      slength = strlen (delims);
-      d2 = (char *)xmalloc (slength + 1);
-      i = ts = 0;
-      while (delims[i])
-       {
-#if defined (HANDLE_MULTIBYTE)
-         mbstate_t state_bak;
-         state_bak = state;
-         mblength = MBRLEN (delims + i, slength, &state);
-         if (MB_INVALIDCH (mblength))
-           state = state_bak;
-         else if (mblength > 1)
-           {
-             memcpy (d2 + ts, delims + i, mblength);
-             ts += mblength;
-             i += mblength;
-             slength -= mblength;
-             continue;
-           }
-#endif
-         if (whitespace (delims[i]) == 0)
-           d2[ts++] = delims[i];
-
-         i++;
-         slength--;
-       }
-      d2[ts] = '\0';
-    }
-
-  ret = (WORD_LIST *)NULL;
-
-  /* Remove sequences of whitespace characters at the start of the string, as
-     long as those characters are delimiters. */
-  for (i = 0; member (string[i], d) && spctabnl (string[i]); i++)
-    ;
-  if (string[i] == '\0')
-    return (ret);
-
-  ts = i;
-  nw = 0;
-  cw = -1;
-  dflags = flags|SD_NOJMP;
-  while (1)
-    {
-      te = skip_to_delim (string, ts, d, dflags);
-
-      /* If we have a non-whitespace delimiter character, use it to make a
-        separate field.  This is just about what $IFS splitting does and
-        is closer to the behavior of the shell parser. */
-      if (ts == te && d2 && member (string[ts], d2))
-       {
-         te = ts + 1;
-         /* If we're using IFS splitting, the non-whitespace delimiter char
-            and any additional IFS whitespace delimits a field. */
-         if (ifs_split)
-           while (member (string[te], d) && spctabnl (string[te]))
-             te++;
-         else
-           while (member (string[te], d2))
-             te++;
-       }
-
-      token = substring (string, ts, te);
-
-      ret = add_string_to_list (token, ret);
-      free (token);
-      nw++;
-
-      if (sentinel >= ts && sentinel <= te)
-       cw = nw;
-
-      /* If the cursor is at whitespace just before word start, set the
-        sentinel word to the current word. */
-      if (cwp && cw == -1 && sentinel == ts-1)
-       cw = nw;
-
-      /* If the cursor is at whitespace between two words, make a new, empty
-        word, add it before (well, after, since the list is in reverse order)
-        the word we just added, and set the current word to that one. */
-      if (cwp && cw == -1 && sentinel < ts)
-       {
-         tl = make_word_list (make_word (""), ret->next);
-         ret->next = tl;
-         cw = nw;
-         nw++;
-       }
-
-      if (string[te] == 0)
-       break;
-
-      i = te;
-      while (member (string[i], d) && (ifs_split || spctabnl(string[i])))
-       i++;
-
-      if (string[i])
-       ts = i;
-      else
-       break;
-    }
-
-  /* Special case for SENTINEL at the end of STRING.  If we haven't found
-     the word containing SENTINEL yet, and the index we're looking for is at
-     the end of STRING (or past the end of the previously-found token,
-     possible if the end of the line is composed solely of IFS whitespace)
-     add an additional null argument and set the current word pointer to that. */
-  if (cwp && cw == -1 && (sentinel >= slen || sentinel >= te))
-    {
-      if (whitespace (string[sentinel - 1]))
-       {
-         token = "";
-         ret = add_string_to_list (token, ret);
-         nw++;
-       }
-      cw = nw;
-    }
-
-  if (nwp)
-    *nwp = nw;
-  if (cwp)
-    *cwp = cw;
-
-  FREE (d2);
-
-  return (REVERSE_LIST (ret, WORD_LIST *));
-}
-#endif /* READLINE */
-
-#if 0
-/* UNUSED */
-/* Extract the name of the variable to bind to from the assignment string. */
-char *
-assignment_name (string)
-     char *string;
-{
-  int offset;
-  char *temp;
-
-  offset = assignment (string, 0);
-  if (offset == 0)
-    return (char *)NULL;
-  temp = substring (string, 0, offset);
-  return (temp);
-}
-#endif
-
-/* **************************************************************** */
-/*                                                                 */
-/*     Functions to convert strings to WORD_LISTs and vice versa    */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Return a single string of all the words in LIST.  SEP is the separator
-   to put between individual elements of LIST in the output string. */
-char *
-string_list_internal (list, sep)
-     WORD_LIST *list;
-     char *sep;
-{
-  register WORD_LIST *t;
-  char *result, *r;
-  int word_len, sep_len, result_size;
-
-  if (list == 0)
-    return ((char *)NULL);
-
-  /* Short-circuit quickly if we don't need to separate anything. */
-  if (list->next == 0)
-    return (savestring (list->word->word));
-
-  /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
-  sep_len = STRLEN (sep);
-  result_size = 0;
-
-  for (t = list; t; t = t->next)
-    {
-      if (t != list)
-       result_size += sep_len;
-      result_size += strlen (t->word->word);
-    }
-
-  r = result = (char *)xmalloc (result_size + 1);
-
-  for (t = list; t; t = t->next)
-    {
-      if (t != list && sep_len)
-       {
-         if (sep_len > 1)
-           {
-             FASTCOPY (sep, r, sep_len);
-             r += sep_len;
-           }
-         else
-           *r++ = sep[0];
-       }
-
-      word_len = strlen (t->word->word);
-      FASTCOPY (t->word->word, r, word_len);
-      r += word_len;
-    }
-
-  *r = '\0';
-  return (result);
-}
-
-/* Return a single string of all the words present in LIST, separating
-   each word with a space. */
-char *
-string_list (list)
-     WORD_LIST *list;
-{
-  return (string_list_internal (list, " "));
-}
-
-/* An external interface that can be used by the rest of the shell to
-   obtain a string containing the first character in $IFS.  Handles all
-   the multibyte complications.  If LENP is non-null, it is set to the
-   length of the returned string. */
-char *
-ifs_firstchar (lenp)
-     int *lenp;
-{
-  char *ret;
-  int len;
-
-  ret = xmalloc (MB_LEN_MAX + 1);
-#if defined (HANDLE_MULTIBYTE)
-  if (ifs_firstc_len == 1)
-    {
-      ret[0] = ifs_firstc[0];
-      ret[1] = '\0';
-      len = ret[0] ? 1 : 0;
-    }
-  else
-    {
-      memcpy (ret, ifs_firstc, ifs_firstc_len);
-      ret[len = ifs_firstc_len] = '\0';
-    }
-#else
-  ret[0] = ifs_firstc;
-  ret[1] = '\0';
-  len = ret[0] ? 0 : 1;
-#endif
-
-  if (lenp)
-    *lenp = len;
-
-  return ret;
-}
-
-/* Return a single string of all the words present in LIST, obeying the
-   quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
-   expansion [of $*] appears within a double quoted string, it expands
-   to a single field with the value of each parameter separated by the
-   first character of the IFS variable, or by a <space> if IFS is unset." */
-char *
-string_list_dollar_star (list)
-     WORD_LIST *list;
-{
-  char *ret;
-#if defined (HANDLE_MULTIBYTE)
-#  if defined (__GNUC__)
-  char sep[MB_CUR_MAX + 1];
-#  else
-  char *sep = 0;
-#  endif
-#else
-  char sep[2];
-#endif
-
-#if defined (HANDLE_MULTIBYTE)
-#  if !defined (__GNUC__)
-  sep = (char *)xmalloc (MB_CUR_MAX + 1);
-#  endif /* !__GNUC__ */
-  if (ifs_firstc_len == 1)
-    {
-      sep[0] = ifs_firstc[0];
-      sep[1] = '\0';
-    }
-  else
-    {
-      memcpy (sep, ifs_firstc, ifs_firstc_len);
-      sep[ifs_firstc_len] = '\0';
-    }
-#else
-  sep[0] = ifs_firstc;
-  sep[1] = '\0';
-#endif
-
-  ret = string_list_internal (list, sep);
-#if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
-  free (sep);
-#endif
-  return ret;
-}
-
-/* Turn $@ into a string.  If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
-   is non-zero, the $@ appears within double quotes, and we should quote
-   the list before converting it into a string.  If IFS is unset, and the
-   word is not quoted, we just need to quote CTLESC and CTLNUL characters
-   in the words in the list, because the default value of $IFS is
-   <space><tab><newline>, IFS characters in the words in the list should
-   also be split.  If IFS is null, and the word is not quoted, we need
-   to quote the words in the list to preserve the positional parameters
-   exactly. */
-char *
-string_list_dollar_at (list, quoted)
-     WORD_LIST *list;
-     int quoted;
-{
-  char *ifs, *ret;
-#if defined (HANDLE_MULTIBYTE)
-#  if defined (__GNUC__)
-  char sep[MB_CUR_MAX + 1];
-#  else
-  char *sep = 0;
-#  endif /* !__GNUC__ */
-#else
-  char sep[2];
-#endif
-  WORD_LIST *tlist;
-
-  /* XXX this could just be ifs = ifs_value; */
-  ifs = ifs_var ? value_cell (ifs_var) : (char *)0;
-
-#if defined (HANDLE_MULTIBYTE)
-#  if !defined (__GNUC__)
-  sep = (char *)xmalloc (MB_CUR_MAX + 1);
-#  endif /* !__GNUC__ */
-  if (ifs && *ifs)
-    {
-      if (ifs_firstc_len == 1)
-       {
-         sep[0] = ifs_firstc[0];
-         sep[1] = '\0';
-       }
-      else
-       {
-         memcpy (sep, ifs_firstc, ifs_firstc_len);
-         sep[ifs_firstc_len] = '\0';
-       }
-    }
-  else
-    {
-      sep[0] = ' ';
-      sep[1] = '\0';
-    }
-#else
-  sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
-  sep[1] = '\0';
-#endif
-
-  /* XXX -- why call quote_list if ifs == 0?  we can get away without doing
-     it now that quote_escapes quotes spaces */
-  tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE))
-               ? quote_list (list)
-               : list_quote_escapes (list);
-
-  ret = string_list_internal (tlist, sep);
-#if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
-  free (sep);
-#endif
-  return ret;
-}
-
-/* Turn the positional paramters into a string, understanding quoting and
-   the various subtleties of using the first character of $IFS as the
-   separator.  Calls string_list_dollar_at, string_list_dollar_star, and
-   string_list as appropriate. */
-char *
-string_list_pos_params (pchar, list, quoted)
-     int pchar;
-     WORD_LIST *list;
-     int quoted;
-{
-  char *ret;
-  WORD_LIST *tlist;
-
-  if (pchar == '*' && (quoted & Q_DOUBLE_QUOTES))
-    {
-      tlist = quote_list (list);
-      word_list_remove_quoted_nulls (tlist);
-      ret = string_list_dollar_star (tlist);
-    }
-  else if (pchar == '*' && (quoted & Q_HERE_DOCUMENT))
-    {
-      tlist = quote_list (list);
-      word_list_remove_quoted_nulls (tlist);
-      ret = string_list (tlist);
-    }
-  else if (pchar == '*')
-    {
-      /* Even when unquoted, string_list_dollar_star does the right thing
-        making sure that the first character of $IFS is used as the
-        separator. */
-      ret = string_list_dollar_star (list);
-    }
-  else if (pchar == '@' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
-    /* We use string_list_dollar_at, but only if the string is quoted, since
-       that quotes the escapes if it's not, which we don't want.  We could
-       use string_list (the old code did), but that doesn't do the right
-       thing if the first character of $IFS is not a space.  We use
-       string_list_dollar_star if the string is unquoted so we make sure that
-       the elements of $@ are separated by the first character of $IFS for
-       later splitting. */
-    ret = string_list_dollar_at (list, quoted);
-  else if (pchar == '@')
-    ret = string_list_dollar_star (list);
-  else
-    ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (list) : list);
-
-  return ret;
-}
-
-/* Return the list of words present in STRING.  Separate the string into
-   words at any of the characters found in SEPARATORS.  If QUOTED is
-   non-zero then word in the list will have its quoted flag set, otherwise
-   the quoted flag is left as make_word () deemed fit.
-
-   This obeys the P1003.2 word splitting semantics.  If `separators' is
-   exactly <space><tab><newline>, then the splitting algorithm is that of
-   the Bourne shell, which treats any sequence of characters from `separators'
-   as a delimiter.  If IFS is unset, which results in `separators' being set
-   to "", no splitting occurs.  If separators has some other value, the
-   following rules are applied (`IFS white space' means zero or more
-   occurrences of <space>, <tab>, or <newline>, as long as those characters
-   are in `separators'):
-
-       1) IFS white space is ignored at the start and the end of the
-          string.
-       2) Each occurrence of a character in `separators' that is not
-          IFS white space, along with any adjacent occurrences of
-          IFS white space delimits a field.
-       3) Any nonzero-length sequence of IFS white space delimits a field.
-   */
-
-/* BEWARE!  list_string strips null arguments.  Don't call it twice and
-   expect to have "" preserved! */
-
-/* This performs word splitting and quoted null character removal on
-   STRING. */
-#define issep(c) \
-       (((separators)[0]) ? ((separators)[1] ? isifs(c) \
-                                             : (c) == (separators)[0]) \
-                          : 0)
-
-WORD_LIST *
-list_string (string, separators, quoted)
-     register char *string, *separators;
-     int quoted;
-{
-  WORD_LIST *result;
-  WORD_DESC *t;
-  char *current_word, *s;
-  int sindex, sh_style_split, whitesep, xflags;
-  size_t slen;
-
-  if (!string || !*string)
-    return ((WORD_LIST *)NULL);
-
-  sh_style_split = separators && separators[0] == ' ' &&
-                                separators[1] == '\t' &&
-                                separators[2] == '\n' &&
-                                separators[3] == '\0';
-  for (xflags = 0, s = ifs_value; s && *s; s++)
-    {
-      if (*s == CTLESC) xflags |= SX_NOCTLESC;
-      else if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
-    }
-
-  slen = 0;
-  /* Remove sequences of whitespace at the beginning of STRING, as
-     long as those characters appear in IFS.  Do not do this if
-     STRING is quoted or if there are no separator characters. */
-  if (!quoted || !separators || !*separators)
-    {
-      for (s = string; *s && spctabnl (*s) && issep (*s); s++);
-
-      if (!*s)
-       return ((WORD_LIST *)NULL);
-
-      string = s;
-    }
-
-  /* OK, now STRING points to a word that does not begin with white space.
-     The splitting algorithm is:
-       extract a word, stopping at a separator
-       skip sequences of spc, tab, or nl as long as they are separators
-     This obeys the field splitting rules in Posix.2. */
-  slen = (MB_CUR_MAX > 1) ? strlen (string) : 1;
-  for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
-    {
-      /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
-        unless multibyte chars are possible. */
-      current_word = string_extract_verbatim (string, slen, &sindex, separators, xflags);
-      if (current_word == 0)
-       break;
-
-      /* If we have a quoted empty string, add a quoted null argument.  We
-        want to preserve the quoted null character iff this is a quoted
-        empty string; otherwise the quoted null characters are removed
-        below. */
-      if (QUOTED_NULL (current_word))
-       {
-         t = alloc_word_desc ();
-         t->word = make_quoted_char ('\0');
-         t->flags |= W_QUOTED|W_HASQUOTEDNULL;
-         result = make_word_list (t, result);
-       }
-      else if (current_word[0] != '\0')
-       {
-         /* If we have something, then add it regardless.  However,
-            perform quoted null character removal on the current word. */
-         remove_quoted_nulls (current_word);
-         result = add_string_to_list (current_word, result);
-         result->word->flags &= ~W_HASQUOTEDNULL;      /* just to be sure */
-         if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
-           result->word->flags |= W_QUOTED;
-       }
-
-      /* If we're not doing sequences of separators in the traditional
-        Bourne shell style, then add a quoted null argument. */
-      else if (!sh_style_split && !spctabnl (string[sindex]))
-       {
-         t = alloc_word_desc ();
-         t->word = make_quoted_char ('\0');
-         t->flags |= W_QUOTED|W_HASQUOTEDNULL;
-         result = make_word_list (t, result);
-       }
-
-      free (current_word);
-
-      /* Note whether or not the separator is IFS whitespace, used later. */
-      whitesep = string[sindex] && spctabnl (string[sindex]);
-
-      /* Move past the current separator character. */
-      if (string[sindex])
-       {
-         DECLARE_MBSTATE;
-         ADVANCE_CHAR (string, slen, sindex);
-       }
-
-      /* Now skip sequences of space, tab, or newline characters if they are
-        in the list of separators. */
-      while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
-       sindex++;
-
-      /* If the first separator was IFS whitespace and the current character
-        is a non-whitespace IFS character, it should be part of the current
-        field delimiter, not a separate delimiter that would result in an
-        empty field.  Look at POSIX.2, 3.6.5, (3)(b). */
-      if (string[sindex] && whitesep && issep (string[sindex]) && !spctabnl (string[sindex]))
-       {
-         sindex++;
-         /* An IFS character that is not IFS white space, along with any
-            adjacent IFS white space, shall delimit a field. (SUSv3) */
-         while (string[sindex] && spctabnl (string[sindex]) && isifs (string[sindex]))
-           sindex++;
-       }
-    }
-  return (REVERSE_LIST (result, WORD_LIST *));
-}
-
-/* Parse a single word from STRING, using SEPARATORS to separate fields.
-   ENDPTR is set to the first character after the word.  This is used by
-   the `read' builtin.  This is never called with SEPARATORS != $IFS;
-   it should be simplified.
-
-   XXX - this function is very similar to list_string; they should be
-        combined - XXX */
-char *
-get_word_from_string (stringp, separators, endptr)
-     char **stringp, *separators, **endptr;
-{
-  register char *s;
-  char *current_word;
-  int sindex, sh_style_split, whitesep, xflags;
-  size_t slen;
-
-  if (!stringp || !*stringp || !**stringp)
-    return ((char *)NULL);
-
-  sh_style_split = separators && separators[0] == ' ' &&
-                                separators[1] == '\t' &&
-                                separators[2] == '\n' &&
-                                separators[3] == '\0';
-  for (xflags = 0, s = ifs_value; s && *s; s++)
-    {
-      if (*s == CTLESC) xflags |= SX_NOCTLESC;
-      if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
-    }
-
-  s = *stringp;
-  slen = 0;
-
-  /* Remove sequences of whitespace at the beginning of STRING, as
-     long as those characters appear in IFS. */
-  if (sh_style_split || !separators || !*separators)
-    {
-      for (; *s && spctabnl (*s) && isifs (*s); s++);
-
-      /* If the string is nothing but whitespace, update it and return. */
-      if (!*s)
-       {
-         *stringp = s;
-         if (endptr)
-           *endptr = s;
-         return ((char *)NULL);
-       }
-    }
-
-  /* OK, S points to a word that does not begin with white space.
-     Now extract a word, stopping at a separator, save a pointer to
-     the first character after the word, then skip sequences of spc,
-     tab, or nl as long as they are separators.
-
-     This obeys the field splitting rules in Posix.2. */
-  sindex = 0;
-  /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
-     unless multibyte chars are possible. */
-  slen = (MB_CUR_MAX > 1) ? strlen (s) : 1;
-  current_word = string_extract_verbatim (s, slen, &sindex, separators, xflags);
-
-  /* Set ENDPTR to the first character after the end of the word. */
-  if (endptr)
-    *endptr = s + sindex;
-
-  /* Note whether or not the separator is IFS whitespace, used later. */
-  whitesep = s[sindex] && spctabnl (s[sindex]);
-
-  /* Move past the current separator character. */
-  if (s[sindex])
-    {
-      DECLARE_MBSTATE;
-      ADVANCE_CHAR (s, slen, sindex);
-    }
-
-  /* Now skip sequences of space, tab, or newline characters if they are
-     in the list of separators. */
-  while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
-    sindex++;
-
-  /* If the first separator was IFS whitespace and the current character is
-     a non-whitespace IFS character, it should be part of the current field
-     delimiter, not a separate delimiter that would result in an empty field.
-     Look at POSIX.2, 3.6.5, (3)(b). */
-  if (s[sindex] && whitesep && isifs (s[sindex]) && !spctabnl (s[sindex]))
-    {
-      sindex++;
-      /* An IFS character that is not IFS white space, along with any adjacent
-        IFS white space, shall delimit a field. */
-      while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
-       sindex++;
-    }
-
-  /* Update STRING to point to the next field. */
-  *stringp = s + sindex;
-  return (current_word);
-}
-
-/* Remove IFS white space at the end of STRING.  Start at the end
-   of the string and walk backwards until the beginning of the string
-   or we find a character that's not IFS white space and not CTLESC.
-   Only let CTLESC escape a white space character if SAW_ESCAPE is
-   non-zero.  */
-char *
-strip_trailing_ifs_whitespace (string, separators, saw_escape)
-     char *string, *separators;
-     int saw_escape;
-{
-  char *s;
-
-  s = string + STRLEN (string) - 1;
-  while (s > string && ((spctabnl (*s) && isifs (*s)) ||
-                       (saw_escape && *s == CTLESC && spctabnl (s[1]))))
-    s--;
-  *++s = '\0';
-  return string;
-}
-
-#if 0
-/* UNUSED */
-/* Split STRING into words at whitespace.  Obeys shell-style quoting with
-   backslashes, single and double quotes. */
-WORD_LIST *
-list_string_with_quotes (string)
-     char *string;
-{
-  WORD_LIST *list;
-  char *token, *s;
-  size_t s_len;
-  int c, i, tokstart, len;
-
-  for (s = string; s && *s && spctabnl (*s); s++)
-    ;
-  if (s == 0 || *s == 0)
-    return ((WORD_LIST *)NULL);
-
-  s_len = strlen (s);
-  tokstart = i = 0;
-  list = (WORD_LIST *)NULL;
-  while (1)
-    {
-      c = s[i];
-      if (c == '\\')
-       {
-         i++;
-         if (s[i])
-           i++;
-       }
-      else if (c == '\'')
-       i = skip_single_quoted (s, s_len, ++i);
-      else if (c == '"')
-       i = skip_double_quoted (s, s_len, ++i);
-      else if (c == 0 || spctabnl (c))
-       {
-         /* We have found the end of a token.  Make a word out of it and
-            add it to the word list. */
-         token = substring (s, tokstart, i);
-         list = add_string_to_list (token, list);
-         free (token);
-         while (spctabnl (s[i]))
-           i++;
-         if (s[i])
-           tokstart = i;
-         else
-           break;
-       }
-      else
-       i++;    /* normal character */
-    }
-  return (REVERSE_LIST (list, WORD_LIST *));
-}
-#endif
-
-/********************************************************/
-/*                                                     */
-/*     Functions to perform assignment statements      */
-/*                                                     */
-/********************************************************/
-
-#if defined (ARRAY_VARS)
-static SHELL_VAR *
-do_compound_assignment (name, value, flags)
-     char *name, *value;
-     int flags;
-{
-  SHELL_VAR *v;
-  int mklocal, mkassoc, mkglobal;
-  WORD_LIST *list;
-
-  mklocal = flags & ASS_MKLOCAL;
-  mkassoc = flags & ASS_MKASSOC;
-  mkglobal = flags & ASS_MKGLOBAL;
-
-  if (mklocal && variable_context)
-    {
-      v = find_variable (name);
-      list = expand_compound_array_assignment (v, value, flags);
-      if (mkassoc)
-       v = make_local_assoc_variable (name);
-      else if (v == 0 || (array_p (v) == 0 && assoc_p (v) == 0) || v->context != variable_context)
-        v = make_local_array_variable (name, 0);
-      if (v)
-       assign_compound_array_list (v, list, flags);
-    }
-  /* In a function but forcing assignment in global context */
-  else if (mkglobal && variable_context)
-    {
-      v = find_global_variable (name);
-      list = expand_compound_array_assignment (v, value, flags);
-      if (v == 0 && mkassoc)
-       v = make_new_assoc_variable (name);
-      else if (v && mkassoc && assoc_p (v) == 0)
-       v = convert_var_to_assoc (v);
-      else if (v == 0)
-       v = make_new_array_variable (name);
-      else if (v && mkassoc == 0 && array_p (v) == 0)
-       v = convert_var_to_array (v);
-      if (v)
-       assign_compound_array_list (v, list, flags);
-    }
-  else
-    v = assign_array_from_string (name, value, flags);
-
-  return (v);
-}
-#endif
-
-/* Given STRING, an assignment string, get the value of the right side
-   of the `=', and bind it to the left side.  If EXPAND is true, then
-   perform parameter expansion, command substitution, and arithmetic
-   expansion on the right-hand side.  Perform tilde expansion in any
-   case.  Do not perform word splitting on the result of expansion. */
-static int
-do_assignment_internal (word, expand)
-     const WORD_DESC *word;
-     int expand;
-{
-  int offset, appendop, assign_list, aflags, retval;
-  char *name, *value, *temp;
-  SHELL_VAR *entry;
-#if defined (ARRAY_VARS)
-  char *t;
-  int ni;
-#endif
-  const char *string;
-
-  if (word == 0 || word->word == 0)
-    return 0;
-
-  appendop = assign_list = aflags = 0;
-  string = word->word;
-  offset = assignment (string, 0);
-  name = savestring (string);
-  value = (char *)NULL;
-
-  if (name[offset] == '=')
-    {
-      if (name[offset - 1] == '+')
-       {
-         appendop = 1;
-         name[offset - 1] = '\0';
-       }
-
-      name[offset] = 0;                /* might need this set later */
-      temp = name + offset + 1;
-
-#if defined (ARRAY_VARS)
-      if (expand && (word->flags & W_COMPASSIGN))
-       {
-         assign_list = ni = 1;
-         value = extract_array_assignment_list (temp, &ni);
-       }
-      else
-#endif
-      if (expand && temp[0])
-       value = expand_string_if_necessary (temp, 0, expand_string_assignment);
-      else
-       value = savestring (temp);
-    }
-
-  if (value == 0)
-    {
-      value = (char *)xmalloc (1);
-      value[0] = '\0';
-    }
-
-  if (echo_command_at_execute)
-    {
-      if (appendop)
-       name[offset - 1] = '+';
-      xtrace_print_assignment (name, value, assign_list, 1);
-      if (appendop)
-       name[offset - 1] = '\0';
-    }
-
-#define ASSIGN_RETURN(r)       do { FREE (value); free (name); return (r); } while (0)
-
-  if (appendop)
-    aflags |= ASS_APPEND;
-
-#if defined (ARRAY_VARS)
-  if (t = mbschr (name, '['))  /*]*/
-    {
-      if (assign_list)
-       {
-         report_error (_("%s: cannot assign list to array member"), name);
-         ASSIGN_RETURN (0);
-       }
-      entry = assign_array_element (name, value, aflags);
-      if (entry == 0)
-       ASSIGN_RETURN (0);
-    }
-  else if (assign_list)
-    {
-      if ((word->flags & W_ASSIGNARG) && (word->flags & W_ASSNGLOBAL) == 0)
-       aflags |= ASS_MKLOCAL;
-      if ((word->flags & W_ASSIGNARG) && (word->flags & W_ASSNGLOBAL))
-       aflags |= ASS_MKGLOBAL;
-      if (word->flags & W_ASSIGNASSOC)
-       aflags |= ASS_MKASSOC;
-      entry = do_compound_assignment (name, value, aflags);
-    }
-  else
-#endif /* ARRAY_VARS */
-  entry = bind_variable (name, value, aflags);
-
-  stupidly_hack_special_variables (name);
-
-  /* Return 1 if the assignment seems to have been performed correctly. */
-  if (entry == 0 || readonly_p (entry))
-    retval = 0;                /* assignment failure */
-  else if (noassign_p (entry))
-    {
-      last_command_exit_value = EXECUTION_FAILURE;
-      retval = 1;      /* error status, but not assignment failure */
-    }
-  else
-    retval = 1;
-
-  if (entry && retval != 0 && noassign_p (entry) == 0)
-    VUNSETATTR (entry, att_invisible);
-
-  ASSIGN_RETURN (retval);
-}
-
-/* Perform the assignment statement in STRING, and expand the
-   right side by doing tilde, command and parameter expansion. */
-int
-do_assignment (string)
-     char *string;
-{
-  WORD_DESC td;
-
-  td.flags = W_ASSIGNMENT;
-  td.word = string;
-
-  return do_assignment_internal (&td, 1);
-}
-
-int
-do_word_assignment (word, flags)
-     WORD_DESC *word;
-     int flags;
-{
-  return do_assignment_internal (word, 1);
-}
-
-/* Given STRING, an assignment string, get the value of the right side
-   of the `=', and bind it to the left side.  Do not perform any word
-   expansions on the right hand side. */
-int
-do_assignment_no_expand (string)
-     char *string;
-{
-  WORD_DESC td;
-
-  td.flags = W_ASSIGNMENT;
-  td.word = string;
-
-  return (do_assignment_internal (&td, 0));
-}
-
-/***************************************************
- *                                                *
- *  Functions to manage the positional parameters  *
- *                                                *
- ***************************************************/
-
-/* Return the word list that corresponds to `$*'. */
-WORD_LIST *
-list_rest_of_args ()
-{
-  register WORD_LIST *list, *args;
-  int i;
-
-  /* Break out of the loop as soon as one of the dollar variables is null. */
-  for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
-    list = make_word_list (make_bare_word (dollar_vars[i]), list);
-
-  for (args = rest_of_args; args; args = args->next)
-    list = make_word_list (make_bare_word (args->word->word), list);
-
-  return (REVERSE_LIST (list, WORD_LIST *));
-}
-
-int
-number_of_args ()
-{
-  register WORD_LIST *list;
-  int n;
-
-  for (n = 0; n < 9 && dollar_vars[n+1]; n++)
-    ;
-  for (list = rest_of_args; list; list = list->next)
-    n++;
-  return n;
-}
-
-/* Return the value of a positional parameter.  This handles values > 10. */
-char *
-get_dollar_var_value (ind)
-     intmax_t ind;
-{
-  char *temp;
-  WORD_LIST *p;
-
-  if (ind < 10)
-    temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
-  else /* We want something like ${11} */
-    {
-      ind -= 10;
-      for (p = rest_of_args; p && ind--; p = p->next)
-       ;
-      temp = p ? savestring (p->word->word) : (char *)NULL;
-    }
-  return (temp);
-}
-
-/* Make a single large string out of the dollar digit variables,
-   and the rest_of_args.  If DOLLAR_STAR is 1, then obey the special
-   case of "$*" with respect to IFS. */
-char *
-string_rest_of_args (dollar_star)
-     int dollar_star;
-{
-  register WORD_LIST *list;
-  char *string;
-
-  list = list_rest_of_args ();
-  string = dollar_star ? string_list_dollar_star (list) : string_list (list);
-  dispose_words (list);
-  return (string);
-}
-
-/* Return a string containing the positional parameters from START to
-   END, inclusive.  If STRING[0] == '*', we obey the rules for $*,
-   which only makes a difference if QUOTED is non-zero.  If QUOTED includes
-   Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise
-   no quoting chars are added. */
-static char *
-pos_params (string, start, end, quoted)
-     char *string;
-     int start, end, quoted;
-{
-  WORD_LIST *save, *params, *h, *t;
-  char *ret;
-  int i;
-
-  /* see if we can short-circuit.  if start == end, we want 0 parameters. */
-  if (start == end)
-    return ((char *)NULL);
-
-  save = params = list_rest_of_args ();
-  if (save == 0)
-    return ((char *)NULL);
-
-  if (start == 0)              /* handle ${@:0[:x]} specially */
-    {
-      t = make_word_list (make_word (dollar_vars[0]), params);
-      save = params = t;
-    }
-
-  for (i = start ? 1 : 0; params && i < start; i++)
-    params = params->next;
-  if (params == 0)
-    return ((char *)NULL);
-  for (h = t = params; params && i < end; i++)
-    {
-      t = params;
-      params = params->next;
-    }
-
-  t->next = (WORD_LIST *)NULL;
-
-  ret = string_list_pos_params (string[0], h, quoted);
-
-  if (t != params)
-    t->next = params;
-
-  dispose_words (save);
-  return (ret);
-}
-
-/******************************************************************/
-/*                                                               */
-/*     Functions to expand strings to strings or WORD_LISTs      */
-/*                                                               */
-/******************************************************************/
-
-#if defined (PROCESS_SUBSTITUTION)
-#define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~')
-#else
-#define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
-#endif
-
-/* If there are any characters in STRING that require full expansion,
-   then call FUNC to expand STRING; otherwise just perform quote
-   removal if necessary.  This returns a new string. */
-static char *
-expand_string_if_necessary (string, quoted, func)
-     char *string;
-     int quoted;
-     EXPFUNC *func;
-{
-  WORD_LIST *list;
-  size_t slen;
-  int i, saw_quote;
-  char *ret;
-  DECLARE_MBSTATE;
-
-  /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
-  slen = (MB_CUR_MAX > 1) ? strlen (string) : 0;
-  i = saw_quote = 0;
-  while (string[i])
-    {
-      if (EXP_CHAR (string[i]))
-       break;
-      else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
-       saw_quote = 1;
-      ADVANCE_CHAR (string, slen, i);
-    }
-
-  if (string[i])
-    {
-      list = (*func) (string, quoted);
-      if (list)
-       {
-         ret = string_list (list);
-         dispose_words (list);
-       }
-      else
-       ret = (char *)NULL;
-    }
-  else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
-    ret = string_quote_removal (string, quoted);
-  else
-    ret = savestring (string);
-
-  return ret;
-}
-
-static inline char *
-expand_string_to_string_internal (string, quoted, func)
-     char *string;
-     int quoted;
-     EXPFUNC *func;
-{
-  WORD_LIST *list;
-  char *ret;
-
-  if (string == 0 || *string == '\0')
-    return ((char *)NULL);
-
-  list = (*func) (string, quoted);
-  if (list)
-    {
-      ret = string_list (list);
-      dispose_words (list);
-    }
-  else
-    ret = (char *)NULL;
-
-  return (ret);
-}
-
-char *
-expand_string_to_string (string, quoted)
-     char *string;
-     int quoted;
-{
-  return (expand_string_to_string_internal (string, quoted, expand_string));
-}
-
-char *
-expand_string_unsplit_to_string (string, quoted)
-     char *string;
-     int quoted;
-{
-  return (expand_string_to_string_internal (string, quoted, expand_string_unsplit));
-}
-
-char *
-expand_assignment_string_to_string (string, quoted)
-     char *string;
-     int quoted;
-{
-  return (expand_string_to_string_internal (string, quoted, expand_string_assignment));
-}
-
-char *
-expand_arith_string (string, quoted)
-     char *string;
-     int quoted;
-{
-  return (expand_string_if_necessary (string, quoted, expand_string));
-}
-
-#if defined (COND_COMMAND)
-/* Just remove backslashes in STRING.  Returns a new string. */
-char *
-remove_backslashes (string)
-     char *string;
-{
-  char *r, *ret, *s;
-
-  r = ret = (char *)xmalloc (strlen (string) + 1);
-  for (s = string; s && *s; )
-    {
-      if (*s == '\\')
-       s++;
-      if (*s == 0)
-       break;
-      *r++ = *s++;
-    }
-  *r = '\0';
-  return ret;
-}
-
-/* This needs better error handling. */
-/* Expand W for use as an argument to a unary or binary operator in a
-   [[...]] expression.  If SPECIAL is 1, this is the rhs argument
-   to the != or == operator, and should be treated as a pattern.  In
-   this case, we quote the string specially for the globbing code.  If
-   SPECIAL is 2, this is an rhs argument for the =~ operator, and should
-   be quoted appropriately for regcomp/regexec.  The caller is responsible
-   for removing the backslashes if the unquoted word is needed later. */   
-char *
-cond_expand_word (w, special)
-     WORD_DESC *w;
-     int special;
-{
-  char *r, *p;
-  WORD_LIST *l;
-  int qflags;
-
-  if (w->word == 0 || w->word[0] == '\0')
-    return ((char *)NULL);
-
-  w->flags |= W_NOSPLIT2;
-  l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
-  if (l)
-    {
-      if (special == 0)
-       {
-         dequote_list (l);
-         r = string_list (l);
-       }
-      else
-       {
-         qflags = QGLOB_CVTNULL;
-         if (special == 2)
-           qflags |= QGLOB_REGEXP;
-         p = string_list (l);
-         r = quote_string_for_globbing (p, qflags);
-         free (p);
-       }
-      dispose_words (l);
-    }
-  else
-    r = (char *)NULL;
-
-  return r;
-}
-#endif
-
-/* Call expand_word_internal to expand W and handle error returns.
-   A convenience function for functions that don't want to handle
-   any errors or free any memory before aborting. */
-static WORD_LIST *
-call_expand_word_internal (w, q, i, c, e)
-     WORD_DESC *w;
-     int q, i, *c, *e;
-{
-  WORD_LIST *result;
-
-  result = expand_word_internal (w, q, i, c, e);
-  if (result == &expand_word_error || result == &expand_word_fatal)
-    {
-      /* By convention, each time this error is returned, w->word has
-        already been freed (it sometimes may not be in the fatal case,
-        but that doesn't result in a memory leak because we're going
-        to exit in most cases). */
-      w->word = (char *)NULL;
-      last_command_exit_value = EXECUTION_FAILURE;
-      exp_jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF);
-      /* NOTREACHED */
-    }
-  else
-    return (result);
-}
-
-/* Perform parameter expansion, command substitution, and arithmetic
-   expansion on STRING, as if it were a word.  Leave the result quoted.
-   Since this does not perform word splitting, it leaves quoted nulls
-   in the result.  */
-static WORD_LIST *
-expand_string_internal (string, quoted)
-     char *string;
-     int quoted;
-{
-  WORD_DESC td;
-  WORD_LIST *tresult;
-
-  if (string == 0 || *string == 0)
-    return ((WORD_LIST *)NULL);
-
-  td.flags = 0;
-  td.word = savestring (string);
-
-  tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
-
-  FREE (td.word);
-  return (tresult);
-}
-
-/* Expand STRING by performing parameter expansion, command substitution,
-   and arithmetic expansion.  Dequote the resulting WORD_LIST before
-   returning it, but do not perform word splitting.  The call to
-   remove_quoted_nulls () is in here because word splitting normally
-   takes care of quote removal. */
-WORD_LIST *
-expand_string_unsplit (string, quoted)
-     char *string;
-     int quoted;
-{
-  WORD_LIST *value;
-
-  if (string == 0 || *string == '\0')
-    return ((WORD_LIST *)NULL);
-
-  expand_no_split_dollar_star = 1;
-  value = expand_string_internal (string, quoted);
-  expand_no_split_dollar_star = 0;
-
-  if (value)
-    {
-      if (value->word)
-       {
-         remove_quoted_nulls (value->word->word);
-         value->word->flags &= ~W_HASQUOTEDNULL;
-       }
-      dequote_list (value);
-    }
-  return (value);
-}
-
-/* Expand the rhs of an assignment statement */
-WORD_LIST *
-expand_string_assignment (string, quoted)
-     char *string;
-     int quoted;
-{
-  WORD_DESC td;
-  WORD_LIST *value;
-
-  if (string == 0 || *string == '\0')
-    return ((WORD_LIST *)NULL);
-
-  expand_no_split_dollar_star = 1;
-
-  td.flags = W_ASSIGNRHS;
-  td.word = savestring (string);
-  value = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
-  FREE (td.word);
-
-  expand_no_split_dollar_star = 0;
-
-  if (value)
-    {
-      if (value->word)
-       {
-         remove_quoted_nulls (value->word->word);
-         value->word->flags &= ~W_HASQUOTEDNULL;
-       }
-      dequote_list (value);
-    }
-  return (value);
-}
-
-
-/* Expand one of the PS? prompt strings. This is a sort of combination of
-   expand_string_unsplit and expand_string_internal, but returns the
-   passed string when an error occurs.  Might want to trap other calls
-   to jump_to_top_level here so we don't endlessly loop. */
-WORD_LIST *
-expand_prompt_string (string, quoted, wflags)
-     char *string;
-     int quoted;
-     int wflags;
-{
-  WORD_LIST *value;
-  WORD_DESC td;
-
-  if (string == 0 || *string == 0)
-    return ((WORD_LIST *)NULL);
-
-  td.flags = wflags;
-  td.word = savestring (string);
-
-  no_longjmp_on_fatal_error = 1;
-  value = expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
-  no_longjmp_on_fatal_error = 0;
-
-  if (value == &expand_word_error || value == &expand_word_fatal)
-    {
-      value = make_word_list (make_bare_word (string), (WORD_LIST *)NULL);
-      return value;
-    }
-  FREE (td.word);
-  if (value)
-    {
-      if (value->word)
-       {
-         remove_quoted_nulls (value->word->word);
-         value->word->flags &= ~W_HASQUOTEDNULL;
-       }
-      dequote_list (value);
-    }
-  return (value);
-}
-
-/* Expand STRING just as if you were expanding a word, but do not dequote
-   the resultant WORD_LIST.  This is called only from within this file,
-   and is used to correctly preserve quoted characters when expanding
-   things like ${1+"$@"}.  This does parameter expansion, command
-   substitution, arithmetic expansion, and word splitting. */
-static WORD_LIST *
-expand_string_leave_quoted (string, quoted)
-     char *string;
-     int quoted;
-{
-  WORD_LIST *tlist;
-  WORD_LIST *tresult;
-
-  if (string == 0 || *string == '\0')
-    return ((WORD_LIST *)NULL);
-
-  tlist = expand_string_internal (string, quoted);
-
-  if (tlist)
-    {
-      tresult = word_list_split (tlist);
-      dispose_words (tlist);
-      return (tresult);
-    }
-  return ((WORD_LIST *)NULL);
-}
-
-/* This does not perform word splitting or dequote the WORD_LIST
-   it returns. */
-static WORD_LIST *
-expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
-     char *string;
-     int quoted, *dollar_at_p, *has_dollar_at;
-{
-  WORD_DESC td;
-  WORD_LIST *tresult;
-
-  if (string == 0 || *string == '\0')
-    return (WORD_LIST *)NULL;
-
-  td.flags = W_NOSPLIT2;               /* no splitting, remove "" and '' */
-  td.word = string;
-  tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
-  return (tresult);
-}
-
-/* Expand STRING just as if you were expanding a word.  This also returns
-   a list of words.  Note that filename globbing is *NOT* done for word
-   or string expansion, just when the shell is expanding a command.  This
-   does parameter expansion, command substitution, arithmetic expansion,
-   and word splitting.  Dequote the resultant WORD_LIST before returning. */
-WORD_LIST *
-expand_string (string, quoted)
-     char *string;
-     int quoted;
-{
-  WORD_LIST *result;
-
-  if (string == 0 || *string == '\0')
-    return ((WORD_LIST *)NULL);
-
-  result = expand_string_leave_quoted (string, quoted);
-  return (result ? dequote_list (result) : result);
-}
-
-/***************************************************
- *                                                *
- *     Functions to handle quoting chars          *
- *                                                *
- ***************************************************/
-
-/* Conventions:
-
-     A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
-     The parser passes CTLNUL as CTLESC CTLNUL. */
-
-/* Quote escape characters in string s, but no other characters.  This is
-   used to protect CTLESC and CTLNUL in variable values from the rest of
-   the word expansion process after the variable is expanded (word splitting
-   and filename generation).  If IFS is null, we quote spaces as well, just
-   in case we split on spaces later (in the case of unquoted $@, we will
-   eventually attempt to split the entire word on spaces).  Corresponding
-   code exists in dequote_escapes.  Even if we don't end up splitting on
-   spaces, quoting spaces is not a problem.  This should never be called on
-   a string that is quoted with single or double quotes or part of a here
-   document (effectively double-quoted). */
-char *
-quote_escapes (string)
-     char *string;
-{
-  register char *s, *t;
-  size_t slen;
-  char *result, *send;
-  int quote_spaces, skip_ctlesc, skip_ctlnul;
-  DECLARE_MBSTATE; 
-
-  slen = strlen (string);
-  send = string + slen;
-
-  quote_spaces = (ifs_value && *ifs_value == 0);
-
-  for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
-    skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
-
-  t = result = (char *)xmalloc ((slen * 2) + 1);
-  s = string;
-
-  while (*s)
-    {
-      if ((skip_ctlesc == 0 && *s == CTLESC) || (skip_ctlnul == 0 && *s == CTLNUL) || (quote_spaces && *s == ' '))
-       *t++ = CTLESC;
-      COPY_CHAR_P (t, s, send);
-    }
-  *t = '\0';
-  return (result);
-}
-
-static WORD_LIST *
-list_quote_escapes (list)
-     WORD_LIST *list;
-{
-  register WORD_LIST *w;
-  char *t;
-
-  for (w = list; w; w = w->next)
-    {
-      t = w->word->word;
-      w->word->word = quote_escapes (t);
-      free (t);
-    }
-  return list;
-}
-
-/* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
-
-   The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
-   This is necessary to make unquoted CTLESC and CTLNUL characters in the
-   data stream pass through properly.
-
-   We need to remove doubled CTLESC characters inside quoted strings before
-   quoting the entire string, so we do not double the number of CTLESC
-   characters.
-
-   Also used by parts of the pattern substitution code. */
-char *
-dequote_escapes (string)
-     char *string;
-{
-  register char *s, *t, *s1;
-  size_t slen;
-  char *result, *send;
-  int quote_spaces;
-  DECLARE_MBSTATE;
-
-  if (string == 0)
-    return string;
-
-  slen = strlen (string);
-  send = string + slen;
-
-  t = result = (char *)xmalloc (slen + 1);
-
-  if (strchr (string, CTLESC) == 0)
-    return (strcpy (result, string));
-
-  quote_spaces = (ifs_value && *ifs_value == 0);
-
-  s = string;
-  while (*s)
-    {
-      if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
-       {
-         s++;
-         if (*s == '\0')
-           break;
-       }
-      COPY_CHAR_P (t, s, send);
-    }
-  *t = '\0';
-  return result;
-}
-
-/* Return a new string with the quoted representation of character C.
-   This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be
-   set in any resultant WORD_DESC where this value is the word. */
-static char *
-make_quoted_char (c)
-     int c;
-{
-  char *temp;
-
-  temp = (char *)xmalloc (3);
-  if (c == 0)
-    {
-      temp[0] = CTLNUL;
-      temp[1] = '\0';
-    }
-  else
-    {
-      temp[0] = CTLESC;
-      temp[1] = c;
-      temp[2] = '\0';
-    }
-  return (temp);
-}
-
-/* Quote STRING, returning a new string.  This turns "" into QUOTED_NULL, so
-   the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where
-   this value is the word. */
-char *
-quote_string (string)
-     char *string;
-{
-  register char *t;
-  size_t slen;
-  char *result, *send;
-
-  if (*string == 0)
-    {
-      result = (char *)xmalloc (2);
-      result[0] = CTLNUL;
-      result[1] = '\0';
-    }
-  else
-    {
-      DECLARE_MBSTATE;
-
-      slen = strlen (string);
-      send = string + slen;
-
-      result = (char *)xmalloc ((slen * 2) + 1);
-
-      for (t = result; string < send; )
-       {
-         *t++ = CTLESC;
-         COPY_CHAR_P (t, string, send);
-       }
-      *t = '\0';
-    }
-  return (result);
-}
-
-/* De-quote quoted characters in STRING. */
-char *
-dequote_string (string)
-     char *string;
-{
-  register char *s, *t;
-  size_t slen;
-  char *result, *send;
-  DECLARE_MBSTATE;
-
-  slen = strlen (string);
-
-  t = result = (char *)xmalloc (slen + 1);
-
-  if (QUOTED_NULL (string))
-    {
-      result[0] = '\0';
-      return (result);
-    }
-
-  /* If no character in the string can be quoted, don't bother examining
-     each character.  Just return a copy of the string passed to us. */
-  if (strchr (string, CTLESC) == NULL)
-    return (strcpy (result, string));
-
-  send = string + slen;
-  s = string;
-  while (*s)
-    {
-      if (*s == CTLESC)
-       {
-         s++;
-         if (*s == '\0')
-           break;
-       }
-      COPY_CHAR_P (t, s, send);
-    }
-
-  *t = '\0';
-  return (result);
-}
-
-/* Quote the entire WORD_LIST list. */
-static WORD_LIST *
-quote_list (list)
-     WORD_LIST *list;
-{
-  register WORD_LIST *w;
-  char *t;
-
-  for (w = list; w; w = w->next)
-    {
-      t = w->word->word;
-      w->word->word = quote_string (t);
-      if (*t == 0)
-       w->word->flags |= W_HASQUOTEDNULL;      /* XXX - turn on W_HASQUOTEDNULL here? */
-      w->word->flags |= W_QUOTED;
-      free (t);
-    }
-  return list;
-}
-
-/* De-quote quoted characters in each word in LIST. */
-WORD_LIST *
-dequote_list (list)
-     WORD_LIST *list;
-{
-  register char *s;
-  register WORD_LIST *tlist;
-
-  for (tlist = list; tlist; tlist = tlist->next)
-    {
-      s = dequote_string (tlist->word->word);
-      if (QUOTED_NULL (tlist->word->word))
-       tlist->word->flags &= ~W_HASQUOTEDNULL;
-      free (tlist->word->word);
-      tlist->word->word = s;
-    }
-  return list;
-}
-
-/* Remove CTLESC protecting a CTLESC or CTLNUL in place.  Return the passed
-   string. */
-char *
-remove_quoted_escapes (string)
-     char *string;
-{
-  char *t;
-
-  if (string)
-    {
-      t = dequote_escapes (string);
-      strcpy (string, t);
-      free (t);
-    }
-
-  return (string);
-}
-
-/* Perform quoted null character removal on STRING.  We don't allow any
-   quoted null characters in the middle or at the ends of strings because
-   of how expand_word_internal works.  remove_quoted_nulls () turns
-   STRING into an empty string iff it only consists of a quoted null,
-   and removes all unquoted CTLNUL characters. */
-char *
-remove_quoted_nulls (string)
-     char *string;
-{
-  register size_t slen;
-  register int i, j, prev_i;
-  DECLARE_MBSTATE;
-
-  if (strchr (string, CTLNUL) == 0)            /* XXX */
-    return string;                             /* XXX */
-
-  slen = strlen (string);
-  i = j = 0;
-
-  while (i < slen)
-    {
-      if (string[i] == CTLESC)
-       {
-         /* Old code had j++, but we cannot assume that i == j at this
-            point -- what if a CTLNUL has already been removed from the
-            string?  We don't want to drop the CTLESC or recopy characters
-            that we've already copied down. */
-         i++; string[j++] = CTLESC;
-         if (i == slen)
-           break;
-       }
-      else if (string[i] == CTLNUL)
-       {
-         i++;
-         continue;
-       }
-
-      prev_i = i;
-      ADVANCE_CHAR (string, slen, i);
-      if (j < prev_i)
-       {
-         do string[j++] = string[prev_i++]; while (prev_i < i);
-       }
-      else
-       j = i;
-    }
-  string[j] = '\0';
-
-  return (string);
-}
-
-/* Perform quoted null character removal on each element of LIST.
-   This modifies LIST. */
-void
-word_list_remove_quoted_nulls (list)
-     WORD_LIST *list;
-{
-  register WORD_LIST *t;
-
-  for (t = list; t; t = t->next)
-    {
-      remove_quoted_nulls (t->word->word);
-      t->word->flags &= ~W_HASQUOTEDNULL;
-    }
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*        Functions for Matching and Removing Patterns             */
-/*                                                                 */
-/* **************************************************************** */
-
-#if defined (HANDLE_MULTIBYTE)
-#if 0 /* Currently unused */
-static unsigned char *
-mb_getcharlens (string, len)
-     char *string;
-     int len;
-{
-  int i, offset, last;
-  unsigned char *ret;
-  char *p;
-  DECLARE_MBSTATE;
-
-  i = offset = 0;
-  last = 0;
-  ret = (unsigned char *)xmalloc (len);
-  memset (ret, 0, len);
-  while (string[last])
-    {
-      ADVANCE_CHAR (string, len, offset);
-      ret[last] = offset - last;
-      last = offset;
-    }
-  return ret;
-}
-#endif
-#endif
-
-/* Remove the portion of PARAM matched by PATTERN according to OP, where OP
-   can have one of 4 values:
-       RP_LONG_LEFT    remove longest matching portion at start of PARAM
-       RP_SHORT_LEFT   remove shortest matching portion at start of PARAM
-       RP_LONG_RIGHT   remove longest matching portion at end of PARAM
-       RP_SHORT_RIGHT  remove shortest matching portion at end of PARAM
-*/
-
-#define RP_LONG_LEFT   1
-#define RP_SHORT_LEFT  2
-#define RP_LONG_RIGHT  3
-#define RP_SHORT_RIGHT 4
-
-/* Returns its first argument if nothing matched; new memory otherwise */
-static char *
-remove_upattern (param, pattern, op)
-     char *param, *pattern;
-     int op;
-{
-  register int len;
-  register char *end;
-  register char *p, *ret, c;
-
-  len = STRLEN (param);
-  end = param + len;
-
-  switch (op)
-    {
-      case RP_LONG_LEFT:       /* remove longest match at start */
-       for (p = end; p >= param; p--)
-         {
-           c = *p; *p = '\0';
-           if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
-             {
-               *p = c;
-               return (savestring (p));
-             }
-           *p = c;
-
-         }
-       break;
-
-      case RP_SHORT_LEFT:      /* remove shortest match at start */
-       for (p = param; p <= end; p++)
-         {
-           c = *p; *p = '\0';
-           if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
-             {
-               *p = c;
-               return (savestring (p));
-             }
-           *p = c;
-         }
-       break;
-
-      case RP_LONG_RIGHT:      /* remove longest match at end */
-       for (p = param; p <= end; p++)
-         {
-           if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
-             {
-               c = *p; *p = '\0';
-               ret = savestring (param);
-               *p = c;
-               return (ret);
-             }
-         }
-       break;
-
-      case RP_SHORT_RIGHT:     /* remove shortest match at end */
-       for (p = end; p >= param; p--)
-         {
-           if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
-             {
-               c = *p; *p = '\0';
-               ret = savestring (param);
-               *p = c;
-               return (ret);
-             }
-         }
-       break;
-    }
-
-  return (param);      /* no match, return original string */
-}
-
-#if defined (HANDLE_MULTIBYTE)
-/* Returns its first argument if nothing matched; new memory otherwise */
-static wchar_t *
-remove_wpattern (wparam, wstrlen, wpattern, op)
-     wchar_t *wparam;
-     size_t wstrlen;
-     wchar_t *wpattern;
-     int op;
-{
-  wchar_t wc, *ret;
-  int n;
-
-  switch (op)
-    {
-      case RP_LONG_LEFT:       /* remove longest match at start */
-        for (n = wstrlen; n >= 0; n--)
-         {
-           wc = wparam[n]; wparam[n] = L'\0';
-           if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
-             {
-               wparam[n] = wc;
-               return (wcsdup (wparam + n));
-             }
-           wparam[n] = wc;
-         }
-       break;
-
-      case RP_SHORT_LEFT:      /* remove shortest match at start */
-       for (n = 0; n <= wstrlen; n++)
-         {
-           wc = wparam[n]; wparam[n] = L'\0';
-           if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
-             {
-               wparam[n] = wc;
-               return (wcsdup (wparam + n));
-             }
-           wparam[n] = wc;
-         }
-       break;
-
-      case RP_LONG_RIGHT:      /* remove longest match at end */
-        for (n = 0; n <= wstrlen; n++)
-         {
-           if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
-             {
-               wc = wparam[n]; wparam[n] = L'\0';
-               ret = wcsdup (wparam);
-               wparam[n] = wc;
-               return (ret);
-             }
-         }
-       break;
-
-      case RP_SHORT_RIGHT:     /* remove shortest match at end */
-       for (n = wstrlen; n >= 0; n--)
-         {
-           if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
-             {
-               wc = wparam[n]; wparam[n] = L'\0';
-               ret = wcsdup (wparam);
-               wparam[n] = wc;
-               return (ret);
-             }
-         }
-       break;
-    }
-
-  return (wparam);     /* no match, return original string */
-}
-#endif /* HANDLE_MULTIBYTE */
-
-static char *
-remove_pattern (param, pattern, op)
-     char *param, *pattern;
-     int op;
-{
-  char *xret;
-
-  if (param == NULL)
-    return (param);
-  if (*param == '\0' || pattern == NULL || *pattern == '\0')   /* minor optimization */
-    return (savestring (param));
-
-#if defined (HANDLE_MULTIBYTE)
-  if (MB_CUR_MAX > 1)
-    {
-      wchar_t *ret, *oret;
-      size_t n;
-      wchar_t *wparam, *wpattern;
-      mbstate_t ps;
-
-      n = xdupmbstowcs (&wpattern, NULL, pattern);
-      if (n == (size_t)-1)
-       {
-         xret = remove_upattern (param, pattern, op);
-         return ((xret == param) ? savestring (param) : xret);
-       }
-      n = xdupmbstowcs (&wparam, NULL, param);
-
-      if (n == (size_t)-1)
-       {
-         free (wpattern);
-         xret = remove_upattern (param, pattern, op);
-         return ((xret == param) ? savestring (param) : xret);
-       }
-      oret = ret = remove_wpattern (wparam, n, wpattern, op);
-      /* Don't bother to convert wparam back to multibyte string if nothing
-        matched; just return copy of original string */
-      if (ret == wparam)
-        {
-          free (wparam);
-          free (wpattern);
-          return (savestring (param));
-        }
-
-      free (wparam);
-      free (wpattern);
-
-      n = strlen (param);
-      xret = (char *)xmalloc (n + 1);
-      memset (&ps, '\0', sizeof (mbstate_t));
-      n = wcsrtombs (xret, (const wchar_t **)&ret, n, &ps);
-      xret[n] = '\0';          /* just to make sure */
-      free (oret);
-      return xret;      
-    }
-  else
-#endif
-    {
-      xret = remove_upattern (param, pattern, op);
-      return ((xret == param) ? savestring (param) : xret);
-    }
-}
-
-/* Match PAT anywhere in STRING and return the match boundaries.
-   This returns 1 in case of a successful match, 0 otherwise.  SP
-   and EP are pointers into the string where the match begins and
-   ends, respectively.  MTYPE controls what kind of match is attempted.
-   MATCH_BEG and MATCH_END anchor the match at the beginning and end
-   of the string, respectively.  The longest match is returned. */
-static int
-match_upattern (string, pat, mtype, sp, ep)
-     char *string, *pat;
-     int mtype;
-     char **sp, **ep;
-{
-  int c, len, mlen;
-  register char *p, *p1, *npat;
-  char *end;
-  int n1;
-
-  /* If the pattern doesn't match anywhere in the string, go ahead and
-     short-circuit right away.  A minor optimization, saves a bunch of
-     unnecessary calls to strmatch (up to N calls for a string of N
-     characters) if the match is unsuccessful.  To preserve the semantics
-     of the substring matches below, we make sure that the pattern has
-     `*' as first and last character, making a new pattern if necessary. */
-  /* XXX - check this later if I ever implement `**' with special meaning,
-     since this will potentially result in `**' at the beginning or end */
-  len = STRLEN (pat);
-  if (pat[0] != '*' || (pat[0] == '*' && pat[1] == LPAREN && extended_glob) || pat[len - 1] != '*')
-    {
-      p = npat = (char *)xmalloc (len + 3);
-      p1 = pat;
-      if (*p1 != '*' || (*p1 == '*' && p1[1] == LPAREN && extended_glob))
-       *p++ = '*';
-      while (*p1)
-       *p++ = *p1++;
-      if (p1[-1] != '*' || p[-2] == '\\')
-       *p++ = '*';
-      *p = '\0';
-    }
-  else
-    npat = pat;
-  c = strmatch (npat, string, FNMATCH_EXTFLAG);
-  if (npat != pat)
-    free (npat);
-  if (c == FNM_NOMATCH)
-    return (0);
-
-  len = STRLEN (string);
-  end = string + len;
-
-  mlen = umatchlen (pat, len);
-
-  switch (mtype)
-    {
-    case MATCH_ANY:
-      for (p = string; p <= end; p++)
-       {
-         if (match_pattern_char (pat, p))
-           {
-             p1 = (mlen == -1) ? end : p + mlen;
-             /* p1 - p = length of portion of string to be considered
-                p = current position in string
-                mlen = number of characters consumed by match (-1 for entire string)
-                end = end of string
-                we want to break immediately if the potential match len
-                is greater than the number of characters remaining in the
-                string
-             */
-             if (p1 > end)
-               break;
-             for ( ; p1 >= p; p1--)
-               {
-                 c = *p1; *p1 = '\0';
-                 if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
-                   {
-                     *p1 = c;
-                     *sp = p;
-                     *ep = p1;
-                     return 1;
-                   }
-                 *p1 = c;
-#if 1
-                 /* If MLEN != -1, we have a fixed length pattern. */
-                 if (mlen != -1)
-                   break;
-#endif
-               }
-           }
-       }
-
-      return (0);
-
-    case MATCH_BEG:
-      if (match_pattern_char (pat, string) == 0)
-       return (0);
-
-      for (p = (mlen == -1) ? end : string + mlen; p >= string; p--)
-       {
-         c = *p; *p = '\0';
-         if (strmatch (pat, string, FNMATCH_EXTFLAG) == 0)
-           {
-             *p = c;
-             *sp = string;
-             *ep = p;
-             return 1;
-           }
-         *p = c;
-         /* If MLEN != -1, we have a fixed length pattern. */
-         if (mlen != -1)
-           break;
-       }
-
-      return (0);
-
-    case MATCH_END:
-      for (p = end - ((mlen == -1) ? len : mlen); p <= end; p++)
-       {
-         if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
-           {
-             *sp = p;
-             *ep = end;
-             return 1;
-           }
-         /* If MLEN != -1, we have a fixed length pattern. */
-         if (mlen != -1)
-           break;
-       }
-
-      return (0);
-    }
-
-  return (0);
-}
-
-#if defined (HANDLE_MULTIBYTE)
-/* Match WPAT anywhere in WSTRING and return the match boundaries.
-   This returns 1 in case of a successful match, 0 otherwise.  Wide
-   character version. */
-static int
-match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
-     wchar_t *wstring;
-     char **indices;
-     size_t wstrlen;
-     wchar_t *wpat;
-     int mtype;
-     char **sp, **ep;
-{
-  wchar_t wc, *wp, *nwpat, *wp1;
-  size_t len;
-  int mlen;
-  int n, n1, n2, simple;
-
-  simple = (wpat[0] != L'\\' && wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'[');
-#if defined (EXTENDED_GLOB)
-  if (extended_glob)
-    simple &= (wpat[1] != L'(' || (wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'+' && wpat[0] != L'!' && wpat[0] != L'@')); /*)*/
-#endif
-
-  /* If the pattern doesn't match anywhere in the string, go ahead and
-     short-circuit right away.  A minor optimization, saves a bunch of
-     unnecessary calls to strmatch (up to N calls for a string of N
-     characters) if the match is unsuccessful.  To preserve the semantics
-     of the substring matches below, we make sure that the pattern has
-     `*' as first and last character, making a new pattern if necessary. */
-  len = wcslen (wpat);
-  if (wpat[0] != L'*' || (wpat[0] == L'*' && wpat[1] == WLPAREN && extended_glob) || wpat[len - 1] != L'*')
-    {
-      wp = nwpat = (wchar_t *)xmalloc ((len + 3) * sizeof (wchar_t));
-      wp1 = wpat;
-      if (*wp1 != L'*' || (*wp1 == '*' && wp1[1] == WLPAREN && extended_glob))
-       *wp++ = L'*';
-      while (*wp1 != L'\0')
-       *wp++ = *wp1++;
-      if (wp1[-1] != L'*' || wp1[-2] == L'\\')
-        *wp++ = L'*';
-      *wp = '\0';
-    }
-  else
-    nwpat = wpat;
-  len = wcsmatch (nwpat, wstring, FNMATCH_EXTFLAG);
-  if (nwpat != wpat)
-    free (nwpat);
-  if (len == FNM_NOMATCH)
-    return (0);
-
-  mlen = wmatchlen (wpat, wstrlen);
-
-/* itrace("wmatchlen (%ls) -> %d", wpat, mlen); */
-  switch (mtype)
-    {
-    case MATCH_ANY:
-      for (n = 0; n <= wstrlen; n++)
-       {
-         n2 = simple ? (*wpat == wstring[n]) : match_pattern_wchar (wpat, wstring + n);
-         if (n2)
-           {
-             n1 = (mlen == -1) ? wstrlen : n + mlen;
-             if (n1 > wstrlen)
-               break;
-
-             for ( ; n1 >= n; n1--)
-               {
-                 wc = wstring[n1]; wstring[n1] = L'\0';
-                 if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
-                   {
-                     wstring[n1] = wc;
-                     *sp = indices[n];
-                     *ep = indices[n1];
-                     return 1;
-                   }
-                 wstring[n1] = wc;
-                 /* If MLEN != -1, we have a fixed length pattern. */
-                 if (mlen != -1)
-                   break;
-               }
-           }
-       }
-
-      return (0);
-
-    case MATCH_BEG:
-      if (match_pattern_wchar (wpat, wstring) == 0)
-       return (0);
-
-      for (n = (mlen == -1) ? wstrlen : mlen; n >= 0; n--)
-       {
-         wc = wstring[n]; wstring[n] = L'\0';
-         if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG) == 0)
-           {
-             wstring[n] = wc;
-             *sp = indices[0];
-             *ep = indices[n];
-             return 1;
-           }
-         wstring[n] = wc;
-         /* If MLEN != -1, we have a fixed length pattern. */
-         if (mlen != -1)
-           break;
-       }
-
-      return (0);
-
-    case MATCH_END:
-      for (n = wstrlen - ((mlen == -1) ? wstrlen : mlen); n <= wstrlen; n++)
-       {
-         if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
-           {
-             *sp = indices[n];
-             *ep = indices[wstrlen];
-             return 1;
-           }
-         /* If MLEN != -1, we have a fixed length pattern. */
-         if (mlen != -1)
-           break;
-       }
-
-      return (0);
-    }
-
-  return (0);
-}
-#endif /* HANDLE_MULTIBYTE */
-
-static int
-match_pattern (string, pat, mtype, sp, ep)
-     char *string, *pat;
-     int mtype;
-     char **sp, **ep;
-{
-#if defined (HANDLE_MULTIBYTE)
-  int ret;
-  size_t n;
-  wchar_t *wstring, *wpat;
-  char **indices;
-  size_t slen, plen, mslen, mplen, wn;
-#endif
-
-  if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
-    return (0);
-
-#if defined (HANDLE_MULTIBYTE)
-  if (MB_CUR_MAX > 1)
-    {
-      if (mbsmbchar (string) == 0 && mbsmbchar (pat) == 0)
-        return (match_upattern (string, pat, mtype, sp, ep));
-
-      n = xdupmbstowcs (&wpat, NULL, pat);
-      if (n == (size_t)-1)
-       return (match_upattern (string, pat, mtype, sp, ep));
-      n = xdupmbstowcs (&wstring, &indices, string);
-      if (n == (size_t)-1)
-       {
-         free (wpat);
-         return (match_upattern (string, pat, mtype, sp, ep));
-       }
-wn = wstring ? wcslen (wstring) : 0;
-if (n != wn)
-  itrace("xdupmbstowcs returns %d != length of wstring %d", n, wn);
-      ret = match_wpattern (wstring, indices, n, wpat, mtype, sp, ep);
-
-      free (wpat);
-      free (wstring);
-      free (indices);
-
-      return (ret);
-    }
-  else
-#endif
-    return (match_upattern (string, pat, mtype, sp, ep));
-}
-
-static int
-getpatspec (c, value)
-     int c;
-     char *value;
-{
-  if (c == '#')
-    return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
-  else /* c == '%' */
-    return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
-}
-
-/* Posix.2 says that the WORD should be run through tilde expansion,
-   parameter expansion, command substitution and arithmetic expansion.
-   This leaves the result quoted, so quote_string_for_globbing () has
-   to be called to fix it up for strmatch ().  If QUOTED is non-zero,
-   it means that the entire expression was enclosed in double quotes.
-   This means that quoting characters in the pattern do not make any
-   special pattern characters quoted.  For example, the `*' in the
-   following retains its special meaning: "${foo#'*'}". */
-static char *
-getpattern (value, quoted, expandpat)
-     char *value;
-     int quoted, expandpat;
-{
-  char *pat, *tword;
-  WORD_LIST *l;
-#if 0
-  int i;
-#endif
-  /* There is a problem here:  how to handle single or double quotes in the
-     pattern string when the whole expression is between double quotes?
-     POSIX.2 says that enclosing double quotes do not cause the pattern to
-     be quoted, but does that leave us a problem with @ and array[@] and their
-     expansions inside a pattern? */
-#if 0
-  if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
-    {
-      i = 0;
-      pat = string_extract_double_quoted (tword, &i, 1);
-      free (tword);
-      tword = pat;
-    }
-#endif
-
-  /* expand_string_for_rhs () leaves WORD quoted and does not perform
-     word splitting. */
-  l = *value ? expand_string_for_rhs (value,
-                                     (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_PATQUOTE : quoted,
-                                     (int *)NULL, (int *)NULL)
-            : (WORD_LIST *)0;
-  pat = string_list (l);
-  dispose_words (l);
-  if (pat)
-    {
-      tword = quote_string_for_globbing (pat, QGLOB_CVTNULL);
-      free (pat);
-      pat = tword;
-    }
-  return (pat);
-}
-
-#if 0
-/* Handle removing a pattern from a string as a result of ${name%[%]value}
-   or ${name#[#]value}. */
-static char *
-variable_remove_pattern (value, pattern, patspec, quoted)
-     char *value, *pattern;
-     int patspec, quoted;
-{
-  char *tword;
-
-  tword = remove_pattern (value, pattern, patspec);
-
-  return (tword);
-}
-#endif
-
-static char *
-list_remove_pattern (list, pattern, patspec, itype, quoted)
-     WORD_LIST *list;
-     char *pattern;
-     int patspec, itype, quoted;
-{
-  WORD_LIST *new, *l;
-  WORD_DESC *w;
-  char *tword;
-
-  for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
-    {
-      tword = remove_pattern (l->word->word, pattern, patspec);
-      w = alloc_word_desc ();
-      w->word = tword ? tword : savestring ("");
-      new = make_word_list (w, new);
-    }
-
-  l = REVERSE_LIST (new, WORD_LIST *);
-  tword = string_list_pos_params (itype, l, quoted);
-  dispose_words (l);
-
-  return (tword);
-}
-
-static char *
-parameter_list_remove_pattern (itype, pattern, patspec, quoted)
-     int itype;
-     char *pattern;
-     int patspec, quoted;
-{
-  char *ret;
-  WORD_LIST *list;
-
-  list = list_rest_of_args ();
-  if (list == 0)
-    return ((char *)NULL);
-  ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
-  dispose_words (list);
-  return (ret);
-}
-
-#if defined (ARRAY_VARS)
-static char *
-array_remove_pattern (var, pattern, patspec, varname, quoted)
-     SHELL_VAR *var;
-     char *pattern;
-     int patspec;
-     char *varname;    /* so we can figure out how it's indexed */
-     int quoted;
-{
-  ARRAY *a;
-  HASH_TABLE *h;
-  int itype;
-  char *ret;
-  WORD_LIST *list;
-  SHELL_VAR *v;
-
-  /* compute itype from varname here */
-  v = array_variable_part (varname, &ret, 0);
-  itype = ret[0];
-
-  a = (v && array_p (v)) ? array_cell (v) : 0;
-  h = (v && assoc_p (v)) ? assoc_cell (v) : 0;
-  
-  list = a ? array_to_word_list (a) : (h ? assoc_to_word_list (h) : 0);
-  if (list == 0)
-   return ((char *)NULL);
-  ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
-  dispose_words (list);
-
-  return ret;
-}
-#endif /* ARRAY_VARS */
-
-static char *
-parameter_brace_remove_pattern (varname, value, ind, patstr, rtype, quoted, flags)
-     char *varname, *value;
-     int ind;
-     char *patstr;
-     int rtype, quoted, flags;
-{
-  int vtype, patspec, starsub;
-  char *temp1, *val, *pattern;
-  SHELL_VAR *v;
-
-  if (value == 0)
-    return ((char *)NULL);
-
-  this_command_name = varname;
-
-  vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
-  if (vtype == -1)
-    return ((char *)NULL);
-
-  starsub = vtype & VT_STARSUB;
-  vtype &= ~VT_STARSUB;
-
-  patspec = getpatspec (rtype, patstr);
-  if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
-    patstr++;
-
-  /* Need to pass getpattern newly-allocated memory in case of expansion --
-     the expansion code will free the passed string on an error. */
-  temp1 = savestring (patstr);
-  pattern = getpattern (temp1, quoted, 1);
-  free (temp1);
-
-  temp1 = (char *)NULL;                /* shut up gcc */
-  switch (vtype)
-    {
-    case VT_VARIABLE:
-    case VT_ARRAYMEMBER:
-      temp1 = remove_pattern (val, pattern, patspec);
-      if (vtype == VT_VARIABLE)
-       FREE (val);
-      if (temp1)
-       {
-         val = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
-                       ? quote_string (temp1)
-                       : quote_escapes (temp1);
-         free (temp1);
-         temp1 = val;
-       }
-      break;
-#if defined (ARRAY_VARS)
-    case VT_ARRAYVAR:
-      temp1 = array_remove_pattern (v, pattern, patspec, varname, quoted);
-      if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
-       {
-         val = quote_escapes (temp1);
-         free (temp1);
-         temp1 = val;
-       }
-      break;
-#endif
-    case VT_POSPARMS:
-      temp1 = parameter_list_remove_pattern (varname[0], pattern, patspec, quoted);
-      if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
-       {
-         val = quote_escapes (temp1);
-         free (temp1);
-         temp1 = val;
-       }
-      break;
-    }
-
-  FREE (pattern);
-  return temp1;
-}    
-
-/*******************************************
- *                                        *
- *     Functions to expand WORD_DESCs     *
- *                                        *
- *******************************************/
-
-/* Expand WORD, performing word splitting on the result.  This does
-   parameter expansion, command substitution, arithmetic expansion,
-   word splitting, and quote removal. */
-
-WORD_LIST *
-expand_word (word, quoted)
-     WORD_DESC *word;
-     int quoted;
-{
-  WORD_LIST *result, *tresult;
-
-  tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
-  result = word_list_split (tresult);
-  dispose_words (tresult);
-  return (result ? dequote_list (result) : result);
-}
-
-/* Expand WORD, but do not perform word splitting on the result.  This
-   does parameter expansion, command substitution, arithmetic expansion,
-   and quote removal. */
-WORD_LIST *
-expand_word_unsplit (word, quoted)
-     WORD_DESC *word;
-     int quoted;
-{
-  WORD_LIST *result;
-
-  expand_no_split_dollar_star = 1;
-#if defined (HANDLE_MULTIBYTE)
-  if (ifs_firstc[0] == 0)
-#else
-  if (ifs_firstc == 0)
-#endif
-    word->flags |= W_NOSPLIT;
-  word->flags |= W_NOSPLIT2;
-  result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
-  expand_no_split_dollar_star = 0;
-
-  return (result ? dequote_list (result) : result);
-}
-
-/* Perform shell expansions on WORD, but do not perform word splitting or
-   quote removal on the result.  Virtually identical to expand_word_unsplit;
-   could be combined if implementations don't diverge. */
-WORD_LIST *
-expand_word_leave_quoted (word, quoted)
-     WORD_DESC *word;
-     int quoted;
-{
-  WORD_LIST *result;
-
-  expand_no_split_dollar_star = 1;
-#if defined (HANDLE_MULTIBYTE)
-  if (ifs_firstc[0] == 0)
-#else
-  if (ifs_firstc == 0)
-#endif
-    word->flags |= W_NOSPLIT;
-  word->flags |= W_NOSPLIT2;
-  result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
-  expand_no_split_dollar_star = 0;
-
-  return result;
-}
-
-#if defined (PROCESS_SUBSTITUTION)
-
-/*****************************************************************/
-/*                                                              */
-/*                 Hacking Process Substitution                 */
-/*                                                              */
-/*****************************************************************/
-
-#if !defined (HAVE_DEV_FD)
-/* Named pipes must be removed explicitly with `unlink'.  This keeps a list
-   of FIFOs the shell has open.  unlink_fifo_list will walk the list and
-   unlink all of them. add_fifo_list adds the name of an open FIFO to the
-   list.  NFIFO is a count of the number of FIFOs in the list. */
-#define FIFO_INCR 20
-
-struct temp_fifo {
-  char *file;
-  pid_t proc;
-};
-
-static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL;
-static int nfifo;
-static int fifo_list_size;
-
-char *
-copy_fifo_list (sizep)
-     int *sizep;
-{
-  if (sizep)
-    *sizep = 0;
-  return (char *)NULL;
-}
-
-static void
-add_fifo_list (pathname)
-     char *pathname;
-{
-  if (nfifo >= fifo_list_size - 1)
-    {
-      fifo_list_size += FIFO_INCR;
-      fifo_list = (struct temp_fifo *)xrealloc (fifo_list,
-                               fifo_list_size * sizeof (struct temp_fifo));
-    }
-
-  fifo_list[nfifo].file = savestring (pathname);
-  nfifo++;
-}
-
-void
-unlink_fifo (i)
-     int i;
-{
-  if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1))
-    {
-      unlink (fifo_list[i].file);
-      free (fifo_list[i].file);
-      fifo_list[i].file = (char *)NULL;
-      fifo_list[i].proc = -1;
-    }
-}
-
-void
-unlink_fifo_list ()
-{
-  int saved, i, j;
-
-  if (nfifo == 0)
-    return;
-
-  for (i = saved = 0; i < nfifo; i++)
-    {
-      if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1))
-       {
-         unlink (fifo_list[i].file);
-         free (fifo_list[i].file);
-         fifo_list[i].file = (char *)NULL;
-         fifo_list[i].proc = -1;
-       }
-      else
-       saved++;
-    }
-
-  /* If we didn't remove some of the FIFOs, compact the list. */
-  if (saved)
-    {
-      for (i = j = 0; i < nfifo; i++)
-       if (fifo_list[i].file)
-         {
-           fifo_list[j].file = fifo_list[i].file;
-           fifo_list[j].proc = fifo_list[i].proc;
-           j++;
-         }
-      nfifo = j;
-    }
-  else
-    nfifo = 0;
-}
-
-/* Take LIST, which is a bitmap denoting active FIFOs in fifo_list
-   from some point in the past, and close all open FIFOs in fifo_list
-   that are not marked as active in LIST.  If LIST is NULL, close
-   everything in fifo_list. LSIZE is the number of elements in LIST, in
-   case it's larger than fifo_list_size (size of fifo_list). */
-void
-close_new_fifos (list, lsize)
-     char *list;
-     int lsize;
-{
-  int i;
-
-  if (list == 0)
-    {
-      unlink_fifo_list ();
-      return;
-    }
-
-  for (i = 0; i < lsize; i++)
-    if (list[i] == 0 && i < fifo_list_size && fifo_list[i].proc != -1)
-      unlink_fifo (i);
-
-  for (i = lsize; i < fifo_list_size; i++)
-    unlink_fifo (i);  
-}
-
-int
-fifos_pending ()
-{
-  return nfifo;
-}
-
-int
-num_fifos ()
-{
-  return nfifo;
-}
-
-static char *
-make_named_pipe ()
-{
-  char *tname;
-
-  tname = sh_mktmpname ("sh-np", MT_USERANDOM|MT_USETMPDIR);
-  if (mkfifo (tname, 0600) < 0)
-    {
-      free (tname);
-      return ((char *)NULL);
-    }
-
-  add_fifo_list (tname);
-  return (tname);
-}
-
-#else /* HAVE_DEV_FD */
-
-/* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
-   has open to children.  NFDS is a count of the number of bits currently
-   set in DEV_FD_LIST.  TOTFDS is a count of the highest possible number
-   of open files. */
-static char *dev_fd_list = (char *)NULL;
-static int nfds;
-static int totfds;     /* The highest possible number of open files. */
-
-char *
-copy_fifo_list (sizep)
-     int *sizep;
-{
-  char *ret;
-
-  if (nfds == 0 || totfds == 0)
-    {
-      if (sizep)
-       *sizep = 0;
-      return (char *)NULL;
-    }
-
-  if (sizep)
-    *sizep = totfds;
-  ret = (char *)xmalloc (totfds);
-  return (memcpy (ret, dev_fd_list, totfds));
-}
-
-static void
-add_fifo_list (fd)
-     int fd;
-{
-  if (dev_fd_list == 0 || fd >= totfds)
-    {
-      int ofds;
-
-      ofds = totfds;
-      totfds = getdtablesize ();
-      if (totfds < 0 || totfds > 256)
-       totfds = 256;
-      if (fd >= totfds)
-       totfds = fd + 2;
-
-      dev_fd_list = (char *)xrealloc (dev_fd_list, totfds);
-      memset (dev_fd_list + ofds, '\0', totfds - ofds);
-    }
-
-  dev_fd_list[fd] = 1;
-  nfds++;
-}
-
-int
-fifos_pending ()
-{
-  return 0;    /* used for cleanup; not needed with /dev/fd */
-}
-
-int
-num_fifos ()
-{
-  return nfds;
-}
-
-void
-unlink_fifo (fd)
-     int fd;
-{
-  if (dev_fd_list[fd])
-    {
-      close (fd);
-      dev_fd_list[fd] = 0;
-      nfds--;
-    }
-}
-
-void
-unlink_fifo_list ()
-{
-  register int i;
-
-  if (nfds == 0)
-    return;
-
-  for (i = 0; nfds && i < totfds; i++)
-    unlink_fifo (i);
-
-  nfds = 0;
-}
-
-/* Take LIST, which is a snapshot copy of dev_fd_list from some point in
-   the past, and close all open fds in dev_fd_list that are not marked
-   as open in LIST.  If LIST is NULL, close everything in dev_fd_list.
-   LSIZE is the number of elements in LIST, in case it's larger than
-   totfds (size of dev_fd_list). */
-void
-close_new_fifos (list, lsize)
-     char *list;
-     int lsize;
-{
-  int i;
-
-  if (list == 0)
-    {
-      unlink_fifo_list ();
-      return;
-    }
-
-  for (i = 0; i < lsize; i++)
-    if (list[i] == 0 && i < totfds && dev_fd_list[i])
-      unlink_fifo (i);
-
-  for (i = lsize; i < totfds; i++)
-    unlink_fifo (i);  
-}
-
-#if defined (NOTDEF)
-print_dev_fd_list ()
-{
-  register int i;
-
-  fprintf (stderr, "pid %ld: dev_fd_list:", (long)getpid ());
-  fflush (stderr);
-
-  for (i = 0; i < totfds; i++)
-    {
-      if (dev_fd_list[i])
-       fprintf (stderr, " %d", i);
-    }
-  fprintf (stderr, "\n");
-}
-#endif /* NOTDEF */
-
-static char *
-make_dev_fd_filename (fd)
-     int fd;
-{
-  char *ret, intbuf[INT_STRLEN_BOUND (int) + 1], *p;
-
-  ret = (char *)xmalloc (sizeof (DEV_FD_PREFIX) + 8);
-
-  strcpy (ret, DEV_FD_PREFIX);
-  p = inttostr (fd, intbuf, sizeof (intbuf));
-  strcpy (ret + sizeof (DEV_FD_PREFIX) - 1, p);
-
-  add_fifo_list (fd);
-  return (ret);
-}
-
-#endif /* HAVE_DEV_FD */
-
-/* Return a filename that will open a connection to the process defined by
-   executing STRING.  HAVE_DEV_FD, if defined, means open a pipe and return
-   a filename in /dev/fd corresponding to a descriptor that is one of the
-   ends of the pipe.  If not defined, we use named pipes on systems that have
-   them.  Systems without /dev/fd and named pipes are out of luck.
-
-   OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
-   use the read end of the pipe and dup that file descriptor to fd 0 in
-   the child.  If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
-   writing or use the write end of the pipe in the child, and dup that
-   file descriptor to fd 1 in the child.  The parent does the opposite. */
-
-static char *
-process_substitute (string, open_for_read_in_child)
-     char *string;
-     int open_for_read_in_child;
-{
-  char *pathname;
-  int fd, result;
-  pid_t old_pid, pid;
-#if defined (HAVE_DEV_FD)
-  int parent_pipe_fd, child_pipe_fd;
-  int fildes[2];
-#endif /* HAVE_DEV_FD */
-#if defined (JOB_CONTROL)
-  pid_t old_pipeline_pgrp;
-#endif
-
-  if (!string || !*string || wordexp_only)
-    return ((char *)NULL);
-
-#if !defined (HAVE_DEV_FD)
-  pathname = make_named_pipe ();
-#else /* HAVE_DEV_FD */
-  if (pipe (fildes) < 0)
-    {
-      sys_error (_("cannot make pipe for process substitution"));
-      return ((char *)NULL);
-    }
-  /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
-     the pipe in the parent, otherwise the read end. */
-  parent_pipe_fd = fildes[open_for_read_in_child];
-  child_pipe_fd = fildes[1 - open_for_read_in_child];
-  /* Move the parent end of the pipe to some high file descriptor, to
-     avoid clashes with FDs used by the script. */
-  parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
-
-  pathname = make_dev_fd_filename (parent_pipe_fd);
-#endif /* HAVE_DEV_FD */
-
-  if (pathname == 0)
-    {
-      sys_error (_("cannot make pipe for process substitution"));
-      return ((char *)NULL);
-    }
-
-  old_pid = last_made_pid;
-
-#if defined (JOB_CONTROL)
-  old_pipeline_pgrp = pipeline_pgrp;
-  pipeline_pgrp = shell_pgrp;
-  save_pipeline (1);
-#endif /* JOB_CONTROL */
-
-  pid = make_child ((char *)NULL, 1);
-  if (pid == 0)
-    {
-      reset_terminating_signals ();    /* XXX */
-      free_pushed_string_input ();
-      /* Cancel traps, in trap.c. */
-      restore_original_signals ();     /* XXX - what about special builtins? bash-4.2 */
-      setup_async_signals ();
-      subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB;
-    }
-
-#if defined (JOB_CONTROL)
-  set_sigchld_handler ();
-  stop_making_children ();
-  /* XXX - should we only do this in the parent? (as in command subst) */
-  pipeline_pgrp = old_pipeline_pgrp;
-#endif /* JOB_CONTROL */
-
-  if (pid < 0)
-    {
-      sys_error (_("cannot make child for process substitution"));
-      free (pathname);
-#if defined (HAVE_DEV_FD)
-      close (parent_pipe_fd);
-      close (child_pipe_fd);
-#endif /* HAVE_DEV_FD */
-      return ((char *)NULL);
-    }
-
-  if (pid > 0)
-    {
-#if defined (JOB_CONTROL)
-      restore_pipeline (1);
-#endif
-
-#if !defined (HAVE_DEV_FD)
-      fifo_list[nfifo-1].proc = pid;
-#endif
-
-      last_made_pid = old_pid;
-
-#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
-      close_pgrp_pipe ();
-#endif /* JOB_CONTROL && PGRP_PIPE */
-
-#if defined (HAVE_DEV_FD)
-      close (child_pipe_fd);
-#endif /* HAVE_DEV_FD */
-
-      return (pathname);
-    }
-
-  set_sigint_handler ();
-
-#if defined (JOB_CONTROL)
-  set_job_control (0);
-#endif /* JOB_CONTROL */
-
-#if !defined (HAVE_DEV_FD)
-  /* Open the named pipe in the child. */
-  fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
-  if (fd < 0)
-    {
-      /* Two separate strings for ease of translation. */
-      if (open_for_read_in_child)
-       sys_error (_("cannot open named pipe %s for reading"), pathname);
-      else
-       sys_error (_("cannot open named pipe %s for writing"), pathname);
-
-      exit (127);
-    }
-  if (open_for_read_in_child)
-    {
-      if (sh_unset_nodelay_mode (fd) < 0)
-       {
-         sys_error (_("cannot reset nodelay mode for fd %d"), fd);
-         exit (127);
-       }
-    }
-#else /* HAVE_DEV_FD */
-  fd = child_pipe_fd;
-#endif /* HAVE_DEV_FD */
-
-  if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
-    {
-      sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname,
-       open_for_read_in_child ? 0 : 1);
-      exit (127);
-    }
-
-  if (fd != (open_for_read_in_child ? 0 : 1))
-    close (fd);
-
-  /* Need to close any files that this process has open to pipes inherited
-     from its parent. */
-  if (current_fds_to_close)
-    {
-      close_fd_bitmap (current_fds_to_close);
-      current_fds_to_close = (struct fd_bitmap *)NULL;
-    }
-
-#if defined (HAVE_DEV_FD)
-  /* Make sure we close the parent's end of the pipe and clear the slot
-     in the fd list so it is not closed later, if reallocated by, for
-     instance, pipe(2). */
-  close (parent_pipe_fd);
-  dev_fd_list[parent_pipe_fd] = 0;
-#endif /* HAVE_DEV_FD */
-
-  /* subshells shouldn't have this flag, which controls using the temporary
-     environment for variable lookups. */
-  expanding_redir = 0;
-
-  result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
-
-#if !defined (HAVE_DEV_FD)
-  /* Make sure we close the named pipe in the child before we exit. */
-  close (open_for_read_in_child ? 0 : 1);
-#endif /* !HAVE_DEV_FD */
-
-  exit (result);
-  /*NOTREACHED*/
-}
-#endif /* PROCESS_SUBSTITUTION */
-
-/***********************************/
-/*                                */
-/*     Command Substitution       */
-/*                                */
-/***********************************/
-
-static char *
-read_comsub (fd, quoted, rflag)
-     int fd, quoted;
-     int *rflag;
-{
-  char *istring, buf[128], *bufp, *s;
-  int istring_index, istring_size, c, tflag, skip_ctlesc, skip_ctlnul;
-  ssize_t bufn;
-
-  istring = (char *)NULL;
-  istring_index = istring_size = bufn = tflag = 0;
-
-  for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
-    skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
-
-  /* Read the output of the command through the pipe.  This may need to be
-     changed to understand multibyte characters in the future. */
-  while (1)
-    {
-      if (fd < 0)
-       break;
-      if (--bufn <= 0)
-       {
-         bufn = zread (fd, buf, sizeof (buf));
-         if (bufn <= 0) 
-           break;
-         bufp = buf;
-       }
-      c = *bufp++;
-
-      if (c == 0)
-       {
-#if 0
-         internal_warning ("read_comsub: ignored null byte in input");
-#endif
-         continue;
-       }
-
-      /* Add the character to ISTRING, possibly after resizing it. */
-      RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
-
-      /* This is essentially quote_string inline */
-      if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
-       istring[istring_index++] = CTLESC;
-      /* Escape CTLESC and CTLNUL in the output to protect those characters
-        from the rest of the word expansions (word splitting and globbing.)
-        This is essentially quote_escapes inline. */
-      else if (skip_ctlesc == 0 && c == CTLESC)
-       {
-         tflag |= W_HASCTLESC;
-         istring[istring_index++] = CTLESC;
-       }
-      else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0)))
-       istring[istring_index++] = CTLESC;
-
-      istring[istring_index++] = c;
-
-#if 0
-#if defined (__CYGWIN__)
-      if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r')
-       {
-         istring_index--;
-         istring[istring_index - 1] = '\n';
-       }
-#endif
-#endif
-    }
-
-  if (istring)
-    istring[istring_index] = '\0';
-
-  /* If we read no output, just return now and save ourselves some
-     trouble. */
-  if (istring_index == 0)
-    {
-      FREE (istring);
-      if (rflag)
-       *rflag = tflag;
-      return (char *)NULL;
-    }
-
-  /* Strip trailing newlines from the output of the command. */
-  if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
-    {
-      while (istring_index > 0)
-       {
-         if (istring[istring_index - 1] == '\n')
-           {
-             --istring_index;
-
-             /* If the newline was quoted, remove the quoting char. */
-             if (istring[istring_index - 1] == CTLESC)
-               --istring_index;
-           }
-         else
-           break;
-       }
-      istring[istring_index] = '\0';
-    }
-  else
-    strip_trailing (istring, istring_index - 1, 1);
-
-  if (rflag)
-    *rflag = tflag;
-  return istring;
-}
-
-/* Perform command substitution on STRING.  This returns a WORD_DESC * with the
-   contained string possibly quoted. */
-WORD_DESC *
-command_substitute (string, quoted)
-     char *string;
-     int quoted;
-{
-  pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
-  char *istring;
-  int result, fildes[2], function_value, pflags, rc, tflag;
-  WORD_DESC *ret;
-
-  istring = (char *)NULL;
-
-  /* Don't fork () if there is no need to.  In the case of no command to
-     run, just return NULL. */
-  if (!string || !*string || (string[0] == '\n' && !string[1]))
-    return ((WORD_DESC *)NULL);
-
-  if (wordexp_only && read_but_dont_execute)
-    {
-      last_command_exit_value = EX_WEXPCOMSUB;
-      jump_to_top_level (EXITPROG);
-    }
-
-  /* We're making the assumption here that the command substitution will
-     eventually run a command from the file system.  Since we'll run
-     maybe_make_export_env in this subshell before executing that command,
-     the parent shell and any other shells it starts will have to remake
-     the environment.  If we make it before we fork, other shells won't
-     have to.  Don't bother if we have any temporary variable assignments,
-     though, because the export environment will be remade after this
-     command completes anyway, but do it if all the words to be expanded
-     are variable assignments. */
-  if (subst_assign_varlist == 0 || garglist == 0)
-    maybe_make_export_env ();  /* XXX */
-
-  /* Flags to pass to parse_and_execute() */
-  pflags = (interactive && sourcelevel == 0) ? SEVAL_RESETLINE : 0;
-
-  /* Pipe the output of executing STRING into the current shell. */
-  if (pipe (fildes) < 0)
-    {
-      sys_error (_("cannot make pipe for command substitution"));
-      goto error_exit;
-    }
-
-  old_pid = last_made_pid;
-#if defined (JOB_CONTROL)
-  old_pipeline_pgrp = pipeline_pgrp;
-  /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
-  if ((subshell_environment & SUBSHELL_PIPE) == 0)
-    pipeline_pgrp = shell_pgrp;
-  cleanup_the_pipeline ();
-#endif /* JOB_CONTROL */
-
-  old_async_pid = last_asynchronous_pid;
-  pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
-  last_asynchronous_pid = old_async_pid;
-
-  if (pid == 0)
-    {
-      /* 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 defined (JOB_CONTROL)
-  /* XXX DO THIS ONLY IN PARENT ? XXX */
-  set_sigchld_handler ();
-  stop_making_children ();
-  if (pid != 0)
-    pipeline_pgrp = old_pipeline_pgrp;
-#else
-  stop_making_children ();
-#endif /* JOB_CONTROL */
-
-  if (pid < 0)
-    {
-      sys_error (_("cannot make child for command substitution"));
-    error_exit:
-
-      last_made_pid = old_pid;
-
-      FREE (istring);
-      close (fildes[0]);
-      close (fildes[1]);
-      return ((WORD_DESC *)NULL);
-    }
-
-  if (pid == 0)
-    {
-      set_sigint_handler ();   /* XXX */
-
-      free_pushed_string_input ();
-
-      if (dup2 (fildes[1], 1) < 0)
-       {
-         sys_error (_("command_substitute: cannot duplicate pipe as fd 1"));
-         exit (EXECUTION_FAILURE);
-       }
-
-      /* If standard output is closed in the parent shell
-        (such as after `exec >&-'), file descriptor 1 will be
-        the lowest available file descriptor, and end up in
-        fildes[0].  This can happen for stdin and stderr as well,
-        but stdout is more important -- it will cause no output
-        to be generated from this command. */
-      if ((fildes[1] != fileno (stdin)) &&
-         (fildes[1] != fileno (stdout)) &&
-         (fildes[1] != fileno (stderr)))
-       close (fildes[1]);
-
-      if ((fildes[0] != fileno (stdin)) &&
-         (fildes[0] != fileno (stdout)) &&
-         (fildes[0] != fileno (stderr)))
-       close (fildes[0]);
-
-#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__ */
-
-      /* The currently executing shell is not interactive. */
-      interactive = 0;
-
-      /* This is a subshell environment. */
-      subshell_environment |= SUBSHELL_COMSUB;
-
-      /* When not in POSIX mode, command substitution does not inherit
-        the -e flag. */
-      if (posixly_correct == 0)
-        {
-          builtin_ignoring_errexit = 0;
-         change_flag ('e', FLAG_OFF);
-         set_shellopts ();
-        }
-
-      remove_quoted_escapes (string);
-
-      startup_state = 2;       /* see if we can avoid a fork */
-      /* Give command substitution a place to jump back to on failure,
-        so we don't go back up to main (). */
-      result = setjmp_nosigs (top_level);
-
-      /* If we're running a command substitution inside a shell function,
-        trap `return' so we don't return from the function in the subshell
-        and go off to never-never land. */
-      if (result == 0 && return_catch_flag)
-       function_value = setjmp_nosigs (return_catch);
-      else
-       function_value = 0;
-
-      if (result == ERREXIT)
-       rc = last_command_exit_value;
-      else if (result == EXITPROG)
-       rc = last_command_exit_value;
-      else if (result)
-       rc = EXECUTION_FAILURE;
-      else if (function_value)
-       rc = return_catch_value;
-      else
-       {
-         subshell_level++;
-         rc = parse_and_execute (string, "command substitution", pflags|SEVAL_NOHIST);
-         subshell_level--;
-       }
-
-      last_command_exit_value = rc;
-      rc = run_exit_trap ();
-#if defined (PROCESS_SUBSTITUTION)
-      unlink_fifo_list ();
-#endif
-      exit (rc);
-    }
-  else
-    {
-#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
-      close_pgrp_pipe ();
-#endif /* JOB_CONTROL && PGRP_PIPE */
-
-      close (fildes[1]);
-
-      tflag = 0;
-      istring = read_comsub (fildes[0], quoted, &tflag);
-
-      close (fildes[0]);
-
-      current_command_subst_pid = pid;
-      last_command_exit_value = wait_for (pid);
-      last_command_subst_pid = pid;
-      last_made_pid = old_pid;
-
-#if defined (JOB_CONTROL)
-      /* If last_command_exit_value > 128, then the substituted command
-        was terminated by a signal.  If that signal was SIGINT, then send
-        SIGINT to ourselves.  This will break out of loops, for instance. */
-      if (last_command_exit_value == (128 + SIGINT) && last_command_exit_signal == SIGINT)
-       kill (getpid (), SIGINT);
-
-      /* wait_for gives the terminal back to shell_pgrp.  If some other
-        process group should have it, give it away to that group here.
-        pipeline_pgrp is non-zero only while we are constructing a
-        pipline, so what we are concerned about is whether or not that
-        pipeline was started in the background.  A pipeline started in
-        the background should never get the tty back here. */
-      if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0)
-       give_terminal_to (pipeline_pgrp, 0);
-#endif /* JOB_CONTROL */
-
-      ret = alloc_word_desc ();
-      ret->word = istring;
-      ret->flags = tflag;
-
-      return ret;
-    }
-}
-
-/********************************************************
- *                                                     *
- *     Utility functions for parameter expansion       *
- *                                                     *
- ********************************************************/
-
-#if defined (ARRAY_VARS)
-
-static arrayind_t
-array_length_reference (s)
-     char *s;
-{
-  int len;
-  arrayind_t ind;
-  char *akey;
-  char *t, c;
-  ARRAY *array;
-  HASH_TABLE *h;
-  SHELL_VAR *var;
-
-  var = array_variable_part (s, &t, &len);
-
-  /* If unbound variables should generate an error, report one and return
-     failure. */
-  if ((var == 0 || (assoc_p (var) == 0 && array_p (var) == 0)) && unbound_vars_is_error)
-    {
-      c = *--t;
-      *t = '\0';
-      last_command_exit_value = EXECUTION_FAILURE;
-      err_unboundvar (s);
-      *t = c;
-      return (-1);
-    }
-  else if (var == 0)
-    return 0;
-
-  /* We support a couple of expansions for variables that are not arrays.
-     We'll return the length of the value for v[0], and 1 for v[@] or
-     v[*].  Return 0 for everything else. */
-
-  array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
-  h = assoc_p (var) ? assoc_cell (var) : (HASH_TABLE *)NULL;
-
-  if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
-    {
-      if (assoc_p (var))
-       return (h ? assoc_num_elements (h) : 0);
-      else if (array_p (var))
-       return (array ? array_num_elements (array) : 0);
-      else
-       return (var_isset (var) ? 1 : 0);
-    }
-
-  if (assoc_p (var))
-    {
-      t[len - 1] = '\0';
-      akey = expand_assignment_string_to_string (t, 0);        /* [ */
-      t[len - 1] = ']';
-      if (akey == 0 || *akey == 0)
-       {
-         err_badarraysub (t);
-         FREE (akey);
-         return (-1);
-       }
-      t = assoc_reference (assoc_cell (var), akey);
-      free (akey);
-    }
-  else
-    {
-      ind = array_expand_index (var, t, len);
-      /* negative subscripts to indexed arrays count back from end */
-      if (var && array_p (var) && ind < 0)
-       ind = array_max_index (array_cell (var)) + 1 + ind;
-      if (ind < 0)
-       {
-         err_badarraysub (t);
-         return (-1);
-       }
-      if (array_p (var))
-       t = array_reference (array, ind);
-      else
-       t = (ind == 0) ? value_cell (var) : (char *)NULL;
-    }
-
-  len = MB_STRLEN (t);
-  return (len);
-}
-#endif /* ARRAY_VARS */
-
-static int
-valid_brace_expansion_word (name, var_is_special)
-     char *name;
-     int var_is_special;
-{
-  if (DIGIT (*name) && all_digits (name))
-    return 1;
-  else if (var_is_special)
-    return 1;
-#if defined (ARRAY_VARS)
-  else if (valid_array_reference (name))
-    return 1;
-#endif /* ARRAY_VARS */
-  else if (legal_identifier (name))
-    return 1;
-  else
-    return 0;
-}
-
-static int
-chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at)
-     char *name;
-     int quoted;
-     int *quoted_dollar_atp, *contains_dollar_at;
-{
-  char *temp1;
-
-  if (name == 0)
-    {
-      if (quoted_dollar_atp)
-       *quoted_dollar_atp = 0;
-      if (contains_dollar_at)
-       *contains_dollar_at = 0;
-      return 0;
-    }
-
-  /* check for $@ and $* */
-  if (name[0] == '@' && name[1] == 0)
-    {
-      if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
-       *quoted_dollar_atp = 1;
-      if (contains_dollar_at)
-       *contains_dollar_at = 1;
-      return 1;
-    }
-  else if (name[0] == '*' && name[1] == '\0' && quoted == 0)
-    {
-      if (contains_dollar_at)
-       *contains_dollar_at = 1;
-      return 1;
-    }
-
-  /* Now check for ${array[@]} and ${array[*]} */
-#if defined (ARRAY_VARS)
-  else if (valid_array_reference (name))
-    {
-      temp1 = mbschr (name, '[');
-      if (temp1 && temp1[1] == '@' && temp1[2] == ']')
-       {
-         if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
-           *quoted_dollar_atp = 1;
-         if (contains_dollar_at)
-           *contains_dollar_at = 1;
-         return 1;
-       }       /* [ */
-      /* ${array[*]}, when unquoted, should be treated like ${array[@]},
-        which should result in separate words even when IFS is unset. */
-      if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0)
-       {
-         if (contains_dollar_at)
-           *contains_dollar_at = 1;
-         return 1;
-       }
-    }
-#endif
-  return 0;
-}
-
-/* Parameter expand NAME, and return a new string which is the expansion,
-   or NULL if there was no expansion.
-   VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
-   the shell, e.g., "@", "$", "*", etc.  QUOTED, if non-zero, means that
-   NAME was found inside of a double-quoted expression. */
-static WORD_DESC *
-parameter_brace_expand_word (name, var_is_special, quoted, pflags, indp)
-     char *name;
-     int var_is_special, quoted, pflags;
-     arrayind_t *indp;
-{
-  WORD_DESC *ret;
-  char *temp, *tt;
-  intmax_t arg_index;
-  SHELL_VAR *var;
-  int atype, rflags;
-  arrayind_t ind;
-
-  ret = 0;
-  temp = 0;
-  rflags = 0;
-
-  if (indp)
-    *indp = INTMAX_MIN;
-
-  /* Handle multiple digit arguments, as in ${11}. */  
-  if (legal_number (name, &arg_index))
-    {
-      tt = get_dollar_var_value (arg_index);
-      if (tt)
-       temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
-                 ? quote_string (tt)
-                 : quote_escapes (tt);
-      else
-        temp = (char *)NULL;
-      FREE (tt);
-    }
-  else if (var_is_special)      /* ${@} */
-    {
-      int sindex;
-      tt = (char *)xmalloc (2 + strlen (name));
-      tt[sindex = 0] = '$';
-      strcpy (tt + 1, name);
-
-      ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
-                         (int *)NULL, (int *)NULL, pflags);
-      free (tt);
-    }
-#if defined (ARRAY_VARS)
-  else if (valid_array_reference (name))
-    {
-expand_arrayref:
-      /* XXX - does this leak if name[@] or name[*]? */
-      if (pflags & PF_ASSIGNRHS)
-        {
-          temp = array_variable_name (name, &tt, (int *)0);
-          if (ALL_ELEMENT_SUB (tt[0]) && tt[1] == ']')
-           temp = array_value (name, quoted|Q_DOUBLE_QUOTES, 0, &atype, &ind);
-         else
-           temp = array_value (name, quoted, 0, &atype, &ind);
-        }
-      else
-       temp = array_value (name, quoted, 0, &atype, &ind);
-      if (atype == 0 && temp)
-       {
-         temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
-                   ? quote_string (temp)
-                   : quote_escapes (temp);
-         rflags |= W_ARRAYIND;
-         if (indp)
-           *indp = ind;
-       }                 
-      else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
-       rflags |= W_HASQUOTEDNULL;
-    }
-#endif
-  else if (var = find_variable (name))
-    {
-      if (var_isset (var) && invisible_p (var) == 0)
-       {
-#if defined (ARRAY_VARS)
-         if (assoc_p (var))
-           temp = assoc_reference (assoc_cell (var), "0");
-         else if (array_p (var))
-           temp = array_reference (array_cell (var), 0);
-         else
-           temp = value_cell (var);
-#else
-         temp = value_cell (var);
-#endif
-
-         if (temp)
-           temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
-                     ? quote_string (temp)
-                     : quote_escapes (temp);
-       }
-      else
-       temp = (char *)NULL;
-    }
-  else if (var = find_variable_last_nameref (name))
-    {
-      temp = nameref_cell (var);
-#if defined (ARRAY_VARS)
-      /* Handle expanding nameref whose value is x[n] */
-      if (temp && *temp && valid_array_reference (temp))
-       {
-         name = temp;
-         goto expand_arrayref;
-       }
-#endif
-      /* y=2 ; typeset -n x=y; echo ${x} is not the same as echo ${2} in ksh */
-      else if (temp && *temp && legal_identifier (temp) == 0)
-        {
-         last_command_exit_value = EXECUTION_FAILURE;
-         report_error (_("%s: invalid variable name for name reference"), temp);
-         temp = &expand_param_error;
-        }
-      else
-       temp = (char *)NULL;
-    }
-  else
-    temp = (char *)NULL;
-
-  if (ret == 0)
-    {
-      ret = alloc_word_desc ();
-      ret->word = temp;
-      ret->flags |= rflags;
-    }
-  return ret;
-}
-
-/* Expand an indirect reference to a variable: ${!NAME} expands to the
-   value of the variable whose name is the value of NAME. */
-static WORD_DESC *
-parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at)
-     char *name;
-     int var_is_special, quoted;
-     int *quoted_dollar_atp, *contains_dollar_at;
-{
-  char *temp, *t;
-  WORD_DESC *w;
-  SHELL_VAR *v;
-
-  /* See if it's a nameref first, behave in ksh93-compatible fashion.
-     There is at least one incompatibility: given ${!foo[0]} where foo=bar,
-     bash performs an indirect lookup on foo[0] and expands the result;
-     ksh93 expands bar[0].  We could do that here -- there are enough usable
-     primitives to do that -- but do not at this point. */
-  if (var_is_special == 0 && (v = find_variable_last_nameref (name)))
-    {
-      if (nameref_p (v) && (t = nameref_cell (v)) && *t)
-       {
-         w = alloc_word_desc ();
-         w->word = savestring (t);
-         w->flags = 0;
-         return w;
-       }
-    }
-
-  /* If var_is_special == 0, and name is not an array reference, this does
-     more expansion than necessary.  It should really look up the variable's
-     value and not try to expand it. */
-  w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND, 0);
-  t = w->word;
-  /* Have to dequote here if necessary */
-  if (t)
-    {
-      temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
-               ? dequote_string (t)
-               : dequote_escapes (t);
-      free (t);
-      t = temp;
-    }
-  dispose_word_desc (w);
-
-  chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
-  if (t == 0)
-    return (WORD_DESC *)NULL;
-
-  w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted, 0, 0);
-  free (t);
-
-  return w;
-}
-
-/* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
-   depending on the value of C, the separating character.  C can be one of
-   "-", "+", or "=".  QUOTED is true if the entire brace expression occurs
-   between double quotes. */
-static WORD_DESC *
-parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
-     char *name, *value;
-     int c, quoted, *qdollaratp, *hasdollarat;
-{
-  WORD_DESC *w;
-  WORD_LIST *l;
-  char *t, *t1, *temp;
-  int hasdol;
-
-  /* If the entire expression is between double quotes, we want to treat
-     the value as a double-quoted string, with the exception that we strip
-     embedded unescaped double quotes (for sh backwards compatibility). */
-  if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
-    {
-      hasdol = 0;
-      temp = string_extract_double_quoted (value, &hasdol, 1);
-    }
-  else
-    temp = value;
-
-  w = alloc_word_desc ();
-  hasdol = 0;
-  /* XXX was 0 not quoted */
-  l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
-           : (WORD_LIST *)0;
-  if (hasdollarat)
-    *hasdollarat = hasdol || (l && l->next);
-  if (temp != value)
-    free (temp);
-  if (l)
-    {
-      /* The expansion of TEMP returned something.  We need to treat things
-         slightly differently if HASDOL is non-zero.  If we have "$@", the
-         individual words have already been quoted.  We need to turn them
-         into a string with the words separated by the first character of
-         $IFS without any additional quoting, so string_list_dollar_at won't
-         do the right thing.  We use string_list_dollar_star instead. */
-      temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l);
-
-      /* If l->next is not null, we know that TEMP contained "$@", since that
-        is the only expansion that creates more than one word. */
-      if (qdollaratp && ((hasdol && quoted) || l->next))
-       *qdollaratp = 1;
-      /* If we have a quoted null result (QUOTED_NULL(temp)) and the word is
-        a quoted null (l->next == 0 && QUOTED_NULL(l->word->word)), the
-        flags indicate it (l->word->flags & W_HASQUOTEDNULL), and the
-        expansion is quoted (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
-        (which is more paranoia than anything else), we need to return the
-        quoted null string and set the flags to indicate it. */
-      if (l->next == 0 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && QUOTED_NULL (temp) && QUOTED_NULL (l->word->word) && (l->word->flags & W_HASQUOTEDNULL))
-       {
-         w->flags |= W_HASQUOTEDNULL;
-       }
-      dispose_words (l);
-    }
-  else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
-    {
-      /* The brace expansion occurred between double quotes and there was
-        a $@ in TEMP.  It does not matter if the $@ is quoted, as long as
-        it does not expand to anything.  In this case, we want to return
-        a quoted empty string. */
-      temp = make_quoted_char ('\0');
-      w->flags |= W_HASQUOTEDNULL;
-    }
-  else
-    temp = (char *)NULL;
-
-  if (c == '-' || c == '+')
-    {
-      w->word = temp;
-      return w;
-    }
-
-  /* c == '=' */
-  t = temp ? savestring (temp) : savestring ("");
-  t1 = dequote_string (t);
-  free (t);
-#if defined (ARRAY_VARS)
-  if (valid_array_reference (name))
-    assign_array_element (name, t1, 0);
-  else
-#endif /* ARRAY_VARS */
-  bind_variable (name, t1, 0);
-#if 0
-  if (STREQ (name, "IFS") == 0)
-#endif
-    stupidly_hack_special_variables (name);
-
-  /* From Posix group discussion Feb-March 2010.  Issue 7 0000221 */
-  free (temp);
-
-  w->word = t1;
-  return w;
-}
-
-/* Deal with the right hand side of a ${name:?value} expansion in the case
-   that NAME is null or not set.  If VALUE is non-null it is expanded and
-   used as the error message to print, otherwise a standard message is
-   printed. */
-static void
-parameter_brace_expand_error (name, value)
-     char *name, *value;
-{
-  WORD_LIST *l;
-  char *temp;
-
-  last_command_exit_value = EXECUTION_FAILURE; /* ensure it's non-zero */
-  if (value && *value)
-    {
-      l = expand_string (value, 0);
-      temp =  string_list (l);
-      report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
-      FREE (temp);
-      dispose_words (l);
-    }
-  else
-    report_error (_("%s: parameter null or not set"), name);
-
-  /* Free the data we have allocated during this expansion, since we
-     are about to longjmp out. */
-  free (name);
-  FREE (value);
-}
-
-/* Return 1 if NAME is something for which parameter_brace_expand_length is
-   OK to do. */
-static int
-valid_length_expression (name)
-     char *name;
-{
-  return (name[1] == '\0' ||                                   /* ${#} */
-         ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') ||  /* special param */
-         (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */
-#if defined (ARRAY_VARS)
-         valid_array_reference (name + 1) ||                   /* ${#a[7]} */
-#endif
-         legal_identifier (name + 1));                         /* ${#PS1} */
-}
-
-/* Handle the parameter brace expansion that requires us to return the
-   length of a parameter. */
-static intmax_t
-parameter_brace_expand_length (name)
-     char *name;
-{
-  char *t, *newname;
-  intmax_t number, arg_index;
-  WORD_LIST *list;
-#if defined (ARRAY_VARS)
-  SHELL_VAR *var;
-#endif
-
-  if (name[1] == '\0')                 /* ${#} */
-    number = number_of_args ();
-  else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0')      /* ${#@}, ${#*} */
-    number = number_of_args ();
-  else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0')
-    {
-      /* Take the lengths of some of the shell's special parameters. */
-      switch (name[1])
-       {
-       case '-':
-         t = which_set_flags ();
-         break;
-       case '?':
-         t = itos (last_command_exit_value);
-         break;
-       case '$':
-         t = itos (dollar_dollar_pid);
-         break;
-       case '!':
-         if (last_asynchronous_pid == NO_PID)
-           t = (char *)NULL;   /* XXX - error if set -u set? */
-         else
-           t = itos (last_asynchronous_pid);
-         break;
-       case '#':
-         t = itos (number_of_args ());
-         break;
-       }
-      number = STRLEN (t);
-      FREE (t);
-    }
-#if defined (ARRAY_VARS)
-  else if (valid_array_reference (name + 1))
-    number = array_length_reference (name + 1);
-#endif /* ARRAY_VARS */
-  else
-    {
-      number = 0;
-
-      if (legal_number (name + 1, &arg_index))         /* ${#1} */
-       {
-         t = get_dollar_var_value (arg_index);
-         if (t == 0 && unbound_vars_is_error)
-           return INTMAX_MIN;
-         number = MB_STRLEN (t);
-         FREE (t);
-       }
-#if defined (ARRAY_VARS)
-      else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && (array_p (var) || assoc_p (var)))
-       {
-         if (assoc_p (var))
-           t = assoc_reference (assoc_cell (var), "0");
-         else
-           t = array_reference (array_cell (var), 0);
-         if (t == 0 && unbound_vars_is_error)
-           return INTMAX_MIN;
-         number = MB_STRLEN (t);
-       }
-#endif
-      else                             /* ${#PS1} */
-       {
-         newname = savestring (name);
-         newname[0] = '$';
-         list = expand_string (newname, Q_DOUBLE_QUOTES);
-         t = list ? string_list (list) : (char *)NULL;
-         free (newname);
-         if (list)
-           dispose_words (list);
-
-         number = t ? MB_STRLEN (t) : 0;
-         FREE (t);
-       }
-    }
-
-  return (number);
-}
-
-/* Skip characters in SUBSTR until DELIM.  SUBSTR is an arithmetic expression,
-   so we do some ad-hoc parsing of an arithmetic expression to find
-   the first DELIM, instead of using strchr(3).  Two rules:
-       1.  If the substring contains a `(', read until closing `)'.
-       2.  If the substring contains a `?', read past one `:' for each `?'.
-*/
-
-static char *
-skiparith (substr, delim)
-     char *substr;
-     int delim;
-{
-  size_t sublen;
-  int skipcol, pcount, i;
-  DECLARE_MBSTATE;
-
-  sublen = strlen (substr);
-  i = skipcol = pcount = 0;
-  while (substr[i])
-    {
-      /* Balance parens */
-      if (substr[i] == LPAREN)
-       {
-         pcount++;
-         i++;
-         continue;
-       }
-      if (substr[i] == RPAREN && pcount)
-       {
-         pcount--;
-         i++;
-         continue;
-       }
-      if (pcount)
-       {
-         ADVANCE_CHAR (substr, sublen, i);
-         continue;
-       }
-
-      /* Skip one `:' for each `?' */
-      if (substr[i] == ':' && skipcol)
-       {
-         skipcol--;
-         i++;
-         continue;
-       }
-      if (substr[i] == delim)
-       break;
-      if (substr[i] == '?')
-       {
-         skipcol++;
-         i++;
-         continue;
-       }
-      ADVANCE_CHAR (substr, sublen, i);
-    }
-
-  return (substr + i);
-}
-
-/* Verify and limit the start and end of the desired substring.  If
-   VTYPE == 0, a regular shell variable is being used; if it is 1,
-   then the positional parameters are being used; if it is 2, then
-   VALUE is really a pointer to an array variable that should be used.
-   Return value is 1 if both values were OK, 0 if there was a problem
-   with an invalid expression, or -1 if the values were out of range. */
-static int
-verify_substring_values (v, value, substr, vtype, e1p, e2p)
-     SHELL_VAR *v;
-     char *value, *substr;
-     int vtype;
-     intmax_t *e1p, *e2p;
-{
-  char *t, *temp1, *temp2;
-  arrayind_t len;
-  int expok;
-#if defined (ARRAY_VARS)
- ARRAY *a;
- HASH_TABLE *h;
-#endif
-
-  /* duplicate behavior of strchr(3) */
-  t = skiparith (substr, ':');
-  if (*t && *t == ':')
-    *t = '\0';
-  else
-    t = (char *)0;
-
-  temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES);
-  *e1p = evalexp (temp1, &expok);
-  free (temp1);
-  if (expok == 0)
-    return (0);
-
-  len = -1;    /* paranoia */
-  switch (vtype)
-    {
-    case VT_VARIABLE:
-    case VT_ARRAYMEMBER:
-      len = MB_STRLEN (value);
-      break;
-    case VT_POSPARMS:
-      len = number_of_args () + 1;
-      if (*e1p == 0)
-       len++;          /* add one arg if counting from $0 */
-      break;
-#if defined (ARRAY_VARS)
-    case VT_ARRAYVAR:
-      /* For arrays, the first value deals with array indices.  Negative
-        offsets count from one past the array's maximum index.  Associative
-        arrays treat the number of elements as the maximum index. */
-      if (assoc_p (v))
-       {
-         h = assoc_cell (v);
-         len = assoc_num_elements (h) + (*e1p < 0);
-       }
-      else
-       {
-         a = (ARRAY *)value;
-         len = array_max_index (a) + (*e1p < 0);       /* arrays index from 0 to n - 1 */
-       }
-      break;
-#endif
-    }
-
-  if (len == -1)       /* paranoia */
-    return -1;
-
-  if (*e1p < 0)                /* negative offsets count from end */
-    *e1p += len;
-
-  if (*e1p > len || *e1p < 0)
-    return (-1);
-
-#if defined (ARRAY_VARS)
-  /* For arrays, the second offset deals with the number of elements. */
-  if (vtype == VT_ARRAYVAR)
-    len = assoc_p (v) ? assoc_num_elements (h) : array_num_elements (a);
-#endif
-
-  if (t)
-    {
-      t++;
-      temp2 = savestring (t);
-      temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
-      free (temp2);
-      t[-1] = ':';
-      *e2p = evalexp (temp1, &expok);
-      free (temp1);
-      if (expok == 0)
-       return (0);
-#if 1
-      if ((vtype == VT_ARRAYVAR || vtype == VT_POSPARMS) && *e2p < 0)
-#else
-      /* bash-4.3: allow positional parameter length < 0 to count backwards
-        from end of positional parameters */
-      if (vtype == VT_ARRAYVAR && *e2p < 0)
-#endif
-       {
-         internal_error (_("%s: substring expression < 0"), t);
-         return (0);
-       }
-#if defined (ARRAY_VARS)
-      /* In order to deal with sparse arrays, push the intelligence about how
-        to deal with the number of elements desired down to the array-
-        specific functions.  */
-      if (vtype != VT_ARRAYVAR)
-#endif
-       {
-         if (*e2p < 0)
-           {
-             *e2p += len;
-             if (*e2p < 0 || *e2p < *e1p)
-               {
-                 internal_error (_("%s: substring expression < 0"), t);
-                 return (0);
-               }
-           }
-         else
-           *e2p += *e1p;               /* want E2 chars starting at E1 */
-         if (*e2p > len)
-           *e2p = len;
-       }
-    }
-  else
-    *e2p = len;
-
-  return (1);
-}
-
-/* Return the type of variable specified by VARNAME (simple variable,
-   positional param, or array variable).  Also return the value specified
-   by VARNAME (value of a variable or a reference to an array element).
-   QUOTED is the standard description of quoting state, using Q_* defines.
-   FLAGS is currently a set of flags to pass to array_value.  If IND is
-   non-null and not INTMAX_MIN, and FLAGS includes AV_USEIND, IND is
-   passed to array_value so the array index is not computed again.
-   If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
-   characters in the value are quoted with CTLESC and takes appropriate
-   steps.  For convenience, *VALP is set to the dequoted VALUE. */
-static int
-get_var_and_type (varname, value, ind, quoted, flags, varp, valp)
-     char *varname, *value;
-     arrayind_t ind;
-     int quoted, flags;
-     SHELL_VAR **varp;
-     char **valp;
-{
-  int vtype;
-  char *temp;
-#if defined (ARRAY_VARS)
-  SHELL_VAR *v;
-#endif
-  arrayind_t lind;
-
-  /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
-  vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
-  if (vtype == VT_POSPARMS && varname[0] == '*')
-    vtype |= VT_STARSUB;
-  *varp = (SHELL_VAR *)NULL;
-
-#if defined (ARRAY_VARS)
-  if (valid_array_reference (varname))
-    {
-      v = array_variable_part (varname, &temp, (int *)0);
-      /* If we want to signal array_value to use an already-computed index,
-        set LIND to that index */
-      lind = (ind != INTMAX_MIN && (flags & AV_USEIND)) ? ind : 0;
-      if (v && (array_p (v) || assoc_p (v)))
-       { /* [ */
-         if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
-           {
-             /* Callers have to differentiate betwen indexed and associative */
-             vtype = VT_ARRAYVAR;
-             if (temp[0] == '*')
-               vtype |= VT_STARSUB;
-             *valp = array_p (v) ? (char *)array_cell (v) : (char *)assoc_cell (v);
-           }
-         else
-           {
-             vtype = VT_ARRAYMEMBER;
-             *valp = array_value (varname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
-           }
-         *varp = v;
-       }
-      else if (v && (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']'))
-       {
-         vtype = VT_VARIABLE;
-         *varp = v;
-         if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
-           *valp = dequote_string (value);
-         else
-           *valp = dequote_escapes (value);
-       }
-      else
-       {
-         vtype = VT_ARRAYMEMBER;
-         *varp = v;
-         *valp = array_value (varname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
-       }
-    }
-  else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v)))
-    {
-      vtype = VT_ARRAYMEMBER;
-      *varp = v;
-      *valp = assoc_p (v) ? assoc_reference (assoc_cell (v), "0") : array_reference (array_cell (v), 0);
-    }
-  else
-#endif
-    {
-      if (value && vtype == VT_VARIABLE)
-       {
-         if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
-           *valp = dequote_string (value);
-         else
-           *valp = dequote_escapes (value);
-       }
-      else
-       *valp = value;
-    }
-
-  return vtype;
-}
-
-/******************************************************/
-/*                                                   */
-/* Functions to extract substrings of variable values */
-/*                                                   */
-/******************************************************/
-
-#if defined (HANDLE_MULTIBYTE)
-/* Character-oriented rather than strictly byte-oriented substrings.  S and
-   E, rather being strict indices into STRING, indicate character (possibly
-   multibyte character) positions that require calculation.
-   Used by the ${param:offset[:length]} expansion. */
-static char *
-mb_substring (string, s, e)
-     char *string;
-     int s, e;
-{
-  char *tt;
-  int start, stop, i, slen;
-  DECLARE_MBSTATE;
-
-  start = 0;
-  /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
-  slen = (MB_CUR_MAX > 1) ? STRLEN (string) : 0;
-
-  i = s;
-  while (string[start] && i--)
-    ADVANCE_CHAR (string, slen, start);
-  stop = start;
-  i = e - s;
-  while (string[stop] && i--)
-    ADVANCE_CHAR (string, slen, stop);
-  tt = substring (string, start, stop);
-  return tt;
-}
-#endif
-  
-/* Process a variable substring expansion: ${name:e1[:e2]}.  If VARNAME
-   is `@', use the positional parameters; otherwise, use the value of
-   VARNAME.  If VARNAME is an array variable, use the array elements. */
-
-static char *
-parameter_brace_substring (varname, value, ind, substr, quoted, flags)
-     char *varname, *value;
-     int ind;
-     char *substr;
-     int quoted, flags;
-{
-  intmax_t e1, e2;
-  int vtype, r, starsub;
-  char *temp, *val, *tt, *oname;
-  SHELL_VAR *v;
-
-  if (value == 0)
-    return ((char *)NULL);
-
-  oname = this_command_name;
-  this_command_name = varname;
-
-  vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
-  if (vtype == -1)
-    {
-      this_command_name = oname;
-      return ((char *)NULL);
-    }
-
-  starsub = vtype & VT_STARSUB;
-  vtype &= ~VT_STARSUB;
-
-  r = verify_substring_values (v, val, substr, vtype, &e1, &e2);
-  this_command_name = oname;
-  if (r <= 0)
-    {
-      if (vtype == VT_VARIABLE)
-       FREE (val);
-      return ((r == 0) ? &expand_param_error : (char *)NULL);
-    }
-
-  switch (vtype)
-    {
-    case VT_VARIABLE:
-    case VT_ARRAYMEMBER:
-#if defined (HANDLE_MULTIBYTE)
-      if (MB_CUR_MAX > 1)
-       tt = mb_substring (val, e1, e2);
-      else
-#endif
-      tt = substring (val, e1, e2);
-
-      if (vtype == VT_VARIABLE)
-       FREE (val);
-      if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
-       temp = quote_string (tt);
-      else
-       temp = tt ? quote_escapes (tt) : (char *)NULL;
-      FREE (tt);
-      break;
-    case VT_POSPARMS:
-      tt = pos_params (varname, e1, e2, quoted);
-      if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
-       {
-         temp = tt ? quote_escapes (tt) : (char *)NULL;
-         FREE (tt);
-       }
-      else
-       temp = tt;
-      break;
-#if defined (ARRAY_VARS)
-    case VT_ARRAYVAR:
-      if (assoc_p (v))
-       /* we convert to list and take first e2 elements starting at e1th
-          element -- officially undefined for now */   
-       temp = assoc_subrange (assoc_cell (v), e1, e2, starsub, quoted);
-      else
-      /* We want E2 to be the number of elements desired (arrays can be sparse,
-        so verify_substring_values just returns the numbers specified and we
-        rely on array_subrange to understand how to deal with them). */
-       temp = array_subrange (array_cell (v), e1, e2, starsub, quoted);
-      /* array_subrange now calls array_quote_escapes as appropriate, so the
-        caller no longer needs to. */
-      break;
-#endif
-    default:
-      temp = (char *)NULL;
-    }
-
-  return temp;
-}
-
-/****************************************************************/
-/*                                                             */
-/* Functions to perform pattern substitution on variable values */
-/*                                                             */
-/****************************************************************/
-
-static int
-shouldexp_replacement (s)
-     char *s;
-{
-  register char *p;
-
-  for (p = s; p && *p; p++)
-    {
-      if (*p == '\\')
-       p++;
-      else if (*p == '&')
-       return 1;
-    }
-  return 0;
-}
-
-char *
-pat_subst (string, pat, rep, mflags)
-     char *string, *pat, *rep;
-     int mflags;
-{
-  char *ret, *s, *e, *str, *rstr, *mstr;
-  int rsize, rptr, l, replen, mtype, rxpand, rslen, mlen;
-
-  if (string  == 0)
-    return (savestring (""));
-
-  mtype = mflags & MATCH_TYPEMASK;
-
-#if 0  /* bash-4.2 ? */
-  rxpand = (rep && *rep) ? shouldexp_replacement (rep) : 0;
-#else
-  rxpand = 0;
-#endif
-
-  /* Special cases:
-   *   1.  A null pattern with mtype == MATCH_BEG means to prefix STRING
-   *       with REP and return the result.
-   *   2.  A null pattern with mtype == MATCH_END means to append REP to
-   *       STRING and return the result.
-   * These don't understand or process `&' in the replacement string.
-   */
-  if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
-    {
-      replen = STRLEN (rep);
-      l = STRLEN (string);
-      ret = (char *)xmalloc (replen + l + 2);
-      if (replen == 0)
-       strcpy (ret, string);
-      else if (mtype == MATCH_BEG)
-       {
-         strcpy (ret, rep);
-         strcpy (ret + replen, string);
-       }
-      else
-       {
-         strcpy (ret, string);
-         strcpy (ret + l, rep);
-       }
-      return (ret);
-    }
-
-  ret = (char *)xmalloc (rsize = 64);
-  ret[0] = '\0';
-
-  for (replen = STRLEN (rep), rptr = 0, str = string;;)
-    {
-      if (match_pattern (str, pat, mtype, &s, &e) == 0)
-       break;
-      l = s - str;
-
-      if (rxpand)
-        {
-          int x;
-          mlen = e - s;
-          mstr = xmalloc (mlen + 1);
-         for (x = 0; x < mlen; x++)
-           mstr[x] = s[x];
-          mstr[mlen] = '\0';
-          rstr = strcreplace (rep, '&', mstr, 0);
-          rslen = strlen (rstr);
-        }
-      else
-        {
-          rstr = rep;
-          rslen = replen;
-        }
-        
-      RESIZE_MALLOCED_BUFFER (ret, rptr, (l + rslen), rsize, 64);
-
-      /* OK, now copy the leading unmatched portion of the string (from
-        str to s) to ret starting at rptr (the current offset).  Then copy
-        the replacement string at ret + rptr + (s - str).  Increment
-        rptr (if necessary) and str and go on. */
-      if (l)
-       {
-         strncpy (ret + rptr, str, l);
-         rptr += l;
-       }
-      if (replen)
-       {
-         strncpy (ret + rptr, rstr, rslen);
-         rptr += rslen;
-       }
-      str = e;         /* e == end of match */
-
-      if (rstr != rep)
-       free (rstr);
-
-      if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
-       break;
-
-      if (s == e)
-       {
-         /* On a zero-length match, make sure we copy one character, since
-            we increment one character to avoid infinite recursion. */
-         RESIZE_MALLOCED_BUFFER (ret, rptr, 1, rsize, 64);
-         ret[rptr++] = *str++;
-         e++;          /* avoid infinite recursion on zero-length match */
-       }
-    }
-
-  /* Now copy the unmatched portion of the input string */
-  if (str && *str)
-    {
-      RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
-      strcpy (ret + rptr, str);
-    }
-  else
-    ret[rptr] = '\0';
-
-  return ret;
-}
-
-/* Do pattern match and replacement on the positional parameters. */
-static char *
-pos_params_pat_subst (string, pat, rep, mflags)
-     char *string, *pat, *rep;
-     int mflags;
-{
-  WORD_LIST *save, *params;
-  WORD_DESC *w;
-  char *ret;
-  int pchar, qflags;
-
-  save = params = list_rest_of_args ();
-  if (save == 0)
-    return ((char *)NULL);
-
-  for ( ; params; params = params->next)
-    {
-      ret = pat_subst (params->word->word, pat, rep, mflags);
-      w = alloc_word_desc ();
-      w->word = ret ? ret : savestring ("");
-      dispose_word (params->word);
-      params->word = w;
-    }
-
-  pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
-  qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
-
-  ret = string_list_pos_params (pchar, save, qflags);
-
-  dispose_words (save);
-
-  return (ret);
-}
-
-/* Perform pattern substitution on VALUE, which is the expansion of
-   VARNAME.  PATSUB is an expression supplying the pattern to match
-   and the string to substitute.  QUOTED is a flags word containing
-   the type of quoting currently in effect. */
-static char *
-parameter_brace_patsub (varname, value, ind, patsub, quoted, flags)
-     char *varname, *value;
-     int ind;
-     char *patsub;
-     int quoted, flags;
-{
-  int vtype, mflags, starsub, delim;
-  char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
-  SHELL_VAR *v;
-
-  if (value == 0)
-    return ((char *)NULL);
-
-  this_command_name = varname;
-
-  vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
-  if (vtype == -1)
-    return ((char *)NULL);
-
-  starsub = vtype & VT_STARSUB;
-  vtype &= ~VT_STARSUB;
-
-  mflags = 0;
-  /* PATSUB is never NULL when this is called. */
-  if (*patsub == '/')
-    {
-      mflags |= MATCH_GLOBREP;
-      patsub++;
-    }
-
-  /* Malloc this because expand_string_if_necessary or one of the expansion
-     functions in its call chain may free it on a substitution error. */
-  lpatsub = savestring (patsub);
-
-  if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
-    mflags |= MATCH_QUOTED;
-
-  if (starsub)
-    mflags |= MATCH_STARSUB;
-
-  /* If the pattern starts with a `/', make sure we skip over it when looking
-     for the replacement delimiter. */
-  delim = skip_to_delim (lpatsub, ((*patsub == '/') ? 1 : 0), "/", 0);
-  if (lpatsub[delim] == '/')
-    {
-      lpatsub[delim] = 0;
-      rep = lpatsub + delim + 1;
-    }
-  else
-    rep = (char *)NULL;
-
-  if (rep && *rep == '\0')
-    rep = (char *)NULL;
-
-  /* Perform the same expansions on the pattern as performed by the
-     pattern removal expansions. */
-  pat = getpattern (lpatsub, quoted, 1);
-
-  if (rep)
-    {
-      /* We want to perform quote removal on the expanded replacement even if
-        the entire expansion is double-quoted because the parser and string
-        extraction functions treated quotes in the replacement string as
-        special.  THIS IS NOT BACKWARDS COMPATIBLE WITH BASH-4.2. */
-      if (shell_compatibility_level > 42)
-       rep = expand_string_if_necessary (rep, quoted & ~(Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT), expand_string_unsplit);
-      /* This is the bash-4.2 code. */      
-      else if ((mflags & MATCH_QUOTED) == 0)
-       rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit);
-      else
-       rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit);
-    }
-
-  /* ksh93 doesn't allow the match specifier to be a part of the expanded
-     pattern.  This is an extension.  Make sure we don't anchor the pattern
-     at the beginning or end of the string if we're doing global replacement,
-     though. */
-  p = pat;
-  if (mflags & MATCH_GLOBREP)
-    mflags |= MATCH_ANY;
-  else if (pat && pat[0] == '#')
-    {
-      mflags |= MATCH_BEG;
-      p++;
-    }
-  else if (pat && pat[0] == '%')
-    {
-      mflags |= MATCH_END;
-      p++;
-    }
-  else
-    mflags |= MATCH_ANY;
-
-  /* OK, we now want to substitute REP for PAT in VAL.  If
-     flags & MATCH_GLOBREP is non-zero, the substitution is done
-     everywhere, otherwise only the first occurrence of PAT is
-     replaced.  The pattern matching code doesn't understand
-     CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
-     values passed in (VT_VARIABLE) so the pattern substitution
-     code works right.  We need to requote special chars after
-     we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
-     other cases if QUOTED == 0, since the posparams and arrays
-     indexed by * or @ do special things when QUOTED != 0. */
-
-  switch (vtype)
-    {
-    case VT_VARIABLE:
-    case VT_ARRAYMEMBER:
-      temp = pat_subst (val, p, rep, mflags);
-      if (vtype == VT_VARIABLE)
-       FREE (val);
-      if (temp)
-       {
-         tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
-         free (temp);
-         temp = tt;
-       }
-      break;
-    case VT_POSPARMS:
-      temp = pos_params_pat_subst (val, p, rep, mflags);
-      if (temp && (mflags & MATCH_QUOTED) == 0)
-       {
-         tt = quote_escapes (temp);
-         free (temp);
-         temp = tt;
-       }
-      break;
-#if defined (ARRAY_VARS)
-    case VT_ARRAYVAR:
-      temp = assoc_p (v) ? assoc_patsub (assoc_cell (v), p, rep, mflags)
-                        : array_patsub (array_cell (v), p, rep, mflags);
-      /* Don't call quote_escapes anymore; array_patsub calls
-        array_quote_escapes as appropriate before adding the
-        space separators; ditto for assoc_patsub. */
-      break;
-#endif
-    }
-
-  FREE (pat);
-  FREE (rep);
-  free (lpatsub);
-
-  return temp;
-}
-
-/****************************************************************/
-/*                                                             */
-/*   Functions to perform case modification on variable values  */
-/*                                                             */
-/****************************************************************/
-
-/* Do case modification on the positional parameters. */
-
-static char *
-pos_params_modcase (string, pat, modop, mflags)
-     char *string, *pat;
-     int modop;
-     int mflags;
-{
-  WORD_LIST *save, *params;
-  WORD_DESC *w;
-  char *ret;
-  int pchar, qflags;
-
-  save = params = list_rest_of_args ();
-  if (save == 0)
-    return ((char *)NULL);
-
-  for ( ; params; params = params->next)
-    {
-      ret = sh_modcase (params->word->word, pat, modop);
-      w = alloc_word_desc ();
-      w->word = ret ? ret : savestring ("");
-      dispose_word (params->word);
-      params->word = w;
-    }
-
-  pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
-  qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
-
-  ret = string_list_pos_params (pchar, save, qflags);
-  dispose_words (save);
-
-  return (ret);
-}
-
-/* Perform case modification on VALUE, which is the expansion of
-   VARNAME.  MODSPEC is an expression supplying the type of modification
-   to perform.  QUOTED is a flags word containing the type of quoting
-   currently in effect. */
-static char *
-parameter_brace_casemod (varname, value, ind, modspec, patspec, quoted, flags)
-     char *varname, *value;
-     int ind, modspec;
-     char *patspec;
-     int quoted, flags;
-{
-  int vtype, starsub, modop, mflags, x;
-  char *val, *temp, *pat, *p, *lpat, *tt;
-  SHELL_VAR *v;
-
-  if (value == 0)
-    return ((char *)NULL);
-
-  this_command_name = varname;
-
-  vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
-  if (vtype == -1)
-    return ((char *)NULL);
-
-  starsub = vtype & VT_STARSUB;
-  vtype &= ~VT_STARSUB;
-
-  modop = 0;
-  mflags = 0;
-  if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
-    mflags |= MATCH_QUOTED;
-  if (starsub)
-    mflags |= MATCH_STARSUB;
-  
-  p = patspec;
-  if (modspec == '^')
-    {
-      x = p && p[0] == modspec;
-      modop = x ? CASE_UPPER : CASE_UPFIRST;
-      p += x;
-    }
-  else if (modspec == ',')
-    {
-      x = p && p[0] == modspec;
-      modop = x ? CASE_LOWER : CASE_LOWFIRST;
-      p += x;
-    }
-  else if (modspec == '~')
-    {
-      x = p && p[0] == modspec;
-      modop = x ? CASE_TOGGLEALL : CASE_TOGGLE;
-      p += x;
-    }
-    
-  lpat = p ? savestring (p) : 0;
-  /* Perform the same expansions on the pattern as performed by the
-     pattern removal expansions.  FOR LATER */
-  pat = lpat ? getpattern (lpat, quoted, 1) : 0;
-
-  /* OK, now we do the case modification. */
-  switch (vtype)
-    {
-    case VT_VARIABLE:
-    case VT_ARRAYMEMBER:
-      temp = sh_modcase (val, pat, modop);
-      if (vtype == VT_VARIABLE)
-       FREE (val);
-      if (temp)
-       {
-         tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
-         free (temp);
-         temp = tt;
-       }
-      break;
-
-    case VT_POSPARMS:
-      temp = pos_params_modcase (val, pat, modop, mflags);
-      if (temp && (mflags & MATCH_QUOTED)  == 0)
-       {
-         tt = quote_escapes (temp);
-         free (temp);
-         temp = tt;
-       }
-      break;
-
-#if defined (ARRAY_VARS)
-    case VT_ARRAYVAR:
-      temp = assoc_p (v) ? assoc_modcase (assoc_cell (v), pat, modop, mflags)
-                        : array_modcase (array_cell (v), pat, modop, mflags);
-      /* Don't call quote_escapes; array_modcase calls array_quote_escapes
-        as appropriate before adding the space separators; ditto for
-        assoc_modcase. */
-      break;
-#endif
-    }
-
-  FREE (pat);
-  free (lpat);
-
-  return temp;
-}
-
-/* Check for unbalanced parens in S, which is the contents of $(( ... )).  If
-   any occur, this must be a nested command substitution, so return 0.
-   Otherwise, return 1.  A valid arithmetic expression must always have a
-   ( before a matching ), so any cases where there are more right parens
-   means that this must not be an arithmetic expression, though the parser
-   will not accept it without a balanced total number of parens. */
-static int
-chk_arithsub (s, len)
-     const char *s;
-     int len;
-{
-  int i, count;
-  DECLARE_MBSTATE;
-
-  i = count = 0;
-  while (i < len)
-    {
-      if (s[i] == LPAREN)
-       count++;
-      else if (s[i] == RPAREN)
-       {
-         count--;
-         if (count < 0)
-           return 0;
-       }
-
-      switch (s[i])
-       {
-       default:
-         ADVANCE_CHAR (s, len, i);
-         break;
-
-       case '\\':
-         i++;
-         if (s[i])
-           ADVANCE_CHAR (s, len, i);
-         break;
-
-       case '\'':
-         i = skip_single_quoted (s, len, ++i);
-         break;
-
-       case '"':
-         i = skip_double_quoted ((char *)s, len, ++i);
-         break;
-       }
-    }
-
-  return (count == 0);
-}
-
-/****************************************************************/
-/*                                                             */
-/*     Functions to perform parameter expansion on a string    */
-/*                                                             */
-/****************************************************************/
-
-/* ${[#][!]name[[:][^[^]][,[,]]#[#]%[%]-=?+[word][:e1[:e2]]]} */
-static WORD_DESC *
-parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, contains_dollar_at)
-     char *string;
-     int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at, pflags;
-{
-  int check_nullness, var_is_set, var_is_null, var_is_special;
-  int want_substring, want_indir, want_patsub, want_casemod;
-  char *name, *value, *temp, *temp1;
-  WORD_DESC *tdesc, *ret;
-  int t_index, sindex, c, tflag, modspec;
-  intmax_t number;
-  arrayind_t ind;
-
-  temp = temp1 = value = (char *)NULL;
-  var_is_set = var_is_null = var_is_special = check_nullness = 0;
-  want_substring = want_indir = want_patsub = want_casemod = 0;
-
-  sindex = *indexp;
-  t_index = ++sindex;
-  /* ${#var} doesn't have any of the other parameter expansions on it. */
-  if (string[t_index] == '#' && legal_variable_starter (string[t_index+1]))            /* {{ */
-    name = string_extract (string, &t_index, "}", SX_VARNAME);
-  else
-#if defined (CASEMOD_EXPANSIONS)
-    /* To enable case-toggling expansions using the `~' operator character
-       change the 1 to 0. */
-#  if defined (CASEMOD_CAPCASE)
-    name = string_extract (string, &t_index, "#%^,~:-=?+/}", SX_VARNAME);
-#  else
-    name = string_extract (string, &t_index, "#%^,:-=?+/}", SX_VARNAME);
-#  endif /* CASEMOD_CAPCASE */
-#else
-    name = string_extract (string, &t_index, "#%:-=?+/}", SX_VARNAME);
-#endif /* CASEMOD_EXPANSIONS */
-
-  ret = 0;
-  tflag = 0;
-
-  ind = INTMAX_MIN;
-
-  /* If the name really consists of a special variable, then make sure
-     that we have the entire name.  We don't allow indirect references
-     to special variables except `#', `?', `@' and `*'. */
-  if ((sindex == t_index && VALID_SPECIAL_LENGTH_PARAM (string[t_index])) ||
-      (sindex == t_index - 1 && string[sindex] == '!' && VALID_INDIR_PARAM (string[t_index])))
-    {
-      t_index++;
-      temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
-      name = (char *)xrealloc (name, 3 + (strlen (temp1)));
-      *name = string[sindex];
-      if (string[sindex] == '!')
-       {
-         /* indirect reference of $#, $?, $@, or $* */
-         name[1] = string[sindex + 1];
-         strcpy (name + 2, temp1);
-       }
-      else     
-       strcpy (name + 1, temp1);
-      free (temp1);
-    }
-  sindex = t_index;
-
-  /* Find out what character ended the variable name.  Then
-     do the appropriate thing. */
-  if (c = string[sindex])
-    sindex++;
-
-  /* If c is followed by one of the valid parameter expansion
-     characters, move past it as normal.  If not, assume that
-     a substring specification is being given, and do not move
-     past it. */
-  if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
-    {
-      check_nullness++;
-      if (c = string[sindex])
-       sindex++;
-    }
-  else if (c == ':' && string[sindex] != RBRACE)
-    want_substring = 1;
-  else if (c == '/' /* && string[sindex] != RBRACE */) /* XXX */
-    want_patsub = 1;
-#if defined (CASEMOD_EXPANSIONS)
-  else if (c == '^' || c == ',' || c == '~')
-    {
-      modspec = c;
-      want_casemod = 1;
-    }
-#endif
-
-  /* Catch the valid and invalid brace expressions that made it through the
-     tests above. */
-  /* ${#-} is a valid expansion and means to take the length of $-.
-     Similarly for ${#?} and ${##}... */
-  if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
-       VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
-    {
-      name = (char *)xrealloc (name, 3);
-      name[1] = c;
-      name[2] = '\0';
-      c = string[sindex++];
-    }
-
-  /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
-  if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
-       member (c, "%:=+/") && string[sindex] == RBRACE)
-    {
-      temp = (char *)NULL;
-      goto bad_substitution;
-    }
-
-  /* Indirect expansion begins with a `!'.  A valid indirect expansion is
-     either a variable name, one of the positional parameters or a special
-     variable that expands to one of the positional parameters. */
-  want_indir = *name == '!' &&
-    (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1])
-                                       || VALID_INDIR_PARAM (name[1]));
-
-  /* Determine the value of this variable. */
-
-  /* Check for special variables, directly referenced. */
-  if (SPECIAL_VAR (name, want_indir))
-    var_is_special++;
-
-  /* Check for special expansion things, like the length of a parameter */
-  if (*name == '#' && name[1])
-    {
-      /* If we are not pointing at the character just after the
-        closing brace, then we haven't gotten all of the name.
-        Since it begins with a special character, this is a bad
-        substitution.  Also check NAME for validity before trying
-        to go on. */
-      if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
-       {
-         temp = (char *)NULL;
-         goto bad_substitution;
-       }
-
-      number = parameter_brace_expand_length (name);
-      if (number == INTMAX_MIN && unbound_vars_is_error)
-       {
-         last_command_exit_value = EXECUTION_FAILURE;
-         err_unboundvar (name+1);
-         free (name);
-         return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
-       }
-      free (name);
-
-      *indexp = sindex;
-      if (number < 0)
-        return (&expand_wdesc_error);
-      else
-       {
-         ret = alloc_word_desc ();
-         ret->word = itos (number);
-         return ret;
-       }
-    }
-
-  /* ${@} is identical to $@. */
-  if (name[0] == '@' && name[1] == '\0')
-    {
-      if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
-       *quoted_dollar_atp = 1;
-
-      if (contains_dollar_at)
-       *contains_dollar_at = 1;
-
-      tflag |= W_DOLLARAT;
-    }
-
-  /* Process ${!PREFIX*} expansion. */
-  if (want_indir && string[sindex - 1] == RBRACE &&
-      (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
-      legal_variable_starter ((unsigned char) name[1]))
-    {
-      char **x;
-      WORD_LIST *xlist;
-
-      temp1 = savestring (name + 1);
-      number = strlen (temp1);
-      temp1[number - 1] = '\0';
-      x = all_variables_matching_prefix (temp1);
-      xlist = strvec_to_word_list (x, 0, 0);
-      if (string[sindex - 2] == '*')
-       temp = string_list_dollar_star (xlist);
-      else
-       {
-         temp = string_list_dollar_at (xlist, quoted);
-         if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
-           *quoted_dollar_atp = 1;
-         if (contains_dollar_at)
-           *contains_dollar_at = 1;
-
-         tflag |= W_DOLLARAT;
-       }
-      free (x);
-      dispose_words (xlist);
-      free (temp1);
-      *indexp = sindex;
-
-      free (name);
-
-      ret = alloc_word_desc ();
-      ret->word = temp;
-      ret->flags = tflag;      /* XXX */
-      return ret;
-    }
-
-#if defined (ARRAY_VARS)      
-  /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */ /* [ */
-  if (want_indir && string[sindex - 1] == RBRACE &&
-      string[sindex - 2] == ']' && valid_array_reference (name+1))
-    {
-      char *x, *x1;
-
-      temp1 = savestring (name + 1);
-      x = array_variable_name (temp1, &x1, (int *)0);  /* [ */
-      FREE (x);
-      if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == ']')
-       {
-         temp = array_keys (temp1, quoted);    /* handles assoc vars too */
-         if (x1[0] == '@')
-           {
-             if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
-               *quoted_dollar_atp = 1;
-             if (contains_dollar_at)
-               *contains_dollar_at = 1;
-
-             tflag |= W_DOLLARAT;
-           }       
-
-         free (temp1);
-         *indexp = sindex;
-
-         ret = alloc_word_desc ();
-         ret->word = temp;
-         ret->flags = tflag;   /* XXX */
-         return ret;
-       }
-
-      free (temp1);
-    }
-#endif /* ARRAY_VARS */
-      
-  /* Make sure that NAME is valid before trying to go on. */
-  if (valid_brace_expansion_word (want_indir ? name + 1 : name,
-                                       var_is_special) == 0)
-    {
-      temp = (char *)NULL;
-      goto bad_substitution;
-    }
-
-  if (want_indir)
-    tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
-  else
-    tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND|(pflags&(PF_NOSPLIT2|PF_ASSIGNRHS)), &ind);
-
-  if (tdesc)
-    {
-      temp = tdesc->word;
-      tflag = tdesc->flags;
-      dispose_word_desc (tdesc);
-    }
-  else
-    temp = (char  *)0;
-
-  if (temp == &expand_param_error || temp == &expand_param_fatal)
-    {
-      FREE (name);
-      FREE (value);
-      return (temp == &expand_param_error ? &expand_wdesc_error : &expand_wdesc_fatal);
-    }
-
-#if defined (ARRAY_VARS)
-  if (valid_array_reference (name))
-    chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at);
-#endif
-
-  var_is_set = temp != (char *)0;
-  var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
-  /* XXX - this may not need to be restricted to special variables */
-  if (check_nullness)
-    var_is_null |= var_is_set && var_is_special && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && QUOTED_NULL (temp);
-
-  /* Get the rest of the stuff inside the braces. */
-  if (c && c != RBRACE)
-    {
-      /* Extract the contents of the ${ ... } expansion
-        according to the Posix.2 rules. */
-      value = extract_dollar_brace_string (string, &sindex, quoted, (c == '%' || c == '#' || c =='/' || c == '^' || c == ',' || c ==':') ? SX_POSIXEXP|SX_WORD : SX_WORD);
-      if (string[sindex] == RBRACE)
-       sindex++;
-      else
-       goto bad_substitution;
-    }
-  else
-    value = (char *)NULL;
-
-  *indexp = sindex;
-
-  /* All the cases where an expansion can possibly generate an unbound
-     variable error. */
-  if (want_substring || want_patsub || want_casemod || c == '#' || c == '%' || c == RBRACE)
-    {
-      if (var_is_set == 0 && unbound_vars_is_error && ((name[0] != '@' && name[0] != '*') || name[1]))
-       {
-         last_command_exit_value = EXECUTION_FAILURE;
-         err_unboundvar (name);
-         FREE (value);
-         FREE (temp);
-         free (name);
-         return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
-       }
-    }
-    
-  /* If this is a substring spec, process it and add the result. */
-  if (want_substring)
-    {
-      temp1 = parameter_brace_substring (name, temp, ind, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
-      FREE (name);
-      FREE (value);
-      FREE (temp);
-
-      if (temp1 == &expand_param_error)
-       return (&expand_wdesc_error);
-      else if (temp1 == &expand_param_fatal)
-       return (&expand_wdesc_fatal);
-
-      ret = alloc_word_desc ();
-      ret->word = temp1;
-      if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
-       ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
-      return ret;
-    }
-  else if (want_patsub)
-    {
-      temp1 = parameter_brace_patsub (name, temp, ind, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
-      FREE (name);
-      FREE (value);
-      FREE (temp);
-
-      if (temp1 == &expand_param_error)
-       return (&expand_wdesc_error);
-      else if (temp1 == &expand_param_fatal)
-       return (&expand_wdesc_fatal);
-
-      ret = alloc_word_desc ();
-      ret->word = temp1;
-      if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
-       ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
-      return ret;
-    }
-#if defined (CASEMOD_EXPANSIONS)
-  else if (want_casemod)
-    {
-      temp1 = parameter_brace_casemod (name, temp, ind, modspec, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
-      FREE (name);
-      FREE (value);
-      FREE (temp);
-
-      if (temp1 == &expand_param_error)
-       return (&expand_wdesc_error);
-      else if (temp1 == &expand_param_fatal)
-       return (&expand_wdesc_fatal);
-
-      ret = alloc_word_desc ();
-      ret->word = temp1;
-      if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
-       ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
-      return ret;
-    }
-#endif
-
-  /* Do the right thing based on which character ended the variable name. */
-  switch (c)
-    {
-    default:
-    case '\0':
-    bad_substitution:
-      last_command_exit_value = EXECUTION_FAILURE;
-      report_error (_("%s: bad substitution"), string ? string : "??");
-      FREE (value);
-      FREE (temp);
-      free (name);
-      return &expand_wdesc_error;
-
-    case RBRACE:
-      break;
-
-    case '#':  /* ${param#[#]pattern} */
-    case '%':  /* ${param%[%]pattern} */
-      if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
-       {
-         FREE (value);
-         break;
-       }
-      temp1 = parameter_brace_remove_pattern (name, temp, ind, value, c, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
-      free (temp);
-      free (value);
-      free (name);
-
-      ret = alloc_word_desc ();
-      ret->word = temp1;
-      if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
-       ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
-      return ret;
-
-    case '-':
-    case '=':
-    case '?':
-    case '+':
-      if (var_is_set && var_is_null == 0)
-       {
-         /* If the operator is `+', we don't want the value of the named
-            variable for anything, just the value of the right hand side. */
-         if (c == '+')
-           {
-             /* XXX -- if we're double-quoted and the named variable is "$@",
-                       we want to turn off any special handling of "$@" --
-                       we're not using it, so whatever is on the rhs applies. */
-             if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
-               *quoted_dollar_atp = 0;
-             if (contains_dollar_at)
-               *contains_dollar_at = 0;
-
-             FREE (temp);
-             if (value)
-               {
-                 /* From Posix discussion on austin-group list.  Issue 221
-                    requires that backslashes escaping `}' inside
-                    double-quoted ${...} be removed. */
-                 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
-                   quoted |= Q_DOLBRACE;
-                 ret = parameter_brace_expand_rhs (name, value, c,
-                                                   quoted,
-                                                   quoted_dollar_atp,
-                                                   contains_dollar_at);
-                 /* XXX - fix up later, esp. noting presence of
-                          W_HASQUOTEDNULL in ret->flags */
-                 free (value);
-               }
-             else
-               temp = (char *)NULL;
-           }
-         else
-           {
-             FREE (value);
-           }
-         /* Otherwise do nothing; just use the value in TEMP. */
-       }
-      else     /* VAR not set or VAR is NULL. */
-       {
-         FREE (temp);
-         temp = (char *)NULL;
-         if (c == '=' && var_is_special)
-           {
-             last_command_exit_value = EXECUTION_FAILURE;
-             report_error (_("$%s: cannot assign in this way"), name);
-             free (name);
-             free (value);
-             return &expand_wdesc_error;
-           }
-         else if (c == '?')
-           {
-             parameter_brace_expand_error (name, value);
-             return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
-           }
-         else if (c != '+')
-           {
-             /* XXX -- if we're double-quoted and the named variable is "$@",
-                       we want to turn off any special handling of "$@" --
-                       we're not using it, so whatever is on the rhs applies. */
-             if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
-               *quoted_dollar_atp = 0;
-             if (contains_dollar_at)
-               *contains_dollar_at = 0;
-
-             /* From Posix discussion on austin-group list.  Issue 221 requires
-                that backslashes escaping `}' inside double-quoted ${...} be
-                removed. */
-             if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
-               quoted |= Q_DOLBRACE;
-             ret = parameter_brace_expand_rhs (name, value, c, quoted,
-                                               quoted_dollar_atp,
-                                               contains_dollar_at);
-             /* XXX - fix up later, esp. noting presence of
-                      W_HASQUOTEDNULL in tdesc->flags */
-           }
-         free (value);
-       }
-
-      break;
-    }
-  free (name);
-
-  if (ret == 0)
-    {
-      ret = alloc_word_desc ();
-      ret->flags = tflag;
-      ret->word = temp;
-    }
-  return (ret);
-}
-
-/* Expand a single ${xxx} expansion.  The braces are optional.  When
-   the braces are used, parameter_brace_expand() does the work,
-   possibly calling param_expand recursively. */
-static WORD_DESC *
-param_expand (string, sindex, quoted, expanded_something,
-             contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
-             pflags)
-     char *string;
-     int *sindex, quoted, *expanded_something, *contains_dollar_at;
-     int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
-{
-  char *temp, *temp1, uerror[3];
-  int zindex, t_index, expok;
-  unsigned char c;
-  intmax_t number;
-  SHELL_VAR *var;
-  WORD_LIST *list;
-  WORD_DESC *tdesc, *ret;
-  int tflag;
-
-  zindex = *sindex;
-  c = string[++zindex];
-
-  temp = (char *)NULL;
-  ret = tdesc = (WORD_DESC *)NULL;
-  tflag = 0;
-
-  /* Do simple cases first. Switch on what follows '$'. */
-  switch (c)
-    {
-    /* $0 .. $9? */
-    case '0':
-    case '1':
-    case '2':
-    case '3':
-    case '4':
-    case '5':
-    case '6':
-    case '7':
-    case '8':
-    case '9':
-      temp1 = dollar_vars[TODIGIT (c)];
-      if (unbound_vars_is_error && temp1 == (char *)NULL)
-       {
-         uerror[0] = '$';
-         uerror[1] = c;
-         uerror[2] = '\0';
-         last_command_exit_value = EXECUTION_FAILURE;
-         err_unboundvar (uerror);
-         return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
-       }
-      if (temp1)
-       temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
-                 ? quote_string (temp1)
-                 : quote_escapes (temp1);
-      else
-       temp = (char *)NULL;
-
-      break;
-
-    /* $$ -- pid of the invoking shell. */
-    case '$':
-      temp = itos (dollar_dollar_pid);
-      break;
-
-    /* $# -- number of positional parameters. */
-    case '#':
-      temp = itos (number_of_args ());
-      break;
-
-    /* $? -- return value of the last synchronous command. */
-    case '?':
-      temp = itos (last_command_exit_value);
-      break;
-
-    /* $- -- flags supplied to the shell on invocation or by `set'. */
-    case '-':
-      temp = which_set_flags ();
-      break;
-
-      /* $! -- Pid of the last asynchronous command. */
-    case '!':
-      /* If no asynchronous pids have been created, expand to nothing.
-        If `set -u' has been executed, and no async processes have
-        been created, this is an expansion error. */
-      if (last_asynchronous_pid == NO_PID)
-       {
-         if (expanded_something)
-           *expanded_something = 0;
-         temp = (char *)NULL;
-         if (unbound_vars_is_error)
-           {
-             uerror[0] = '$';
-             uerror[1] = c;
-             uerror[2] = '\0';
-             last_command_exit_value = EXECUTION_FAILURE;
-             err_unboundvar (uerror);
-             return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
-           }
-       }
-      else
-       temp = itos (last_asynchronous_pid);
-      break;
-
-    /* The only difference between this and $@ is when the arg is quoted. */
-    case '*':          /* `$*' */
-      list = list_rest_of_args ();
-
-#if 0
-      /* According to austin-group posix proposal by Geoff Clare in
-        <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
-
-       "The shell shall write a message to standard error and
-        immediately exit when it tries to expand an unset parameter
-        other than the '@' and '*' special parameters."
-      */
-
-      if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
-       {
-         uerror[0] = '$';
-         uerror[1] = '*';
-         uerror[2] = '\0';
-         last_command_exit_value = EXECUTION_FAILURE;
-         err_unboundvar (uerror);
-         return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
-       }
-#endif
-
-      /* If there are no command-line arguments, this should just
-        disappear if there are other characters in the expansion,
-        even if it's quoted. */
-      if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
-       temp = (char *)NULL;
-      else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE))
-       {
-         /* If we have "$*" we want to make a string of the positional
-            parameters, separated by the first character of $IFS, and
-            quote the whole string, including the separators.  If IFS
-            is unset, the parameters are separated by ' '; if $IFS is
-            null, the parameters are concatenated. */
-         temp = (quoted & (Q_DOUBLE_QUOTES|Q_PATQUOTE)) ? string_list_dollar_star (list) : string_list (list);
-         if (temp)
-           {
-             temp1 = quote_string (temp);
-             if (*temp == 0)
-               tflag |= W_HASQUOTEDNULL;
-             free (temp);
-             temp = temp1;
-           }
-       }
-      else
-       {
-         /* We check whether or not we're eventually going to split $* here,
-            for example when IFS is empty and we are processing the rhs of
-            an assignment statement.  In that case, we don't separate the
-            arguments at all.  Otherwise, if the $* is not quoted it is
-            identical to $@ */
-#  if defined (HANDLE_MULTIBYTE)
-         if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
-#  else
-         if (expand_no_split_dollar_star && ifs_firstc == 0)
-#  endif
-           temp = string_list_dollar_star (list);
-         else
-           {
-             temp = string_list_dollar_at (list, quoted);
-             if (quoted == 0 && (ifs_is_set == 0 || ifs_is_null))
-               tflag |= W_SPLITSPACE;
-           }
-
-         if (expand_no_split_dollar_star == 0 && contains_dollar_at)
-           *contains_dollar_at = 1;
-       }
-
-      dispose_words (list);
-      break;
-
-    /* When we have "$@" what we want is "$1" "$2" "$3" ... This
-       means that we have to turn quoting off after we split into
-       the individually quoted arguments so that the final split
-       on the first character of $IFS is still done.  */
-    case '@':          /* `$@' */
-      list = list_rest_of_args ();
-
-#if 0
-      /* According to austin-group posix proposal by Geoff Clare in
-        <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
-
-       "The shell shall write a message to standard error and
-        immediately exit when it tries to expand an unset parameter
-        other than the '@' and '*' special parameters."
-      */
-
-      if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
-       {
-         uerror[0] = '$';
-         uerror[1] = '@';
-         uerror[2] = '\0';
-         last_command_exit_value = EXECUTION_FAILURE;
-         err_unboundvar (uerror);
-         return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
-       }
-#endif
-
-      /* We want to flag the fact that we saw this.  We can't turn
-        off quoting entirely, because other characters in the
-        string might need it (consider "\"$@\""), but we need some
-        way to signal that the final split on the first character
-        of $IFS should be done, even though QUOTED is 1. */
-      /* XXX - should this test include Q_PATQUOTE? */
-      if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
-       *quoted_dollar_at_p = 1;
-      if (contains_dollar_at)
-       *contains_dollar_at = 1;
-
-      /* We want to separate the positional parameters with the first
-        character of $IFS in case $IFS is something other than a space.
-        We also want to make sure that splitting is done no matter what --
-        according to POSIX.2, this expands to a list of the positional
-        parameters no matter what IFS is set to. */
-      temp = string_list_dollar_at (list, (pflags & PF_ASSIGNRHS) ? (quoted|Q_DOUBLE_QUOTES) : quoted);
-
-      tflag |= W_DOLLARAT;
-      dispose_words (list);
-      break;
-
-    case LBRACE:
-      tdesc = parameter_brace_expand (string, &zindex, quoted, pflags,
-                                     quoted_dollar_at_p,
-                                     contains_dollar_at);
-
-      if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
-       return (tdesc);
-      temp = tdesc ? tdesc->word : (char *)0;
-
-      /* XXX */
-      /* Quoted nulls should be removed if there is anything else
-        in the string. */
-      /* Note that we saw the quoted null so we can add one back at
-        the end of this function if there are no other characters
-        in the string, discard TEMP, and go on.  The exception to
-        this is when we have "${@}" and $1 is '', since $@ needs
-        special handling. */
-      if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
-       {
-         if (had_quoted_null_p)
-           *had_quoted_null_p = 1;
-         if (*quoted_dollar_at_p == 0)
-           {
-             free (temp);
-             tdesc->word = temp = (char *)NULL;
-           }
-           
-       }
-
-      ret = tdesc;
-      goto return0;
-
-    /* Do command or arithmetic substitution. */
-    case LPAREN:
-      /* We have to extract the contents of this paren substitution. */
-      t_index = zindex + 1;
-      temp = extract_command_subst (string, &t_index, 0);
-      zindex = t_index;
-
-      /* For Posix.2-style `$(( ))' arithmetic substitution,
-        extract the expression and pass it to the evaluator. */
-      if (temp && *temp == LPAREN)
-       {
-         char *temp2;
-         temp1 = temp + 1;
-         temp2 = savestring (temp1);
-         t_index = strlen (temp2) - 1;
-
-         if (temp2[t_index] != RPAREN)
-           {
-             free (temp2);
-             goto comsub;
-           }
-
-         /* Cut off ending `)' */
-         temp2[t_index] = '\0';
-
-         if (chk_arithsub (temp2, t_index) == 0)
-           {
-             free (temp2);
-#if 0
-             internal_warning (_("future versions of the shell will force evaluation as an arithmetic substitution"));
-#endif
-             goto comsub;
-           }
-
-         /* Expand variables found inside the expression. */
-         temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
-         free (temp2);
-
-arithsub:
-         /* No error messages. */
-         this_command_name = (char *)NULL;
-         number = evalexp (temp1, &expok);
-         free (temp);
-         free (temp1);
-         if (expok == 0)
-           {
-             if (interactive_shell == 0 && posixly_correct)
-               {
-                 last_command_exit_value = EXECUTION_FAILURE;
-                 return (&expand_wdesc_fatal);
-               }
-             else
-               return (&expand_wdesc_error);
-           }
-         temp = itos (number);
-         break;
-       }
-
-comsub:
-      if (pflags & PF_NOCOMSUB)
-       /* we need zindex+1 because string[zindex] == RPAREN */
-       temp1 = substring (string, *sindex, zindex+1);
-      else
-       {
-         tdesc = command_substitute (temp, quoted);
-         temp1 = tdesc ? tdesc->word : (char *)NULL;
-         if (tdesc)
-           dispose_word_desc (tdesc);
-       }
-      FREE (temp);
-      temp = temp1;
-      break;
-
-    /* Do POSIX.2d9-style arithmetic substitution.  This will probably go
-       away in a future bash release. */
-    case '[':
-      /* Extract the contents of this arithmetic substitution. */
-      t_index = zindex + 1;
-      temp = extract_arithmetic_subst (string, &t_index);
-      zindex = t_index;
-      if (temp == 0)
-       {
-         temp = savestring (string);
-         if (expanded_something)
-           *expanded_something = 0;
-         goto return0;
-       }         
-
-       /* Do initial variable expansion. */
-      temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
-
-      goto arithsub;
-
-    default:
-      /* Find the variable in VARIABLE_LIST. */
-      temp = (char *)NULL;
-
-      for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
-       ;
-      temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
-
-      /* If this isn't a variable name, then just output the `$'. */
-      if (temp1 == 0 || *temp1 == '\0')
-       {
-         FREE (temp1);
-         temp = (char *)xmalloc (2);
-         temp[0] = '$';
-         temp[1] = '\0';
-         if (expanded_something)
-           *expanded_something = 0;
-         goto return0;
-       }
-
-      /* If the variable exists, return its value cell. */
-      var = find_variable (temp1);
-
-      if (var && invisible_p (var) == 0 && var_isset (var))
-       {
-#if defined (ARRAY_VARS)
-         if (assoc_p (var) || array_p (var))
-           {
-             temp = array_p (var) ? array_reference (array_cell (var), 0)
-                                  : assoc_reference (assoc_cell (var), "0");
-             if (temp)
-               temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
-                         ? quote_string (temp)
-                         : quote_escapes (temp);
-             else if (unbound_vars_is_error)
-               goto unbound_variable;
-           }
-         else
-#endif
-           {
-             temp = value_cell (var);
-
-             temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
-                       ? quote_string (temp)
-                       : quote_escapes (temp);
-           }
-
-         free (temp1);
-
-         goto return0;
-       }
-      else if (var = find_variable_last_nameref (temp1))
-       {
-         temp = nameref_cell (var);
-#if defined (ARRAY_VARS)
-         if (temp && *temp && valid_array_reference (temp))
-           {
-             tdesc = parameter_brace_expand_word (temp, SPECIAL_VAR (temp, 0), quoted, pflags, (arrayind_t *)NULL);
-             if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
-               return (tdesc);
-             ret = tdesc;
-             goto return0;
-           }
-         else
-#endif
-         /* y=2 ; typeset -n x=y; echo $x is not the same as echo $2 in ksh */
-         if (temp && *temp && legal_identifier (temp) == 0)
-           {
-             last_command_exit_value = EXECUTION_FAILURE;
-             report_error (_("%s: invalid variable name for name reference"), temp);
-             return (&expand_wdesc_error);     /* XXX */
-           }
-         else
-           temp = (char *)NULL;
-       }
-
-      temp = (char *)NULL;
-
-unbound_variable:
-      if (unbound_vars_is_error)
-       {
-         last_command_exit_value = EXECUTION_FAILURE;
-         err_unboundvar (temp1);
-       }
-      else
-       {
-         free (temp1);
-         goto return0;
-       }
-
-      free (temp1);
-      last_command_exit_value = EXECUTION_FAILURE;
-      return ((unbound_vars_is_error && interactive_shell == 0)
-               ? &expand_wdesc_fatal
-               : &expand_wdesc_error);
-    }
-
-  if (string[zindex])
-    zindex++;
-
-return0:
-  *sindex = zindex;
-
-  if (ret == 0)
-    {
-      ret = alloc_word_desc ();
-      ret->flags = tflag;      /* XXX */
-      ret->word = temp;
-    }
-  return ret;
-}
-
-/* Make a word list which is the result of parameter and variable
-   expansion, command substitution, arithmetic substitution, and
-   quote removal of WORD.  Return a pointer to a WORD_LIST which is
-   the result of the expansion.  If WORD contains a null word, the
-   word list returned is also null.
-
-   QUOTED contains flag values defined in shell.h.
-
-   ISEXP is used to tell expand_word_internal that the word should be
-   treated as the result of an expansion.  This has implications for
-   how IFS characters in the word are treated.
-
-   CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
-   they point to an integer value which receives information about expansion.
-   CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
-   EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
-   else zero.
-
-   This only does word splitting in the case of $@ expansion.  In that
-   case, we split on ' '. */
-
-/* Values for the local variable quoted_state. */
-#define UNQUOTED        0
-#define PARTIALLY_QUOTED 1
-#define WHOLLY_QUOTED    2
-
-static WORD_LIST *
-expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
-     WORD_DESC *word;
-     int quoted, isexp;
-     int *contains_dollar_at;
-     int *expanded_something;
-{
-  WORD_LIST *list;
-  WORD_DESC *tword;
-
-  /* The intermediate string that we build while expanding. */
-  char *istring;
-
-  /* The current size of the above object. */
-  int istring_size;
-
-  /* Index into ISTRING. */
-  int istring_index;
-
-  /* Temporary string storage. */
-  char *temp, *temp1;
-
-  /* The text of WORD. */
-  register char *string;
-
-  /* The size of STRING. */
-  size_t string_size;
-
-  /* The index into STRING. */
-  int sindex;
-
-  /* This gets 1 if we see a $@ while quoted. */
-  int quoted_dollar_at;
-
-  /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
-     whether WORD contains no quoting characters, a partially quoted
-     string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
-  int quoted_state;
-
-  /* State flags */
-  int had_quoted_null;
-  int has_dollar_at, temp_has_dollar_at;
-  int split_on_spaces;
-  int tflag;
-  int pflags;                  /* flags passed to param_expand */
-
-  int assignoff;               /* If assignment, offset of `=' */
-
-  register unsigned char c;    /* Current character. */
-  int t_index;                 /* For calls to string_extract_xxx. */
-
-  char twochars[2];
-
-  DECLARE_MBSTATE;
-
-  istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
-  istring[istring_index = 0] = '\0';
-  quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
-  split_on_spaces = 0;
-  quoted_state = UNQUOTED;
-
-  string = word->word;
-  if (string == 0)
-    goto finished_with_string;
-  /* Don't need the string length for the SADD... and COPY_ macros unless
-     multibyte characters are possible. */
-  string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1;
-
-  if (contains_dollar_at)
-    *contains_dollar_at = 0;
-
-  assignoff = -1;
-
-  /* Begin the expansion. */
-
-  for (sindex = 0; ;)
-    {
-      c = string[sindex];
-
-      /* Case on toplevel character. */
-      switch (c)
-       {
-       case '\0':
-         goto finished_with_string;
-
-       case CTLESC:
-         sindex++;
-#if HANDLE_MULTIBYTE
-         if (MB_CUR_MAX > 1 && string[sindex])
-           {
-             SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
-           }
-         else
-#endif
-           {
-             temp = (char *)xmalloc (3);
-             temp[0] = CTLESC;
-             temp[1] = c = string[sindex];
-             temp[2] = '\0';
-           }
-
-dollar_add_string:
-         if (string[sindex])
-           sindex++;
-
-add_string:
-         if (temp)
-           {
-             istring = sub_append_string (temp, istring, &istring_index, &istring_size);
-             temp = (char *)0;
-           }
-
-         break;
-
-#if defined (PROCESS_SUBSTITUTION)
-         /* Process substitution. */
-       case '<':
-       case '>':
-         {
-           if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)) || posixly_correct)
-             {
-               sindex--;       /* add_character: label increments sindex */
-               goto add_character;
-             }
-           else
-             t_index = sindex + 1; /* skip past both '<' and LPAREN */
-
-           temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
-           sindex = t_index;
-
-           /* If the process substitution specification is `<()', we want to
-              open the pipe for writing in the child and produce output; if
-              it is `>()', we want to open the pipe for reading in the child
-              and consume input. */
-           temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
-
-           FREE (temp1);
-
-           goto dollar_add_string;
-         }
-#endif /* PROCESS_SUBSTITUTION */
-
-       case '=':
-         /* Posix.2 section 3.6.1 says that tildes following `=' in words
-            which are not assignment statements are not expanded.  If the
-            shell isn't in posix mode, though, we perform tilde expansion
-            on `likely candidate' unquoted assignment statements (flags
-            include W_ASSIGNMENT but not W_QUOTED).  A likely candidate
-            contains an unquoted :~ or =~.  Something to think about: we
-            now have a flag that says  to perform tilde expansion on arguments
-            to `assignment builtins' like declare and export that look like
-            assignment statements.  We now do tilde expansion on such words
-            even in POSIX mode. */     
-         if (word->flags & (W_ASSIGNRHS|W_NOTILDE))
-           {
-             if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
-               goto add_ifs_character;
-             else
-               goto add_character;
-           }
-         /* If we're not in posix mode or forcing assignment-statement tilde
-            expansion, note where the `=' appears in the word and prepare to
-            do tilde expansion following the first `='. */
-         if ((word->flags & W_ASSIGNMENT) &&
-             (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
-             assignoff == -1 && sindex > 0)
-           assignoff = sindex;
-         if (sindex == assignoff && string[sindex+1] == '~')   /* XXX */
-           word->flags |= W_ITILDE;
-#if 0
-         else if ((word->flags & W_ASSIGNMENT) &&
-                  (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
-                  string[sindex+1] == '~')
-           word->flags |= W_ITILDE;
-#endif
-         if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
-           goto add_ifs_character;
-         else
-           goto add_character;
-
-       case ':':
-         if (word->flags & W_NOTILDE)
-           {
-             if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
-               goto add_ifs_character;
-             else
-               goto add_character;
-           }
-
-         if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) &&
-             string[sindex+1] == '~')
-           word->flags |= W_ITILDE;
-
-         if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
-           goto add_ifs_character;
-         else
-           goto add_character;
-
-       case '~':
-         /* If the word isn't supposed to be tilde expanded, or we're not
-            at the start of a word or after an unquoted : or = in an
-            assignment statement, we don't do tilde expansion. */
-         if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
-             (sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
-             (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
-           {
-             word->flags &= ~W_ITILDE;
-             if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
-               goto add_ifs_character;
-             else
-               goto add_character;
-           }
-
-         if (word->flags & W_ASSIGNRHS)
-           tflag = 2;
-         else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP))
-           tflag = 1;
-         else
-           tflag = 0;
-
-         temp = bash_tilde_find_word (string + sindex, tflag, &t_index);
-           
-         word->flags &= ~W_ITILDE;
-
-         if (temp && *temp && t_index > 0)
-           {
-             temp1 = bash_tilde_expand (temp, tflag);
-             if  (temp1 && *temp1 == '~' && STREQ (temp, temp1))
-               {
-                 FREE (temp);
-                 FREE (temp1);
-                 goto add_character;           /* tilde expansion failed */
-               }
-             free (temp);
-             temp = temp1;
-             sindex += t_index;
-             goto add_quoted_string;           /* XXX was add_string */
-           }
-         else
-           {
-             FREE (temp);
-             goto add_character;
-           }
-       
-       case '$':
-         if (expanded_something)
-           *expanded_something = 1;
-
-         temp_has_dollar_at = 0;
-         pflags = (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0;
-         if (word->flags & W_NOSPLIT2)
-           pflags |= PF_NOSPLIT2;
-         if (word->flags & W_ASSIGNRHS)
-           pflags |= PF_ASSIGNRHS;
-         tword = param_expand (string, &sindex, quoted, expanded_something,
-                              &temp_has_dollar_at, &quoted_dollar_at,
-                              &had_quoted_null, pflags);
-         has_dollar_at += temp_has_dollar_at;
-         split_on_spaces += (tword->flags & W_SPLITSPACE);
-
-         if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
-           {
-             free (string);
-             free (istring);
-             return ((tword == &expand_wdesc_error) ? &expand_word_error
-                                                    : &expand_word_fatal);
-           }
-         if (contains_dollar_at && has_dollar_at)
-           *contains_dollar_at = 1;
-
-         if (tword && (tword->flags & W_HASQUOTEDNULL))
-           had_quoted_null = 1;
-
-         temp = tword ? tword->word : (char *)NULL;
-         dispose_word_desc (tword);
-
-         /* Kill quoted nulls; we will add them back at the end of
-            expand_word_internal if nothing else in the string */
-         if (had_quoted_null && temp && QUOTED_NULL (temp))
-           {
-             FREE (temp);
-             temp = (char *)NULL;
-           }
-
-         goto add_string;
-         break;
-
-       case '`':               /* Backquoted command substitution. */
-         {
-           t_index = sindex++;
-
-           temp = string_extract (string, &sindex, "`", SX_REQMATCH);
-           /* The test of sindex against t_index is to allow bare instances of
-              ` to pass through, for backwards compatibility. */
-           if (temp == &extract_string_error || temp == &extract_string_fatal)
-             {
-               if (sindex - 1 == t_index)
-                 {
-                   sindex = t_index;
-                   goto add_character;
-                 }
-               last_command_exit_value = EXECUTION_FAILURE;
-               report_error (_("bad substitution: no closing \"`\" in %s") , string+t_index);
-               free (string);
-               free (istring);
-               return ((temp == &extract_string_error) ? &expand_word_error
-                                                       : &expand_word_fatal);
-             }
-               
-           if (expanded_something)
-             *expanded_something = 1;
-
-           if (word->flags & W_NOCOMSUB)
-             /* sindex + 1 because string[sindex] == '`' */
-             temp1 = substring (string, t_index, sindex + 1);
-           else
-             {
-               de_backslash (temp);
-               tword = command_substitute (temp, quoted);
-               temp1 = tword ? tword->word : (char *)NULL;
-               if (tword)
-                 dispose_word_desc (tword);
-             }
-           FREE (temp);
-           temp = temp1;
-           goto dollar_add_string;
-         }
-
-       case '\\':
-         if (string[sindex + 1] == '\n')
-           {
-             sindex += 2;
-             continue;
-           }
-
-         c = string[++sindex];
-
-         if (quoted & Q_HERE_DOCUMENT)
-           tflag = CBSHDOC;
-         else if (quoted & Q_DOUBLE_QUOTES)
-           tflag = CBSDQUOTE;
-         else
-           tflag = 0;
-
-         /* From Posix discussion on austin-group list:  Backslash escaping
-            a } in ${...} is removed.  Issue 0000221 */
-         if ((quoted & Q_DOLBRACE) && c == RBRACE)
-           {
-             SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
-           }
-         /* This is the fix for " $@\ " */
-         else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0) & isexp == 0 && isifs (c))
-           {
-             RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
-                                     DEFAULT_ARRAY_SIZE);
-             istring[istring_index++] = CTLESC;
-             istring[istring_index++] = '\\';
-             istring[istring_index] = '\0';
-
-             SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
-           }
-         else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
-           {
-             SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
-           }
-         else if (c == 0)
-           {
-             c = CTLNUL;
-             sindex--;         /* add_character: label increments sindex */
-             goto add_character;
-           }
-         else
-           {
-             SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
-           }
-
-         sindex++;
-add_twochars:
-         /* BEFORE jumping here, we need to increment sindex if appropriate */
-         RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
-                                 DEFAULT_ARRAY_SIZE);
-         istring[istring_index++] = twochars[0];
-         istring[istring_index++] = twochars[1];
-         istring[istring_index] = '\0';
-
-         break;
-
-       case '"':
-         if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
-           goto add_character;
-
-         t_index = ++sindex;
-         temp = string_extract_double_quoted (string, &sindex, 0);
-
-         /* If the quotes surrounded the entire string, then the
-            whole word was quoted. */
-         quoted_state = (t_index == 1 && string[sindex] == '\0')
-                           ? WHOLLY_QUOTED
-                           : PARTIALLY_QUOTED;
-
-         if (temp && *temp)
-           {
-             tword = alloc_word_desc ();
-             tword->word = temp;
-
-             temp = (char *)NULL;
-
-             temp_has_dollar_at = 0;   /* XXX */
-             /* Need to get W_HASQUOTEDNULL flag through this function. */
-             list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &temp_has_dollar_at, (int *)NULL);
-             has_dollar_at += temp_has_dollar_at;
-
-             if (list == &expand_word_error || list == &expand_word_fatal)
-               {
-                 free (istring);
-                 free (string);
-                 /* expand_word_internal has already freed temp_word->word
-                    for us because of the way it prints error messages. */
-                 tword->word = (char *)NULL;
-                 dispose_word (tword);
-                 return list;
-               }
-
-             dispose_word (tword);
-
-             /* "$@" (a double-quoted dollar-at) expands into nothing,
-                not even a NULL word, when there are no positional
-                parameters. */
-             if (list == 0 && has_dollar_at)
-               {
-                 quoted_dollar_at++;
-                 break;
-               }
-
-             /* If we get "$@", we know we have expanded something, so we
-                need to remember it for the final split on $IFS.  This is
-                a special case; it's the only case where a quoted string
-                can expand into more than one word.  It's going to come back
-                from the above call to expand_word_internal as a list with
-                a single word, in which all characters are quoted and
-                separated by blanks.  What we want to do is to turn it back
-                into a list for the next piece of code. */
-             if (list)
-               dequote_list (list);
-
-             if (list && list->word && (list->word->flags & W_HASQUOTEDNULL))
-               had_quoted_null = 1;            /* XXX */
-
-             if (has_dollar_at)
-               {
-                 quoted_dollar_at++;
-                 if (contains_dollar_at)
-                   *contains_dollar_at = 1;
-                 if (expanded_something)
-                   *expanded_something = 1;
-               }
-           }
-         else
-           {
-             /* What we have is "".  This is a minor optimization. */
-             FREE (temp);
-             list = (WORD_LIST *)NULL;
-           }
-
-         /* The code above *might* return a list (consider the case of "$@",
-            where it returns "$1", "$2", etc.).  We can't throw away the
-            rest of the list, and we have to make sure each word gets added
-            as quoted.  We test on tresult->next:  if it is non-NULL, we
-            quote the whole list, save it to a string with string_list, and
-            add that string. We don't need to quote the results of this
-            (and it would be wrong, since that would quote the separators
-            as well), so we go directly to add_string. */
-         if (list)
-           {
-             if (list->next)
-               {
-                 /* Testing quoted_dollar_at makes sure that "$@" is
-                    split correctly when $IFS does not contain a space. */
-                 temp = quoted_dollar_at
-                               ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
-                               : string_list (quote_list (list));
-                 dispose_words (list);
-                 goto add_string;
-               }
-             else
-               {
-                 temp = savestring (list->word->word);
-                 tflag = list->word->flags;
-                 dispose_words (list);
-
-                 /* If the string is not a quoted null string, we want
-                    to remove any embedded unquoted CTLNUL characters.
-                    We do not want to turn quoted null strings back into
-                    the empty string, though.  We do this because we
-                    want to remove any quoted nulls from expansions that
-                    contain other characters.  For example, if we have
-                    x"$*"y or "x$*y" and there are no positional parameters,
-                    the $* should expand into nothing. */
-                 /* We use the W_HASQUOTEDNULL flag to differentiate the
-                    cases:  a quoted null character as above and when
-                    CTLNUL is contained in the (non-null) expansion
-                    of some variable.  We use the had_quoted_null flag to
-                    pass the value through this function to its caller. */
-                 if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
-                   remove_quoted_nulls (temp); /* XXX */
-               }
-           }
-         else
-           temp = (char *)NULL;
-
-         /* We do not want to add quoted nulls to strings that are only
-            partially quoted; we can throw them away.  The exception to
-            this is when we are going to be performing word splitting,
-            since we have to preserve a null argument if the next character
-            will cause word splitting. */
-         if (temp == 0 && quoted_state == PARTIALLY_QUOTED && (word->flags & (W_NOSPLIT|W_NOSPLIT2)))
-           continue;
-
-       add_quoted_string:
-
-         if (temp)
-           {
-             temp1 = temp;
-             temp = quote_string (temp);
-             free (temp1);
-             goto add_string;
-           }
-         else
-           {
-             /* Add NULL arg. */
-             c = CTLNUL;
-             sindex--;         /* add_character: label increments sindex */
-             goto add_character;
-           }
-
-         /* break; */
-
-       case '\'':
-         if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
-           goto add_character;
-
-         t_index = ++sindex;
-         temp = string_extract_single_quoted (string, &sindex);
-
-         /* If the entire STRING was surrounded by single quotes,
-            then the string is wholly quoted. */
-         quoted_state = (t_index == 1 && string[sindex] == '\0')
-                           ? WHOLLY_QUOTED
-                           : PARTIALLY_QUOTED;
-
-         /* If all we had was '', it is a null expansion. */
-         if (*temp == '\0')
-           {
-             free (temp);
-             temp = (char *)NULL;
-           }
-         else
-           remove_quoted_escapes (temp);       /* ??? */
-
-         /* We do not want to add quoted nulls to strings that are only
-            partially quoted; such nulls are discarded. */
-         if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
-           continue;
-
-         /* If we have a quoted null expansion, add a quoted NULL to istring. */
-         if (temp == 0)
-           {
-             c = CTLNUL;
-             sindex--;         /* add_character: label increments sindex */
-             goto add_character;
-           }
-         else
-           goto add_quoted_string;
-
-         /* break; */
-
-       default:
-         /* This is the fix for " $@ " */
-       add_ifs_character:
-         if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
-           {
-             if (string[sindex])       /* from old goto dollar_add_string */
-               sindex++;
-             if (c == 0)
-               {
-                 c = CTLNUL;
-                 goto add_character;
-               }
-             else
-               {
-#if HANDLE_MULTIBYTE
-                 if (MB_CUR_MAX > 1)
-                   sindex--;
-
-                 if (MB_CUR_MAX > 1)
-                   {
-                     SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
-                   }
-                 else
-#endif
-                   {
-                     twochars[0] = CTLESC;
-                     twochars[1] = c;
-                     goto add_twochars;
-                   }
-               }
-           }
-
-         SADD_MBCHAR (temp, string, sindex, string_size);
-
-       add_character:
-         RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
-                                 DEFAULT_ARRAY_SIZE);
-         istring[istring_index++] = c;
-         istring[istring_index] = '\0';
-
-         /* Next character. */
-         sindex++;
-       }
-    }
-
-finished_with_string:
-  /* OK, we're ready to return.  If we have a quoted string, and
-     quoted_dollar_at is not set, we do no splitting at all; otherwise
-     we split on ' '.  The routines that call this will handle what to
-     do if nothing has been expanded. */
-
-  /* Partially and wholly quoted strings which expand to the empty
-     string are retained as an empty arguments.  Unquoted strings
-     which expand to the empty string are discarded.  The single
-     exception is the case of expanding "$@" when there are no
-     positional parameters.  In that case, we discard the expansion. */
-
-  /* Because of how the code that handles "" and '' in partially
-     quoted strings works, we need to make ISTRING into a QUOTED_NULL
-     if we saw quoting characters, but the expansion was empty.
-     "" and '' are tossed away before we get to this point when
-     processing partially quoted strings.  This makes "" and $xxx""
-     equivalent when xxx is unset.  We also look to see whether we
-     saw a quoted null from a ${} expansion and add one back if we
-     need to. */
-
-  /* If we expand to nothing and there were no single or double quotes
-     in the word, we throw it away.  Otherwise, we return a NULL word.
-     The single exception is for $@ surrounded by double quotes when
-     there are no positional parameters.  In that case, we also throw
-     the word away. */
-
-  if (*istring == '\0')
-    {
-      if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
-       {
-         istring[0] = CTLNUL;
-         istring[1] = '\0';
-         tword = make_bare_word (istring);
-         tword->flags |= W_HASQUOTEDNULL;              /* XXX */
-         list = make_word_list (tword, (WORD_LIST *)NULL);
-         if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
-           tword->flags |= W_QUOTED;
-       }
-      /* According to sh, ksh, and Posix.2, if a word expands into nothing
-        and a double-quoted "$@" appears anywhere in it, then the entire
-        word is removed. */
-      else  if (quoted_state == UNQUOTED || quoted_dollar_at)
-       list = (WORD_LIST *)NULL;
-#if 0
-      else
-       {
-         tword = make_bare_word (istring);
-         if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
-           tword->flags |= W_QUOTED;
-         list = make_word_list (tword, (WORD_LIST *)NULL);
-       }
-#else
-      else
-       list = (WORD_LIST *)NULL;
-#endif
-    }
-  else if (word->flags & W_NOSPLIT)
-    {
-      tword = make_bare_word (istring);
-      if (word->flags & W_ASSIGNMENT)
-       tword->flags |= W_ASSIGNMENT;   /* XXX */
-      if (word->flags & W_COMPASSIGN)
-       tword->flags |= W_COMPASSIGN;   /* XXX */
-      if (word->flags & W_NOGLOB)
-       tword->flags |= W_NOGLOB;       /* XXX */
-      if (word->flags & W_NOBRACE)
-       tword->flags |= W_NOBRACE;      /* XXX */
-      if (word->flags & W_NOEXPAND)
-       tword->flags |= W_NOEXPAND;     /* XXX */
-      if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
-       tword->flags |= W_QUOTED;
-      if (had_quoted_null && QUOTED_NULL (istring))
-       tword->flags |= W_HASQUOTEDNULL;
-      list = make_word_list (tword, (WORD_LIST *)NULL);
-    }
-  else
-    {
-      char *ifs_chars;
-
-      ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
-
-      /* If we have $@, we need to split the results no matter what.  If
-        IFS is unset or NULL, string_list_dollar_at has separated the
-        positional parameters with a space, so we split on space (we have
-        set ifs_chars to " \t\n" above if ifs is unset).  If IFS is set,
-        string_list_dollar_at has separated the positional parameters
-        with the first character of $IFS, so we split on $IFS.  If
-        SPLIT_ON_SPACES is set, we expanded $* (unquoted) with IFS either
-        unset or null, and we want to make sure that we split on spaces
-        regardless of what else has happened to IFS since the expansion. */
-      if (split_on_spaces)
-       list = list_string (istring, " ", 1);   /* XXX quoted == 1? */
-      else if (has_dollar_at && ifs_chars)
-       list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
-      else
-       {
-         tword = make_bare_word (istring);
-         if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
-           tword->flags |= W_QUOTED;
-         if (word->flags & W_ASSIGNMENT)
-           tword->flags |= W_ASSIGNMENT;
-         if (word->flags & W_COMPASSIGN)
-           tword->flags |= W_COMPASSIGN;
-         if (word->flags & W_NOGLOB)
-           tword->flags |= W_NOGLOB;
-         if (word->flags & W_NOBRACE)
-           tword->flags |= W_NOBRACE;
-         if (word->flags & W_NOEXPAND)
-           tword->flags |= W_NOEXPAND;
-         if (had_quoted_null && QUOTED_NULL (istring))
-           tword->flags |= W_HASQUOTEDNULL;    /* XXX */
-         list = make_word_list (tword, (WORD_LIST *)NULL);
-       }
-    }
-
-  free (istring);
-  return (list);
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                Functions for Quote Removal                      */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Perform quote removal on STRING.  If QUOTED > 0, assume we are obeying the
-   backslash quoting rules for within double quotes or a here document. */
-char *
-string_quote_removal (string, quoted)
-     char *string;
-     int quoted;
-{
-  size_t slen;
-  char *r, *result_string, *temp, *send;
-  int sindex, tindex, dquote;
-  unsigned char c;
-  DECLARE_MBSTATE;
-
-  /* The result can be no longer than the original string. */
-  slen = strlen (string);
-  send = string + slen;
-
-  r = result_string = (char *)xmalloc (slen + 1);
-
-  for (dquote = sindex = 0; c = string[sindex];)
-    {
-      switch (c)
-       {
-       case '\\':
-         c = string[++sindex];
-         if (c == 0)
-           {
-             *r++ = '\\';
-             break;
-           }
-         if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
-           *r++ = '\\';
-         /* FALLTHROUGH */
-
-       default:
-         SCOPY_CHAR_M (r, string, send, sindex);
-         break;
-
-       case '\'':
-         if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
-           {
-             *r++ = c;
-             sindex++;
-             break;
-           }
-         tindex = sindex + 1;
-         temp = string_extract_single_quoted (string, &tindex);
-         if (temp)
-           {
-             strcpy (r, temp);
-             r += strlen (r);
-             free (temp);
-           }
-         sindex = tindex;
-         break;
-
-       case '"':
-         dquote = 1 - dquote;
-         sindex++;
-         break;
-       }
-    }
-    *r = '\0';
-    return (result_string);
-}
-
-#if 0
-/* UNUSED */
-/* Perform quote removal on word WORD.  This allocates and returns a new
-   WORD_DESC *. */
-WORD_DESC *
-word_quote_removal (word, quoted)
-     WORD_DESC *word;
-     int quoted;
-{
-  WORD_DESC *w;
-  char *t;
-
-  t = string_quote_removal (word->word, quoted);
-  w = alloc_word_desc ();
-  w->word = t ? t : savestring ("");
-  return (w);
-}
-
-/* Perform quote removal on all words in LIST.  If QUOTED is non-zero,
-   the members of the list are treated as if they are surrounded by
-   double quotes.  Return a new list, or NULL if LIST is NULL. */
-WORD_LIST *
-word_list_quote_removal (list, quoted)
-     WORD_LIST *list;
-     int quoted;
-{
-  WORD_LIST *result, *t, *tresult, *e;
-
-  for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
-    {
-      tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
-#if 0
-      result = (WORD_LIST *) list_append (result, tresult);
-#else
-      if (result == 0)
-       result = e = tresult;
-      else
-       {
-         e->next = tresult;
-         while (e->next)
-           e = e->next;
-       }
-#endif
-    }
-  return (result);
-}
-#endif
-
-/*******************************************
- *                                        *
- *    Functions to perform word splitting  *
- *                                        *
- *******************************************/
-
-void
-setifs (v)
-     SHELL_VAR *v;
-{
-  char *t;
-  unsigned char uc;
-
-  ifs_var = v;
-  ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
-
-  ifs_is_set = ifs_var != 0;
-  ifs_is_null = ifs_is_set && (*ifs_value == 0);
-
-  /* Should really merge ifs_cmap with sh_syntaxtab.  XXX - doesn't yet
-     handle multibyte chars in IFS */
-  memset (ifs_cmap, '\0', sizeof (ifs_cmap));
-  for (t = ifs_value ; t && *t; t++)
-    {
-      uc = *t;
-      ifs_cmap[uc] = 1;
-    }
-
-#if defined (HANDLE_MULTIBYTE)
-  if (ifs_value == 0)
-    {
-      ifs_firstc[0] = '\0';
-      ifs_firstc_len = 1;
-    }
-  else
-    {
-      size_t ifs_len;
-      ifs_len = strnlen (ifs_value, MB_CUR_MAX);
-      ifs_firstc_len = MBLEN (ifs_value, ifs_len);
-      if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len))
-       {
-         ifs_firstc[0] = ifs_value[0];
-         ifs_firstc[1] = '\0';
-         ifs_firstc_len = 1;
-       }
-      else
-       memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
-    }
-#else
-  ifs_firstc = ifs_value ? *ifs_value : 0;
-#endif
-}
-
-char *
-getifs ()
-{
-  return ifs_value;
-}
-
-/* This splits a single word into a WORD LIST on $IFS, but only if the word
-   is not quoted.  list_string () performs quote removal for us, even if we
-   don't do any splitting. */
-WORD_LIST *
-word_split (w, ifs_chars)
-     WORD_DESC *w;
-     char *ifs_chars;
-{
-  WORD_LIST *result;
-
-  if (w)
-    {
-      char *xifs;
-
-      xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
-      result = list_string (w->word, xifs, w->flags & W_QUOTED);
-    }
-  else
-    result = (WORD_LIST *)NULL;
-
-  return (result);
-}
-
-/* Perform word splitting on LIST and return the RESULT.  It is possible
-   to return (WORD_LIST *)NULL. */
-static WORD_LIST *
-word_list_split (list)
-     WORD_LIST *list;
-{
-  WORD_LIST *result, *t, *tresult, *e;
-
-  for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
-    {
-      tresult = word_split (t->word, ifs_value);
-      if (result == 0)
-        result = e = tresult;
-      else
-       {
-         e->next = tresult;
-         while (e->next)
-           e = e->next;
-       }
-    }
-  return (result);
-}
-
-/**************************************************
- *                                               *
- *    Functions to expand an entire WORD_LIST    *
- *                                               *
- **************************************************/
-
-/* Do any word-expansion-specific cleanup and jump to top_level */
-static void
-exp_jump_to_top_level (v)
-     int v;
-{
-  set_pipestatus_from_exit (last_command_exit_value);
-
-  /* Cleanup code goes here. */
-  expand_no_split_dollar_star = 0;     /* XXX */
-  expanding_redir = 0;
-  assigning_in_environment = 0;
-
-  if (parse_and_execute_level == 0)
-    top_level_cleanup ();                      /* from sig.c */
-
-  jump_to_top_level (v);
-}
-
-/* Put NLIST (which is a WORD_LIST * of only one element) at the front of
-   ELIST, and set ELIST to the new list. */
-#define PREPEND_LIST(nlist, elist) \
-       do { nlist->next = elist; elist = nlist; } while (0)
-
-/* Separate out any initial variable assignments from TLIST.  If set -k has
-   been executed, remove all assignment statements from TLIST.  Initial
-   variable assignments and other environment assignments are placed
-   on SUBST_ASSIGN_VARLIST. */
-static WORD_LIST *
-separate_out_assignments (tlist)
-     WORD_LIST *tlist;
-{
-  register WORD_LIST *vp, *lp;
-
-  if (tlist == 0)
-    return ((WORD_LIST *)NULL);
-
-  if (subst_assign_varlist)
-    dispose_words (subst_assign_varlist);      /* Clean up after previous error */
-
-  subst_assign_varlist = (WORD_LIST *)NULL;
-  vp = lp = tlist;
-
-  /* Separate out variable assignments at the start of the command.
-     Loop invariant: vp->next == lp
-     Loop postcondition:
-       lp = list of words left after assignment statements skipped
-       tlist = original list of words
-  */
-  while (lp && (lp->word->flags & W_ASSIGNMENT))
-    {
-      vp = lp;
-      lp = lp->next;
-    }
-
-  /* If lp != tlist, we have some initial assignment statements.
-     We make SUBST_ASSIGN_VARLIST point to the list of assignment
-     words and TLIST point to the remaining words.  */
-  if (lp != tlist)
-    {
-      subst_assign_varlist = tlist;
-      /* ASSERT(vp->next == lp); */
-      vp->next = (WORD_LIST *)NULL;    /* terminate variable list */
-      tlist = lp;                      /* remainder of word list */
-    }
-
-  /* vp == end of variable list */
-  /* tlist == remainder of original word list without variable assignments */
-  if (!tlist)
-    /* All the words in tlist were assignment statements */
-    return ((WORD_LIST *)NULL);
-
-  /* ASSERT(tlist != NULL); */
-  /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
-
-  /* If the -k option is in effect, we need to go through the remaining
-     words, separate out the assignment words, and place them on
-     SUBST_ASSIGN_VARLIST. */
-  if (place_keywords_in_env)
-    {
-      WORD_LIST *tp;   /* tp == running pointer into tlist */
-
-      tp = tlist;
-      lp = tlist->next;
-
-      /* Loop Invariant: tp->next == lp */
-      /* Loop postcondition: tlist == word list without assignment statements */
-      while (lp)
-       {
-         if (lp->word->flags & W_ASSIGNMENT)
-           {
-             /* Found an assignment statement, add this word to end of
-                subst_assign_varlist (vp). */
-             if (!subst_assign_varlist)
-               subst_assign_varlist = vp = lp;
-             else
-               {
-                 vp->next = lp;
-                 vp = lp;
-               }
-
-             /* Remove the word pointed to by LP from TLIST. */
-             tp->next = lp->next;
-             /* ASSERT(vp == lp); */
-             lp->next = (WORD_LIST *)NULL;
-             lp = tp->next;
-           }
-         else
-           {
-             tp = lp;
-             lp = lp->next;
-           }
-       }
-    }
-  return (tlist);
-}
-
-#define WEXP_VARASSIGN 0x001
-#define WEXP_BRACEEXP  0x002
-#define WEXP_TILDEEXP  0x004
-#define WEXP_PARAMEXP  0x008
-#define WEXP_PATHEXP   0x010
-
-/* All of the expansions, including variable assignments at the start of
-   the list. */
-#define WEXP_ALL       (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
-
-/* All of the expansions except variable assignments at the start of
-   the list. */
-#define WEXP_NOVARS    (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
-
-/* All of the `shell expansions': brace expansion, tilde expansion, parameter
-   expansion, command substitution, arithmetic expansion, word splitting, and
-   quote removal. */
-#define WEXP_SHELLEXP  (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
-
-/* Take the list of words in LIST and do the various substitutions.  Return
-   a new list of words which is the expanded list, and without things like
-   variable assignments. */
-
-WORD_LIST *
-expand_words (list)
-     WORD_LIST *list;
-{
-  return (expand_word_list_internal (list, WEXP_ALL));
-}
-
-/* Same as expand_words (), but doesn't hack variable or environment
-   variables. */
-WORD_LIST *
-expand_words_no_vars (list)
-     WORD_LIST *list;
-{
-  return (expand_word_list_internal (list, WEXP_NOVARS));
-}
-
-WORD_LIST *
-expand_words_shellexp (list)
-     WORD_LIST *list;
-{
-  return (expand_word_list_internal (list, WEXP_SHELLEXP));
-}
-
-static WORD_LIST *
-glob_expand_word_list (tlist, eflags)
-     WORD_LIST *tlist;
-     int eflags;
-{
-  char **glob_array, *temp_string;
-  register int glob_index;
-  WORD_LIST *glob_list, *output_list, *disposables, *next;
-  WORD_DESC *tword;
-
-  output_list = disposables = (WORD_LIST *)NULL;
-  glob_array = (char **)NULL;
-  while (tlist)
-    {
-      /* For each word, either globbing is attempted or the word is
-        added to orig_list.  If globbing succeeds, the results are
-        added to orig_list and the word (tlist) is added to the list
-        of disposable words.  If globbing fails and failed glob
-        expansions are left unchanged (the shell default), the
-        original word is added to orig_list.  If globbing fails and
-        failed glob expansions are removed, the original word is
-        added to the list of disposable words.  orig_list ends up
-        in reverse order and requires a call to REVERSE_LIST to
-        be set right.  After all words are examined, the disposable
-        words are freed. */
-      next = tlist->next;
-
-      /* If the word isn't an assignment and contains an unquoted
-        pattern matching character, then glob it. */
-      if ((tlist->word->flags & W_NOGLOB) == 0 &&
-         unquoted_glob_pattern_p (tlist->word->word))
-       {
-         glob_array = shell_glob_filename (tlist->word->word);
-
-         /* Handle error cases.
-            I don't think we should report errors like "No such file
-            or directory".  However, I would like to report errors
-            like "Read failed". */
-
-         if (glob_array == 0 || GLOB_FAILED (glob_array))
-           {
-             glob_array = (char **)xmalloc (sizeof (char *));
-             glob_array[0] = (char *)NULL;
-           }
-
-         /* Dequote the current word in case we have to use it. */
-         if (glob_array[0] == NULL)
-           {
-             temp_string = dequote_string (tlist->word->word);
-             free (tlist->word->word);
-             tlist->word->word = temp_string;
-           }
-
-         /* Make the array into a word list. */
-         glob_list = (WORD_LIST *)NULL;
-         for (glob_index = 0; glob_array[glob_index]; glob_index++)
-           {
-             tword = make_bare_word (glob_array[glob_index]);
-             glob_list = make_word_list (tword, glob_list);
-           }
-
-         if (glob_list)
-           {
-             output_list = (WORD_LIST *)list_append (glob_list, output_list);
-             PREPEND_LIST (tlist, disposables);
-           }
-         else if (fail_glob_expansion != 0)
-           {
-             last_command_exit_value = EXECUTION_FAILURE;
-             report_error (_("no match: %s"), tlist->word->word);
-             exp_jump_to_top_level (DISCARD);
-           }
-         else if (allow_null_glob_expansion == 0)
-           {
-             /* Failed glob expressions are left unchanged. */
-             PREPEND_LIST (tlist, output_list);
-           }
-         else
-           {
-             /* Failed glob expressions are removed. */
-             PREPEND_LIST (tlist, disposables);
-           }
-       }
-      else
-       {
-         /* Dequote the string. */
-         temp_string = dequote_string (tlist->word->word);
-         free (tlist->word->word);
-         tlist->word->word = temp_string;
-         PREPEND_LIST (tlist, output_list);
-       }
-
-      strvec_dispose (glob_array);
-      glob_array = (char **)NULL;
-
-      tlist = next;
-    }
-
-  if (disposables)
-    dispose_words (disposables);
-
-  if (output_list)
-    output_list = REVERSE_LIST (output_list, WORD_LIST *);
-
-  return (output_list);
-}
-
-#if defined (BRACE_EXPANSION)
-static WORD_LIST *
-brace_expand_word_list (tlist, eflags)
-     WORD_LIST *tlist;
-     int eflags;
-{
-  register char **expansions;
-  char *temp_string;
-  WORD_LIST *disposables, *output_list, *next;
-  WORD_DESC *w;
-  int eindex;
-
-  for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
-    {
-      next = tlist->next;
-
-      if (tlist->word->flags & W_NOBRACE)
-        {
-/*itrace("brace_expand_word_list: %s: W_NOBRACE", tlist->word->word);*/
-         PREPEND_LIST (tlist, output_list);
-         continue;
-        }
-
-      if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
-        {
-/*itrace("brace_expand_word_list: %s: W_COMPASSIGN|W_ASSIGNARG", tlist->word->word);*/
-         PREPEND_LIST (tlist, output_list);
-         continue;
-        }
-
-      /* Only do brace expansion if the word has a brace character.  If
-        not, just add the word list element to BRACES and continue.  In
-        the common case, at least when running shell scripts, this will
-        degenerate to a bunch of calls to `mbschr', and then what is
-        basically a reversal of TLIST into BRACES, which is corrected
-        by a call to REVERSE_LIST () on BRACES when the end of TLIST
-        is reached. */
-      if (mbschr (tlist->word->word, LBRACE))
-       {
-         expansions = brace_expand (tlist->word->word);
-
-         for (eindex = 0; temp_string = expansions[eindex]; eindex++)
-           {
-             w = alloc_word_desc ();
-             w->word = temp_string;
-
-             /* If brace expansion didn't change the word, preserve
-                the flags.  We may want to preserve the flags
-                unconditionally someday -- XXX */
-             if (STREQ (temp_string, tlist->word->word))
-               w->flags = tlist->word->flags;
-             else
-               w = make_word_flags (w, temp_string);
-
-             output_list = make_word_list (w, output_list);
-           }
-         free (expansions);
-
-         /* Add TLIST to the list of words to be freed after brace
-            expansion has been performed. */
-         PREPEND_LIST (tlist, disposables);
-       }
-      else
-       PREPEND_LIST (tlist, output_list);
-    }
-
-  if (disposables)
-    dispose_words (disposables);
-
-  if (output_list)
-    output_list = REVERSE_LIST (output_list, WORD_LIST *);
-
-  return (output_list);
-}
-#endif
-
-#if defined (ARRAY_VARS)
-/* Take WORD, a compound associative array assignment, and internally run
-   'declare -A w', where W is the variable name portion of WORD. */
-static int
-make_internal_declare (word, option)
-     char *word;
-     char *option;
-{
-  int t;
-  WORD_LIST *wl;
-  WORD_DESC *w;
-
-  w = make_word (word);
-
-  t = assignment (w->word, 0);
-  w->word[t] = '\0';
-
-  wl = make_word_list (w, (WORD_LIST *)NULL);
-  wl = make_word_list (make_word (option), wl);
-
-  return (declare_builtin (wl));  
-}  
-#endif
-
-static WORD_LIST *
-shell_expand_word_list (tlist, eflags)
-     WORD_LIST *tlist;
-     int eflags;
-{
-  WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
-  int expanded_something, has_dollar_at;
-  char *temp_string;
-
-  /* We do tilde expansion all the time.  This is what 1003.2 says. */
-  new_list = (WORD_LIST *)NULL;
-  for (orig_list = tlist; tlist; tlist = next)
-    {
-      temp_string = tlist->word->word;
-
-      next = tlist->next;
-
-#if defined (ARRAY_VARS)
-      /* If this is a compound array assignment to a builtin that accepts
-         such assignments (e.g., `declare'), take the assignment and perform
-         it separately, handling the semantics of declarations inside shell
-         functions.  This avoids the double-evaluation of such arguments,
-         because `declare' does some evaluation of compound assignments on
-         its own. */
-      if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
-       {
-         int t;
-
-         if ((tlist->word->flags & (W_ASSIGNASSOC|W_ASSNGLOBAL)) == (W_ASSIGNASSOC|W_ASSNGLOBAL))
-           make_internal_declare (tlist->word->word, "-gA");
-         else if (tlist->word->flags & W_ASSIGNASSOC)
-           make_internal_declare (tlist->word->word, "-A");
-         else if ((tlist->word->flags & (W_ASSIGNARRAY|W_ASSNGLOBAL)) == (W_ASSIGNARRAY|W_ASSNGLOBAL))
-           make_internal_declare (tlist->word->word, "-ga");
-         else if (tlist->word->flags & W_ASSIGNARRAY)
-           make_internal_declare (tlist->word->word, "-a");
-         else if (tlist->word->flags & W_ASSNGLOBAL)
-           make_internal_declare (tlist->word->word, "-g");
-
-         t = do_word_assignment (tlist->word, 0);
-         if (t == 0)
-           {
-             last_command_exit_value = EXECUTION_FAILURE;
-             exp_jump_to_top_level (DISCARD);
-           }
-
-         /* Now transform the word as ksh93 appears to do and go on */
-         t = assignment (tlist->word->word, 0);
-         tlist->word->word[t] = '\0';
-         tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG|W_ASSIGNASSOC|W_ASSIGNARRAY);
-       }
-#endif
-
-      expanded_something = 0;
-      expanded = expand_word_internal
-       (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
-
-      if (expanded == &expand_word_error || expanded == &expand_word_fatal)
-       {
-         /* By convention, each time this error is returned,
-            tlist->word->word has already been freed. */
-         tlist->word->word = (char *)NULL;
-
-         /* Dispose our copy of the original list. */
-         dispose_words (orig_list);
-         /* Dispose the new list we're building. */
-         dispose_words (new_list);
-
-         last_command_exit_value = EXECUTION_FAILURE;
-         if (expanded == &expand_word_error)
-           exp_jump_to_top_level (DISCARD);
-         else
-           exp_jump_to_top_level (FORCE_EOF);
-       }
-
-      /* Don't split words marked W_NOSPLIT. */
-      if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
-       {
-         temp_list = word_list_split (expanded);
-         dispose_words (expanded);
-       }
-      else
-       {
-         /* If no parameter expansion, command substitution, process
-            substitution, or arithmetic substitution took place, then
-            do not do word splitting.  We still have to remove quoted
-            null characters from the result. */
-         word_list_remove_quoted_nulls (expanded);
-         temp_list = expanded;
-       }
-
-      expanded = REVERSE_LIST (temp_list, WORD_LIST *);
-      new_list = (WORD_LIST *)list_append (expanded, new_list);
-    }
-
-  if (orig_list)  
-    dispose_words (orig_list);
-
-  if (new_list)
-    new_list = REVERSE_LIST (new_list, WORD_LIST *);
-
-  return (new_list);
-}
-
-/* The workhorse for expand_words () and expand_words_no_vars ().
-   First arg is LIST, a WORD_LIST of words.
-   Second arg EFLAGS is a flags word controlling which expansions are
-   performed.
-
-   This does all of the substitutions: brace expansion, tilde expansion,
-   parameter expansion, command substitution, arithmetic expansion,
-   process substitution, word splitting, and pathname expansion, according
-   to the bits set in EFLAGS.  Words with the W_QUOTED or W_NOSPLIT bits
-   set, or for which no expansion is done, do not undergo word splitting.
-   Words with the W_NOGLOB bit set do not undergo pathname expansion; words
-   with W_NOBRACE set do not undergo brace expansion (see
-   brace_expand_word_list above). */
-static WORD_LIST *
-expand_word_list_internal (list, eflags)
-     WORD_LIST *list;
-     int eflags;
-{
-  WORD_LIST *new_list, *temp_list;
-  int tint;
-
-  tempenv_assign_error = 0;
-  if (list == 0)
-    return ((WORD_LIST *)NULL);
-
-  garglist = new_list = copy_word_list (list);
-  if (eflags & WEXP_VARASSIGN)
-    {
-      garglist = new_list = separate_out_assignments (new_list);
-      if (new_list == 0)
-       {
-         if (subst_assign_varlist)
-           {
-             /* All the words were variable assignments, so they are placed
-                into the shell's environment. */
-             for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
-               {
-                 this_command_name = (char *)NULL;     /* no arithmetic errors */
-                 tint = do_word_assignment (temp_list->word, 0);
-                 /* Variable assignment errors in non-interactive shells
-                    running in Posix.2 mode cause the shell to exit. */
-                 if (tint == 0)
-                   {
-                     last_command_exit_value = EXECUTION_FAILURE;
-                     if (interactive_shell == 0 && posixly_correct)
-                       exp_jump_to_top_level (FORCE_EOF);
-                     else
-                       exp_jump_to_top_level (DISCARD);
-                   }
-               }
-             dispose_words (subst_assign_varlist);
-             subst_assign_varlist = (WORD_LIST *)NULL;
-           }
-         return ((WORD_LIST *)NULL);
-       }
-    }
-
-  /* Begin expanding the words that remain.  The expansions take place on
-     things that aren't really variable assignments. */
-
-#if defined (BRACE_EXPANSION)
-  /* Do brace expansion on this word if there are any brace characters
-     in the string. */
-  if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
-    new_list = brace_expand_word_list (new_list, eflags);
-#endif /* BRACE_EXPANSION */
-
-  /* Perform the `normal' shell expansions: tilde expansion, parameter and
-     variable substitution, command substitution, arithmetic expansion,
-     and word splitting. */
-  new_list = shell_expand_word_list (new_list, eflags);
-
-  /* Okay, we're almost done.  Now let's just do some filename
-     globbing. */
-  if (new_list)
-    {
-      if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
-       /* Glob expand the word list unless globbing has been disabled. */
-       new_list = glob_expand_word_list (new_list, eflags);
-      else
-       /* Dequote the words, because we're not performing globbing. */
-       new_list = dequote_list (new_list);
-    }
-
-  if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
-    {
-      sh_wassign_func_t *assign_func;
-      int is_special_builtin, is_builtin_or_func;
-
-      /* If the remainder of the words expand to nothing, Posix.2 requires
-        that the variable and environment assignments affect the shell's
-        environment. */
-      assign_func = new_list ? assign_in_env : do_word_assignment;
-      tempenv_assign_error = 0;
-
-      is_builtin_or_func = (new_list && new_list->word && (find_shell_builtin (new_list->word->word) || find_function (new_list->word->word)));
-      /* Posix says that special builtins exit if a variable assignment error
-        occurs in an assignment preceding it. */
-      is_special_builtin = (posixly_correct && new_list && new_list->word && find_special_builtin (new_list->word->word));
-      
-      for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
-       {
-         this_command_name = (char *)NULL;
-         assigning_in_environment = (assign_func == assign_in_env);
-         tint = (*assign_func) (temp_list->word, is_builtin_or_func);
-         assigning_in_environment = 0;
-         /* Variable assignment errors in non-interactive shells running
-            in Posix.2 mode cause the shell to exit. */
-         if (tint == 0)
-           {
-             if (assign_func == do_word_assignment)
-               {
-                 last_command_exit_value = EXECUTION_FAILURE;
-                 if (interactive_shell == 0 && posixly_correct && is_special_builtin)
-                   exp_jump_to_top_level (FORCE_EOF);
-                 else
-                   exp_jump_to_top_level (DISCARD);
-               }
-             else
-               tempenv_assign_error++;
-           }
-       }
-
-      dispose_words (subst_assign_varlist);
-      subst_assign_varlist = (WORD_LIST *)NULL;
-    }
-
-  return (new_list);
-}
diff --git a/tests/misc/regress/log.orig b/tests/misc/regress/log.orig
deleted file mode 100644 (file)
index c1f1e19..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-:; ./shx
-
-sh:
-<&$fd  ok
-nlbq   Mon Aug  3 02:45:00 EDT 1992
-bang   geoff
-quote  712824302
-setbq  defmsgid=<1992Aug3.024502.6176@host>
-bgwait sleep done... wait 6187
-
-
-bash:
-<&$fd  ok
-nlbq   Mon Aug  3 02:45:09 EDT 1992
-bang   geoff
-quote  712824311
-setbq  defmsgid=<1992Aug3.024512.6212@host>
-bgwait sleep done... wait 6223
-
-
-ash:
-<&$fd  shx1: 4: Syntax error: Bad fd number
-nlbq   Mon Aug  3 02:45:19 EDT 1992
-bang   geoff
-quote  getdate: `"now"' not a valid date
-
-setbq  defmsgid=<1992Aug3.` echo 024521
-bgwait sleep done... wait 6241
-
-
-ksh:
-<&$fd  ok
-nlbq   ./shx: 6248 Memory fault - core dumped
-bang   geoff
-quote  getdate: `"now"' not a valid date
-
-setbq  defmsgid=<1992Aug3.024530.6257@host>
-bgwait no such job: 6265
-wait 6265
-sleep done... 
-
-zsh:
-<&$fd  ok
-nlbq   Mon Aug 3 02:45:36 EDT 1992
-bang   shx3: event not found: /s/ [4]
-quote  712824337
-setbq  defmsgid=<..6290@host>
-bgwait shx7: unmatched " [9]
-sleep done... 
-:; 
diff --git a/tests/misc/regress/shx.orig b/tests/misc/regress/shx.orig
deleted file mode 100644 (file)
index 4b3bf2b..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#! /bin/sh
-for cmd in sh bash ash ksh zsh
-do
-       echo
-       echo $cmd:
-       for demo in shx?
-       do
-               $cmd $demo
-       done
-done
diff --git a/trap.c~ b/trap.c~
deleted file mode 100644 (file)
index b030747..0000000
--- a/trap.c~
+++ /dev/null
@@ -1,1209 +0,0 @@
-/* trap.c -- Not the trap command, but useful functions for manipulating
-   those objects.  The trap command is in builtins/trap.def. */
-
-/* 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 (HAVE_UNISTD_H)
-#  include <unistd.h>
-#endif
-
-#include "bashtypes.h"
-#include "bashansi.h"
-
-#include <stdio.h>
-#include <errno.h>
-
-#include "bashintl.h"
-
-#include <signal.h>
-
-#include "trap.h"
-
-#include "shell.h"
-#include "flags.h"
-#include "input.h"     /* for save_token_state, restore_token_state */
-#include "jobs.h"
-#include "signames.h"
-#include "builtins.h"
-#include "builtins/common.h"
-#include "builtins/builtext.h"
-
-#if defined (READLINE)
-#  include <readline/readline.h>
-#  include "bashline.h"
-#endif
-
-#ifndef errno
-extern int errno;
-#endif
-
-/* Flags which describe the current handling state of a signal. */
-#define SIG_INHERITED   0x0    /* Value inherited from parent. */
-#define SIG_TRAPPED     0x1    /* Currently trapped. */
-#define SIG_HARD_IGNORE 0x2    /* Signal was ignored on shell entry. */
-#define SIG_SPECIAL     0x4    /* Treat this signal specially. */
-#define SIG_NO_TRAP     0x8    /* Signal cannot be trapped. */
-#define SIG_INPROGRESS 0x10    /* Signal handler currently executing. */
-#define SIG_CHANGED    0x20    /* Trap value changed in trap handler. */
-#define SIG_IGNORED    0x40    /* The signal is currently being ignored. */
-
-#define SPECIAL_TRAP(s)        ((s) == EXIT_TRAP || (s) == DEBUG_TRAP || (s) == ERROR_TRAP || (s) == RETURN_TRAP)
-
-/* An array of such flags, one for each signal, describing what the
-   shell will do with a signal.  DEBUG_TRAP == NSIG; some code below
-   assumes this. */
-static int sigmodes[BASH_NSIG];
-
-static void free_trap_command __P((int));
-static void change_signal __P((int, char *));
-
-static void get_original_signal __P((int));
-
-static int _run_trap_internal __P((int, char *));
-
-static void free_trap_string __P((int));
-static void reset_signal __P((int));
-static void restore_signal __P((int));
-static void reset_or_restore_signal_handlers __P((sh_resetsig_func_t *));
-
-/* Variables used here but defined in other files. */
-extern int last_command_exit_value;
-extern int line_number;
-
-extern int sigalrm_seen;
-extern procenv_t alrmbuf;
-
-extern char *this_command_name;
-extern sh_builtin_func_t *this_shell_builtin;
-extern procenv_t wait_intr_buf;
-extern int return_catch_flag, return_catch_value;
-extern int subshell_level;
-extern WORD_LIST *subst_assign_varlist;
-
-/* The list of things to do originally, before we started trapping. */
-SigHandler *original_signals[NSIG];
-
-/* For each signal, a slot for a string, which is a command to be
-   executed when that signal is recieved.  The slot can also contain
-   DEFAULT_SIG, which means do whatever you were going to do before
-   you were so rudely interrupted, or IGNORE_SIG, which says ignore
-   this signal. */
-char *trap_list[BASH_NSIG];
-
-/* A bitmap of signals received for which we have trap handlers. */
-int pending_traps[NSIG];
-
-/* Set to the number of the signal we're running the trap for + 1.
-   Used in execute_cmd.c and builtins/common.c to clean up when
-   parse_and_execute does not return normally after executing the
-   trap command (e.g., when `return' is executed in the trap command). */
-int running_trap;
-
-/* Set to last_command_exit_value before running a trap. */
-int trap_saved_exit_value;
-
-/* The (trapped) signal received while executing in the `wait' builtin */
-int wait_signal_received;
-
-int trapped_signal_received;
-
-#define GETORIGSIG(sig) \
-  do { \
-    original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL); \
-    set_signal_handler (sig, original_signals[sig]); \
-    if (original_signals[sig] == SIG_IGN) \
-      sigmodes[sig] |= SIG_HARD_IGNORE; \
-  } while (0)
-
-#define SETORIGSIG(sig,handler) \
-  do { \
-    original_signals[sig] = handler; \
-    if (original_signals[sig] == SIG_IGN) \
-      sigmodes[sig] |= SIG_HARD_IGNORE; \
-  } while (0)
-
-#define GET_ORIGINAL_SIGNAL(sig) \
-  if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
-    GETORIGSIG(sig)
-
-void
-initialize_traps ()
-{
-  register int i;
-
-  initialize_signames();
-
-  trap_list[EXIT_TRAP] = trap_list[DEBUG_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
-  sigmodes[EXIT_TRAP] = sigmodes[DEBUG_TRAP] = sigmodes[ERROR_TRAP] = sigmodes[RETURN_TRAP] = SIG_INHERITED;
-  original_signals[EXIT_TRAP] = IMPOSSIBLE_TRAP_HANDLER;
-
-  for (i = 1; i < NSIG; i++)
-    {
-      pending_traps[i] = 0;
-      trap_list[i] = (char *)DEFAULT_SIG;
-      sigmodes[i] = SIG_INHERITED;     /* XXX - only set, not used */
-      original_signals[i] = IMPOSSIBLE_TRAP_HANDLER;
-    }
-
-  /* Show which signals are treated specially by the shell. */
-#if defined (SIGCHLD)
-  GETORIGSIG (SIGCHLD);
-  sigmodes[SIGCHLD] |= (SIG_SPECIAL | SIG_NO_TRAP);
-#endif /* SIGCHLD */
-
-  GETORIGSIG (SIGINT);
-  sigmodes[SIGINT] |= SIG_SPECIAL;
-
-#if defined (__BEOS__)
-  /* BeOS sets SIGINT to SIG_IGN! */
-  original_signals[SIGINT] = SIG_DFL;
-  sigmodes[SIGINT] &= ~SIG_HARD_IGNORE;
-#endif
-
-  GETORIGSIG (SIGQUIT);
-  sigmodes[SIGQUIT] |= SIG_SPECIAL;
-
-  if (interactive)
-    {
-      GETORIGSIG (SIGTERM);
-      sigmodes[SIGTERM] |= SIG_SPECIAL;
-    }
-}
-
-#ifdef DEBUG
-/* Return a printable representation of the trap handler for SIG. */
-static char *
-trap_handler_string (sig)
-     int sig;
-{
-  if (trap_list[sig] == (char *)DEFAULT_SIG)
-    return "DEFAULT_SIG";
-  else if (trap_list[sig] == (char *)IGNORE_SIG)
-    return "IGNORE_SIG";
-  else if (trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
-    return "IMPOSSIBLE_TRAP_HANDLER";
-  else if (trap_list[sig])
-    return trap_list[sig];
-  else
-    return "NULL";
-}
-#endif
-
-/* Return the print name of this signal. */
-char *
-signal_name (sig)
-     int sig;
-{
-  char *ret;
-
-  /* on cygwin32, signal_names[sig] could be null */
-  ret = (sig >= BASH_NSIG || sig < 0 || signal_names[sig] == NULL)
-       ? _("invalid signal number")
-       : signal_names[sig];
-
-  return ret;
-}
-
-/* Turn a string into a signal number, or a number into
-   a signal number.  If STRING is "2", "SIGINT", or "INT",
-   then (int)2 is returned.  Return NO_SIG if STRING doesn't
-   contain a valid signal descriptor. */
-int
-decode_signal (string, flags)
-     char *string;
-     int flags;
-{
-  intmax_t sig;
-  char *name;
-
-  if (legal_number (string, &sig))
-    return ((sig >= 0 && sig < NSIG) ? (int)sig : NO_SIG);
-
-  /* A leading `SIG' may be omitted. */
-  for (sig = 0; sig < BASH_NSIG; sig++)
-    {
-      name = signal_names[sig];
-      if (name == 0 || name[0] == '\0')
-       continue;
-
-      /* Check name without the SIG prefix first case sensitivly or
-        insensitively depending on whether flags includes DSIG_NOCASE */
-      if (STREQN (name, "SIG", 3))
-       {
-         name += 3;
-
-         if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
-           return ((int)sig);
-         else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
-           return ((int)sig);
-         /* If we can't use the `SIG' prefix to match, punt on this
-            name now. */
-         else if ((flags & DSIG_SIGPREFIX) == 0)
-           continue;
-       }
-
-      /* Check name with SIG prefix case sensitively or insensitively
-        depending on whether flags includes DSIG_NOCASE */
-      name = signal_names[sig];
-      if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
-       return ((int)sig);
-      else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
-       return ((int)sig);
-    }
-
-  return (NO_SIG);
-}
-
-/* Non-zero when we catch a trapped signal. */
-static int catch_flag;
-
-void
-run_pending_traps ()
-{
-  register int sig;
-  int old_exit_value, *token_state;
-  WORD_LIST *save_subst_varlist;
-#if defined (ARRAY_VARS)
-  ARRAY *ps;
-#endif
-
-  if (catch_flag == 0)         /* simple optimization */
-    return;
-
-  catch_flag = trapped_signal_received = 0;
-
-  /* Preserve $? when running trap. */
-  old_exit_value = last_command_exit_value;
-#if defined (ARRAY_VARS)
-  ps = save_pipestatus_array ();
-#endif
-
-  for (sig = 1; sig < NSIG; sig++)
-    {
-      /* XXX this could be made into a counter by using
-        while (pending_traps[sig]--) instead of the if statement. */
-      if (pending_traps[sig])
-       {
-         sigset_t set, oset;
-
-         BLOCK_SIGNAL (sig, set, oset);
-
-         if (sig == SIGINT)
-           {
-             run_interrupt_trap ();
-             CLRINTERRUPT;
-           }
-#if defined (JOB_CONTROL) && defined (SIGCHLD)
-         else if (sig == SIGCHLD &&
-                  trap_list[SIGCHLD] != (char *)IMPOSSIBLE_TRAP_HANDLER &&
-                  (sigmodes[SIGCHLD] & SIG_INPROGRESS) == 0)
-           {
-             sigmodes[SIGCHLD] |= SIG_INPROGRESS;
-             run_sigchld_trap (pending_traps[sig]);    /* use as counter */
-             sigmodes[SIGCHLD] &= ~SIG_INPROGRESS;
-           }
-         else if (sig == SIGCHLD &&
-                  trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER &&
-                  (sigmodes[SIGCHLD] & SIG_INPROGRESS) != 0)
-           {
-             /* This can happen when run_pending_traps is called while
-                running a SIGCHLD trap handler. */
-             UNBLOCK_SIGNAL (oset);
-             continue;                                 /* XXX */
-           }
-#endif
-         else if (trap_list[sig] == (char *)DEFAULT_SIG ||
-                  trap_list[sig] == (char *)IGNORE_SIG ||
-                  trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
-           {
-             /* This is possible due to a race condition.  Say a bash
-                process has SIGTERM trapped.  A subshell is spawned
-                using { list; } & and the parent does something and kills
-                the subshell with SIGTERM.  It's possible for the subshell
-                to set pending_traps[SIGTERM] to 1 before the code in
-                execute_cmd.c eventually calls restore_original_signals
-                to reset the SIGTERM signal handler in the subshell.  The
-                next time run_pending_traps is called, pending_traps[SIGTERM]
-                will be 1, but the trap handler in trap_list[SIGTERM] will
-                be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
-                Unless we catch this, the subshell will dump core when
-                trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
-                usually 0x0. */
-             internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),
-                               sig, trap_list[sig]);
-             if (trap_list[sig] == (char *)DEFAULT_SIG)
-               {
-                 internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig, signal_name (sig));
-                 kill (getpid (), sig);
-               }
-           }
-         else
-           {
-             token_state = save_token_state ();
-             save_subst_varlist = subst_assign_varlist;
-             subst_assign_varlist = 0;
-
-             evalstring (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE);
-             restore_token_state (token_state);
-             free (token_state);
-
-             subst_assign_varlist = save_subst_varlist;
-           }
-
-         pending_traps[sig] = 0;
-
-         UNBLOCK_SIGNAL (oset);
-       }
-    }
-
-#if defined (ARRAY_VARS)
-  restore_pipestatus_array (ps);
-#endif
-  last_command_exit_value = old_exit_value;
-}
-
-sighandler
-trap_handler (sig)
-     int sig;
-{
-  int oerrno;
-
-  if ((sigmodes[sig] & SIG_TRAPPED) == 0)
-    {
-#if defined (DEBUG)
-      internal_warning ("trap_handler: signal %d: signal not trapped", sig);
-#endif
-      SIGRETURN (0);
-    }
-
-  if ((sig >= NSIG) ||
-      (trap_list[sig] == (char *)DEFAULT_SIG) ||
-      (trap_list[sig] == (char *)IGNORE_SIG))
-    programming_error (_("trap_handler: bad signal %d"), sig);
-  else
-    {
-      oerrno = errno;
-#if defined (MUST_REINSTALL_SIGHANDLERS)
-#  if defined (JOB_CONTROL) && defined (SIGCHLD)
-      if (sig != SIGCHLD)
-#  endif /* JOB_CONTROL && SIGCHLD */
-      set_signal_handler (sig, trap_handler);
-#endif /* MUST_REINSTALL_SIGHANDLERS */
-
-      catch_flag = 1;
-      pending_traps[sig]++;
-
-      trapped_signal_received = sig;
-
-      if (this_shell_builtin && (this_shell_builtin == wait_builtin))
-       {
-         wait_signal_received = sig;
-         if (interrupt_immediately)
-           longjmp (wait_intr_buf, 1);
-       }
-
-#if defined (READLINE)
-      /* Set the event hook so readline will call it after the signal handlers
-        finish executing, so if this interrupted character input we can get
-        quick response. */
-      if (RL_ISSTATE (RL_STATE_SIGHANDLER) && interrupt_immediately == 0)
-        bashline_set_event_hook ();
-#endif
-
-      if (interrupt_immediately)
-       run_pending_traps ();
-
-      errno = oerrno;
-    }
-
-  SIGRETURN (0);
-}
-
-int
-first_pending_trap ()
-{
-  register int i;
-
-  for (i = 1; i < NSIG; i++)
-    if (pending_traps[i])
-      return i;
-  return -1;
-}
-
-int
-any_signals_trapped ()
-{
-  register int i;
-
-  for (i = 1; i < NSIG; i++)
-    if (sigmodes[i] & SIG_TRAPPED)
-      return i;
-  return -1;
-}
-
-void
-check_signals ()
-{
-  CHECK_ALRM;          /* set by the read builtin */
-  QUIT;
-}
-
-/* Convenience functions the rest of the shell can use */
-void
-check_signals_and_traps ()
-{
-  check_signals ();
-
-  run_pending_traps ();
-}
-
-#if defined (JOB_CONTROL) && defined (SIGCHLD)
-
-#ifdef INCLUDE_UNUSED
-/* Make COMMAND_STRING be executed when SIGCHLD is caught. */
-void
-set_sigchld_trap (command_string)
-     char *command_string;
-{
-  set_signal (SIGCHLD, command_string);
-}
-#endif
-
-/* Make COMMAND_STRING be executed when SIGCHLD is caught iff SIGCHLD
-   is not already trapped.  IMPOSSIBLE_TRAP_HANDLER is used as a sentinel
-   to make sure that a SIGCHLD trap handler run via run_sigchld_trap can
-   reset the disposition to the default and not have the original signal
-   accidentally restored, undoing the user's command. */
-void
-maybe_set_sigchld_trap (command_string)
-     char *command_string;
-{
-  if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0 && trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER)
-    set_signal (SIGCHLD, command_string);
-}
-
-/* Temporarily set the SIGCHLD trap string to IMPOSSIBLE_TRAP_HANDLER.  Used
-   as a sentinel in run_sigchld_trap and maybe_set_sigchld_trap to see whether
-   or not a SIGCHLD trap handler reset SIGCHLD disposition to the default. */
-void
-set_impossible_sigchld_trap ()
-{
-  restore_default_signal (SIGCHLD);
-  change_signal (SIGCHLD, (char *)IMPOSSIBLE_TRAP_HANDLER);
-  sigmodes[SIGCHLD] &= ~SIG_TRAPPED;   /* maybe_set_sigchld_trap checks this */
-}
-
-/* Act as if we received SIGCHLD NCHILD times and increment
-   pending_traps[SIGCHLD] by that amount.  This allows us to still run the
-   SIGCHLD trap once for each exited child. */
-void
-queue_sigchld_trap (nchild)
-     int nchild;
-{
-  if (nchild > 0)
-    {
-      catch_flag = 1;
-      pending_traps[SIGCHLD] += nchild;
-      trapped_signal_received = SIGCHLD;
-    }
-}
-#endif /* JOB_CONTROL && SIGCHLD */
-
-void
-set_debug_trap (command)
-     char *command;
-{
-  set_signal (DEBUG_TRAP, command);
-}
-
-void
-set_error_trap (command)
-     char *command;
-{
-  set_signal (ERROR_TRAP, command);
-}
-
-void
-set_return_trap (command)
-     char *command;
-{
-  set_signal (RETURN_TRAP, command);
-}
-
-#ifdef INCLUDE_UNUSED
-void
-set_sigint_trap (command)
-     char *command;
-{
-  set_signal (SIGINT, command);
-}
-#endif
-
-/* Reset the SIGINT handler so that subshells that are doing `shellsy'
-   things, like waiting for command substitution or executing commands
-   in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
-SigHandler *
-set_sigint_handler ()
-{
-  if (sigmodes[SIGINT] & SIG_HARD_IGNORE)
-    return ((SigHandler *)SIG_IGN);
-
-  else if (sigmodes[SIGINT] & SIG_IGNORED)
-    return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN)); /* XXX */
-
-  else if (sigmodes[SIGINT] & SIG_TRAPPED)
-    return ((SigHandler *)set_signal_handler (SIGINT, trap_handler));
-
-  /* The signal is not trapped, so set the handler to the shell's special
-     interrupt handler. */
-  else if (interactive)        /* XXX - was interactive_shell */
-    return (set_signal_handler (SIGINT, sigint_sighandler));
-  else
-    return (set_signal_handler (SIGINT, termsig_sighandler));
-}
-
-/* Return the correct handler for signal SIG according to the values in
-   sigmodes[SIG]. */
-SigHandler *
-trap_to_sighandler (sig)
-     int sig;
-{
-  if (sigmodes[sig] & (SIG_IGNORED|SIG_HARD_IGNORE))
-    return (SIG_IGN);
-  else if (sigmodes[sig] & SIG_TRAPPED)
-    return (trap_handler);
-  else
-    return (SIG_DFL);
-}
-
-/* Set SIG to call STRING as a command. */
-void
-set_signal (sig, string)
-     int sig;
-     char *string;
-{
-  sigset_t set, oset;
-
-  if (SPECIAL_TRAP (sig))
-    {
-      change_signal (sig, savestring (string));
-      if (sig == EXIT_TRAP && interactive == 0)
-       initialize_terminating_signals ();
-      return;
-    }
-
-  /* A signal ignored on entry to the shell cannot be trapped or reset, but
-     no error is reported when attempting to do so.  -- Posix.2 */
-  if (sigmodes[sig] & SIG_HARD_IGNORE)
-    return;
-
-  /* Make sure we have original_signals[sig] if the signal has not yet
-     been trapped. */
-  if ((sigmodes[sig] & SIG_TRAPPED) == 0)
-    {
-      /* If we aren't sure of the original value, check it. */
-      if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
-        GETORIGSIG (sig);
-      if (original_signals[sig] == SIG_IGN)
-       return;
-    }
-
-  /* Only change the system signal handler if SIG_NO_TRAP is not set.
-     The trap command string is changed in either case.  The shell signal
-     handlers for SIGINT and SIGCHLD run the user specified traps in an
-     environment in which it is safe to do so. */
-  if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
-    {
-      BLOCK_SIGNAL (sig, set, oset);
-      change_signal (sig, savestring (string));
-      set_signal_handler (sig, trap_handler);
-      UNBLOCK_SIGNAL (oset);
-    }
-  else
-    change_signal (sig, savestring (string));
-}
-
-static void
-free_trap_command (sig)
-     int sig;
-{
-  if ((sigmodes[sig] & SIG_TRAPPED) && trap_list[sig] &&
-      (trap_list[sig] != (char *)IGNORE_SIG) &&
-      (trap_list[sig] != (char *)DEFAULT_SIG) &&
-      (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER))
-    free (trap_list[sig]);
-}
-
-/* If SIG has a string assigned to it, get rid of it.  Then give it
-   VALUE. */
-static void
-change_signal (sig, value)
-     int sig;
-     char *value;
-{
-  if ((sigmodes[sig] & SIG_INPROGRESS) == 0)
-    free_trap_command (sig);
-  trap_list[sig] = value;
-
-  sigmodes[sig] |= SIG_TRAPPED;
-  if (value == (char *)IGNORE_SIG)
-    sigmodes[sig] |= SIG_IGNORED;
-  else
-    sigmodes[sig] &= ~SIG_IGNORED;
-  if (sigmodes[sig] & SIG_INPROGRESS)
-    sigmodes[sig] |= SIG_CHANGED;
-}
-
-static void
-get_original_signal (sig)
-     int sig;
-{
-  /* If we aren't sure the of the original value, then get it. */
-  if (sig > 0 && sig < NSIG && original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
-    GETORIGSIG (sig);
-}
-
-void
-get_all_original_signals ()
-{
-  register int i;
-
-  for (i = 1; i < NSIG; i++)
-    GET_ORIGINAL_SIGNAL (i);
-}
-
-void
-set_original_signal (sig, handler)
-     int sig;
-     SigHandler *handler;
-{
-  if (sig > 0 && sig < NSIG && original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
-    SETORIGSIG (sig, handler);
-}
-
-/* Restore the default action for SIG; i.e., the action the shell
-   would have taken before you used the trap command.  This is called
-   from trap_builtin (), which takes care to restore the handlers for
-   the signals the shell treats specially. */
-void
-restore_default_signal (sig)
-     int sig;
-{
-  if (SPECIAL_TRAP (sig))
-    {
-      if ((sig != DEBUG_TRAP && sig != ERROR_TRAP && sig != RETURN_TRAP) ||
-         (sigmodes[sig] & SIG_INPROGRESS) == 0)
-       free_trap_command (sig);
-      trap_list[sig] = (char *)NULL;
-      sigmodes[sig] &= ~SIG_TRAPPED;
-      if (sigmodes[sig] & SIG_INPROGRESS)
-       sigmodes[sig] |= SIG_CHANGED;
-      return;
-    }
-
-  GET_ORIGINAL_SIGNAL (sig);
-
-  /* A signal ignored on entry to the shell cannot be trapped or reset, but
-     no error is reported when attempting to do so.  Thanks Posix.2. */
-  if (sigmodes[sig] & SIG_HARD_IGNORE)
-    return;
-
-  /* If we aren't trapping this signal, don't bother doing anything else. */
-  if ((sigmodes[sig] & SIG_TRAPPED) == 0)
-    return;
-
-  /* Only change the signal handler for SIG if it allows it. */
-  if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
-    set_signal_handler (sig, original_signals[sig]);
-
-  /* Change the trap command in either case. */
-  change_signal (sig, (char *)DEFAULT_SIG);
-
-  /* Mark the signal as no longer trapped. */
-  sigmodes[sig] &= ~SIG_TRAPPED;
-}
-
-/* Make this signal be ignored. */
-void
-ignore_signal (sig)
-     int sig;
-{
-  if (SPECIAL_TRAP (sig) && ((sigmodes[sig] & SIG_IGNORED) == 0))
-    {
-      change_signal (sig, (char *)IGNORE_SIG);
-      return;
-    }
-
-  GET_ORIGINAL_SIGNAL (sig);
-
-  /* A signal ignored on entry to the shell cannot be trapped or reset.
-     No error is reported when the user attempts to do so. */
-  if (sigmodes[sig] & SIG_HARD_IGNORE)
-    return;
-
-  /* If already trapped and ignored, no change necessary. */
-  if (sigmodes[sig] & SIG_IGNORED)
-    return;
-
-  /* Only change the signal handler for SIG if it allows it. */
-  if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
-    set_signal_handler (sig, SIG_IGN);
-
-  /* Change the trap command in either case. */
-  change_signal (sig, (char *)IGNORE_SIG);
-}
-
-/* Handle the calling of "trap 0".  The only sticky situation is when
-   the command to be executed includes an "exit".  This is why we have
-   to provide our own place for top_level to jump to. */
-int
-run_exit_trap ()
-{
-  char *trap_command;
-  int code, function_code, retval;
-#if defined (ARRAY_VARS)
-  ARRAY *ps;
-#endif
-
-  trap_saved_exit_value = last_command_exit_value;
-#if defined (ARRAY_VARS)
-  ps = save_pipestatus_array ();
-#endif
-  function_code = 0;
-
-  /* Run the trap only if signal 0 is trapped and not ignored, and we are not
-     currently running in the trap handler (call to exit in the list of
-     commands given to trap 0). */
-  if ((sigmodes[EXIT_TRAP] & SIG_TRAPPED) &&
-      (sigmodes[EXIT_TRAP] & (SIG_IGNORED|SIG_INPROGRESS)) == 0)
-    {
-      trap_command = savestring (trap_list[EXIT_TRAP]);
-      sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
-      sigmodes[EXIT_TRAP] |= SIG_INPROGRESS;
-
-      retval = trap_saved_exit_value;
-      running_trap = 1;
-
-      code = setjmp_nosigs (top_level);
-
-      /* If we're in a function, make sure return longjmps come here, too. */
-      if (return_catch_flag)
-       function_code = setjmp_nosigs (return_catch);
-
-      if (code == 0 && function_code == 0)
-       {
-         reset_parser ();
-         parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE);
-       }
-      else if (code == ERREXIT)
-       retval = last_command_exit_value;
-      else if (code == EXITPROG)
-       retval = last_command_exit_value;
-      else if (function_code != 0)
-        retval = return_catch_value;
-      else
-       retval = trap_saved_exit_value;
-
-      running_trap = 0;
-      return retval;
-    }
-
-#if defined (ARRAY_VARS)
-  restore_pipestatus_array (ps);
-#endif
-  return (trap_saved_exit_value);
-}
-
-void
-run_trap_cleanup (sig)
-     int sig;
-{
-  sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED);
-}
-
-/* Run a trap command for SIG.  SIG is one of the signals the shell treats
-   specially.  Returns the exit status of the executed trap command list. */
-static int
-_run_trap_internal (sig, tag)
-     int sig;
-     char *tag;
-{
-  char *trap_command, *old_trap;
-  int trap_exit_value, *token_state;
-  volatile int save_return_catch_flag, function_code;
-  int flags;
-  procenv_t save_return_catch;
-  WORD_LIST *save_subst_varlist;
-#if defined (ARRAY_VARS)
-  ARRAY *ps;
-#endif
-
-  trap_exit_value = function_code = 0;
-  /* Run the trap only if SIG is trapped and not ignored, and we are not
-     currently executing in the trap handler. */
-  if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) &&
-      (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER) &&
-      ((sigmodes[sig] & SIG_INPROGRESS) == 0))
-    {
-      old_trap = trap_list[sig];
-      sigmodes[sig] |= SIG_INPROGRESS;
-      sigmodes[sig] &= ~SIG_CHANGED;           /* just to be sure */
-      trap_command =  savestring (old_trap);
-
-      running_trap = sig + 1;
-      trap_saved_exit_value = last_command_exit_value;
-#if defined (ARRAY_VARS)
-      ps = save_pipestatus_array ();
-#endif
-
-      token_state = save_token_state ();
-      save_subst_varlist = subst_assign_varlist;
-      subst_assign_varlist = 0;
-
-      /* If we're in a function, make sure return longjmps come here, too. */
-      save_return_catch_flag = return_catch_flag;
-      if (return_catch_flag)
-       {
-         COPY_PROCENV (return_catch, save_return_catch);
-         function_code = setjmp_nosigs (return_catch);
-       }
-
-      flags = SEVAL_NONINT|SEVAL_NOHIST;
-      if (sig != DEBUG_TRAP && sig != RETURN_TRAP && sig != ERROR_TRAP)
-       flags |= SEVAL_RESETLINE;
-      if (function_code == 0)
-       parse_and_execute (trap_command, tag, flags);
-
-      restore_token_state (token_state);
-      free (token_state);
-
-      subst_assign_varlist = save_subst_varlist;
-
-      trap_exit_value = last_command_exit_value;
-      last_command_exit_value = trap_saved_exit_value;
-#if defined (ARRAY_VARS)
-      restore_pipestatus_array (ps);
-#endif
-      running_trap = 0;
-
-      sigmodes[sig] &= ~SIG_INPROGRESS;
-
-      if (sigmodes[sig] & SIG_CHANGED)
-       {
-#if 0
-         /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in
-            the places where they can be changed using unwind-protects.  For
-            example, look at execute_cmd.c:execute_function(). */
-         if (SPECIAL_TRAP (sig) == 0)
-#endif
-           free (old_trap);
-         sigmodes[sig] &= ~SIG_CHANGED;
-       }
-
-      if (save_return_catch_flag)
-       {
-         return_catch_flag = save_return_catch_flag;
-         return_catch_value = trap_exit_value;
-         COPY_PROCENV (save_return_catch, return_catch);
-         if (function_code)
-           longjmp (return_catch, 1);
-       }
-    }
-
-  return trap_exit_value;
-}
-
-int
-run_debug_trap ()
-{
-  int trap_exit_value;
-  pid_t save_pgrp;
-  int save_pipe[2];
-
-  /* XXX - question:  should the DEBUG trap inherit the RETURN trap? */
-  trap_exit_value = 0;
-  if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_IGNORED) == 0) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0))
-    {
-#if defined (JOB_CONTROL)
-      save_pgrp = pipeline_pgrp;
-      pipeline_pgrp = 0;
-      save_pipeline (1);
-#  if defined (PGRP_PIPE)
-      save_pgrp_pipe (save_pipe, 1);
-#  endif
-      stop_making_children ();
-#endif
-
-      trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
-
-#if defined (JOB_CONTROL)
-      pipeline_pgrp = save_pgrp;
-      restore_pipeline (1);
-#  if defined (PGRP_PIPE)
-      close_pgrp_pipe ();
-      restore_pgrp_pipe (save_pipe);
-#  endif
-      if (pipeline_pgrp > 0)
-       give_terminal_to (pipeline_pgrp, 1);
-      notify_and_cleanup ();
-#endif
-      
-#if defined (DEBUGGER)
-      /* If we're in the debugger and the DEBUG trap returns 2 while we're in
-        a function or sourced script, we force a `return'. */
-      if (debugging_mode && trap_exit_value == 2 && return_catch_flag)
-       {
-         return_catch_value = trap_exit_value;
-         longjmp (return_catch, 1);
-       }
-#endif
-    }
-  return trap_exit_value;
-}
-
-void
-run_error_trap ()
-{
-  if ((sigmodes[ERROR_TRAP] & SIG_TRAPPED) && ((sigmodes[ERROR_TRAP] & SIG_IGNORED) == 0) && (sigmodes[ERROR_TRAP] & SIG_INPROGRESS) == 0)
-    _run_trap_internal (ERROR_TRAP, "error trap");
-}
-
-void
-run_return_trap ()
-{
-  int old_exit_value;
-
-#if 0
-  if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && (sigmodes[DEBUG_TRAP] & SIG_INPROGRESS))
-    return;
-#endif
-
-  if ((sigmodes[RETURN_TRAP] & SIG_TRAPPED) && ((sigmodes[RETURN_TRAP] & SIG_IGNORED) == 0) && (sigmodes[RETURN_TRAP] & SIG_INPROGRESS) == 0)
-    {
-      old_exit_value = last_command_exit_value;
-      _run_trap_internal (RETURN_TRAP, "return trap");
-      last_command_exit_value = old_exit_value;
-    }
-}
-
-/* Run a trap set on SIGINT.  This is called from throw_to_top_level (), and
-   declared here to localize the trap functions. */
-void
-run_interrupt_trap ()
-{
-  _run_trap_internal (SIGINT, "interrupt trap");
-}
-
-/* Free all the allocated strings in the list of traps and reset the trap
-   values to the default.  Intended to be called from subshells that want
-   to complete work done by reset_signal_handlers upon execution of a
-   subsequent `trap' command that changes a signal's disposition.  We need
-   to make sure that we duplicate the behavior of
-   reset_or_restore_signal_handlers and not change the disposition of signals
-   that are set to be ignored. */
-void
-free_trap_strings ()
-{
-  register int i;
-
-  for (i = 0; i < BASH_NSIG; i++)
-    {
-      if (trap_list[i] != (char *)IGNORE_SIG)
-       free_trap_string (i);
-    }
-  trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
-}
-
-/* Free a trap command string associated with SIG without changing signal
-   disposition.  Intended to be called from free_trap_strings()  */
-static void
-free_trap_string (sig)
-     int sig;
-{
-  change_signal (sig, (char *)DEFAULT_SIG);
-  sigmodes[sig] &= ~SIG_TRAPPED;
-}
-
-/* Reset the handler for SIG to the original value but leave the trap string
-   in place. */
-static void
-reset_signal (sig)
-     int sig;
-{
-  set_signal_handler (sig, original_signals[sig]);
-  sigmodes[sig] &= ~SIG_TRAPPED;
-}
-
-/* Set the handler signal SIG to the original and free any trap
-   command associated with it. */
-static void
-restore_signal (sig)
-     int sig;
-{
-  set_signal_handler (sig, original_signals[sig]);
-  change_signal (sig, (char *)DEFAULT_SIG);
-  sigmodes[sig] &= ~SIG_TRAPPED;
-}
-
-static void
-reset_or_restore_signal_handlers (reset)
-     sh_resetsig_func_t *reset;
-{
-  register int i;
-
-  /* Take care of the exit trap first */
-  if (sigmodes[EXIT_TRAP] & SIG_TRAPPED)
-    {
-      sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
-      if (reset != reset_signal)
-       {
-         free_trap_command (EXIT_TRAP);
-         trap_list[EXIT_TRAP] = (char *)NULL;
-       }
-    }
-
-  for (i = 1; i < NSIG; i++)
-    {
-      if (sigmodes[i] & SIG_TRAPPED)
-       {
-         if (trap_list[i] == (char *)IGNORE_SIG)
-           set_signal_handler (i, SIG_IGN);
-         else
-           (*reset) (i);
-       }
-      else if (sigmodes[i] & SIG_SPECIAL)
-       (*reset) (i);
-    }
-
-  /* Command substitution and other child processes don't inherit the
-     debug, error, or return traps.  If we're in the debugger, and the
-     `functrace' or `errtrace' options have been set, then let command
-     substitutions inherit them.  Let command substitution inherit the
-     RETURN trap if we're in the debugger and tracing functions. */
-  if (function_trace_mode == 0)
-    {
-      sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
-      sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED;
-    }
-  if (error_trace_mode == 0)
-    sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED;
-}
-
-/* Reset trapped signals to their original values, but don't free the
-   trap strings.  Called by the command substitution code and other places
-   that create a "subshell environment". */
-void
-reset_signal_handlers ()
-{
-  reset_or_restore_signal_handlers (reset_signal);
-}
-
-/* Reset all trapped signals to their original values.  Signals set to be
-   ignored with trap '' SIGNAL should be ignored, so we make sure that they
-   are.  Called by child processes after they are forked. */
-void
-restore_original_signals ()
-{
-  reset_or_restore_signal_handlers (restore_signal);
-}
-
-/* If a trap handler exists for signal SIG, then call it; otherwise just
-   return failure.  Returns 1 if it called the trap handler. */
-int
-maybe_call_trap_handler (sig)
-     int sig;
-{
-  /* Call the trap handler for SIG if the signal is trapped and not ignored. */
-  if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0))
-    {
-      switch (sig)
-       {
-       case SIGINT:
-         run_interrupt_trap ();
-         break;
-       case EXIT_TRAP:
-         run_exit_trap ();
-         break;
-       case DEBUG_TRAP:
-         run_debug_trap ();
-         break;
-       case ERROR_TRAP:
-         run_error_trap ();
-         break;
-       default:
-         trap_handler (sig);
-         break;
-       }
-      return (1);
-    }
-  else
-    return (0);
-}
-
-int
-signal_is_trapped (sig)
-     int sig;
-{
-  return (sigmodes[sig] & SIG_TRAPPED);
-}
-
-int
-signal_is_pending (sig)
-     int sig;
-{
-  return (pending_traps[sig]);
-}
-
-int
-signal_is_special (sig)
-     int sig;
-{
-  return (sigmodes[sig] & SIG_SPECIAL);
-}
-
-int
-signal_is_ignored (sig)
-     int sig;
-{
-  return (sigmodes[sig] & SIG_IGNORED);
-}
-
-int
-signal_is_hard_ignored (sig)
-     int sig;
-{
-  return (sigmodes[sig] & SIG_HARD_IGNORE);
-}
-
-void
-set_signal_ignored (sig)
-     int sig;
-{
-  sigmodes[sig] |= SIG_HARD_IGNORE;
-  original_signals[sig] = SIG_IGN;
-}
-
-int
-signal_in_progress (sig)
-     int sig;
-{
-  return (sigmodes[sig] & SIG_INPROGRESS);
-}
diff --git a/trap.h~ b/trap.h~
deleted file mode 100644 (file)
index 694999d..0000000
--- a/trap.h~
+++ /dev/null
@@ -1,112 +0,0 @@
-/* trap.h -- data structures used in the trap mechanism. */
-
-/* Copyright (C) 1993-2010 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/>.
-*/
-
-#if !defined (_TRAP_H_)
-#define _TRAP_H_
-
-#include "stdc.h"
-
-#if !defined (SIG_DFL)
-#include "bashtypes.h"
-#include <signal.h>
-#endif /* SIG_DFL */
-
-#if !defined (NSIG)
-#define NSIG 64
-#endif /* !NSIG */
-
-#define NO_SIG -1
-#define DEFAULT_SIG    SIG_DFL
-#define IGNORE_SIG     SIG_IGN
-
-/* Special shell trap names. */
-#define DEBUG_TRAP     NSIG
-#define ERROR_TRAP     NSIG+1
-#define RETURN_TRAP    NSIG+2
-#define EXIT_TRAP      0
-
-/* system signals plus special bash traps */
-#define BASH_NSIG      NSIG+3
-
-/* Flags values for decode_signal() */
-#define DSIG_SIGPREFIX 0x01            /* don't alllow `SIG' PREFIX */
-#define DSIG_NOCASE    0x02            /* case-insensitive comparison */
-
-/* A value which can never be the target of a trap handler. */
-#define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps
-
-#define signal_object_p(x,f) (decode_signal (x,f) != NO_SIG)
-
-#define TRAP_STRING(s) \
-  (signal_is_trapped (s) && signal_is_ignored (s) == 0) ? trap_list[s] \
-                                                       : (char *)NULL
-
-extern char *trap_list[];
-
-/* Externally-visible functions declared in trap.c. */
-extern void initialize_traps __P((void));
-
-extern void run_pending_traps __P((void));
-
-extern void queue_sigchld_trap __P((int));
-extern void maybe_set_sigchld_trap __P((char *));
-extern void set_impossible_sigchld_trap __P((void));
-extern void set_sigchld_trap __P((char *));
-
-extern void set_debug_trap __P((char *));
-extern void set_error_trap __P((char *));
-extern void set_return_trap __P((char *));
-
-extern void set_sigint_trap __P((char *));
-extern void set_signal __P((int, char *));
-
-extern void restore_default_signal __P((int));
-extern void ignore_signal __P((int));
-extern int run_exit_trap __P((void));
-extern void run_trap_cleanup __P((int));
-extern int run_debug_trap __P((void));
-extern void run_error_trap __P((void));
-extern void run_return_trap __P((void));
-
-extern void free_trap_strings __P((void));
-extern void reset_signal_handlers __P((void));
-extern void restore_original_signals __P((void));
-
-extern void get_original_signal __P((int));
-extern void get_all_original_signals __P((void));
-
-extern char *signal_name __P((int));
-
-extern int decode_signal __P((char *, int));
-extern void run_interrupt_trap __P((void));
-extern int maybe_call_trap_handler __P((int));
-extern int signal_is_special __P((int));
-extern int signal_is_trapped __P((int));
-extern int signal_is_pending __P((int));
-extern int signal_is_ignored __P((int));
-extern int signal_is_hard_ignored __P((int));
-extern void set_signal_ignored __P((int));
-extern int signal_in_progress __P((int));
-
-extern int first_pending_trap __P((void));
-extern int any_signals_trapped __P((void));
-extern void check_signals_and_traps __P((void));
-
-#endif /* _TRAP_H_ */
diff --git a/unwind_prot.c~ b/unwind_prot.c~
deleted file mode 100644 (file)
index a477c03..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-/* unwind_prot.c - a simple unwind-protect system for internal variables */
-
-/* I can't stand it anymore!  Please can't we just write the
-   whole Unix system in lisp or something? */
-
-/* Copyright (C) 1987-2009 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/>.
-*/
-
-/* **************************************************************** */
-/*                                                                 */
-/*                   Unwind Protection Scheme for Bash             */
-/*                                                                 */
-/* **************************************************************** */
-#include "config.h"
-
-#include "bashtypes.h"
-#include "bashansi.h"
-
-#if defined (HAVE_UNISTD_H)
-#  include <unistd.h>
-#endif
-
-#if STDC_HEADERS
-#  include <stddef.h>
-#endif
-
-#ifndef offsetof
-#  define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-#endif
-
-#include "command.h"
-#include "general.h"
-#include "unwind_prot.h"
-#include "quit.h"
-#include "sig.h"
-#include "error.h"     /* for internal_warning */
-
-/* Structure describing a saved variable and the value to restore it to.  */
-typedef struct {
-  char *variable;
-  int size;
-  char desired_setting[1]; /* actual size is `size' */
-} SAVED_VAR;
-
-/* If HEAD.CLEANUP is null, then ARG.V contains a tag to throw back to.
-   If HEAD.CLEANUP is restore_variable, then SV.V contains the saved
-   variable.  Otherwise, call HEAD.CLEANUP (ARG.V) to clean up.  */
-typedef union uwp {
-  struct uwp_head {
-    union uwp *next;
-    Function *cleanup;
-  } head;
-  struct {
-    struct uwp_head uwp_head;
-    char *v;
-  } arg;
-  struct {
-    struct uwp_head uwp_head;
-    SAVED_VAR v;
-  } sv;
-} UNWIND_ELT;
-
-
-static void without_interrupts __P((VFunction *, char *, char *));
-static void unwind_frame_discard_internal __P((char *, char *));
-static void unwind_frame_run_internal __P((char *, char *));
-static void add_unwind_protect_internal __P((Function *, char *));
-static void remove_unwind_protect_internal __P((char *, char *));
-static void run_unwind_protects_internal __P((char *, char *));
-static void clear_unwind_protects_internal __P((char *, char *));
-static inline void restore_variable __P((SAVED_VAR *));
-static void unwind_protect_mem_internal __P((char *, char *));
-
-static UNWIND_ELT *unwind_protect_list = (UNWIND_ELT *)NULL;
-
-#define uwpalloc(elt)  (elt) = (UNWIND_ELT *)xmalloc (sizeof (UNWIND_ELT))
-#define uwpfree(elt)   free(elt)
-
-/* Run a function without interrupts.  This relies on the fact that the
-   FUNCTION cannot change the value of interrupt_immediately.  (I.e., does
-   not call QUIT (). */
-static void
-without_interrupts (function, arg1, arg2)
-     VFunction *function;
-     char *arg1, *arg2;
-{
-  int old_interrupt_immediately;
-
-  old_interrupt_immediately = interrupt_immediately;
-  interrupt_immediately = 0;
-
-  (*function)(arg1, arg2);
-
-  interrupt_immediately = old_interrupt_immediately;
-}
-
-/* Start the beginning of a region. */
-void
-begin_unwind_frame (tag)
-     char *tag;
-{
-  add_unwind_protect ((Function *)NULL, tag);
-}
-
-/* Discard the unwind protects back to TAG. */
-void
-discard_unwind_frame (tag)
-     char *tag;
-{
-  if (unwind_protect_list)
-    without_interrupts (unwind_frame_discard_internal, tag, (char *)NULL);
-}
-
-/* Run the unwind protects back to TAG. */
-void
-run_unwind_frame (tag)
-     char *tag;
-{
-  if (unwind_protect_list)
-    without_interrupts (unwind_frame_run_internal, tag, (char *)NULL);
-}
-
-/* Add the function CLEANUP with ARG to the list of unwindable things. */
-void
-add_unwind_protect (cleanup, arg)
-     Function *cleanup;
-     char *arg;
-{
-  without_interrupts (add_unwind_protect_internal, (char *)cleanup, arg);
-}
-
-/* Remove the top unwind protect from the list. */
-void
-remove_unwind_protect ()
-{
-  if (unwind_protect_list)
-    without_interrupts
-      (remove_unwind_protect_internal, (char *)NULL, (char *)NULL);
-}
-
-/* Run the list of cleanup functions in unwind_protect_list. */
-void
-run_unwind_protects ()
-{
-  if (unwind_protect_list)
-    without_interrupts
-      (run_unwind_protects_internal, (char *)NULL, (char *)NULL);
-}
-
-/* Erase the unwind-protect list.  If flags is 1, free the elements. */
-void
-clear_unwind_protect_list (flags)
-     int flags;
-{
-  char *flag;
-
-  if (unwind_protect_list)
-    {
-      flag = flags ? "" : (char *)NULL;
-      without_interrupts
-        (clear_unwind_protects_internal, flag, (char *)NULL);
-    }
-}
-
-int
-have_unwind_protects ()
-{
-  return (unwind_protect_list != 0);
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     The Actual Functions                        */
-/*                                                                 */
-/* **************************************************************** */
-
-static void
-add_unwind_protect_internal (cleanup, arg)
-     Function *cleanup;
-     char *arg;
-{
-  UNWIND_ELT *elt;
-
-  uwpalloc (elt);
-  elt->head.next = unwind_protect_list;
-  elt->head.cleanup = cleanup;
-  elt->arg.v = arg;
-  unwind_protect_list = elt;
-}
-
-static void
-remove_unwind_protect_internal (ignore1, ignore2)
-     char *ignore1, *ignore2;
-{
-  UNWIND_ELT *elt;
-
-  elt = unwind_protect_list;
-  if (elt)
-    {
-      unwind_protect_list = unwind_protect_list->head.next;
-      uwpfree (elt);
-    }
-}
-
-static void
-run_unwind_protects_internal (ignore1, ignore2)
-     char *ignore1, *ignore2;
-{
-  unwind_frame_run_internal ((char *) NULL, (char *) NULL);
-}
-
-static void
-clear_unwind_protects_internal (flag, ignore)
-     char *flag, *ignore;
-{
-  if (flag)
-    {
-      while (unwind_protect_list)
-       remove_unwind_protect_internal ((char *)NULL, (char *)NULL);
-    }
-  unwind_protect_list = (UNWIND_ELT *)NULL;
-}
-
-static void
-unwind_frame_discard_internal (tag, ignore)
-     char *tag, *ignore;
-{
-  UNWIND_ELT *elt;
-  int found;
-
-  found = 0;
-  while (elt = unwind_protect_list)
-    {
-      unwind_protect_list = unwind_protect_list->head.next;
-      if (elt->head.cleanup == 0 && (STREQ (elt->arg.v, tag)))
-       {
-         uwpfree (elt);
-         found = 1;
-         break;
-       }
-      else
-       uwpfree (elt);
-    }
-
-  if (found == 0)
-    internal_warning ("unwind_frame_discard: %s: frame not found", tag);
-}
-
-/* Restore the value of a variable, based on the contents of SV.
-   sv->desired_setting is a block of memory SIZE bytes long holding the
-   value itself.  This block of memory is copied back into the variable. */
-static inline void
-restore_variable (sv)
-     SAVED_VAR *sv;
-{
-  FASTCOPY (sv->desired_setting, sv->variable, sv->size);
-}
-
-static void
-unwind_frame_run_internal (tag, ignore)
-     char *tag, *ignore;
-{
-  UNWIND_ELT *elt;
-  int found;
-
-  found = 0;
-  while (elt = unwind_protect_list)
-    {
-      unwind_protect_list = elt->head.next;
-
-      /* If tag, then compare. */
-      if (elt->head.cleanup == 0)
-       {
-         if (tag && STREQ (elt->arg.v, tag))
-           {
-             uwpfree (elt);
-             found = 1;
-             break;
-           }
-       }
-      else
-       {
-         if (elt->head.cleanup == (Function *) restore_variable)
-           restore_variable (&elt->sv.v);
-         else
-           (*(elt->head.cleanup)) (elt->arg.v);
-       }
-
-      uwpfree (elt);
-    }
-  if (tag && found == 0)
-    internal_warning ("unwind_frame_run: %s: frame not found", tag);
-}
-
-static void
-unwind_protect_mem_internal (var, psize)
-     char *var;
-     char *psize;
-{
-  int size, allocated;
-  UNWIND_ELT *elt;
-
-  size = *(int *) psize;
-  allocated = size + offsetof (UNWIND_ELT, sv.v.desired_setting[0]);
-  elt = (UNWIND_ELT *)xmalloc (allocated);
-  elt->head.next = unwind_protect_list;
-  elt->head.cleanup = (Function *) restore_variable;
-  elt->sv.v.variable = var;
-  elt->sv.v.size = size;
-  FASTCOPY (var, elt->sv.v.desired_setting, size);
-  unwind_protect_list = elt;
-}
-
-/* Save the value of a variable so it will be restored when unwind-protects
-   are run.  VAR is a pointer to the variable.  SIZE is the size in
-   bytes of VAR.  */
-void
-unwind_protect_mem (var, size)
-     char *var;
-     int size;
-{
-  without_interrupts (unwind_protect_mem_internal, var, (char *) &size);
-}
-
-#if defined (DEBUG)
-#include <stdio.h>
-
-void
-print_unwind_protect_tags ()
-{
-  UNWIND_ELT *elt;
-
-  elt = unwind_protect_list;
-  while (elt)
-    {
-      unwind_protect_list = unwind_protect_list->head.next;
-      if (elt->head.cleanup == 0)
-        fprintf(stderr, "tag: %s\n", elt->arg.v);
-      elt = unwind_protect_list;
-    }
-}
-#endif
diff --git a/variables.c~ b/variables.c~
deleted file mode 100644 (file)
index 481722e..0000000
+++ /dev/null
@@ -1,5240 +0,0 @@
-/* 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
-
-/* 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.  Intialize 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);
-  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;
-
-  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);
-      v = find_variable_internal (newname, (expanding_redir == 0 && (assigning_in_environment || executing_builtin)));
-    }
-  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;
-    }
-  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;
-
-  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);
-      return (old_var);
-    }
-
-  was_tmpvar = old_var && tempvar_p (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);
-#if 0
-      /* Let noassign variables through with a warning */
-      else if (noassign_p (old_var))
-       builtin_warning (_("%s: local variable shadows special variable"), name);
-      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 - 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);
-
-  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 responsibilty 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);
-       }
-      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))
-                   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;
-
-  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);
-      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);
-
-  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;
-  char *name, *temp, *value;
-  SHELL_VAR *var;
-  const char *string;
-
-  string = word->word;
-
-  offset = assignment (string, 0);
-  name = savestring (string);
-  value = (char *)NULL;
-
-  if (name[offset] == '=')
-    {
-      name[offset] = 0;
-
-      /* ignore the `+' when assigning temporary environment */
-      if (name[offset - 1] == '+')
-       name[offset - 1] = '\0';
-
-      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 (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 */
-
-/* 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