]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
bash-20130125 remove leftover and stray files
authorChet Ramey <chet@caleb.ins.cwru.edu>
Tue, 5 Feb 2013 21:45:12 +0000 (16:45 -0500)
committerChet Ramey <chet@caleb.ins.cwru.edu>
Tue, 5 Feb 2013 21:45:12 +0000 (16:45 -0500)
35 files changed:
CHANGES-4.3~ [deleted file]
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]
NEWS-4.3~ [deleted file]
bashline.c~ [deleted file]
builtins/mapfile.def~ [deleted file]
command.h~ [deleted file]
cross-build/cygwin32.cache.old [deleted file]
doc/FAQ.orig [deleted file]
doc/bash.1~ [deleted file]
doc/bashref.texi~ [deleted file]
doc/version.texi~ [deleted file]
examples/loadables/Makefile.in.save [deleted file]
examples/scripts/adventure.sh.save1 [deleted file]
execute_cmd.c~ [deleted file]
init-termsigs.patch~ [deleted file]
lib/intl/Makefile.in~ [deleted file]
lib/readline/doc/Makefile.old [deleted file]
lib/readline/doc/rltech.texi~ [deleted file]
lib/readline/input.c~ [deleted file]
lib/readline/readline.c~ [deleted file]
lib/readline/readline.h~ [deleted file]
lib/readline/signals.c~ [deleted file]
quit.h~ [deleted file]
redir.c~ [deleted file]
sig.c~ [deleted file]
subst.c.save [deleted file]
subst.c~ [deleted file]
tests/RUN-ONE-TEST~ [deleted file]
tests/misc/regress/log.orig [deleted file]
tests/misc/regress/shx.orig [deleted file]
trap.c~ [deleted file]
variables.c~ [deleted file]

diff --git a/CHANGES-4.3~ b/CHANGES-4.3~
deleted file mode 100644 (file)
index 8b579a4..0000000
+++ /dev/null
@@ -1,498 +0,0 @@
-This document details the changes between this version, bash-4.3-alpha,
-and the previous version, bash-4.2-release.
-
-1.  Changes to Bash
-
-a.  Fixed several bugs concerning incomplete bracket expressions in filename
-    generation (globbing) patterns.
-
-b.  Fixed a bug with single quotes and WORD in ${param op WORD} when running
-    in Posix mode.
-
-c.  Fixed a bug that caused the pattern removal and pattern substitution word
-    expansions and case statement word expansion to not match the empty string.
-
-d.  Fixed a bug that caused the tzset() function to not work after changing
-    the TZ enviroment variable.
-
-e.  Fixed a bug that caused the RHS of an assignment statement to undergo
-    word splitting when it contained an unquoted $@.
-
-f.  Fixed bugs that caused the shell to not react to a SIGINT sent while
-    waiting for a child process to exit.
-
-g.  Bash doesn't try to run things in a signal handler context when it gets a
-    signal (SIGINT/SIGHUP/etc) while reading input using readline but still
-    be responsive to terminating signals.
-
-h.  Fixed a bug that caused bash to go into an infinite loop if a filename
-    to be matched contained an invalid multibyte character.
-
-i.  Fixed a bug that caused PS4 to end up being truncated if it is longer
-    than 128 bytes.
-
-j.  Fixed a bug that caused brace expansion to not skip over double-quoted
-    command substitution.
-
-k.  System-specific updates for: DJGPP, HP/UX, Mac OS X
-
-l.  Fixed a bug in displaying commands that caused redirections to be associated
-    with the wrong part of the command.
-
-m.  Fixed the coproc cleanup to unset the appropriate shell variables when a
-    coproc terminates.
-
-n.  Fixed a bug that caused `fc' to dump core due to incorrect calculation of
-    the last history entry.
-
-o.  Added workarounds for FreeBSD's implementation of faccessat/eaccess and
-    `test -x'.
-
-p.  Fixed a bug that caused the shell to not match patterns containing
-    control-A.
-
-q.  Fixed a bug that could result in doubled error messages when the `printf'
-    builtin got a write error.
-
-r.  Fixed a bug that caused the shell to not correctly expand words containing
-    multiple consecutive quoted empty strings (""""""aa).
-
-s.  Fixed a bug that caused the shell to not correctly parse multi-line
-    process substitutions containing comments and quoted strings.
-
-t.  Fixed a problem with the bash malloc's internal idea of the top of the
-    memory heap that resulted in incorrect decisions to try to reduce the
-    break and give memory back to the kernel.
-
-u.  There are changes to the expansions peformed on compound array assignments,
-    in an effort to make foo=( [ind1]=bar [ind2]=baz ) identical to
-    foo[ind1]=bar foo[ind2]=baz.
-
-v.  Bash now reports an error if `read -a name' is used when `name' is an
-    existing associative array.
-
-w.  Fixed a bug that allowed an attempted assignment to a readonly variable
-    in an arithmetic expression to not return failure.
-
-x.  Fixed several bugs that caused completion functions to be invoked even when
-    the cursor was before the first word in the command.
-
-y.  Fixed a bug that caused parsing a command substitution to overwrite the
-    parsing state associated with the complete input line.
-
-z.  Fixed several bugs with the built-in snprintf replacement and field widths
-    and floating point.
-
-aa. Fixed a bug that caused incorrect offset calculations and input buffer
-    corruption when reading files longer than 2^31 bytes.
-
-bb. Fixed several bugs where bash performed arithmetic evaluation in contexts
-    where evaluation is suppressed.
-
-cc. Fixed a bug that caused bash to close FIFOs used for process substitution
-    too early when a shell function was executing, but protect against using
-    all file descriptors when the shell functions are invoked inside loops.
-
-dd. Added checks for printable (and non-printable) multibyte characters for
-    use in error messages.
-
-ee. Fixed a bug that caused ^O (operate-and-get-next) to not work correctly
-    at the end of the history list.
-
-ff. Fixed a bug that caused command-oriented history to incorrectly combine
-    here documents into one line.
-
-gg. Fixed a bug that caused importing SHELLOPTS from the environment into a
-    Posix-mode shell to print an error message and refuse to parse it.
-
-hh. Fixed a bug that caused the shell to delete an extra history entry when
-    using `history -s'.
-
-ii. Fixed a bug that caused floating-point exceptions and overflow errors
-    for the / and % arithmetic operators when using INTMAX_MIN and -1.
-
-jj. Fixed a bug that caused parsing errors when reading an arithmetic for
-    loop inside a command substitution.
-
-kk. Fixed a bug that caused a readonly function to be unset when unset was
-    called without the -f or -v option.
-
-ll. Fixed several bugs in the code that quotes characters special to regular
-    expressions when used in a quoted string on the RHS of the =~ operator
-    to the [[ command.
-
-mm. Fixed a bug that caused redirections to fail because the file descriptor
-    limit was set to a value less than 10.
-
-nn. Fixed a bug that caused the `read' builtin to execute code in a signal
-    handler context if read timed out.
-
-oo. Fixed a bug that caused extended globbing patterns to not match files
-    beginning with `.' correctly when a `.' was explicitly supplied in the
-    pattern.
-
-pp. Fixed a bug that caused key sequences longer than two characters to not
-    work when used with `bind -x'.
-
-qq. Fixed a bug that resulted in redefined functions having the wrong source
-    file names in BASH_SOURCE.
-
-rr. Fixed a bug that caused the read builtin to assign null strings to variables
-    when using `read -N', which caused core dumps when referenced
-
-ss. Fixed a bug that caused `bash -m script' to not enable job control while
-    running the script.
-
-tt. Fixed a bug that caused `printf -v var' to dump core when used with the
-    %b format code.
-
-uu. Fixed a bug that caused the shell to exit with the wrong status if -e was
-    active and the shell exited on a substitution error.
-
-vv. Fixed a bug that caused the shell to seg fault if an array variable with
-    the same name as an existing associative array was implicitly created by
-    an assignment (declare a[n]=b).
-
-ww. Fixed a bug that caused a redirection to misbehave if the number specified
-    for a file descriptor overflows an intmax_t.
-
-xx. Fixed several bugs with the handling of valid and invalid unicode character
-    values when used with the \u and \U escape sequences to printf and $'...'.
-
-yy. Fixed a bug that caused tildes to not be escaped in expanded filenames,
-    making them subject to later expansion.
-
-zz. When using the pattern substitution word expansion, bash now runs the
-    replacement string through quote removal, since it allows quotes in that
-    string to act as escape characters.  This is not backwards compatible, so
-    it can be disabled by setting the bash compatibility mode to 4.2.
-
-aaa. Fixed the rest of the cases where the shell runs non-allowed code in a
-     signal handler context.
-
-bbb. Fixed a bug that caused spurious DEL characters (\177) to appear in
-     double-quoted expansion where the RHS is evaluated to the empty string.
-
-ccc. Fixed a bug that caused the use of the shell's internal random number
-     generator for temporary file names to perturb the random number
-     sequence.
-
-ddd. Fixed several bugs that caused `declare -g' to not set the right global
-     variables or to misbehave when declaring global indexed arrays.
-
-eee. Fixed a logic bug that caused extended globbing in a multibyte locale to
-     cause failures when using the pattern substititution word expansions.
-
-fff. Fixed a bug that caused the `lastpipe' option to corrupt the file
-     descriptor used to read the script.
-
-ggg. Fixed a bug that causes the shell to delete DEL characters in the
-     expanded value of variables used in the same quoted string as variables
-     that expand to nothing.
-
-hhh. Fixed a bug that caused the shell to assign the wrong value from an
-     assignment like (( x=7 )) when `x' was an existing array variable.
-
-iii. Fixed a bug that caused the shell to misbehave when generating sequences
-     and the boundary values overflow an intmax_t.
-
-jjj. Fixed a bug caused expansion errors if an expansion of "$@" appeared
-     next to another expansion (e.g.. "${@}${x}").
-
-kkk. Fixed a potential buffer overflow bug when performing /dev/fd expansion.
-
-lll. Fixed a bug that resulted in an extra semicolon being added to compound
-     assignments when they were added to the history list.
-
-mmm. Fixed a bug that caused mapfile to read one extra line from the input.
-
-nnn. Fixed a bug that caused the mail checking code to use uninitialized
-     values.
-
-ooo. Fixed a bug that prevented history timestamps from being saved if the
-     history comment character is unset.
-
-ppp. Fixed a bug that caused the case-modifying expansions to not work with
-     multibyte characters.
-
-qqq. Fixed a bug that caused the edit-and-execute bindable readline command
-     to see the wrong data if invoked in the middle of a multi-line quoted
-     string.
-
-rrr. Fixed a bug that resulted in the shell returning the wrong exit status
-     for a background command on systems that recycle PIDs very quickly.
-
-sss. Fixed a bug that caused asynchronous group commands to not run any EXIT
-     trap defined in the body of the command.
-
-ttt. Fixed a bug that caused `eval "... ; return"' to not clean up properly.
-
-uuu. Fixed a bug that caused the shell to dump core if `read' reads an escaped
-     IFS whitespace character.
-
-vvv. Fixed a bug that caused BASH_COMMAND to be set to an incorrect value when
-     executing a (...) subshell.
-
-www. Fixed a pointer aliasing bug with the token string in arithmetic
-     evaluation.
-
-xxx. Fixed a bug with parsing multi-line command substitutions when reading
-     the `do' keyword followed by whitespace.
-
-yyy. Fixed a bug that caused the shell to seg fault if the time given to the
-     printf %(...)T format overflowed the value accepted by localtime(3).
-
-zzz. Fixed a problem with displaying help topics in two columns when the
-     translated text contained multibyte characters.
-
-aaaa. Fixed a bug with the extended globbing pattern matcher where a `*' was
-      followed by a negated extended glob pattern.
-
-bbbb. Fixed a race condition with short-lived coproc creation and reaping that
-      caused the child process to be reaped before the various coproc shell
-      variables were initialized.
-
-cccc. Fixed a bug where turning off `errexit' in command substitution subshells
-      was not reflected in $SHELLOPTS.
-
-dddd. Partially fixed an inconsistency in how the shell treated shell
-      functions run from an EXIT trap.
-
-eeee. Fixed a bug in how the shell invalidated FIFOs used for process
-      substitution when executing a pipeline (once rather than in every child).
-
-ffff. Fixed a bug that occurred when expanding a special variable ($@, $*)
-      within double quotes and the expansion resulted in an empty string.
-
-gggg. Fixed bugs with executing a SIGCHLD trap handler to make sure that it's
-      executed once per exited child.
-
-hhhh. Fixed a bug that caused `declare' and `test' to find variables that
-      had been given attributes but not assigned values.  Such variables are
-      not set.
-
-iiii. Fixed a bug that caused commands in process substitutions to not look in
-      the local temporary environment when performing word expansions.
-
-jjjj. Fixed several problems with globstar expansions (**/**) returning null
-      filenames and multiple instances of the same pathname.
-
-kkkk. Fixed an oversight that did not allow the exit status of `coproc' to
-      be inverted using `!'.
-
-llll. Fixed a bug that caused the -e option to be re-enabled using `set -e'
-      even when executing in a context where -e is ignored.
-
-mmmm. Fixed a (mostly theoretical) bug with input lines longer than SIZE_MAX.
-
-2.  Changes to Readline
-
-a.  Fixed a bug that did not allow the `dd', `cc', or `yy' vi editing mode
-    commands to work on the entire line.
-
-b.  Fixed a bug that caused redisplay problems with prompts longer than 128
-    characters and history searches.
-
-c.  Fixed a bug that caused readline to try and run code to modify its idea
-    of the screen size in a signal handler context upon receiving a SIGWINCH.
-
-d.  Fixed a bug that caused the `meta' key to be enabled beyond the duration
-    of an individual call top readline().
-    
-e.  Added a workaround for a wcwidth bug in Mac OS X that caused readline's
-    redisplay to mishandle zero-width combining characters.
-
-f.  Fixed a bug that caused readline to `forget' part of a key sequence when
-    a multiple-key sequence caused it to break out of an incremental search.
-
-g.  Fixed bugs that caused readline to execute code in a signal handler
-    context if interrupted while reading from the file system during completion.
-
-h.  Fixed a bug that caused readline to `forget' part of a key sequence when
-    reading an unbound multi-character key sequence.
-
-i.  Fixed a bug that caused Readline's signal handlers to be installed beyond
-    the bounds of a single call to readline().
-
-j.  Fixed a bug that caused the `.' command to not redo the most recent `R'
-    command in vi mode.
-
-k.  Fixed a bug that caused ignoring case in completion matches to result in
-    readline using the wrong match.
-
-l.  Paren matching now works in vi insert mode.
-
-m.  Fix menu-completion to make show-all-if-ambiguous and menu-complete-display-prefix
-    work together.
-
-n.  Fixed a bug that didn't allow the `cc', `dd', or `yy' commands to be redone
-    in vi editing mode.
-
-o.  Fixed a bug that caused the filename comparison code to not compare
-    multibyte characters correctly when using case-sensitive or case-mapping
-    comparisons.
-
-p.  Fixed the input reading loop to call the input hook function only when there
-    is no terminal input available.
-
-q.  Fixed a bug that caused binding a macro to a multi-character key sequence
-    where the sequence and macro value share a common prefix to not perform
-    the macro replacement.
-
-r.  Fixed several redisplay errors with multibyte characters and prompts
-    containing invisible characters when using horizontal scrolling.
-
-3.  New Features in Bash
-
-a.  The `helptopic' completion action now maps to all the help topics, not just
-    the shell builtins.
-
-b.  The `help' builtin no longer does prefix substring matching, so `help read'
-    does not match `readonly'.
-
-c.  The shell can be compiled to not display a message about processes that
-    terminate due to SIGTERM.
-
-d.  Non-interactive shells now react to the setting of checkwinsize and set
-    LINES and COLUMNS after a foreground job exits.
-
-e.  There is a new shell option, `globasciiranges', which, when set to on,
-    forces globbing range comparisons to use character ordering as if they
-    were run in the C locale.
-
-f.  There is a new shell option, `direxpand', which makes filename completion
-    expand variables in directory names in the way bash-4.1 did.
-
-g.  In Posix mode, the `command' builtin does not change whether or not a
-    builtin it shadows is treated as an assignment builtin.
-
-h.  The `return' and `exit' builtins accept negative exit status arguments.
-
-i.  The word completion code checks whether or not a filename containing a
-    shell variable expands to a directory name and appends `/' to the word
-    as appropriate.  The same code expands shell variables in command names
-    when performing command completion.
-
-j.  In Posix mode, it is now an error to attempt to define a shell function
-    with the same name as a Posix special builtin.
-
-k.  When compiled for strict Posix conformance, history expansion is disabled
-    by default.
-
-l.  The history expansion character (!) does not cause history expansion when
-    followed by the closing quote in a double-quoted string.
-
-m.  `complete' and its siblings compgen/compopt now takes a new `-o noquote'
-    option to inhibit quoting of the completions.
-
-n.  Setting HISTSIZE to a value less than zero causes the history list to be
-    unlimited (setting it 0 zero disables the history list).
-
-o.  Setting HISTFILESIZE to a value less than zero causes the history file size
-    to be unlimited (setting it to 0 causes the history file to be truncated
-    to zero size).
-
-p.  The `read' builtin now skips NUL bytes in the input.
-
-q.  There is a new `bind -X' option to print all key sequences bound to Unix
-    commands.
-
-r.  When in Posix mode, `read' is interruptible by a trapped signal.  After
-    running the trap handler, read returns 128+signal and throws away any
-    partially-read input.
-
-s.  The command completion code skips whitespace and assignment statements
-    before looking for the command name word to be completed.
-
-t.  The build process has a new mechanism for constructing separate help files
-    that better reflects the current set of compilation options.
-
-u.  The -nt and -ot options to test now work with files with nanosecond
-    timestamp resolution.
-
-v.  The shell saves the command history in any shell for which history is
-    enabled and HISTFILE is set, not just interactive shells.
-
-w.  The shell has `nameref' variables and new -n(/+n) options to declare and
-    unset to use them, and a `test -R' option to test for them.
-
-x.  The shell now allows assigning, referencing, and unsetting elements of
-    indexed arrays using negative subscripts (a[-1]=2, echo ${a[-1]}) which
-    count back from the last element of the array.
-
-y.  The {x}<word redirection feature now allows words like {array[ind]} and
-    can use variables with special meanings to the shell (e.g., BASH_XTRACEFD).
-
-z.  There is a new CHILD_MAX special shell variable; its value controls the
-    number of exited child statues the shell remembers.
-
-aa. There is a new configuration option (--enable-direxpand-default) that
-    causes the `direxpand' shell option to be enabled by default.
-
-bb. Bash does not do anything special to ensure that the file descriptor
-    assigned to X in {x}<foo remains open after the block containing it
-    completes.
-
-cc. The `wait' builtin has a new `-n' option to wait for the next child to
-    change status.
-
-dd. The `printf' %(...)T format specifier now uses the current time if no
-    argument is supplied.
-
-ee. There is a new variable, BASH_COMPAT, that controls the current shell
-    compatibility level.
-
-4.  New Features in Readline
-
-a.  Readline is now more responsive to SIGHUP and other fatal signals when
-    reading input from the terminal or performing word completion but no
-    longer attempts to run any not-allowable functions from a signal handler
-    context.
-
-b.  There are new bindable commands to search the history for the string of
-    characters between the beginning of the line and the point
-    (history-substring-search-forward, history-substring-search-backward)
-
-c.  Readline allows quoted strings as the values of variables when setting
-    them with `set'.  As a side effect, trailing spaces and tabs are ignored
-    when setting a string variable's value.
-
-d.  The history library creates a backup of the history file when writing it
-    and restores the backup on a write error.
-
-e.  New application-settable variable: rl_filename_stat_hook: a function called
-    with a filename before using it in a call to stat(2).  Bash uses it to
-    expand shell variables so things like $HOME/Downloads have a slash
-    appended.
-
-f.  New bindable function `print-last-kbd-macro', prints the most-recently-
-    defined keyboard macro in a reusable format.
-
-g.  New user-settable variable `colored-stats', enables use of colored text
-    to denote file types when displaying possible completions (colored analog
-    of visible-stats).
-
-h.  New user-settable variable `keyseq-timout', acts as an inter-character
-    timeout when reading input or incremental search strings.
-
-i.  New application-callable function: rl_clear_history. Clears the history list
-    and frees all readline-associated private data.
-
-j.  New user-settable variable, show-mode-in-prompt, adds a characters to the
-    beginning of the prompt indicating the current editing mode.
-
-k.  New application-settable variable: rl_input_available_hook; function to be
-    called when readline detects there is data available on its input file
-    descriptor.
-
-l.  Readline calls an application-set event hook (rl_event_hook) after it gets
-    a signal while reading input (read returns -1/EINTR but readline does not
-    handle the signal immediately) to allow the application to handle or
-    otherwise note it.
-
-m.  If the user-settable variable `history-size' is set to a value less than
-    0, the history list size is unlimited.
-
-n.  New application-settable variable: rl_signal_event_hook; function that is
-    called when readline is reading terminal input and read(2) is interrupted
-    by a signal.  Currently not called for SIGHUP or SIGTERM.
diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~
deleted file mode 100644 (file)
index 7b2010f..0000000
+++ /dev/null
@@ -1,4433 +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
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/NEWS-4.3~ b/NEWS-4.3~
deleted file mode 100644 (file)
index 325bb82..0000000
--- a/NEWS-4.3~
+++ /dev/null
@@ -1,154 +0,0 @@
-This is a terse description of the new features added to bash-4.3 since
-the release of bash-4.2.  As always, the manual page (doc/bash.1) is
-the place to look for complete descriptions.
-
-1.  New Features in Bash
-
-a.  The `helptopic' completion action now maps to all the help topics, not just
-    the shell builtins.
-
-b.  The `help' builtin no longer does prefix substring matching, so `help read'
-    does not match `readonly'.
-
-c.  The shell can be compiled to not display a message about processes that
-    terminate due to SIGTERM.
-
-d.  Non-interactive shells now react to the setting of checkwinsize and set
-    LINES and COLUMNS after a foreground job exits.
-
-e.  There is a new shell option, `globasciiranges', which, when set to on,
-    forces globbing range comparisons to use character ordering as if they
-    were run in the C locale.
-
-f.  There is a new shell option, `direxpand', which makes filename completion
-    expand variables in directory names in the way bash-4.1 did.
-
-g.  In Posix mode, the `command' builtin does not change whether or not a
-    builtin it shadows is treated as an assignment builtin.
-
-h.  The `return' and `exit' builtins accept negative exit status arguments.
-
-i.  The word completion code checks whether or not a filename containing a
-    shell variable expands to a directory name and appends `/' to the word
-    as appropriate.  The same code expands shell variables in command names
-    when performing command completion.
-
-j.  In Posix mode, it is now an error to attempt to define a shell function
-    with the same name as a Posix special builtin.
-
-k.  When compiled for strict Posix conformance, history expansion is disabled
-    by default.
-
-l.  The history expansion character (!) does not cause history expansion when
-    followed by the closing quote in a double-quoted string.
-
-m.  `complete' and its siblings compgen/compopt now takes a new `-o noquote'
-    option to inhibit quoting of the completions.
-
-n.  Setting HISTSIZE to a value less than zero causes the history list to be
-    unlimited (setting it 0 zero disables the history list).
-
-o.  Setting HISTFILESIZE to a value less than zero causes the history file size
-    to be unlimited (setting it to 0 causes the history file to be truncated
-    to zero size).
-
-p.  The `read' builtin now skips NUL bytes in the input.
-
-q.  There is a new `bind -X' option to print all key sequences bound to Unix
-    commands.
-
-r.  When in Posix mode, `read' is interruptible by a trapped signal.  After
-    running the trap handler, read returns 128+signal and throws away any
-    partially-read input.
-
-s.  The command completion code skips whitespace and assignment statements
-    before looking for the command name word to be completed.
-
-t.  The build process has a new mechanism for constructing separate help files
-    that better reflects the current set of compilation options.
-
-u.  The -nt and -ot options to test now work with files with nanosecond
-    timestamp resolution.
-
-v.  The shell saves the command history in any shell for which history is
-    enabled and HISTFILE is set, not just interactive shells.
-
-w.  The shell has `nameref' variables and new -n(/+n) options to declare and
-    unset to use them, and a `test -R' option to test for them.
-
-x.  The shell now allows assigning, referencing, and unsetting elements of
-    indexed arrays using negative subscripts (a[-1]=2, echo ${a[-1]}) which
-    count back from the last element of the array.
-
-y.  The {x}<word redirection feature now allows words like {array[ind]} and
-    can use variables with special meanings to the shell (e.g., BASH_XTRACEFD).
-
-z.  There is a new CHILD_MAX special shell variable; its value controls the
-    number of exited child statues the shell remembers.
-
-aa. There is a new configuration option (--enable-direxpand-default) that
-    causes the `direxpand' shell option to be enabled by default.
-
-bb. Bash does not do anything special to ensure that the file descriptor
-    assigned to X in {x}<foo remains open after the block containing it
-    completes.
-
-cc. The `wait' builtin has a new `-n' option to wait for the next child to
-    change status.
-
-dd. The `printf' %(...)T format specifier now uses the current time if no
-    argument is supplied.
-
-ee. There is a new variable, BASH_COMPAT, that controls the current shell
-    compatibility level.
-
-2.  New Features in Readline
-
-a.  Readline is now more responsive to SIGHUP and other fatal signals when
-    reading input from the terminal or performing word completion but no
-    longer attempts to run any not-allowable functions from a signal handler
-    context.
-
-b.  There are new bindable commands to search the history for the string of
-    characters between the beginning of the line and the point
-    (history-substring-search-forward, history-substring-search-backward)
-
-c.  Readline allows quoted strings as the values of variables when setting
-    them with `set'.  As a side effect, trailing spaces and tabs are ignored
-    when setting a string variable's value.
-
-d.  The history library creates a backup of the history file when writing it
-    and restores the backup on a write error.
-
-e.  New application-settable variable: rl_filename_stat_hook: a function called
-    with a filename before using it in a call to stat(2).  Bash uses it to
-    expand shell variables so things like $HOME/Downloads have a slash
-    appended.
-
-f.  New bindable function `print-last-kbd-macro', prints the most-recently-
-    defined keyboard macro in a reusable format.
-
-g.  New user-settable variable `colored-stats', enables use of colored text
-    to denote file types when displaying possible completions (colored analog
-    of visible-stats).
-
-h.  New user-settable variable `keyseq-timout', acts as an inter-character
-    timeout when reading input or incremental search strings.
-
-i.  New application-callable function: rl_clear_history. Clears the history list
-    and frees all readline-associated private data.
-
-j.  New user-settable variable, show-mode-in-prompt, adds a characters to the
-    beginning of the prompt indicating the current editing mode.
-
-k.  New application-settable variable: rl_input_available_hook; function to be
-    called when readline detects there is data available on its input file
-    descriptor.
-
-l.  Readline calls an application-set event hook (rl_event_hook) after it gets
-    a signal while reading input (read returns -1/EINTR but readline does not
-    handle the signal immediately) to allow the application to handle or
-    otherwise note it.
-
-m.  If the user-settable variable `history-size' is set to a value less than
-    0, the history list size is unlimited.
diff --git a/bashline.c~ b/bashline.c~
deleted file mode 100644 (file)
index 2bc5a29..0000000
+++ /dev/null
@@ -1,4153 +0,0 @@
-/* bashline.c -- Bash's interface to the readline library. */
-
-/* Copyright (C) 1987-2013 Free Software Foundation, Inc.
-
-   This file is part of GNU Bash, the Bourne Again SHell.
-
-   Bash is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   Bash is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "config.h"
-
-#if defined (READLINE)
-
-#include "bashtypes.h"
-#include "posixstat.h"
-
-#if defined (HAVE_UNISTD_H)
-#  include <unistd.h>
-#endif
-
-#if defined (HAVE_GRP_H)
-#  include <grp.h>
-#endif
-
-#if defined (HAVE_NETDB_H)
-#  include <netdb.h>
-#endif
-
-#include <stdio.h>
-#include "chartypes.h"
-#include "bashansi.h"
-#include "bashintl.h"
-
-#include "shell.h"
-#include "input.h"
-#include "builtins.h"
-#include "bashhist.h"
-#include "bashline.h"
-#include "execute_cmd.h"
-#include "findcmd.h"
-#include "pathexp.h"
-#include "shmbutil.h"
-
-#include "builtins/common.h"
-
-#include <readline/rlconf.h>
-#include <readline/readline.h>
-#include <readline/history.h>
-
-#include <glob/glob.h>
-
-#if defined (ALIAS)
-#  include "alias.h"
-#endif
-
-#if defined (PROGRAMMABLE_COMPLETION)
-#  include "pcomplete.h"
-#endif
-
-/* These should agree with the defines for emacs_mode and vi_mode in
-   rldefs.h, even though that's not a public readline header file. */
-#ifndef EMACS_EDITING_MODE
-#  define NO_EDITING_MODE      -1
-#  define EMACS_EDITING_MODE    1
-#  define VI_EDITING_MODE       0
-#endif
-
-#define RL_BOOLEAN_VARIABLE_VALUE(s)   ((s)[0] == 'o' && (s)[1] == 'n' && (s)[2] == '\0')
-
-#if defined (BRACE_COMPLETION)
-extern int bash_brace_completion __P((int, int));
-#endif /* BRACE_COMPLETION */
-
-/* To avoid including curses.h/term.h/termcap.h and that whole mess. */
-#ifdef _MINIX
-extern int tputs __P((const char *string, int nlines, void (*outx)(int)));
-#else
-extern int tputs __P((const char *string, int nlines, int (*outx)(int)));
-#endif
-
-/* Forward declarations */
-
-/* Functions bound to keys in Readline for Bash users. */
-static int shell_expand_line __P((int, int));
-static int display_shell_version __P((int, int));
-static int operate_and_get_next __P((int, int));
-
-static int bash_ignore_filenames __P((char **));
-static int bash_ignore_everything __P((char **));
-
-#if defined (BANG_HISTORY)
-static char *history_expand_line_internal __P((char *));
-static int history_expand_line __P((int, int));
-static int tcsh_magic_space __P((int, int));
-#endif /* BANG_HISTORY */
-#ifdef ALIAS
-static int alias_expand_line __P((int, int));
-#endif
-#if defined (BANG_HISTORY) && defined (ALIAS)
-static int history_and_alias_expand_line __P((int, int));
-#endif
-
-static int bash_forward_shellword __P((int, int));
-static int bash_backward_shellword __P((int, int));
-static int bash_kill_shellword __P((int, int));
-static int bash_backward_kill_shellword __P((int, int));
-
-/* Helper functions for Readline. */
-static char *restore_tilde __P((char *, char *));
-
-static char *bash_filename_rewrite_hook __P((char *, int));
-
-static void bash_directory_expansion __P((char **));
-static int bash_filename_stat_hook __P((char **));
-static int bash_command_name_stat_hook __P((char **));
-static int bash_directory_completion_hook __P((char **));
-static int filename_completion_ignore __P((char **));
-static int bash_push_line __P((void));
-
-static int executable_completion __P((const char *, int));
-
-static rl_icppfunc_t *save_directory_hook __P((void));
-static void restore_directory_hook __P((rl_icppfunc_t));
-
-static void cleanup_expansion_error __P((void));
-static void maybe_make_readline_line __P((char *));
-static void set_up_new_line __P((char *));
-
-static int check_redir __P((int));
-static char **attempt_shell_completion __P((const char *, int, int));
-static char *variable_completion_function __P((const char *, int));
-static char *hostname_completion_function __P((const char *, int));
-static char *command_subst_completion_function __P((const char *, int));
-
-static void build_history_completion_array __P((void));
-static char *history_completion_generator __P((const char *, int));
-static int dynamic_complete_history __P((int, int));
-static int bash_dabbrev_expand __P((int, int));
-
-static void initialize_hostname_list __P((void));
-static void add_host_name __P((char *));
-static void snarf_hosts_from_file __P((char *));
-static char **hostnames_matching __P((char *));
-
-static void _ignore_completion_names __P((char **, sh_ignore_func_t *));
-static int name_is_acceptable __P((const char *));
-static int test_for_directory __P((const char *));
-static int return_zero __P((const char *));
-
-static char *bash_dequote_filename __P((char *, int));
-static char *quote_word_break_chars __P((char *));
-static void set_filename_bstab __P((const char *));
-static char *bash_quote_filename __P((char *, int, char *));
-
-#ifdef _MINIX
-static void putx __P((int));
-#else
-static int putx __P((int));
-#endif
-static int bash_execute_unix_command __P((int, int));
-static void init_unix_command_map __P((void));
-static int isolate_sequence __P((char *, int, int, int *));
-
-static int set_saved_history __P((void));
-
-#if defined (ALIAS)
-static int posix_edit_macros __P((int, int));
-#endif
-
-static int bash_event_hook __P((void));
-
-#if defined (PROGRAMMABLE_COMPLETION)
-static int find_cmd_start __P((int));
-static int find_cmd_end __P((int));
-static char *find_cmd_name __P((int, int *, int *));
-static char *prog_complete_return __P((const char *, int));
-
-static char **prog_complete_matches;
-#endif
-
-/* Variables used here but defined in other files. */
-#if defined (BANG_HISTORY)
-extern int hist_verify;
-#endif
-
-extern int current_command_line_count, saved_command_line_count;
-extern int last_command_exit_value;
-extern int array_needs_making;
-extern int posixly_correct, no_symbolic_links;
-extern char *current_prompt_string, *ps1_prompt;
-extern STRING_INT_ALIST word_token_alist[];
-extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
-
-/* SPECIFIC_COMPLETION_FUNCTIONS specifies that we have individual
-   completion functions which indicate what type of completion should be
-   done (at or before point) that can be bound to key sequences with
-   the readline library. */
-#define SPECIFIC_COMPLETION_FUNCTIONS
-
-#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
-static int bash_specific_completion __P((int, rl_compentry_func_t *));
-
-static int bash_complete_filename_internal __P((int));
-static int bash_complete_username_internal __P((int));
-static int bash_complete_hostname_internal __P((int));
-static int bash_complete_variable_internal __P((int));
-static int bash_complete_command_internal __P((int));
-
-static int bash_complete_filename __P((int, int));
-static int bash_possible_filename_completions __P((int, int));
-static int bash_complete_username __P((int, int));
-static int bash_possible_username_completions __P((int, int));
-static int bash_complete_hostname __P((int, int));
-static int bash_possible_hostname_completions __P((int, int));
-static int bash_complete_variable __P((int, int));
-static int bash_possible_variable_completions __P((int, int));
-static int bash_complete_command __P((int, int));
-static int bash_possible_command_completions __P((int, int));
-
-static char *glob_complete_word __P((const char *, int));
-static int bash_glob_completion_internal __P((int));
-static int bash_glob_complete_word __P((int, int));
-static int bash_glob_expand_word __P((int, int));
-static int bash_glob_list_expansions __P((int, int));
-
-#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
-
-static int edit_and_execute_command __P((int, int, int, char *));
-#if defined (VI_MODE)
-static int vi_edit_and_execute_command __P((int, int));
-static int bash_vi_complete __P((int, int));
-#endif
-static int emacs_edit_and_execute_command __P((int, int));
-
-/* Non-zero once initalize_readline () has been called. */
-int bash_readline_initialized = 0;
-
-/* If non-zero, we do hostname completion, breaking words at `@' and
-   trying to complete the stuff after the `@' from our own internal
-   host list. */
-int perform_hostname_completion = 1;
-
-/* If non-zero, we don't do command completion on an empty line. */
-int no_empty_command_completion;
-
-/* Set FORCE_FIGNORE if you want to honor FIGNORE even if it ignores the
-   only possible matches.  Set to 0 if you want to match filenames if they
-   are the only possible matches, even if FIGNORE says to. */
-int force_fignore = 1;
-
-/* Perform spelling correction on directory names during word completion */
-int dircomplete_spelling = 0;
-
-/* Expand directory names during word/filename completion. */
-#if DIRCOMPLETE_EXPAND_DEFAULT
-int dircomplete_expand = 1;
-int dircomplete_expand_relpath = 1;
-#else
-int dircomplete_expand = 0;
-int dircomplete_expand_relpath = 0;
-#endif
-
-/* When non-zero, perform `normal' shell quoting on completed filenames
-   even when the completed name contains a directory name with a shell
-   variable referene, so dollar signs in a filename get quoted appropriately.
-   Set to zero to remove dollar sign (and braces or parens as needed) from
-   the set of characters that will be quoted. */
-int complete_fullquote = 1;
-
-static char *bash_completer_word_break_characters = " \t\n\"'@><=;|&(:";
-static char *bash_nohostname_word_break_characters = " \t\n\"'><=;|&(:";
-/* )) */
-
-static const char *default_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{~";        /*}*/
-static char *custom_filename_quote_characters = 0;
-static char filename_bstab[256];
-
-static rl_hook_func_t *old_rl_startup_hook = (rl_hook_func_t *)NULL;
-
-static int dot_in_path = 0;
-
-/* Set to non-zero when dabbrev-expand is running */
-static int dabbrev_expand_active = 0;
-
-/* What kind of quoting is performed by bash_quote_filename:
-       COMPLETE_DQUOTE = double-quoting the filename
-       COMPLETE_SQUOTE = single_quoting the filename
-       COMPLETE_BSQUOTE = backslash-quoting special chars in the filename
-*/
-#define COMPLETE_DQUOTE  1
-#define COMPLETE_SQUOTE  2
-#define COMPLETE_BSQUOTE 3
-static int completion_quoting_style = COMPLETE_BSQUOTE;
-
-/* Flag values for the final argument to bash_default_completion */
-#define DEFCOMP_CMDPOS         1
-
-/* Change the readline VI-mode keymaps into or out of Posix.2 compliance.
-   Called when the shell is put into or out of `posix' mode. */
-void
-posix_readline_initialize (on_or_off)
-     int on_or_off;
-{
-  if (on_or_off)
-    rl_variable_bind ("comment-begin", "#");
-#if defined (VI_MODE)
-  rl_bind_key_in_map (CTRL ('I'), on_or_off ? rl_insert : rl_complete, vi_insertion_keymap);
-#endif
-}
-
-void
-reset_completer_word_break_chars ()
-{
-  rl_completer_word_break_characters = perform_hostname_completion ? savestring (bash_completer_word_break_characters) : savestring (bash_nohostname_word_break_characters);
-}
-
-/* When this function returns, rl_completer_word_break_characters points to
-   dynamically allocated memory. */
-int
-enable_hostname_completion (on_or_off)
-     int on_or_off;
-{
-  int old_value;
-  char *at, *nv, *nval;
-
-  old_value = perform_hostname_completion;
-
-  if (on_or_off)
-    {
-      perform_hostname_completion = 1;
-      rl_special_prefixes = "$@";
-    }
-  else
-    {
-      perform_hostname_completion = 0;
-      rl_special_prefixes = "$";
-    }
-
-  /* Now we need to figure out how to appropriately modify and assign
-     rl_completer_word_break_characters depending on whether we want
-     hostname completion on or off. */
-
-  /* If this is the first time this has been called
-     (bash_readline_initialized == 0), use the sames values as before, but
-     allocate new memory for rl_completer_word_break_characters. */
-
-  if (bash_readline_initialized == 0 &&
-      (rl_completer_word_break_characters == 0 || 
-       rl_completer_word_break_characters == rl_basic_word_break_characters))
-    {
-      if (on_or_off)
-       rl_completer_word_break_characters = savestring (bash_completer_word_break_characters);
-      else
-       rl_completer_word_break_characters = savestring (bash_nohostname_word_break_characters);
-    }
-  else
-    {
-      /* See if we have anything to do. */
-      at = strchr (rl_completer_word_break_characters, '@');
-      if ((at == 0 && on_or_off == 0) || (at != 0 && on_or_off != 0))
-        return old_value;
-
-      /* We have something to do.  Do it. */
-      nval = (char *)xmalloc (strlen (rl_completer_word_break_characters) + 1 + on_or_off);
-
-      if (on_or_off == 0)
-       {
-         /* Turn it off -- just remove `@' from word break chars.  We want
-            to remove all occurrences of `@' from the char list, so we loop
-            rather than just copy the rest of the list over AT. */
-         for (nv = nval, at = rl_completer_word_break_characters; *at; )
-           if (*at != '@')
-             *nv++ = *at++;
-           else
-             at++;
-         *nv = '\0';
-       }
-      else
-       {
-         nval[0] = '@';
-         strcpy (nval + 1, rl_completer_word_break_characters);
-        }
-
-      free (rl_completer_word_break_characters);
-      rl_completer_word_break_characters = nval;
-    }
-
-  return (old_value);
-}
-
-/* Called once from parse.y if we are going to use readline. */
-void
-initialize_readline ()
-{
-  rl_command_func_t *func;
-  char kseq[2];
-
-  if (bash_readline_initialized)
-    return;
-
-  rl_terminal_name = get_string_value ("TERM");
-  rl_instream = stdin;
-  rl_outstream = stderr;
-
-  /* Allow conditional parsing of the ~/.inputrc file. */
-  rl_readline_name = "Bash";
-
-  /* Add bindable names before calling rl_initialize so they may be
-     referenced in the various inputrc files. */
-  rl_add_defun ("shell-expand-line", shell_expand_line, -1);
-#ifdef BANG_HISTORY
-  rl_add_defun ("history-expand-line", history_expand_line, -1);
-  rl_add_defun ("magic-space", tcsh_magic_space, -1);
-#endif
-
-  rl_add_defun ("shell-forward-word", bash_forward_shellword, -1);
-  rl_add_defun ("shell-backward-word", bash_backward_shellword, -1);
-  rl_add_defun ("shell-kill-word", bash_kill_shellword, -1);
-  rl_add_defun ("shell-backward-kill-word", bash_backward_kill_shellword, -1);
-
-#ifdef ALIAS
-  rl_add_defun ("alias-expand-line", alias_expand_line, -1);
-#  ifdef BANG_HISTORY
-  rl_add_defun ("history-and-alias-expand-line", history_and_alias_expand_line, -1);
-#  endif
-#endif
-
-  /* Backwards compatibility. */
-  rl_add_defun ("insert-last-argument", rl_yank_last_arg, -1);
-
-  rl_add_defun ("operate-and-get-next", operate_and_get_next, -1);
-  rl_add_defun ("display-shell-version", display_shell_version, -1);
-  rl_add_defun ("edit-and-execute-command", emacs_edit_and_execute_command, -1);
-
-#if defined (BRACE_COMPLETION)
-  rl_add_defun ("complete-into-braces", bash_brace_completion, -1);
-#endif
-
-#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
-  rl_add_defun ("complete-filename", bash_complete_filename, -1);
-  rl_add_defun ("possible-filename-completions", bash_possible_filename_completions, -1);
-  rl_add_defun ("complete-username", bash_complete_username, -1);
-  rl_add_defun ("possible-username-completions", bash_possible_username_completions, -1);
-  rl_add_defun ("complete-hostname", bash_complete_hostname, -1);
-  rl_add_defun ("possible-hostname-completions", bash_possible_hostname_completions, -1);
-  rl_add_defun ("complete-variable", bash_complete_variable, -1);
-  rl_add_defun ("possible-variable-completions", bash_possible_variable_completions, -1);
-  rl_add_defun ("complete-command", bash_complete_command, -1);
-  rl_add_defun ("possible-command-completions", bash_possible_command_completions, -1);
-  rl_add_defun ("glob-complete-word", bash_glob_complete_word, -1);
-  rl_add_defun ("glob-expand-word", bash_glob_expand_word, -1);
-  rl_add_defun ("glob-list-expansions", bash_glob_list_expansions, -1);
-#endif
-
-  rl_add_defun ("dynamic-complete-history", dynamic_complete_history, -1);
-  rl_add_defun ("dabbrev-expand", bash_dabbrev_expand, -1);
-
-  /* Bind defaults before binding our custom shell keybindings. */
-  if (RL_ISSTATE(RL_STATE_INITIALIZED) == 0)
-    rl_initialize ();
-
-  /* Bind up our special shell functions. */
-  rl_bind_key_if_unbound_in_map (CTRL('E'), shell_expand_line, emacs_meta_keymap);
-
-#ifdef BANG_HISTORY
-  rl_bind_key_if_unbound_in_map ('^', history_expand_line, emacs_meta_keymap);
-#endif
-
-  rl_bind_key_if_unbound_in_map (CTRL ('O'), operate_and_get_next, emacs_standard_keymap);
-  rl_bind_key_if_unbound_in_map (CTRL ('V'), display_shell_version, emacs_ctlx_keymap);
-
-  /* In Bash, the user can switch editing modes with "set -o [vi emacs]",
-     so it is not necessary to allow C-M-j for context switching.  Turn
-     off this occasionally confusing behaviour. */
-  kseq[0] = CTRL('J');
-  kseq[1] = '\0';
-  func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
-  if (func == rl_vi_editing_mode)
-    rl_unbind_key_in_map (CTRL('J'), emacs_meta_keymap);
-  kseq[0] = CTRL('M');
-  func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
-  if (func == rl_vi_editing_mode)
-    rl_unbind_key_in_map (CTRL('M'), emacs_meta_keymap);
-#if defined (VI_MODE)
-  rl_unbind_key_in_map (CTRL('E'), vi_movement_keymap);
-#endif
-
-#if defined (BRACE_COMPLETION)
-  rl_bind_key_if_unbound_in_map ('{', bash_brace_completion, emacs_meta_keymap); /*}*/
-#endif /* BRACE_COMPLETION */
-
-#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
-  rl_bind_key_if_unbound_in_map ('/', bash_complete_filename, emacs_meta_keymap);
-  rl_bind_key_if_unbound_in_map ('/', bash_possible_filename_completions, emacs_ctlx_keymap);
-
-  /* Have to jump through hoops here because there is a default binding for
-     M-~ (rl_tilde_expand) */
-  kseq[0] = '~';
-  kseq[1] = '\0';
-  func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
-  if (func == 0 || func == rl_tilde_expand)
-    rl_bind_keyseq_in_map (kseq, bash_complete_username, emacs_meta_keymap);
-
-  rl_bind_key_if_unbound_in_map ('~', bash_possible_username_completions, emacs_ctlx_keymap);
-
-  rl_bind_key_if_unbound_in_map ('@', bash_complete_hostname, emacs_meta_keymap);
-  rl_bind_key_if_unbound_in_map ('@', bash_possible_hostname_completions, emacs_ctlx_keymap);
-
-  rl_bind_key_if_unbound_in_map ('$', bash_complete_variable, emacs_meta_keymap);
-  rl_bind_key_if_unbound_in_map ('$', bash_possible_variable_completions, emacs_ctlx_keymap);
-
-  rl_bind_key_if_unbound_in_map ('!', bash_complete_command, emacs_meta_keymap);
-  rl_bind_key_if_unbound_in_map ('!', bash_possible_command_completions, emacs_ctlx_keymap);
-
-  rl_bind_key_if_unbound_in_map ('g', bash_glob_complete_word, emacs_meta_keymap);
-  rl_bind_key_if_unbound_in_map ('*', bash_glob_expand_word, emacs_ctlx_keymap);
-  rl_bind_key_if_unbound_in_map ('g', bash_glob_list_expansions, emacs_ctlx_keymap);
-
-#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
-
-  kseq[0] = TAB;
-  kseq[1] = '\0';
-  func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
-  if (func == 0 || func == rl_tab_insert)
-    rl_bind_key_in_map (TAB, dynamic_complete_history, emacs_meta_keymap);
-
-  /* Tell the completer that we want a crack first. */
-  rl_attempted_completion_function = attempt_shell_completion;
-
-  /* Tell the completer that we might want to follow symbolic links or
-     do other expansion on directory names. */
-  set_directory_hook ();
-
-  rl_filename_rewrite_hook = bash_filename_rewrite_hook;
-
-  rl_filename_stat_hook = bash_filename_stat_hook;
-
-  /* Tell the filename completer we want a chance to ignore some names. */
-  rl_ignore_some_completions_function = filename_completion_ignore;
-
-  /* Bind C-xC-e to invoke emacs and run result as commands. */
-  rl_bind_key_if_unbound_in_map (CTRL ('E'), emacs_edit_and_execute_command, emacs_ctlx_keymap);
-#if defined (VI_MODE)
-  rl_bind_key_if_unbound_in_map ('v', vi_edit_and_execute_command, vi_movement_keymap);
-#  if defined (ALIAS)
-  rl_bind_key_if_unbound_in_map ('@', posix_edit_macros, vi_movement_keymap);
-#  endif
-
-  rl_bind_key_in_map ('\\', bash_vi_complete, vi_movement_keymap);
-  rl_bind_key_in_map ('*', bash_vi_complete, vi_movement_keymap);
-  rl_bind_key_in_map ('=', bash_vi_complete, vi_movement_keymap);
-#endif
-
-  rl_completer_quote_characters = "'\"";
-
-  /* This sets rl_completer_word_break_characters and rl_special_prefixes
-     to the appropriate values, depending on whether or not hostname
-     completion is enabled. */
-  enable_hostname_completion (perform_hostname_completion);
-
-  /* characters that need to be quoted when appearing in filenames. */
-  rl_filename_quote_characters = default_filename_quote_characters;
-  set_filename_bstab (rl_filename_quote_characters);
-
-  rl_filename_quoting_function = bash_quote_filename;
-  rl_filename_dequoting_function = bash_dequote_filename;
-  rl_char_is_quoted_p = char_is_quoted;
-
-#if 0
-  /* This is superfluous and makes it impossible to use tab completion in
-     vi mode even when explicitly binding it in ~/.inputrc.  sv_strict_posix()
-     should already have called posix_readline_initialize() when
-     posixly_correct was set. */
-  if (posixly_correct)
-    posix_readline_initialize (1);
-#endif
-
-  bash_readline_initialized = 1;
-}
-
-void
-bashline_reinitialize ()
-{
-  bash_readline_initialized = 0;
-}
-
-void
-bashline_set_event_hook ()
-{
-  rl_event_hook = bash_event_hook;
-}
-
-void
-bashline_reset_event_hook ()
-{
-  rl_event_hook = 0;
-}
-
-/* On Sun systems at least, rl_attempted_completion_function can end up
-   getting set to NULL, and rl_completion_entry_function set to do command
-   word completion if Bash is interrupted while trying to complete a command
-   word.  This just resets all the completion functions to the right thing.
-   It's called from throw_to_top_level(). */
-void
-bashline_reset ()
-{
-  tilde_initialize ();
-  rl_attempted_completion_function = attempt_shell_completion;
-  rl_completion_entry_function = NULL;
-  rl_ignore_some_completions_function = filename_completion_ignore;
-  rl_filename_quote_characters = default_filename_quote_characters;
-  set_filename_bstab (rl_filename_quote_characters);
-
-  set_directory_hook ();
-  rl_filename_stat_hook = bash_filename_stat_hook;
-
-  bashline_reset_event_hook ();
-}
-
-/* Contains the line to push into readline. */
-static char *push_to_readline = (char *)NULL;
-
-/* Push the contents of push_to_readline into the
-   readline buffer. */
-static int
-bash_push_line ()
-{
-  if (push_to_readline)
-    {
-      rl_insert_text (push_to_readline);
-      free (push_to_readline);
-      push_to_readline = (char *)NULL;
-      rl_startup_hook = old_rl_startup_hook;
-    }
-  return 0;
-}
-
-/* Call this to set the initial text for the next line to read
-   from readline. */
-int
-bash_re_edit (line)
-     char *line;
-{
-  FREE (push_to_readline);
-
-  push_to_readline = savestring (line);
-  old_rl_startup_hook = rl_startup_hook;
-  rl_startup_hook = bash_push_line;
-
-  return (0);
-}
-
-static int
-display_shell_version (count, c)
-     int count, c;
-{
-  rl_crlf ();
-  show_shell_version (0);
-  putc ('\r', rl_outstream);
-  fflush (rl_outstream);
-  rl_on_new_line ();
-  rl_redisplay ();
-  return 0;
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                          Readline Stuff                         */
-/*                                                                 */
-/* **************************************************************** */
-
-/* If the user requests hostname completion, then simply build a list
-   of hosts, and complete from that forever more, or at least until
-   HOSTFILE is unset. */
-
-/* THIS SHOULD BE A STRINGLIST. */
-/* The kept list of hostnames. */
-static char **hostname_list = (char **)NULL;
-
-/* The physical size of the above list. */
-static int hostname_list_size;
-
-/* The number of hostnames in the above list. */
-static int hostname_list_length;
-
-/* Whether or not HOSTNAME_LIST has been initialized. */
-int hostname_list_initialized = 0;
-
-/* Initialize the hostname completion table. */
-static void
-initialize_hostname_list ()
-{
-  char *temp;
-
-  temp = get_string_value ("HOSTFILE");
-  if (temp == 0)
-    temp = get_string_value ("hostname_completion_file");
-  if (temp == 0)
-    temp = DEFAULT_HOSTS_FILE;
-
-  snarf_hosts_from_file (temp);
-
-  if (hostname_list)
-    hostname_list_initialized++;
-}
-
-/* Add NAME to the list of hosts. */
-static void
-add_host_name (name)
-     char *name;
-{
-  if (hostname_list_length + 2 > hostname_list_size)
-    {
-      hostname_list_size = (hostname_list_size + 32) - (hostname_list_size % 32);
-      hostname_list = strvec_resize (hostname_list, hostname_list_size);
-    }
-
-  hostname_list[hostname_list_length++] = savestring (name);
-  hostname_list[hostname_list_length] = (char *)NULL;
-}
-
-#define cr_whitespace(c) ((c) == '\r' || (c) == '\n' || whitespace(c))
-
-static void
-snarf_hosts_from_file (filename)
-     char *filename;
-{
-  FILE *file;
-  char *temp, buffer[256], name[256];
-  register int i, start;
-
-  file = fopen (filename, "r");
-  if (file == 0)
-    return;
-
-  while (temp = fgets (buffer, 255, file))
-    {
-      /* Skip to first character. */
-      for (i = 0; buffer[i] && cr_whitespace (buffer[i]); i++)
-       ;
-
-      /* If comment or blank line, ignore. */
-      if (buffer[i] == '\0' || buffer[i] == '#')
-       continue;
-
-      /* If `preprocessor' directive, do the include. */
-      if (strncmp (buffer + i, "$include ", 9) == 0)
-       {
-         char *incfile, *t;
-
-         /* Find start of filename. */
-         for (incfile = buffer + i + 9; *incfile && whitespace (*incfile); incfile++)
-           ;
-
-         /* Find end of filename. */
-         for (t = incfile; *t && cr_whitespace (*t) == 0; t++)
-           ;
-
-         *t = '\0';
-
-         snarf_hosts_from_file (incfile);
-         continue;
-       }
-
-      /* Skip internet address if present. */
-      if (DIGIT (buffer[i]))
-       for (; buffer[i] && cr_whitespace (buffer[i]) == 0; i++);
-
-      /* Gobble up names.  Each name is separated with whitespace. */
-      while (buffer[i])
-       {
-         for (; cr_whitespace (buffer[i]); i++)
-           ;
-         if (buffer[i] == '\0' || buffer[i] ==  '#')
-           break;
-
-         /* Isolate the current word. */
-         for (start = i; buffer[i] && cr_whitespace (buffer[i]) == 0; i++)
-           ;
-         if (i == start)
-           continue;
-         strncpy (name, buffer + start, i - start);
-         name[i - start] = '\0';
-         add_host_name (name);
-       }
-    }
-  fclose (file);
-}
-
-/* Return the hostname list. */
-char **
-get_hostname_list ()
-{
-  if (hostname_list_initialized == 0)
-    initialize_hostname_list ();
-  return (hostname_list);
-}
-
-void
-clear_hostname_list ()
-{
-  register int i;
-
-  if (hostname_list_initialized == 0)
-    return;
-  for (i = 0; i < hostname_list_length; i++)
-    free (hostname_list[i]);
-  hostname_list_length = hostname_list_initialized = 0;
-}
-
-/* Return a NULL terminated list of hostnames which begin with TEXT.
-   Initialize the hostname list the first time if neccessary.
-   The array is malloc ()'ed, but not the individual strings. */
-static char **
-hostnames_matching (text)
-     char *text;
-{
-  register int i, len, nmatch, rsize;
-  char **result;
-
-  if (hostname_list_initialized == 0)
-    initialize_hostname_list ();
-
-  if (hostname_list_initialized == 0)
-    return ((char **)NULL);
-
-  /* Special case.  If TEXT consists of nothing, then the whole list is
-     what is desired. */
-  if (*text == '\0')
-    {
-      result = strvec_create (1 + hostname_list_length);
-      for (i = 0; i < hostname_list_length; i++)
-       result[i] = hostname_list[i];
-      result[i] = (char *)NULL;
-      return (result);
-    }
-
-  /* Scan until found, or failure. */
-  len = strlen (text);
-  result = (char **)NULL;
-  for (i = nmatch = rsize = 0; i < hostname_list_length; i++)
-    {
-      if (STREQN (text, hostname_list[i], len) == 0)
-       continue;
-
-      /* OK, it matches.  Add it to the list. */
-      if (nmatch >= (rsize - 1))
-       {
-         rsize = (rsize + 16) - (rsize % 16);
-         result = strvec_resize (result, rsize);
-       }
-
-      result[nmatch++] = hostname_list[i];
-    }
-  if (nmatch)
-    result[nmatch] = (char *)NULL;
-  return (result);
-}
-
-/* The equivalent of the Korn shell C-o operate-and-get-next-history-line
-   editing command. */
-static int saved_history_line_to_use = -1;
-static int last_saved_history_line = -1;
-
-#define HISTORY_FULL() (history_is_stifled () && history_length >= history_max_entries)
-
-static int
-set_saved_history ()
-{
-  /* XXX - compensate for assumption that history was `shuffled' if it was
-     actually not. */
-  if (HISTORY_FULL () &&
-      hist_last_line_added == 0 &&
-      saved_history_line_to_use < history_length - 1)
-    saved_history_line_to_use++;
-
-  if (saved_history_line_to_use >= 0)
-    {
-     rl_get_previous_history (history_length - saved_history_line_to_use, 0);
-     last_saved_history_line = saved_history_line_to_use;
-    }
-  saved_history_line_to_use = -1;
-  rl_startup_hook = old_rl_startup_hook;
-  return (0);
-}
-
-static int
-operate_and_get_next (count, c)
-     int count, c;
-{
-  int where;
-
-  /* Accept the current line. */
-  rl_newline (1, c);
-
-  /* Find the current line, and find the next line to use. */
-  where = where_history ();
-
-  if (HISTORY_FULL () || (where >= history_length - 1))
-    saved_history_line_to_use = where;
-  else
-    saved_history_line_to_use = where + 1;
-
-  old_rl_startup_hook = rl_startup_hook;
-  rl_startup_hook = set_saved_history;
-
-  return 0;
-}
-
-/* This vi mode command causes VI_EDIT_COMMAND to be run on the current
-   command being entered (if no explicit argument is given), otherwise on
-   a command from the history file. */
-
-#define VI_EDIT_COMMAND                "fc -e \"${VISUAL:-${EDITOR:-vi}}\""
-#define EMACS_EDIT_COMMAND     "fc -e \"${VISUAL:-${EDITOR:-emacs}}\""
-#define POSIX_VI_EDIT_COMMAND  "fc -e vi"
-
-static int
-edit_and_execute_command (count, c, editing_mode, edit_command)
-     int count, c, editing_mode;
-     char *edit_command;
-{
-  char *command, *metaval;
-  int r, rrs, metaflag;
-  sh_parser_state_t ps;
-
-  rrs = rl_readline_state;
-  saved_command_line_count = current_command_line_count;
-
-  /* Accept the current line. */
-  rl_newline (1, c);
-
-  if (rl_explicit_arg)
-    {
-      command = (char *)xmalloc (strlen (edit_command) + 8);
-      sprintf (command, "%s %d", edit_command, count);
-    }
-  else
-    {
-      /* Take the command we were just editing, add it to the history file,
-        then call fc to operate on it.  We have to add a dummy command to
-        the end of the history because fc ignores the last command (assumes
-        it's supposed to deal with the command before the `fc'). */
-      /* This breaks down when using command-oriented history and are not
-        finished with the command, so we should not ignore the last command */
-      using_history ();
-      current_command_line_count++;    /* for rl_newline above */
-      bash_add_history (rl_line_buffer);
-      current_command_line_count = 0;  /* for dummy history entry */
-      bash_add_history ("");
-      history_lines_this_session++;
-      using_history ();
-      command = savestring (edit_command);
-    }
-
-  metaval = rl_variable_value ("input-meta");
-  metaflag = RL_BOOLEAN_VARIABLE_VALUE (metaval);
-  
-  /* Now, POSIX.1-2001 and SUSv3 say that the commands executed from the
-     temporary file should be placed into the history.  We don't do that
-     yet. */
-  if (rl_deprep_term_function)
-    (*rl_deprep_term_function) ();
-  save_parser_state (&ps);
-  r = parse_and_execute (command, (editing_mode == VI_EDITING_MODE) ? "v" : "C-xC-e", SEVAL_NOHIST);
-  restore_parser_state (&ps);
-  if (rl_prep_term_function)
-    (*rl_prep_term_function) (metaflag);
-
-  current_command_line_count = saved_command_line_count;
-
-  /* Now erase the contents of the current line and undo the effects of the
-     rl_accept_line() above.  We don't even want to make the text we just
-     executed available for undoing. */
-  rl_line_buffer[0] = '\0';    /* XXX */
-  rl_point = rl_end = 0;
-  rl_done = 0;
-  rl_readline_state = rrs;
-
-  rl_forced_update_display ();
-
-  return r;
-}
-
-#if defined (VI_MODE)
-static int
-vi_edit_and_execute_command (count, c)
-     int count, c;
-{
-  if (posixly_correct)
-    return (edit_and_execute_command (count, c, VI_EDITING_MODE, POSIX_VI_EDIT_COMMAND));
-  else
-    return (edit_and_execute_command (count, c, VI_EDITING_MODE, VI_EDIT_COMMAND));
-}
-#endif /* VI_MODE */
-
-static int
-emacs_edit_and_execute_command (count, c)
-     int count, c;
-{
-  return (edit_and_execute_command (count, c, EMACS_EDITING_MODE, EMACS_EDIT_COMMAND));
-}
-
-#if defined (ALIAS)
-static int
-posix_edit_macros (count, key)
-     int count, key;
-{
-  int c;
-  char alias_name[3], *alias_value, *macro;
-
-  c = rl_read_key ();
-  alias_name[0] = '_';
-  alias_name[1] = c;
-  alias_name[2] = '\0';
-
-  alias_value = get_alias_value (alias_name);
-  if (alias_value && *alias_value)
-    {
-      macro = savestring (alias_value);
-      rl_push_macro_input (macro);
-    }
-  return 0;
-}
-#endif
-
-/* Bindable commands that move `shell-words': that is, sequences of
-   non-unquoted-metacharacters. */
-
-#define WORDDELIM(c)   (shellmeta(c) || shellblank(c))
-
-static int
-bash_forward_shellword (count, key)
-     int count, key;
-{
-  size_t slen;
-  int sindex, c, p;
-  DECLARE_MBSTATE;
-
-  if (count < 0)
-    return (bash_backward_shellword (-count, key));
-
-  /* The tricky part of this is deciding whether or not the first character
-     we're on is an unquoted metacharacter.  Not completely handled yet. */
-  /* XXX - need to test this stuff with backslash-escaped shell
-     metacharacters and unclosed single- and double-quoted strings. */
-
-  p = rl_point;
-  slen = rl_end;
-
-  while (count)
-    {
-      if (p == rl_end)
-       {
-         rl_point = rl_end;
-         return 0;
-       }
-
-      /* Are we in a quoted string?  If we are, move to the end of the quoted
-         string and continue the outer loop. We only want quoted strings, not
-         backslash-escaped characters, but char_is_quoted doesn't
-         differentiate. */
-      if (char_is_quoted (rl_line_buffer, p) && p > 0 && rl_line_buffer[p-1] != '\\')
-       {
-         do
-           ADVANCE_CHAR (rl_line_buffer, slen, p);
-         while (p < rl_end && char_is_quoted (rl_line_buffer, p));
-         count--;
-         continue;
-       }
-
-      /* Rest of code assumes we are not in a quoted string. */
-      /* Move forward until we hit a non-metacharacter. */
-      while (p < rl_end && (c = rl_line_buffer[p]) && WORDDELIM (c))
-       {
-         switch (c)
-           {
-           default:
-             ADVANCE_CHAR (rl_line_buffer, slen, p);
-             continue;         /* straight back to loop, don't increment p */
-           case '\\':
-             if (p < rl_end && rl_line_buffer[p])
-               ADVANCE_CHAR (rl_line_buffer, slen, p);
-             break;
-           case '\'':
-             p = skip_to_delim (rl_line_buffer, ++p, "'", SD_NOJMP);
-             break;
-           case '"':
-             p = skip_to_delim (rl_line_buffer, ++p, "\"", SD_NOJMP);
-             break;
-           }
-
-         if (p < rl_end)
-           p++;
-       }
-
-      if (rl_line_buffer[p] == 0 || p == rl_end)
-        {
-         rl_point = rl_end;
-         rl_ding ();
-         return 0;
-        }
-       
-      /* Now move forward until we hit a non-quoted metacharacter or EOL */
-      while (p < rl_end && (c = rl_line_buffer[p]) && WORDDELIM (c) == 0)
-       {
-         switch (c)
-           {
-           default:
-             ADVANCE_CHAR (rl_line_buffer, slen, p);
-             continue;         /* straight back to loop, don't increment p */
-           case '\\':
-             if (p < rl_end && rl_line_buffer[p])
-               ADVANCE_CHAR (rl_line_buffer, slen, p);
-             break;
-           case '\'':
-             p = skip_to_delim (rl_line_buffer, ++p, "'", SD_NOJMP);
-             break;
-           case '"':
-             p = skip_to_delim (rl_line_buffer, ++p, "\"", SD_NOJMP);
-             break;
-           }
-
-         if (p < rl_end)
-           p++;
-       }
-
-      if (p == rl_end || rl_line_buffer[p] == 0)
-       {
-         rl_point = rl_end;
-         return (0);
-       }
-
-      count--;      
-    }
-
-  rl_point = p;
-  return (0);
-}
-
-static int
-bash_backward_shellword (count, key)
-     int count, key;
-{
-  size_t slen;
-  int sindex, c, p;
-  DECLARE_MBSTATE;
-  
-  if (count < 0)
-    return (bash_forward_shellword (-count, key));
-
-  p = rl_point;
-  slen = rl_end;
-  
-  while (count)
-    {
-      if (p == 0)
-       {
-         rl_point = 0;
-         return 0;
-       }
-
-      /* Move backward until we hit a non-metacharacter. */
-      while (p > 0)
-       {
-         c = rl_line_buffer[p];
-         if (WORDDELIM (c) && char_is_quoted (rl_line_buffer, p) == 0)
-           BACKUP_CHAR (rl_line_buffer, slen, p);
-         break;
-       }
-
-      if (p == 0)
-       {
-         rl_point = 0;
-         return 0;
-       }
-
-      /* Now move backward until we hit a metacharacter or BOL. */
-      while (p > 0)
-       {
-         c = rl_line_buffer[p];
-         if (WORDDELIM (c) && char_is_quoted (rl_line_buffer, p) == 0)
-           break;
-         BACKUP_CHAR (rl_line_buffer, slen, p);
-       }
-
-      count--;
-    }
-
-  rl_point = p;
-  return 0;
-}
-
-static int
-bash_kill_shellword (count, key)
-     int count, key;
-{
-  int p;
-
-  if (count < 0)
-    return (bash_backward_kill_shellword (-count, key));
-
-  p = rl_point;
-  bash_forward_shellword (count, key);
-
-  if (rl_point != p)
-    rl_kill_text (p, rl_point);
-
-  rl_point = p;
-  if (rl_editing_mode == 1)    /* 1 == emacs_mode */
-    rl_mark = rl_point;
-
-  return 0;
-}
-
-static int
-bash_backward_kill_shellword (count, key)
-     int count, key;
-{
-  int p;
-
-  if (count < 0)
-    return (bash_kill_shellword (-count, key));
-
-  p = rl_point;
-  bash_backward_shellword (count, key);
-
-  if (rl_point != p)
-    rl_kill_text (p, rl_point);
-
-  if (rl_editing_mode == 1)    /* 1 == emacs_mode */
-    rl_mark = rl_point;
-
-  return 0;
-}
-
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     How To Do Shell Completion                  */
-/*                                                                 */
-/* **************************************************************** */
-
-#define COMMAND_SEPARATORS ";|&{(`"
-/* )} */ 
-#define COMMAND_SEPARATORS_PLUS_WS ";|&{(` \t"
-/* )} */ 
-
-/* check for redirections and other character combinations that are not
-   command separators */
-static int
-check_redir (ti)
-     int ti;
-{
-  register int this_char, prev_char;
-
-  /* Handle the two character tokens `>&', `<&', and `>|'.
-     We are not in a command position after one of these. */
-  this_char = rl_line_buffer[ti];
-  prev_char = rl_line_buffer[ti - 1];
-
-  if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) ||
-      (this_char == '|' && prev_char == '>'))
-    return (1);
-  else if (this_char == '{' && prev_char == '$') /*}*/
-    return (1);
-#if 0  /* Not yet */
-  else if (this_char == '(' && prev_char == '$') /*)*/
-    return (1);
-  else if (this_char == '(' && prev_char == '<') /*)*/
-    return (1);
-#if defined (EXTENDED_GLOB)
-  else if (extended_glob && this_char == '(' && prev_char == '!') /*)*/
-    return (1);
-#endif
-#endif
-  else if (char_is_quoted (rl_line_buffer, ti))
-    return (1);
-  return (0);
-}
-
-#if defined (PROGRAMMABLE_COMPLETION)
-/*
- * XXX - because of the <= start test, and setting os = s+1, this can
- * potentially return os > start.  This is probably not what we want to
- * happen, but fix later after 2.05a-release.
- */
-static int
-find_cmd_start (start)
-     int start;
-{
-  register int s, os;
-
-  os = 0;
-  /* Flags == SD_NOJMP only because we want to skip over command substitutions
-     in assignment statements.  Have to test whether this affects `standalone'
-     command substitutions as individual words. */
-  while (((s = skip_to_delim (rl_line_buffer, os, COMMAND_SEPARATORS, SD_NOJMP/*|SD_NOSKIPCMD*/)) <= start) &&
-        rl_line_buffer[s])
-    os = s+1;
-  return os;
-}
-
-static int
-find_cmd_end (end)
-     int end;
-{
-  register int e;
-
-  e = skip_to_delim (rl_line_buffer, end, COMMAND_SEPARATORS, SD_NOJMP);
-  return e;
-}
-
-static char *
-find_cmd_name (start, sp, ep)
-     int start;
-     int *sp, *ep;
-{
-  char *name;
-  register int s, e;
-
-  for (s = start; whitespace (rl_line_buffer[s]); s++)
-    ;
-
-  /* skip until a shell break character */
-  e = skip_to_delim (rl_line_buffer, s, "()<>;&| \t\n", SD_NOJMP);
-
-  name = substring (rl_line_buffer, s, e);
-
-  if (sp)
-    *sp = s;
-  if (ep)
-    *ep = e;
-
-  return (name);
-}
-
-static char *
-prog_complete_return (text, matchnum)
-     const char *text;
-     int matchnum;
-{
-  static int ind;
-
-  if (matchnum == 0)
-    ind = 0;
-
-  if (prog_complete_matches == 0 || prog_complete_matches[ind] == 0)
-    return (char *)NULL;
-  return (prog_complete_matches[ind++]);
-}
-
-#endif /* PROGRAMMABLE_COMPLETION */
-
-/* Do some completion on TEXT.  The indices of TEXT in RL_LINE_BUFFER are
-   at START and END.  Return an array of matches, or NULL if none. */
-static char **
-attempt_shell_completion (text, start, end)
-     const char *text;
-     int start, end;
-{
-  int in_command_position, ti, saveti, qc, dflags;
-  char **matches, *command_separator_chars;
-
-  command_separator_chars = COMMAND_SEPARATORS;
-  matches = (char **)NULL;
-  rl_ignore_some_completions_function = filename_completion_ignore;
-
-  rl_filename_quote_characters = default_filename_quote_characters;
-  set_filename_bstab (rl_filename_quote_characters);
-  set_directory_hook ();
-  rl_filename_stat_hook = bash_filename_stat_hook;
-
-  /* Determine if this could be a command word.  It is if it appears at
-     the start of the line (ignoring preceding whitespace), or if it
-     appears after a character that separates commands.  It cannot be a
-     command word if we aren't at the top-level prompt. */
-  ti = start - 1;
-  saveti = qc = -1;
-
-  while ((ti > -1) && (whitespace (rl_line_buffer[ti])))
-    ti--;
-
-#if 1
-  /* If this is an open quote, maybe we're trying to complete a quoted
-     command name. */
-  if (ti >= 0 && (rl_line_buffer[ti] == '"' || rl_line_buffer[ti] == '\''))
-    {
-      qc = rl_line_buffer[ti];
-      saveti = ti--;
-      while (ti > -1 && (whitespace (rl_line_buffer[ti])))
-       ti--;
-    }
-#endif
-      
-  in_command_position = 0;
-  if (ti < 0)
-    {
-      /* Only do command completion at the start of a line when we
-        are prompting at the top level. */
-      if (current_prompt_string == ps1_prompt)
-       in_command_position++;
-      else if (parser_in_command_position ())
-       in_command_position++;
-    }
-  else if (member (rl_line_buffer[ti], command_separator_chars))
-    {
-      in_command_position++;
-
-      if (check_redir (ti) == 1)
-       in_command_position = 0;
-    }
-  else
-    {
-      /* This still could be in command position.  It is possible
-        that all of the previous words on the line are variable
-        assignments. */
-    }
-
-  /* Check that we haven't incorrectly flagged a closed command substitution
-     as indicating we're in a command position. */
-  if (in_command_position && ti >= 0 && rl_line_buffer[ti] == '`' &&
-       *text != '`' && unclosed_pair (rl_line_buffer, end, "`") == 0)
-    in_command_position = 0;
-
-  /* Special handling for command substitution.  If *TEXT is a backquote,
-     it can be the start or end of an old-style command substitution, or
-     unmatched.  If it's unmatched, both calls to unclosed_pair will
-     succeed.  Don't bother if readline found a single quote and we are
-     completing on the substring.  */
-  if (*text == '`' && rl_completion_quote_character != '\'' &&
-       (in_command_position || (unclosed_pair (rl_line_buffer, start, "`") &&
-                                unclosed_pair (rl_line_buffer, end, "`"))))
-    matches = rl_completion_matches (text, command_subst_completion_function);
-
-#if defined (PROGRAMMABLE_COMPLETION)
-  /* Attempt programmable completion. */
-  if (matches == 0 && (in_command_position == 0 || text[0] == '\0') &&
-      prog_completion_enabled && (progcomp_size () > 0) &&
-      current_prompt_string == ps1_prompt)
-    {
-      int s, e, s1, e1, os, foundcs;
-      char *n;
-
-      /* XXX - don't free the members */
-      if (prog_complete_matches)
-       free (prog_complete_matches);
-      prog_complete_matches = (char **)NULL;
-
-      os = start;
-      n = 0;
-      s = find_cmd_start (os);
-      e = find_cmd_end (end);
-      do
-       {
-         /* Skip over assignment statements preceding a command name.  If we
-            don't find a command name at all, we can perform command name
-            completion.  If we find a partial command name, we should perform
-            command name completion on it. */
-         FREE (n);
-         n = find_cmd_name (s, &s1, &e1);
-         s = e1 + 1;
-       }
-      while (assignment (n, 0));
-      s = s1;          /* reset to index where name begins */
-
-      if (start == 0 && end == 0 && e != 0 && text[0] == '\0') /* beginning of non-empty line */
-        foundcs = 0;
-      else if (start == end && start == s1 && e != 0 && e1 > end)      /* beginning of command name, leading whitespace */
-       foundcs = 0;
-      else if (e == 0 && e == s && text[0] == '\0')    /* beginning of empty line */
-        prog_complete_matches = programmable_completions ("_EmptycmD_", text, s, e, &foundcs);
-      else if (start == end && text[0] == '\0' && s1 > start && whitespace (rl_line_buffer[start]))
-        foundcs = 0;           /* whitespace before command name */
-      else if (e > s && assignment (n, 0) == 0)
-       prog_complete_matches = programmable_completions (n, text, s, e, &foundcs);
-      else if (s >= e && n[0] == '\0' && text[0] == '\0' && start > 0)
-        {
-          foundcs = 0; /* empty command name following assignments */
-          in_command_position = 1;
-        }
-      else if (s == start && e == end && STREQ (n, text) && start > 0)
-        {
-          foundcs = 0; /* partial command name following assignments */
-          in_command_position = 1;
-        }
-      else
-       foundcs = 0;
-      FREE (n);
-      /* XXX - if we found a COMPSPEC for the command, just return whatever
-        the programmable completion code returns, and disable the default
-        filename completion that readline will do unless the COPT_DEFAULT
-        option has been set with the `-o default' option to complete or
-        compopt. */
-      if (foundcs)
-       {
-         pcomp_set_readline_variables (foundcs, 1);
-         /* Turn what the programmable completion code returns into what
-            readline wants.  I should have made compute_lcd_of_matches
-            external... */
-         matches = rl_completion_matches (text, prog_complete_return);
-         if ((foundcs & COPT_DEFAULT) == 0)
-           rl_attempted_completion_over = 1;   /* no default */
-         if (matches || ((foundcs & COPT_BASHDEFAULT) == 0))
-           return (matches);
-       }
-    }
-#endif
-
-  if (matches == 0)
-    {
-      dflags = 0;
-      if (in_command_position)
-       dflags |= DEFCOMP_CMDPOS;
-      matches = bash_default_completion (text, start, end, qc, dflags);
-    }
-
-  return matches;
-}
-
-char **
-bash_default_completion (text, start, end, qc, compflags)
-     const char *text;
-     int start, end, qc, compflags;
-{
-  char **matches, *t;
-
-  matches = (char **)NULL;
-
-  /* New posix-style command substitution or variable name? */
-  if (!matches && *text == '$')
-    {
-      if (qc != '\'' && text[1] == '(') /* ) */
-       matches = rl_completion_matches (text, command_subst_completion_function);
-      else
-       {
-         matches = rl_completion_matches (text, variable_completion_function);
-         if (matches && matches[0] && matches[1] == 0)
-           {
-             t = savestring (matches[0]);
-             bash_filename_stat_hook (&t);
-             /* doesn't use test_for_directory because that performs tilde
-                expansion */
-             if (file_isdir (t))
-               rl_completion_append_character = '/';
-             free (t);
-           }
-       }
-    }
-
-  /* If the word starts in `~', and there is no slash in the word, then
-     try completing this word as a username. */
-  if (matches == 0 && *text == '~' && mbschr (text, '/') == 0)
-    matches = rl_completion_matches (text, rl_username_completion_function);
-
-  /* Another one.  Why not?  If the word starts in '@', then look through
-     the world of known hostnames for completion first. */
-  if (matches == 0 && perform_hostname_completion && *text == '@')
-    matches = rl_completion_matches (text, hostname_completion_function);
-
-  /* And last, (but not least) if this word is in a command position, then
-     complete over possible command names, including aliases, functions,
-     and command names. */
-  if (matches == 0 && (compflags & DEFCOMP_CMDPOS))
-    {
-      /* If END == START and text[0] == 0, we are trying to complete an empty
-        command word. */
-      if (no_empty_command_completion && end == start && text[0] == '\0')
-       {
-         matches = (char **)NULL;
-         rl_ignore_some_completions_function = bash_ignore_everything;
-       }
-      else
-       {
-#define CMD_IS_DIR(x)  (absolute_pathname(x) == 0 && absolute_program(x) == 0 && *(x) != '~' && test_for_directory (x))
-
-         dot_in_path = 0;
-         matches = rl_completion_matches (text, command_word_completion_function);
-
-         /* If we are attempting command completion and nothing matches, we
-            do not want readline to perform filename completion for us.  We
-            still want to be able to complete partial pathnames, so set the
-            completion ignore function to something which will remove
-            filenames and leave directories in the match list. */
-         if (matches == (char **)NULL)
-           rl_ignore_some_completions_function = bash_ignore_filenames;
-         else if (matches[1] == 0 && CMD_IS_DIR(matches[0]) && dot_in_path == 0)
-           /* If we found a single match, without looking in the current
-              directory (because it's not in $PATH), but the found name is
-              also a command in the current directory, suppress appending any
-              terminating character, since it's ambiguous. */
-           {
-             rl_completion_suppress_append = 1;
-             rl_filename_completion_desired = 0;
-           }
-         else if (matches[0] && matches[1] && STREQ (matches[0], matches[1]) && CMD_IS_DIR (matches[0]))
-           /* There are multiple instances of the same match (duplicate
-              completions haven't yet been removed).  In this case, all of
-              the matches will be the same, and the duplicate removal code
-              will distill them all down to one.  We turn on
-              rl_completion_suppress_append for the same reason as above.
-              Remember: we only care if there's eventually a single unique
-              completion.  If there are multiple completions this won't
-              make a difference and the problem won't occur. */
-           {
-             rl_completion_suppress_append = 1;
-             rl_filename_completion_desired = 0;
-           }
-       }
-    }
-
-  /* This could be a globbing pattern, so try to expand it using pathname
-     expansion. */
-  if (!matches && glob_pattern_p (text))
-    {
-      matches = rl_completion_matches (text, glob_complete_word);
-      /* A glob expression that matches more than one filename is problematic.
-        If we match more than one filename, punt. */
-      if (matches && matches[1] && rl_completion_type == TAB)
-       {
-         strvec_dispose (matches);
-         matches = (char **)0;
-       }
-    }
-
-  return (matches);
-}
-
-static int
-bash_command_name_stat_hook (name)
-     char **name;
-{
-  char *cname, *result;
-
-  cname = *name;
-  /* XXX - we could do something here with converting aliases, builtins,
-     and functions into something that came out as executable, but we don't. */
-  result = search_for_command (cname, 0);
-  if (result)
-    {
-      *name = result;
-      return 1;
-    }
-  return 0;
-}
-
-static int
-executable_completion (filename, searching_path)
-     const char *filename;
-     int searching_path;
-{
-  char *f;
-  int r;
-
-  f = savestring (filename);
-  bash_directory_completion_hook (&f);
-  
-  r = searching_path ? executable_file (f) : executable_or_directory (f);
-  free (f);
-  return r;
-}
-
-/* This is the function to call when the word to complete is in a position
-   where a command word can be found.  It grovels $PATH, looking for commands
-   that match.  It also scans aliases, function names, and the shell_builtin
-   table. */
-char *
-command_word_completion_function (hint_text, state)
-     const char *hint_text;
-     int state;
-{
-  static char *hint = (char *)NULL;
-  static char *path = (char *)NULL;
-  static char *val = (char *)NULL;
-  static char *filename_hint = (char *)NULL;
-  static char *dequoted_hint = (char *)NULL;
-  static char *directory_part = (char *)NULL;
-  static char **glob_matches = (char **)NULL;
-  static int path_index, hint_len, dequoted_len, istate, igncase;
-  static int mapping_over, local_index, searching_path, hint_is_dir;
-  static int old_glob_ignore_case, globpat;
-  static SHELL_VAR **varlist = (SHELL_VAR **)NULL;
-#if defined (ALIAS)
-  static alias_t **alias_list = (alias_t **)NULL;
-#endif /* ALIAS */
-  char *temp, *cval;
-
-  /* We have to map over the possibilities for command words.  If we have
-     no state, then make one just for that purpose. */
-  if (state == 0)
-    {
-      rl_filename_stat_hook = bash_command_name_stat_hook;
-
-      if (dequoted_hint && dequoted_hint != hint)
-       free (dequoted_hint);
-      if (hint)
-       free (hint);
-
-      mapping_over = searching_path = 0;
-      hint_is_dir = CMD_IS_DIR (hint_text);
-      val = (char *)NULL;
-
-      temp = rl_variable_value ("completion-ignore-case");
-      igncase = RL_BOOLEAN_VARIABLE_VALUE (temp);
-
-      if (glob_matches)
-       {
-         free (glob_matches);
-         glob_matches = (char **)NULL;
-       }
-
-      globpat = glob_pattern_p (hint_text);
-
-      /* If this is an absolute program name, do not check it against
-        aliases, reserved words, functions or builtins.  We must check
-        whether or not it is unique, and, if so, whether that filename
-        is executable. */
-      if (globpat || absolute_program (hint_text))
-       {
-         /* Perform tilde expansion on what's passed, so we don't end up
-            passing filenames with tildes directly to stat(). */
-         if (*hint_text == '~')
-           {
-             hint = bash_tilde_expand (hint_text, 0);
-             directory_part = savestring (hint_text);
-             temp = strchr (directory_part, '/');
-             if (temp)
-               *temp = 0;
-             else
-               {
-                 free (directory_part);
-                 directory_part = (char *)NULL;
-               }
-           }
-         else
-           hint = savestring (hint_text);
-
-         dequoted_hint = hint;
-         /* If readline's completer found a quote character somewhere, but
-            didn't set the quote character, there must have been a quote
-            character embedded in the filename.  It can't be at the start of
-            the filename, so we need to dequote the filename before we look
-            in the file system for it. */
-         if (rl_completion_found_quote && rl_completion_quote_character == 0)
-           {
-             dequoted_hint = bash_dequote_filename (hint, 0);
-             free (hint);
-             hint = dequoted_hint;
-           }
-         dequoted_len = hint_len = strlen (hint);
-
-         if (filename_hint)
-           free (filename_hint);
-
-         filename_hint = savestring (hint);
-
-         istate = 0;
-
-         if (globpat)
-           {
-             mapping_over = 5;
-             goto globword;
-           }
-         else
-           {
-            if (dircomplete_expand && path_dot_or_dotdot (filename_hint))
-               {
-                 dircomplete_expand = 0;
-                 set_directory_hook ();
-                 dircomplete_expand = 1;
-               }
-             mapping_over = 4;
-             goto inner;
-           }
-       }
-
-      dequoted_hint = hint = savestring (hint_text);
-      dequoted_len = hint_len = strlen (hint);
-
-      if (rl_completion_found_quote && rl_completion_quote_character == 0)
-       {
-         dequoted_hint = bash_dequote_filename (hint, 0);
-         dequoted_len = strlen (dequoted_hint);
-       }
-      
-      path = get_string_value ("PATH");
-      path_index = dot_in_path = 0;
-
-      /* Initialize the variables for each type of command word. */
-      local_index = 0;
-
-      if (varlist)
-       free (varlist);
-
-      varlist = all_visible_functions ();
-
-#if defined (ALIAS)
-      if (alias_list)
-       free (alias_list);
-
-      alias_list = all_aliases ();
-#endif /* ALIAS */
-    }
-
-  /* mapping_over says what we are currently hacking.  Note that every case
-     in this list must fall through when there are no more possibilities. */
-
-  switch (mapping_over)
-    {
-    case 0:                    /* Aliases come first. */
-#if defined (ALIAS)
-      while (alias_list && alias_list[local_index])
-       {
-         register char *alias;
-
-         alias = alias_list[local_index++]->name;
-
-         if (STREQN (alias, hint, hint_len))
-           return (savestring (alias));
-       }
-#endif /* ALIAS */
-      local_index = 0;
-      mapping_over++;
-
-    case 1:                    /* Then shell reserved words. */
-      {
-       while (word_token_alist[local_index].word)
-         {
-           register char *reserved_word;
-
-           reserved_word = word_token_alist[local_index++].word;
-
-           if (STREQN (reserved_word, hint, hint_len))
-             return (savestring (reserved_word));
-         }
-       local_index = 0;
-       mapping_over++;
-      }
-
-    case 2:                    /* Then function names. */
-      while (varlist && varlist[local_index])
-       {
-         register char *varname;
-
-         varname = varlist[local_index++]->name;
-
-         if (STREQN (varname, hint, hint_len))
-           return (savestring (varname));
-       }
-      local_index = 0;
-      mapping_over++;
-
-    case 3:                    /* Then shell builtins. */
-      for (; local_index < num_shell_builtins; local_index++)
-       {
-         /* Ignore it if it doesn't have a function pointer or if it
-            is not currently enabled. */
-         if (!shell_builtins[local_index].function ||
-             (shell_builtins[local_index].flags & BUILTIN_ENABLED) == 0)
-           continue;
-
-         if (STREQN (shell_builtins[local_index].name, hint, hint_len))
-           {
-             int i = local_index++;
-
-             return (savestring (shell_builtins[i].name));
-           }
-       }
-      local_index = 0;
-      mapping_over++;
-    }
-
-globword:
-  /* Limited support for completing command words with globbing chars.  Only
-     a single match (multiple matches that end up reducing the number of
-     characters in the common prefix are bad) will ever be returned on
-     regular completion. */
-  if (globpat)
-    {
-      if (state == 0)
-       {
-         glob_ignore_case = igncase;
-         glob_matches = shell_glob_filename (hint);
-         glob_ignore_case = old_glob_ignore_case;
-
-         if (GLOB_FAILED (glob_matches) || glob_matches == 0)
-           {
-             glob_matches = (char **)NULL;
-             return ((char *)NULL);
-           }
-
-         local_index = 0;
-               
-         if (glob_matches[1] && rl_completion_type == TAB)     /* multiple matches are bad */
-           return ((char *)NULL);
-       }
-
-      while (val = glob_matches[local_index++])
-        {
-         if (executable_or_directory (val))
-           {
-             if (*hint_text == '~' && directory_part)
-               {
-                 temp = restore_tilde (val, directory_part);
-                 free (val);
-                 val = temp;
-               }
-             return (val);
-           }
-         free (val);
-        }
-
-      glob_ignore_case = old_glob_ignore_case;
-      return ((char *)NULL);
-    }
-
-  /* If the text passed is a directory in the current directory, return it
-     as a possible match.  Executables in directories in the current
-     directory can be specified using relative pathnames and successfully
-     executed even when `.' is not in $PATH. */
-  if (hint_is_dir)
-    {
-      hint_is_dir = 0; /* only return the hint text once */
-      return (savestring (hint_text));
-    }
-    
-  /* Repeatedly call filename_completion_function while we have
-     members of PATH left.  Question:  should we stat each file?
-     Answer: we call executable_file () on each file. */
- outer:
-
-  istate = (val != (char *)NULL);
-
-  if (istate == 0)
-    {
-      char *current_path;
-
-      /* Get the next directory from the path.  If there is none, then we
-        are all done. */
-      if (path == 0 || path[path_index] == 0 ||
-         (current_path = extract_colon_unit (path, &path_index)) == 0)
-       return ((char *)NULL);
-
-      searching_path = 1;
-      if (*current_path == 0)
-       {
-         free (current_path);
-         current_path = savestring (".");
-       }
-
-      if (*current_path == '~')
-       {
-         char *t;
-
-         t = bash_tilde_expand (current_path, 0);
-         free (current_path);
-         current_path = t;
-       }
-
-      if (current_path[0] == '.' && current_path[1] == '\0')
-       dot_in_path = 1;
-
-      if (filename_hint)
-       free (filename_hint);
-
-      filename_hint = sh_makepath (current_path, hint, 0);
-      free (current_path);             /* XXX */
-    }
-
- inner:
-  val = rl_filename_completion_function (filename_hint, istate);
-  if (mapping_over == 4 && dircomplete_expand)
-    set_directory_hook ();
-
-  istate = 1;
-
-  if (val == 0)
-    {
-      /* If the hint text is an absolute program, then don't bother
-        searching through PATH. */
-      if (absolute_program (hint))
-       return ((char *)NULL);
-
-      goto outer;
-    }
-  else
-    {
-      int match, freetemp;
-
-      if (absolute_program (hint))
-       {
-         if (igncase == 0)
-           match = strncmp (val, hint, hint_len) == 0;
-         else
-           match = strncasecmp (val, hint, hint_len) == 0;
-
-         /* If we performed tilde expansion, restore the original
-            filename. */
-         if (*hint_text == '~')
-           temp = restore_tilde (val, directory_part);
-         else
-           temp = savestring (val);
-         freetemp = 1;
-       }
-      else
-       {
-         temp = strrchr (val, '/');
-
-         if (temp)
-           {
-             temp++;
-             if (igncase == 0)
-               freetemp = match = strncmp (temp, hint, hint_len) == 0;
-             else
-               freetemp = match = strncasecmp (temp, hint, hint_len) == 0;
-             if (match)
-               temp = savestring (temp);
-           }
-         else
-           freetemp = match = 0;
-       }
-
-      /* If we have found a match, and it is an executable file, return it.
-        We don't return directory names when searching $PATH, since the
-        bash execution code won't find executables in directories which
-        appear in directories in $PATH when they're specified using
-        relative pathnames.  */
-#if 0
-      /* If we're not searching $PATH and we have a relative pathname, we
-        need to re-canonicalize it before testing whether or not it's an
-        executable or a directory so the shell treats .. relative to $PWD
-        according to the physical/logical option.  The shell already
-        canonicalizes the directory name in order to tell readline where
-        to look, so not doing it here will be inconsistent. */
-      /* XXX -- currently not used -- will introduce more inconsistency,
-        since shell does not canonicalize ../foo before passing it to
-        shell_execve().  */
-      if (match && searching_path == 0 && *val == '.')
-       {
-         char *t, *t1;
-
-         t = get_working_directory ("command-word-completion");
-         t1 = make_absolute (val, t);
-         free (t);
-         cval = sh_canonpath (t1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
-       }
-      else
-#endif
-       cval = val;
-
-      if (match && executable_completion ((searching_path ? val : cval), searching_path))
-       {
-         if (cval != val)
-           free (cval);
-         free (val);
-         val = "";             /* So it won't be NULL. */
-         return (temp);
-       }
-      else
-       {
-         if (freetemp)
-           free (temp);
-         if (cval != val)
-           free (cval);
-         free (val);
-         goto inner;
-       }
-    }
-}
-
-/* Completion inside an unterminated command substitution. */
-static char *
-command_subst_completion_function (text, state)
-     const char *text;
-     int state;
-{
-  static char **matches = (char **)NULL;
-  static const char *orig_start;
-  static char *filename_text = (char *)NULL;
-  static int cmd_index, start_len;
-  char *value;
-
-  if (state == 0)
-    {
-      if (filename_text)
-       free (filename_text);
-      orig_start = text;
-      if (*text == '`')
-       text++;
-      else if (*text == '$' && text[1] == '(') /* ) */
-       text += 2;
-      /* If the text was quoted, suppress any quote character that the
-        readline completion code would insert. */
-      rl_completion_suppress_quote = 1;
-      start_len = text - orig_start;
-      filename_text = savestring (text);
-      if (matches)
-       free (matches);
-
-      /*
-       * At this point we can entertain the idea of re-parsing
-       * `filename_text' into a (possibly incomplete) command name and
-       * arguments, and doing completion based on that.  This is
-       * currently very rudimentary, but it is a small improvement.
-       */
-      for (value = filename_text + strlen (filename_text) - 1; value > filename_text; value--)
-        if (whitespace (*value) || member (*value, COMMAND_SEPARATORS))
-          break;
-      if (value <= filename_text)
-       matches = rl_completion_matches (filename_text, command_word_completion_function);
-      else
-       {
-         value++;
-         start_len += value - filename_text;
-         if (whitespace (value[-1]))
-           matches = rl_completion_matches (value, rl_filename_completion_function);
-         else
-           matches = rl_completion_matches (value, command_word_completion_function);
-       }
-
-      /* If there is more than one match, rl_completion_matches has already
-        put the lcd in matches[0].  Skip over it. */
-      cmd_index = matches && matches[0] && matches[1];
-
-      /* If there's a single match and it's a directory, set the append char
-        to the expected `/'.  Otherwise, don't append anything. */
-      if (matches && matches[0] && matches[1] == 0 && test_for_directory (matches[0]))
-       rl_completion_append_character = '/';
-      else
-       rl_completion_suppress_append = 1;
-    }
-
-  if (matches == 0 || matches[cmd_index] == 0)
-    {
-      rl_filename_quoting_desired = 0; /* disable quoting */
-      return ((char *)NULL);
-    }
-  else
-    {
-      value = (char *)xmalloc (1 + start_len + strlen (matches[cmd_index]));
-
-      if (start_len == 1)
-       value[0] = *orig_start;
-      else
-       strncpy (value, orig_start, start_len);
-
-      strcpy (value + start_len, matches[cmd_index]);
-
-      cmd_index++;
-      return (value);
-    }
-}
-
-/* Okay, now we write the entry_function for variable completion. */
-static char *
-variable_completion_function (text, state)
-     const char *text;
-     int state;
-{
-  static char **varlist = (char **)NULL;
-  static int varlist_index;
-  static char *varname = (char *)NULL;
-  static int namelen;
-  static int first_char, first_char_loc;
-
-  if (!state)
-    {
-      if (varname)
-       free (varname);
-
-      first_char_loc = 0;
-      first_char = text[0];
-
-      if (first_char == '$')
-       first_char_loc++;
-
-      if (text[first_char_loc] == '{')
-       first_char_loc++;
-
-      varname = savestring (text + first_char_loc);
-
-      namelen = strlen (varname);
-      if (varlist)
-       strvec_dispose (varlist);
-
-      varlist = all_variables_matching_prefix (varname);
-      varlist_index = 0;
-    }
-
-  if (!varlist || !varlist[varlist_index])
-    {
-      return ((char *)NULL);
-    }
-  else
-    {
-      char *value;
-
-      value = (char *)xmalloc (4 + strlen (varlist[varlist_index]));
-
-      if (first_char_loc)
-       {
-         value[0] = first_char;
-         if (first_char_loc == 2)
-           value[1] = '{';
-       }
-
-      strcpy (value + first_char_loc, varlist[varlist_index]);
-      if (first_char_loc == 2)
-       strcat (value, "}");
-
-      varlist_index++;
-      return (value);
-    }
-}
-
-/* How about a completion function for hostnames? */
-static char *
-hostname_completion_function (text, state)
-     const char *text;
-     int state;
-{
-  static char **list = (char **)NULL;
-  static int list_index = 0;
-  static int first_char, first_char_loc;
-
-  /* If we don't have any state, make some. */
-  if (state == 0)
-    {
-      FREE (list);
-
-      list = (char **)NULL;
-
-      first_char_loc = 0;
-      first_char = *text;
-
-      if (first_char == '@')
-       first_char_loc++;
-
-      list = hostnames_matching ((char *)text+first_char_loc);
-      list_index = 0;
-    }
-
-  if (list && list[list_index])
-    {
-      char *t;
-
-      t = (char *)xmalloc (2 + strlen (list[list_index]));
-      *t = first_char;
-      strcpy (t + first_char_loc, list[list_index]);
-      list_index++;
-      return (t);
-    }
-
-  return ((char *)NULL);
-}
-
-/*
- * A completion function for service names from /etc/services (or wherever).
- */
-char *
-bash_servicename_completion_function (text, state)
-     const char *text;
-     int state;
-{
-#if defined (__WIN32__) || defined (__OPENNT) || !defined (HAVE_GETSERVENT)
-  return ((char *)NULL);
-#else
-  static char *sname = (char *)NULL;
-  static struct servent *srvent;
-  static int snamelen, firstc;
-  char *value;
-  char **alist, *aentry;
-  int afound;
-
-  if (state == 0)
-    {
-      FREE (sname);
-      firstc = *text;
-
-      sname = savestring (text);
-      snamelen = strlen (sname);
-      setservent (0);
-    }
-
-  while (srvent = getservent ())
-    {
-      afound = 0;
-      if (snamelen == 0 || (STREQN (sname, srvent->s_name, snamelen)))
-       break;
-      /* Not primary, check aliases */
-      for (alist = srvent->s_aliases; *alist; alist++)
-       {
-         aentry = *alist;
-         if (STREQN (sname, aentry, snamelen))
-           {
-             afound = 1;
-             break;
-           }
-       }
-
-      if (afound)
-       break;
-    }
-
-  if (srvent == 0)
-    {
-      endservent ();
-      return ((char *)NULL);
-    }
-
-  value = afound ? savestring (aentry) : savestring (srvent->s_name);
-  return value;
-#endif
-}
-
-/*
- * A completion function for group names from /etc/group (or wherever).
- */
-char *
-bash_groupname_completion_function (text, state)
-     const char *text;
-     int state;
-{
-#if defined (__WIN32__) || defined (__OPENNT) || !defined (HAVE_GRP_H)
-  return ((char *)NULL);
-#else
-  static char *gname = (char *)NULL;
-  static struct group *grent;
-  static int gnamelen;
-  char *value;
-
-  if (state == 0)
-    {
-      FREE (gname);
-      gname = savestring (text);
-      gnamelen = strlen (gname);
-
-      setgrent ();
-    }
-
-  while (grent = getgrent ())
-    {
-      if (gnamelen == 0 || (STREQN (gname, grent->gr_name, gnamelen)))
-        break;
-    }
-
-  if (grent == 0)
-    {
-      endgrent ();
-      return ((char *)NULL);
-    }
-
-  value = savestring (grent->gr_name);
-  return (value);
-#endif
-}
-
-/* Functions to perform history and alias expansions on the current line. */
-
-#if defined (BANG_HISTORY)
-/* Perform history expansion on the current line.  If no history expansion
-   is done, pre_process_line() returns what it was passed, so we need to
-   allocate a new line here. */
-static char *
-history_expand_line_internal (line)
-     char *line;
-{
-  char *new_line;
-  int old_verify;
-
-  old_verify = hist_verify;
-  hist_verify = 0;
-  new_line = pre_process_line (line, 0, 0);
-  hist_verify = old_verify;
-
-  return (new_line == line) ? savestring (line) : new_line;
-}
-#endif
-
-/* There was an error in expansion.  Let the preprocessor print
-   the error here. */
-static void
-cleanup_expansion_error ()
-{
-  char *to_free;
-#if defined (BANG_HISTORY)
-  int old_verify;
-
-  old_verify = hist_verify;
-  hist_verify = 0;
-#endif
-
-  fprintf (rl_outstream, "\r\n");
-  to_free = pre_process_line (rl_line_buffer, 1, 0);
-#if defined (BANG_HISTORY)
-  hist_verify = old_verify;
-#endif
-  if (to_free != rl_line_buffer)
-    FREE (to_free);
-  putc ('\r', rl_outstream);
-  rl_forced_update_display ();
-}
-
-/* If NEW_LINE differs from what is in the readline line buffer, add an
-   undo record to get from the readline line buffer contents to the new
-   line and make NEW_LINE the current readline line. */
-static void
-maybe_make_readline_line (new_line)
-     char *new_line;
-{
-  if (strcmp (new_line, rl_line_buffer) != 0)
-    {
-      rl_point = rl_end;
-
-      rl_add_undo (UNDO_BEGIN, 0, 0, 0);
-      rl_delete_text (0, rl_point);
-      rl_point = rl_end = rl_mark = 0;
-      rl_insert_text (new_line);
-      rl_add_undo (UNDO_END, 0, 0, 0);
-    }
-}
-
-/* Make NEW_LINE be the current readline line.  This frees NEW_LINE. */
-static void
-set_up_new_line (new_line)
-     char *new_line;
-{
-  int old_point, at_end;
-
-  old_point = rl_point;
-  at_end = rl_point == rl_end;
-
-  /* If the line was history and alias expanded, then make that
-     be one thing to undo. */
-  maybe_make_readline_line (new_line);
-  free (new_line);
-
-  /* Place rl_point where we think it should go. */
-  if (at_end)
-    rl_point = rl_end;
-  else if (old_point < rl_end)
-    {
-      rl_point = old_point;
-      if (!whitespace (rl_line_buffer[rl_point]))
-       rl_forward_word (1, 0);
-    }
-}
-
-#if defined (ALIAS)
-/* Expand aliases in the current readline line. */
-static int
-alias_expand_line (count, ignore)
-     int count, ignore;
-{
-  char *new_line;
-
-  new_line = alias_expand (rl_line_buffer);
-
-  if (new_line)
-    {
-      set_up_new_line (new_line);
-      return (0);
-    }
-  else
-    {
-      cleanup_expansion_error ();
-      return (1);
-    }
-}
-#endif
-
-#if defined (BANG_HISTORY)
-/* History expand the line. */
-static int
-history_expand_line (count, ignore)
-     int count, ignore;
-{
-  char *new_line;
-
-  new_line = history_expand_line_internal (rl_line_buffer);
-
-  if (new_line)
-    {
-      set_up_new_line (new_line);
-      return (0);
-    }
-  else
-    {
-      cleanup_expansion_error ();
-      return (1);
-    }
-}
-
-/* Expand history substitutions in the current line and then insert a
-   space (hopefully close to where we were before). */
-static int
-tcsh_magic_space (count, ignore)
-     int count, ignore;
-{
-  int dist_from_end, old_point;
-
-  old_point = rl_point;
-  dist_from_end = rl_end - rl_point;
-  if (history_expand_line (count, ignore) == 0)
-    {
-      /* Try a simple heuristic from Stephen Gildea <gildea@intouchsys.com>.
-        This works if all expansions were before rl_point or if no expansions
-        were performed. */
-      rl_point = (old_point == 0) ? old_point : rl_end - dist_from_end;
-      rl_insert (1, ' ');
-      return (0);
-    }
-  else
-    return (1);
-}
-#endif /* BANG_HISTORY */
-
-/* History and alias expand the line. */
-static int
-history_and_alias_expand_line (count, ignore)
-     int count, ignore;
-{
-  char *new_line;
-
-  new_line = 0;
-#if defined (BANG_HISTORY)
-  new_line = history_expand_line_internal (rl_line_buffer);
-#endif
-
-#if defined (ALIAS)
-  if (new_line)
-    {
-      char *alias_line;
-
-      alias_line = alias_expand (new_line);
-      free (new_line);
-      new_line = alias_line;
-    }
-#endif /* ALIAS */
-
-  if (new_line)
-    {
-      set_up_new_line (new_line);
-      return (0);
-    }
-  else
-    {
-      cleanup_expansion_error ();
-      return (1);
-    }
-}
-
-/* History and alias expand the line, then perform the shell word
-   expansions by calling expand_string.  This can't use set_up_new_line()
-   because we want the variable expansions as a separate undo'able
-   set of operations. */
-static int
-shell_expand_line (count, ignore)
-     int count, ignore;
-{
-  char *new_line;
-  WORD_LIST *expanded_string;
-
-  new_line = 0;
-#if defined (BANG_HISTORY)
-  new_line = history_expand_line_internal (rl_line_buffer);
-#endif
-
-#if defined (ALIAS)
-  if (new_line)
-    {
-      char *alias_line;
-
-      alias_line = alias_expand (new_line);
-      free (new_line);
-      new_line = alias_line;
-    }
-#endif /* ALIAS */
-
-  if (new_line)
-    {
-      int old_point = rl_point;
-      int at_end = rl_point == rl_end;
-
-      /* If the line was history and alias expanded, then make that
-        be one thing to undo. */
-      maybe_make_readline_line (new_line);
-      free (new_line);
-
-      /* If there is variable expansion to perform, do that as a separate
-        operation to be undone. */
-      new_line = savestring (rl_line_buffer);
-      expanded_string = expand_string (new_line, 0);
-      FREE (new_line);
-      if (expanded_string == 0)
-       {
-         new_line = (char *)xmalloc (1);
-         new_line[0] = '\0';
-       }
-      else
-       {
-         new_line = string_list (expanded_string);
-         dispose_words (expanded_string);
-       }
-
-      maybe_make_readline_line (new_line);
-      free (new_line);
-
-      /* Place rl_point where we think it should go. */
-      if (at_end)
-       rl_point = rl_end;
-      else if (old_point < rl_end)
-       {
-         rl_point = old_point;
-         if (!whitespace (rl_line_buffer[rl_point]))
-           rl_forward_word (1, 0);
-       }
-      return 0;
-    }
-  else
-    {
-      cleanup_expansion_error ();
-      return 1;
-    }
-}
-
-/* If FIGNORE is set, then don't match files with the given suffixes when
-   completing filenames.  If only one of the possibilities has an acceptable
-   suffix, delete the others, else just return and let the completer
-   signal an error.  It is called by the completer when real
-   completions are done on filenames by the completer's internal
-   function, not for completion lists (M-?) and not on "other"
-   completion types, such as hostnames or commands. */
-
-static struct ignorevar fignore =
-{
-  "FIGNORE",
-  (struct ign *)0,
-  0,
-  (char *)0,
-  (sh_iv_item_func_t *) 0,
-};
-
-static void
-_ignore_completion_names (names, name_func)
-     char **names;
-     sh_ignore_func_t *name_func;
-{
-  char **newnames;
-  int idx, nidx;
-  char **oldnames;
-  int oidx;
-
-  /* If there is only one completion, see if it is acceptable.  If it is
-     not, free it up.  In any case, short-circuit and return.  This is a
-     special case because names[0] is not the prefix of the list of names
-     if there is only one completion; it is the completion itself. */
-  if (names[1] == (char *)0)
-    {
-      if (force_fignore)
-       if ((*name_func) (names[0]) == 0)
-         {
-           free (names[0]);
-           names[0] = (char *)NULL;
-         }
-
-      return;
-    }
-
-  /* Allocate space for array to hold list of pointers to matching
-     filenames.  The pointers are copied back to NAMES when done. */
-  for (nidx = 1; names[nidx]; nidx++)
-    ;
-  newnames = strvec_create (nidx + 1);
-
-  if (force_fignore == 0)
-    {
-      oldnames = strvec_create (nidx - 1);
-      oidx = 0;
-    }
-
-  newnames[0] = names[0];
-  for (idx = nidx = 1; names[idx]; idx++)
-    {
-      if ((*name_func) (names[idx]))
-       newnames[nidx++] = names[idx];
-      else if (force_fignore == 0)
-       oldnames[oidx++] = names[idx];
-      else
-       free (names[idx]);
-    }
-
-  newnames[nidx] = (char *)NULL;
-
-  /* If none are acceptable then let the completer handle it. */
-  if (nidx == 1)
-    {
-      if (force_fignore)
-       {
-         free (names[0]);
-         names[0] = (char *)NULL;
-       }
-      else
-       free (oldnames);
-
-      free (newnames);
-      return;
-    }
-
-  if (force_fignore == 0)
-    {
-      while (oidx)
-       free (oldnames[--oidx]);
-      free (oldnames);
-    }
-
-  /* If only one is acceptable, copy it to names[0] and return. */
-  if (nidx == 2)
-    {
-      free (names[0]);
-      names[0] = newnames[1];
-      names[1] = (char *)NULL;
-      free (newnames);
-      return;
-    }
-
-  /* Copy the acceptable names back to NAMES, set the new array end,
-     and return. */
-  for (nidx = 1; newnames[nidx]; nidx++)
-    names[nidx] = newnames[nidx];
-  names[nidx] = (char *)NULL;
-  free (newnames);
-}
-
-static int
-name_is_acceptable (name)
-     const char *name;
-{
-  struct ign *p;
-  int nlen;
-
-  for (nlen = strlen (name), p = fignore.ignores; p->val; p++)
-    {
-      if (nlen > p->len && p->len > 0 && STREQ (p->val, &name[nlen - p->len]))
-       return (0);
-    }
-
-  return (1);
-}
-
-#if 0
-static int
-ignore_dot_names (name)
-     char *name;
-{
-  return (name[0] != '.');
-}
-#endif
-
-static int
-filename_completion_ignore (names)
-     char **names;
-{
-#if 0
-  if (glob_dot_filenames == 0)
-    _ignore_completion_names (names, ignore_dot_names);
-#endif
-
-  setup_ignore_patterns (&fignore);
-
-  if (fignore.num_ignores == 0)
-    return 0;
-
-  _ignore_completion_names (names, name_is_acceptable);
-
-  return 0;
-}
-
-/* Return 1 if NAME is a directory.  NAME undergoes tilde expansion. */
-static int
-test_for_directory (name)
-     const char *name;
-{
-  char *fn;
-  int r;
-
-  fn = bash_tilde_expand (name, 0);
-  r = file_isdir (fn);
-  free (fn);
-
-  return (r);
-}
-
-/* Remove files from NAMES, leaving directories. */
-static int
-bash_ignore_filenames (names)
-     char **names;
-{
-  _ignore_completion_names (names, test_for_directory);
-  return 0;
-}
-
-static int
-return_zero (name)
-     const char *name;
-{
-  return 0;
-}
-
-static int
-bash_ignore_everything (names)
-     char **names;
-{
-  _ignore_completion_names (names, return_zero);
-  return 0;
-}
-
-/* Replace a tilde-prefix in VAL with a `~', assuming the user typed it.  VAL
-   is an expanded filename.  DIRECTORY_PART is the tilde-prefix portion
-   of the un-tilde-expanded version of VAL (what the user typed). */
-static char *
-restore_tilde (val, directory_part)
-     char *val, *directory_part;
-{
-  int l, vl, dl2, xl;
-  char *dh2, *expdir, *ret;
-
-  vl = strlen (val);
-
-  /* We need to duplicate the expansions readline performs on the directory
-     portion before passing it to our completion function. */
-  dh2 = directory_part ? bash_dequote_filename (directory_part, 0) : 0;
-  bash_directory_expansion (&dh2);
-  dl2 = strlen (dh2);
-
-  expdir = bash_tilde_expand (directory_part, 0);
-  xl = strlen (expdir);
-  free (expdir);
-
-  /*
-     dh2 = unexpanded but dequoted tilde-prefix
-     dl2 = length of tilde-prefix
-     expdir = tilde-expanded tilde-prefix
-     xl = length of expanded tilde-prefix
-     l = length of remainder after tilde-prefix
-  */
-  l = (vl - xl) + 1;
-
-  ret = (char *)xmalloc (dl2 + 2 + l);
-  strcpy (ret, dh2);
-  strcpy (ret + dl2, val + xl);
-
-  free (dh2);
-  return (ret);
-}
-
-/* Simulate the expansions that will be performed by
-   rl_filename_completion_function.  This must be called with the address of
-   a pointer to malloc'd memory. */
-static void
-bash_directory_expansion (dirname)
-     char **dirname;
-{
-  char *d, *nd;
-
-  d = savestring (*dirname);
-
-  if ((rl_directory_rewrite_hook) && (*rl_directory_rewrite_hook) (&d))
-    {
-      free (*dirname);
-      *dirname = d;
-    }
-  else if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&d))
-    {
-      free (*dirname);
-      *dirname = d;
-    }
-  else if (rl_completion_found_quote)
-    {
-      nd = bash_dequote_filename (d, rl_completion_quote_character);
-      free (*dirname);
-      free (d);
-      *dirname = nd;
-    }
-}
-
-/* If necessary, rewrite directory entry */
-static char *
-bash_filename_rewrite_hook (fname, fnlen)
-     char *fname;
-     int fnlen;
-{
-  char *conv;
-
-  conv = fnx_fromfs (fname, fnlen);
-  if (conv != fname)
-    conv = savestring (conv);
-  return conv;
-}
-
-/* Functions to save and restore the appropriate directory hook */
-/* This is not static so the shopt code can call it */
-void
-set_directory_hook ()
-{
-  if (dircomplete_expand)
-    {
-      rl_directory_completion_hook = bash_directory_completion_hook;
-      rl_directory_rewrite_hook = (rl_icppfunc_t *)0;
-    }
-  else
-    {
-      rl_directory_rewrite_hook = bash_directory_completion_hook;
-      rl_directory_completion_hook = (rl_icppfunc_t *)0;
-    }
-}
-
-static rl_icppfunc_t *
-save_directory_hook ()
-{
-  rl_icppfunc_t *ret;
-
-  if (dircomplete_expand)
-    {
-      ret = rl_directory_completion_hook;
-      rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
-    }
-  else
-    {
-      ret = rl_directory_rewrite_hook;
-      rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
-    }
-
-  return ret;
-}
-
-static void
-restore_directory_hook (hookf)
-     rl_icppfunc_t *hookf;
-{
-  if (dircomplete_expand)
-    rl_directory_completion_hook = hookf;
-  else
-    rl_directory_rewrite_hook = hookf;
-}
-
-/* Expand a filename before the readline completion code passes it to stat(2).
-   The filename will already have had tilde expansion performed. */
-static int
-bash_filename_stat_hook (dirname)
-     char **dirname;
-{
-  char *local_dirname, *new_dirname, *t;
-  int should_expand_dirname, return_value;
-  WORD_LIST *wl;
-  struct stat sb;
-
-  local_dirname = *dirname;
-  should_expand_dirname = return_value = 0;
-  if (t = mbschr (local_dirname, '$'))
-    should_expand_dirname = '$';
-  else if (t = mbschr (local_dirname, '`'))    /* XXX */
-    should_expand_dirname = '`';
-
-#if defined (HAVE_LSTAT)
-  if (should_expand_dirname && lstat (local_dirname, &sb) == 0)
-#else
-  if (should_expand_dirname && stat (local_dirname, &sb) == 0)
-#endif
-    should_expand_dirname = 0;
-  
-  if (should_expand_dirname)  
-    {
-      new_dirname = savestring (local_dirname);
-      wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB);  /* does the right thing */
-      if (wl)
-       {
-         free (new_dirname);
-         new_dirname = string_list (wl);
-         /* Tell the completer we actually expanded something and change
-            *dirname only if we expanded to something non-null -- stat
-            behaves unpredictably when passed null or empty strings */
-         if (new_dirname && *new_dirname)
-           {
-             free (local_dirname);     /* XXX */
-             local_dirname = *dirname = new_dirname;
-             return_value = STREQ (local_dirname, *dirname) == 0;
-           }
-         else
-           free (new_dirname);
-         dispose_words (wl);
-       }
-      else
-       free (new_dirname);
-    }  
-
-  /* This is very similar to the code in bash_directory_completion_hook below,
-     but without spelling correction and not worrying about whether or not
-     we change relative pathnames. */
-  if (no_symbolic_links == 0 && (local_dirname[0] != '.' || local_dirname[1]))
-    {
-      char *temp1, *temp2;
-
-      t = get_working_directory ("symlink-hook");
-      temp1 = make_absolute (local_dirname, t);
-      free (t);
-      temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
-
-      /* If we can't canonicalize, bail. */
-      if (temp2 == 0)
-       {
-         free (temp1);
-         return return_value;
-       }
-
-      free (local_dirname);
-      *dirname = temp2;
-      free (temp1);
-    }
-
-  return (return_value);
-}
-
-/* Handle symbolic link references and other directory name
-   expansions while hacking completion.  This should return 1 if it modifies
-   the DIRNAME argument, 0 otherwise.  It should make sure not to modify
-   DIRNAME if it returns 0. */
-static int
-bash_directory_completion_hook (dirname)
-     char **dirname;
-{
-  char *local_dirname, *new_dirname, *t;
-  int return_value, should_expand_dirname, nextch, closer;
-  WORD_LIST *wl;
-  struct stat sb;
-
-  return_value = should_expand_dirname = nextch = closer = 0;
-  local_dirname = *dirname;
-
-  if (t = mbschr (local_dirname, '$'))
-    {
-      should_expand_dirname = '$';
-      nextch = t[1];
-      /* Deliberately does not handle the deprecated $[...] arithmetic
-        expansion syntax */
-      if (nextch == '(')
-       closer = ')';
-      else if (nextch == '{')
-       closer = '}';
-      else
-       nextch = 0;
-    }
-  else if (local_dirname[0] == '~')
-    should_expand_dirname = '~';
-  else
-    {
-      t = mbschr (local_dirname, '`');
-      if (t && unclosed_pair (local_dirname, strlen (local_dirname), "`") == 0)
-       should_expand_dirname = '`';
-    }
-
-#if defined (HAVE_LSTAT)
-  if (should_expand_dirname && lstat (local_dirname, &sb) == 0)
-#else
-  if (should_expand_dirname && stat (local_dirname, &sb) == 0)
-#endif
-    should_expand_dirname = 0;
-
-  if (should_expand_dirname)  
-    {
-      new_dirname = savestring (local_dirname);
-      wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB);  /* does the right thing */
-      if (wl)
-       {
-         *dirname = string_list (wl);
-         /* Tell the completer to replace the directory name only if we
-            actually expanded something. */
-         return_value = STREQ (local_dirname, *dirname) == 0;
-         free (local_dirname);
-         free (new_dirname);
-         dispose_words (wl);
-         local_dirname = *dirname;
-         /* XXX - change rl_filename_quote_characters here based on
-            should_expand_dirname/nextch/closer.  This is the only place
-            custom_filename_quote_characters is modified. */
-         if (rl_filename_quote_characters && *rl_filename_quote_characters)
-           {
-             int i, j, c;
-             i = strlen (default_filename_quote_characters);
-             custom_filename_quote_characters = xrealloc (custom_filename_quote_characters, i+1);
-             for (i = j = 0; c = default_filename_quote_characters[i]; i++)
-               {
-                 if (c == should_expand_dirname || c == nextch || c == closer)
-                   continue;
-                 custom_filename_quote_characters[j++] = c;
-               }
-             custom_filename_quote_characters[j] = '\0';
-             rl_filename_quote_characters = custom_filename_quote_characters;
-             set_filename_bstab (rl_filename_quote_characters);
-           }
-       }
-      else
-       {
-         free (new_dirname);
-         free (local_dirname);
-         *dirname = (char *)xmalloc (1);
-         **dirname = '\0';
-         return 1;
-       }
-    }
-  else 
-    {
-      /* Dequote the filename even if we don't expand it. */
-      new_dirname = bash_dequote_filename (local_dirname, rl_completion_quote_character);
-      return_value = STREQ (local_dirname, new_dirname) == 0;
-      free (local_dirname);
-      local_dirname = *dirname = new_dirname;
-    }
-
-  /* no_symbolic_links == 0 -> use (default) logical view of the file system.
-     local_dirname[0] == '.' && local_dirname[1] == '/' means files in the
-     current directory (./).
-     local_dirname[0] == '.' && local_dirname[1] == 0 means relative pathnames
-     in the current directory (e.g., lib/sh).
-     XXX - should we do spelling correction on these? */
-
-  /* This is test as it was in bash-4.2: skip relative pathnames in current
-     directory.  Change test to
-      (local_dirname[0] != '.' || (local_dirname[1] && local_dirname[1] != '/'))
-     if we want to skip paths beginning with ./ also. */
-  if (no_symbolic_links == 0 && (local_dirname[0] != '.' || local_dirname[1]))
-    {
-      char *temp1, *temp2;
-      int len1, len2;
-
-      /* If we have a relative path
-               (local_dirname[0] != '/' && local_dirname[0] != '.')
-        that is canonical after appending it to the current directory, then
-               temp1 = temp2+'/'
-        That is,
-               strcmp (temp1, temp2) == 0
-        after adding a slash to temp2 below.  It should be safe to not
-        change those.
-      */
-      t = get_working_directory ("symlink-hook");
-      temp1 = make_absolute (local_dirname, t);
-      free (t);
-      temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
-
-      /* Try spelling correction if initial canonicalization fails.  Make
-        sure we are set to replace the directory name with the results so
-        subsequent directory checks don't fail. */
-      if (temp2 == 0 && dircomplete_spelling && dircomplete_expand)
-       {
-         temp2 = dirspell (temp1);
-         if (temp2)
-           {
-             free (temp1);
-             temp1 = temp2;
-             temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
-             return_value |= temp2 != 0;
-           }
-       }
-      /* If we can't canonicalize, bail. */
-      if (temp2 == 0)
-       {
-         free (temp1);
-         return return_value;
-       }
-      len1 = strlen (temp1);
-      if (temp1[len1 - 1] == '/')
-       {
-         len2 = strlen (temp2);
-         if (len2 > 2)         /* don't append `/' to `/' or `//' */
-           {
-             temp2 = (char *)xrealloc (temp2, len2 + 2);
-             temp2[len2] = '/';
-             temp2[len2 + 1] = '\0';
-           }
-       }
-
-      /* dircomplete_expand_relpath == 0 means we want to leave relative
-        pathnames that are unchanged by canonicalization alone.
-        *local_dirname != '/' && *local_dirname != '.' == relative pathname
-        (consistent with general.c:absolute_pathname())
-        temp1 == temp2 (after appending a slash to temp2) means the pathname
-        is not changed by canonicalization as described above. */
-      if (dircomplete_expand_relpath || ((local_dirname[0] != '/' && local_dirname[0] != '.') && STREQ (temp1, temp2) == 0))
-       return_value |= STREQ (local_dirname, temp2) == 0;
-      free (local_dirname);
-      *dirname = temp2;
-      free (temp1);
-    }
-
-  return (return_value);
-}
-
-static char **history_completion_array = (char **)NULL;
-static int harry_size;
-static int harry_len;
-
-static void
-build_history_completion_array ()
-{
-  register int i, j;
-  HIST_ENTRY **hlist;
-  char **tokens;
-
-  /* First, clear out the current dynamic history completion list. */
-  if (harry_size)
-    {
-      strvec_dispose (history_completion_array);
-      history_completion_array = (char **)NULL;
-      harry_size = 0;
-      harry_len = 0;
-    }
-
-  /* Next, grovel each line of history, making each shell-sized token
-     a separate entry in the history_completion_array. */
-  hlist = history_list ();
-
-  if (hlist)
-    {
-      for (i = 0; hlist[i]; i++)
-       ;
-      for ( --i; i >= 0; i--)
-       {
-         /* Separate each token, and place into an array. */
-         tokens = history_tokenize (hlist[i]->line);
-
-         for (j = 0; tokens && tokens[j]; j++)
-           {
-             if (harry_len + 2 > harry_size)
-               history_completion_array = strvec_resize (history_completion_array, harry_size += 10);
-
-             history_completion_array[harry_len++] = tokens[j];
-             history_completion_array[harry_len] = (char *)NULL;
-           }
-         free (tokens);
-       }
-
-      /* Sort the complete list of tokens. */
-      if (dabbrev_expand_active == 0)
-        qsort (history_completion_array, harry_len, sizeof (char *), (QSFUNC *)strvec_strcmp);
-    }
-}
-
-static char *
-history_completion_generator (hint_text, state)
-     const char *hint_text;
-     int state;
-{
-  static int local_index, len;
-  static const char *text;
-
-  /* If this is the first call to the generator, then initialize the
-     list of strings to complete over. */
-  if (state == 0)
-    {
-      if (dabbrev_expand_active)       /* This is kind of messy */
-       rl_completion_suppress_append = 1;
-      local_index = 0;
-      build_history_completion_array ();
-      text = hint_text;
-      len = strlen (text);
-    }
-
-  while (history_completion_array && history_completion_array[local_index])
-    {
-      if (strncmp (text, history_completion_array[local_index++], len) == 0)
-       return (savestring (history_completion_array[local_index - 1]));
-    }
-  return ((char *)NULL);
-}
-
-static int
-dynamic_complete_history (count, key)
-     int count, key;
-{
-  int r;
-  rl_compentry_func_t *orig_func;
-  rl_completion_func_t *orig_attempt_func;
-  rl_compignore_func_t *orig_ignore_func;
-
-  orig_func = rl_completion_entry_function;
-  orig_attempt_func = rl_attempted_completion_function;
-  orig_ignore_func = rl_ignore_some_completions_function;
-
-  rl_completion_entry_function = history_completion_generator;
-  rl_attempted_completion_function = (rl_completion_func_t *)NULL;
-  rl_ignore_some_completions_function = filename_completion_ignore;
-
-  /* XXX - use rl_completion_mode here? */
-  if (rl_last_func == dynamic_complete_history)
-    r = rl_complete_internal ('?');
-  else
-    r = rl_complete_internal (TAB);
-
-  rl_completion_entry_function = orig_func;
-  rl_attempted_completion_function = orig_attempt_func;
-  rl_ignore_some_completions_function = orig_ignore_func;
-
-  return r;
-}
-
-static int
-bash_dabbrev_expand (count, key)
-     int count, key;
-{
-  int r, orig_suppress, orig_sort;
-  rl_compentry_func_t *orig_func;
-  rl_completion_func_t *orig_attempt_func;
-  rl_compignore_func_t *orig_ignore_func;
-
-  orig_func = rl_menu_completion_entry_function;
-  orig_attempt_func = rl_attempted_completion_function;
-  orig_ignore_func = rl_ignore_some_completions_function;
-  orig_suppress = rl_completion_suppress_append;
-  orig_sort = rl_sort_completion_matches;
-
-  rl_menu_completion_entry_function = history_completion_generator;
-  rl_attempted_completion_function = (rl_completion_func_t *)NULL;
-  rl_ignore_some_completions_function = filename_completion_ignore;
-  rl_filename_completion_desired = 0;
-  rl_completion_suppress_append = 1;
-  rl_sort_completion_matches = 0;
-
-  /* XXX - use rl_completion_mode here? */
-  dabbrev_expand_active = 1;
-  if (rl_last_func == bash_dabbrev_expand)
-    rl_last_func = rl_menu_complete;
-  r = rl_menu_complete (count, key);
-  dabbrev_expand_active = 0;
-
-  rl_last_func = bash_dabbrev_expand;
-  rl_menu_completion_entry_function = orig_func;
-  rl_attempted_completion_function = orig_attempt_func;
-  rl_ignore_some_completions_function = orig_ignore_func;
-  rl_completion_suppress_append = orig_suppress;
-  rl_sort_completion_matches = orig_sort;
-
-  return r;
-}
-
-#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
-static int
-bash_complete_username (ignore, ignore2)
-     int ignore, ignore2;
-{
-  return bash_complete_username_internal (rl_completion_mode (bash_complete_username));
-}
-
-static int
-bash_possible_username_completions (ignore, ignore2)
-     int ignore, ignore2;
-{
-  return bash_complete_username_internal ('?');
-}
-
-static int
-bash_complete_username_internal (what_to_do)
-     int what_to_do;
-{
-  return bash_specific_completion (what_to_do, rl_username_completion_function);
-}
-
-static int
-bash_complete_filename (ignore, ignore2)
-     int ignore, ignore2;
-{
-  return bash_complete_filename_internal (rl_completion_mode (bash_complete_filename));
-}
-
-static int
-bash_possible_filename_completions (ignore, ignore2)
-     int ignore, ignore2;
-{
-  return bash_complete_filename_internal ('?');
-}
-
-static int
-bash_complete_filename_internal (what_to_do)
-     int what_to_do;
-{
-  rl_compentry_func_t *orig_func;
-  rl_completion_func_t *orig_attempt_func;
-  rl_icppfunc_t *orig_dir_func;
-  rl_compignore_func_t *orig_ignore_func;
-  /*const*/ char *orig_rl_completer_word_break_characters;
-  int r;
-
-  orig_func = rl_completion_entry_function;
-  orig_attempt_func = rl_attempted_completion_function;
-  orig_ignore_func = rl_ignore_some_completions_function;
-  orig_rl_completer_word_break_characters = rl_completer_word_break_characters;
-
-  orig_dir_func = save_directory_hook ();
-
-  rl_completion_entry_function = rl_filename_completion_function;
-  rl_attempted_completion_function = (rl_completion_func_t *)NULL;
-  rl_ignore_some_completions_function = filename_completion_ignore;
-  rl_completer_word_break_characters = " \t\n\"\'";
-
-  r = rl_complete_internal (what_to_do);
-
-  rl_completion_entry_function = orig_func;
-  rl_attempted_completion_function = orig_attempt_func;
-  rl_ignore_some_completions_function = orig_ignore_func;
-  rl_completer_word_break_characters = orig_rl_completer_word_break_characters;
-
-  restore_directory_hook (orig_dir_func);
-
-  return r;
-}
-
-static int
-bash_complete_hostname (ignore, ignore2)
-     int ignore, ignore2;
-{
-  return bash_complete_hostname_internal (rl_completion_mode (bash_complete_hostname));
-}
-
-static int
-bash_possible_hostname_completions (ignore, ignore2)
-     int ignore, ignore2;
-{
-  return bash_complete_hostname_internal ('?');
-}
-
-static int
-bash_complete_variable (ignore, ignore2)
-     int ignore, ignore2;
-{
-  return bash_complete_variable_internal (rl_completion_mode (bash_complete_variable));
-}
-
-static int
-bash_possible_variable_completions (ignore, ignore2)
-     int ignore, ignore2;
-{
-  return bash_complete_variable_internal ('?');
-}
-
-static int
-bash_complete_command (ignore, ignore2)
-     int ignore, ignore2;
-{
-  return bash_complete_command_internal (rl_completion_mode (bash_complete_command));
-}
-
-static int
-bash_possible_command_completions (ignore, ignore2)
-     int ignore, ignore2;
-{
-  return bash_complete_command_internal ('?');
-}
-
-static int
-bash_complete_hostname_internal (what_to_do)
-     int what_to_do;
-{
-  return bash_specific_completion (what_to_do, hostname_completion_function);
-}
-
-static int
-bash_complete_variable_internal (what_to_do)
-     int what_to_do;
-{
-  return bash_specific_completion (what_to_do, variable_completion_function);
-}
-
-static int
-bash_complete_command_internal (what_to_do)
-     int what_to_do;
-{
-  return bash_specific_completion (what_to_do, command_word_completion_function);
-}
-
-static char *globtext;
-static char *globorig;
-
-static char *
-glob_complete_word (text, state)
-     const char *text;
-     int state;
-{
-  static char **matches = (char **)NULL;
-  static int ind;
-  int glen;
-  char *ret, *ttext;
-
-  if (state == 0)
-    {
-      rl_filename_completion_desired = 1;
-      FREE (matches);
-      if (globorig != globtext)
-       FREE (globorig);
-      FREE (globtext);
-
-      ttext = bash_tilde_expand (text, 0);
-
-      if (rl_explicit_arg)
-       {
-         globorig = savestring (ttext);
-         glen = strlen (ttext);
-         globtext = (char *)xmalloc (glen + 2);
-         strcpy (globtext, ttext);
-         globtext[glen] = '*';
-         globtext[glen+1] = '\0';
-       }
-      else
-        globtext = globorig = savestring (ttext);
-
-      if (ttext != text)
-       free (ttext);
-
-      matches = shell_glob_filename (globtext);
-      if (GLOB_FAILED (matches))
-       matches = (char **)NULL;
-      ind = 0;
-    }
-
-  ret = matches ? matches[ind] : (char *)NULL;
-  ind++;
-  return ret;
-}
-
-static int
-bash_glob_completion_internal (what_to_do)
-     int what_to_do;
-{
-  return bash_specific_completion (what_to_do, glob_complete_word);
-}
-
-/* A special quoting function so we don't end up quoting globbing characters
-   in the word if there are no matches or multiple matches. */
-static char *
-bash_glob_quote_filename (s, rtype, qcp)
-     char *s;
-     int rtype;
-     char *qcp;
-{
-  if (globorig && qcp && *qcp == '\0' && STREQ (s, globorig))
-    return (savestring (s));
-  else
-    return (bash_quote_filename (s, rtype, qcp));
-}
-
-static int
-bash_glob_complete_word (count, key)
-     int count, key;
-{
-  int r;
-  rl_quote_func_t *orig_quoting_function;
-
-  if (rl_editing_mode == EMACS_EDITING_MODE)
-    rl_explicit_arg = 1;       /* force `*' append */
-  orig_quoting_function = rl_filename_quoting_function;
-  rl_filename_quoting_function = bash_glob_quote_filename;
-  
-  r = bash_glob_completion_internal (rl_completion_mode (bash_glob_complete_word));
-
-  rl_filename_quoting_function = orig_quoting_function;
-  return r;
-}
-
-static int
-bash_glob_expand_word (count, key)
-     int count, key;
-{
-  return bash_glob_completion_internal ('*');
-}
-
-static int
-bash_glob_list_expansions (count, key)
-     int count, key;
-{
-  return bash_glob_completion_internal ('?');
-}
-
-static int
-bash_specific_completion (what_to_do, generator)
-     int what_to_do;
-     rl_compentry_func_t *generator;
-{
-  rl_compentry_func_t *orig_func;
-  rl_completion_func_t *orig_attempt_func;
-  rl_compignore_func_t *orig_ignore_func;
-  int r;
-
-  orig_func = rl_completion_entry_function;
-  orig_attempt_func = rl_attempted_completion_function;
-  orig_ignore_func = rl_ignore_some_completions_function;
-  rl_completion_entry_function = generator;
-  rl_attempted_completion_function = NULL;
-  rl_ignore_some_completions_function = orig_ignore_func;
-
-  r = rl_complete_internal (what_to_do);
-
-  rl_completion_entry_function = orig_func;
-  rl_attempted_completion_function = orig_attempt_func;
-  rl_ignore_some_completions_function = orig_ignore_func;
-
-  return r;
-}
-
-#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
-
-#if defined (VI_MODE)
-/* Completion, from vi mode's point of view.  This is a modified version of
-   rl_vi_complete which uses the bash globbing code to implement what POSIX
-   specifies, which is to append a `*' and attempt filename generation (which
-   has the side effect of expanding any globbing characters in the word). */
-static int
-bash_vi_complete (count, key)
-     int count, key;
-{
-#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
-  int p, r;
-  char *t;
-
-  if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
-    {
-      if (!whitespace (rl_line_buffer[rl_point + 1]))
-       rl_vi_end_word (1, 'E');
-      rl_point++;
-    }
-
-  /* Find boundaries of current word, according to vi definition of a
-     `bigword'. */
-  t = 0;
-  if (rl_point > 0)
-    {
-      p = rl_point;
-      rl_vi_bWord (1, 'B');
-      r = rl_point;
-      rl_point = p;
-      p = r;
-
-      t = substring (rl_line_buffer, p, rl_point);
-    }      
-
-  if (t && glob_pattern_p (t) == 0)
-    rl_explicit_arg = 1;       /* XXX - force glob_complete_word to append `*' */
-  FREE (t);
-
-  if (key == '*')      /* Expansion and replacement. */
-    r = bash_glob_expand_word (count, key);
-  else if (key == '=') /* List possible completions. */
-    r = bash_glob_list_expansions (count, key);
-  else if (key == '\\')        /* Standard completion */
-    r = bash_glob_complete_word (count, key);
-  else
-    r = rl_complete (0, key);
-
-  if (key == '*' || key == '\\')
-    rl_vi_start_inserting (key, 1, 1);
-
-  return (r);
-#else
-  return rl_vi_complete (count, key);
-#endif /* !SPECIFIC_COMPLETION_FUNCTIONS */
-}
-#endif /* VI_MODE */
-
-/* Filename quoting for completion. */
-/* A function to strip unquoted quote characters (single quotes, double
-   quotes, and backslashes).  It allows single quotes to appear
-   within double quotes, and vice versa.  It should be smarter. */
-static char *
-bash_dequote_filename (text, quote_char)
-     char *text;
-     int quote_char;
-{
-  char *ret, *p, *r;
-  int l, quoted;
-
-  l = strlen (text);
-  ret = (char *)xmalloc (l + 1);
-  for (quoted = quote_char, p = text, r = ret; p && *p; p++)
-    {
-      /* Allow backslash-escaped characters to pass through unscathed. */
-      if (*p == '\\')
-       {
-         /* Backslashes are preserved within single quotes. */
-         if (quoted == '\'')
-           *r++ = *p;
-         /* Backslashes are preserved within double quotes unless the
-            character is one that is defined to be escaped */
-         else if (quoted == '"' && ((sh_syntaxtab[p[1]] & CBSDQUOTE) == 0))
-           *r++ = *p;
-
-         *r++ = *++p;
-         if (*p == '\0')
-           return ret;         /* XXX - was break; */
-         continue;
-       }
-      /* Close quote. */
-      if (quoted && *p == quoted)
-       {
-         quoted = 0;
-         continue;
-       }
-      /* Open quote. */
-      if (quoted == 0 && (*p == '\'' || *p == '"'))
-       {
-         quoted = *p;
-         continue;
-       }
-      *r++ = *p;
-    }
-  *r = '\0';
-  return ret;
-}
-
-/* Quote characters that the readline completion code would treat as
-   word break characters with backslashes.  Pass backslash-quoted
-   characters through without examination. */
-static char *
-quote_word_break_chars (text)
-     char *text;
-{
-  char *ret, *r, *s;
-  int l;
-
-  l = strlen (text);
-  ret = (char *)xmalloc ((2 * l) + 1);
-  for (s = text, r = ret; *s; s++)
-    {
-      /* Pass backslash-quoted characters through, including the backslash. */
-      if (*s == '\\')
-       {
-         *r++ = '\\';
-         *r++ = *++s;
-         if (*s == '\0')
-           break;
-         continue;
-       }
-      /* OK, we have an unquoted character.  Check its presence in
-        rl_completer_word_break_characters. */
-      if (mbschr (rl_completer_word_break_characters, *s))
-       *r++ = '\\';
-      /* XXX -- check for standalone tildes here and backslash-quote them */
-      if (s == text && *s == '~' && file_exists (text))
-        *r++ = '\\';
-      *r++ = *s;
-    }
-  *r = '\0';
-  return ret;
-}
-
-/* Use characters in STRING to populate the table of characters that should
-   be backslash-quoted.  The table will be used for sh_backslash_quote from
-   this file. */
-static void
-set_filename_bstab (string)
-     const char *string;
-{
-  const char *s;
-
-  memset (filename_bstab, 0, sizeof (filename_bstab));
-  for (s = string; s && *s; s++)
-    filename_bstab[*s] = 1;
-}
-
-/* Quote a filename using double quotes, single quotes, or backslashes
-   depending on the value of completion_quoting_style.  If we're
-   completing using backslashes, we need to quote some additional
-   characters (those that readline treats as word breaks), so we call
-   quote_word_break_chars on the result.  This returns newly-allocated
-   memory. */
-static char *
-bash_quote_filename (s, rtype, qcp)
-     char *s;
-     int rtype;
-     char *qcp;
-{
-  char *rtext, *mtext, *ret;
-  int rlen, cs;
-
-  rtext = (char *)NULL;
-
-  /* If RTYPE == MULT_MATCH, it means that there is
-     more than one match.  In this case, we do not add
-     the closing quote or attempt to perform tilde
-     expansion.  If RTYPE == SINGLE_MATCH, we try
-     to perform tilde expansion, because single and double
-     quotes inhibit tilde expansion by the shell. */
-
-  cs = completion_quoting_style;
-  /* Might need to modify the default completion style based on *qcp,
-     since it's set to any user-provided opening quote.  We also change
-     to single-quoting if there is no user-provided opening quote and
-     the word being completed contains newlines, since those are not
-     quoted correctly using backslashes (a backslash-newline pair is
-     special to the shell parser). */
-  if (*qcp == '\0' && cs == COMPLETE_BSQUOTE && mbschr (s, '\n'))
-    cs = COMPLETE_SQUOTE;
-  else if (*qcp == '"')
-    cs = COMPLETE_DQUOTE;
-  else if (*qcp == '\'')
-    cs = COMPLETE_SQUOTE;
-#if defined (BANG_HISTORY)
-  else if (*qcp == '\0' && history_expansion && cs == COMPLETE_DQUOTE &&
-          history_expansion_inhibited == 0 && mbschr (s, '!'))
-    cs = COMPLETE_BSQUOTE;
-
-  if (*qcp == '"' && history_expansion && cs == COMPLETE_DQUOTE &&
-       history_expansion_inhibited == 0 && mbschr (s, '!'))
-    {
-      cs = COMPLETE_BSQUOTE;
-      *qcp = '\0';
-    }
-#endif
-
-  /* Don't tilde-expand backslash-quoted filenames, since only single and
-     double quotes inhibit tilde expansion. */
-  mtext = s;
-  if (mtext[0] == '~' && rtype == SINGLE_MATCH && cs != COMPLETE_BSQUOTE)
-    mtext = bash_tilde_expand (s, 0);
-
-  switch (cs)
-    {
-    case COMPLETE_DQUOTE:
-      rtext = sh_double_quote (mtext);
-      break;
-    case COMPLETE_SQUOTE:
-      rtext = sh_single_quote (mtext);
-      break;
-    case COMPLETE_BSQUOTE:
-      rtext = sh_backslash_quote (mtext, complete_fullquote ? 0 : filename_bstab, 0);
-      break;
-    }
-
-  if (mtext != s)
-    free (mtext);
-
-  /* We may need to quote additional characters: those that readline treats
-     as word breaks that are not quoted by backslash_quote. */
-  if (rtext && cs == COMPLETE_BSQUOTE)
-    {
-      mtext = quote_word_break_chars (rtext);
-      free (rtext);
-      rtext = mtext;
-    }
-
-  /* Leave the opening quote intact.  The readline completion code takes
-     care of avoiding doubled opening quotes. */
-  if (rtext)
-    {
-      rlen = strlen (rtext);
-      ret = (char *)xmalloc (rlen + 1);
-      strcpy (ret, rtext);
-    }
-  else
-    {
-      ret = (char *)xmalloc (rlen = 1);
-      ret[0] = '\0';
-    }
-
-  /* If there are multiple matches, cut off the closing quote. */
-  if (rtype == MULT_MATCH && cs != COMPLETE_BSQUOTE)
-    ret[rlen - 1] = '\0';
-  free (rtext);
-  return ret;
-}
-
-/* Support for binding readline key sequences to Unix commands. */
-static Keymap cmd_xmap;
-
-#ifdef _MINIX
-static void
-#else
-static int
-#endif
-putx(c)
-     int c;
-{
-  int x;
-  x = putc (c, rl_outstream);
-#ifndef _MINIX
-  return x;
-#endif
-}
-  
-static int
-bash_execute_unix_command (count, key)
-     int count;        /* ignored */
-     int key;
-{
-  Keymap ckmap;                /* current keymap */
-  Keymap xkmap;                /* unix command executing keymap */
-  rl_command_func_t *func;
-  int type;
-  register int i, r;
-  intmax_t mi;
-  sh_parser_state_t ps;
-  char *cmd, *value, *l, *l1, *ce;
-  SHELL_VAR *v;
-  char ibuf[INT_STRLEN_BOUND(int) + 1];
-
-  /* First, we need to find the right command to execute.  This is tricky,
-     because we might have already indirected into another keymap, so we
-     have to walk cmd_xmap using the entire key sequence. */
-  cmd = (char *)rl_function_of_keyseq (rl_executing_keyseq, cmd_xmap, &type);
-    
-  if (cmd == 0 || type != ISMACR)
-    {
-      rl_crlf ();
-      internal_error (_("bash_execute_unix_command: cannot find keymap for command"));
-      rl_forced_update_display ();
-      return 1;
-    }
-
-  ce = rl_get_termcap ("ce");
-  if (ce)      /* clear current line */
-    {
-      fprintf (rl_outstream, "\r");
-      tputs (ce, 1, putx);
-      fflush (rl_outstream);
-    }
-  else
-    rl_crlf ();        /* move to a new line */
-
-  v = bind_variable ("READLINE_LINE", rl_line_buffer, 0);
-  if (v)
-    VSETATTR (v, att_exported);
-  l = v ? value_cell (v) : 0;
-  value = inttostr (rl_point, ibuf, sizeof (ibuf));
-  v = bind_int_variable ("READLINE_POINT", value);
-  if (v)
-    VSETATTR (v, att_exported);
-  array_needs_making = 1;
-
-  save_parser_state (&ps);
-  r = parse_and_execute (cmd, "bash_execute_unix_command", SEVAL_NOHIST|SEVAL_NOFREE);
-  restore_parser_state (&ps);
-
-  v = find_variable ("READLINE_LINE");
-  l1 = v ? value_cell (v) : 0;
-  if (l1 != l)
-    maybe_make_readline_line (value_cell (v));
-  v = find_variable ("READLINE_POINT");
-  if (v && legal_number (value_cell (v), &mi))
-    {
-      i = mi;
-      if (i != rl_point)
-       {
-         rl_point = i;
-         if (rl_point > rl_end)
-           rl_point = rl_end;
-         else if (rl_point < 0)
-           rl_point = 0;
-       }
-    }      
-
-  unbind_variable ("READLINE_LINE");
-  unbind_variable ("READLINE_POINT");
-  array_needs_making = 1;
-
-  /* and restore the readline buffer and display after command execution. */
-  rl_forced_update_display ();
-  return 0;
-}
-
-int
-print_unix_command_map ()
-{
-  Keymap save;
-
-  save = rl_get_keymap ();
-  rl_set_keymap (cmd_xmap);
-  rl_macro_dumper (1);
-  rl_set_keymap (save);
-  return 0;
-}
-
-static void
-init_unix_command_map ()
-{
-  cmd_xmap = rl_make_bare_keymap ();
-}
-
-static int
-isolate_sequence (string, ind, need_dquote, startp)
-     char *string;
-     int ind, need_dquote, *startp;
-{
-  register int i;
-  int c, passc, delim;
-
-  for (i = ind; string[i] && whitespace (string[i]); i++)
-    ;
-  /* NEED_DQUOTE means that the first non-white character *must* be `"'. */
-  if (need_dquote && string[i] != '"')
-    {
-      builtin_error (_("%s: first non-whitespace character is not `\"'"), string);
-      return -1;
-    }
-
-  /* We can have delimited strings even if NEED_DQUOTE == 0, like the command
-     string to bind the key sequence to. */
-  delim = (string[i] == '"' || string[i] == '\'') ? string[i] : 0;
-    
-  if (startp)
-    *startp = delim ? ++i : i;
-
-  for (passc = 0; c = string[i]; i++)
-    {
-      if (passc)
-       {
-         passc = 0;
-         continue;
-       }
-      if (c == '\\')
-       {
-         passc++;
-         continue;
-       }
-      if (c == delim)
-       break;
-    }
-
-  if (delim && string[i] != delim)
-    {
-      builtin_error (_("no closing `%c' in %s"), delim, string);
-      return -1;
-    }
-
-  return i;
-}
-
-int
-bind_keyseq_to_unix_command (line)
-     char *line;
-{
-  Keymap kmap;
-  char *kseq, *value;
-  int i, kstart;
-
-  if (cmd_xmap == 0)
-    init_unix_command_map ();
-
-  kmap = rl_get_keymap ();
-
-  /* We duplicate some of the work done by rl_parse_and_bind here, but
-     this code only has to handle `"keyseq": ["]command["]' and can
-     generate an error for anything else. */
-  i = isolate_sequence (line, 0, 1, &kstart);
-  if (i < 0)
-    return -1;
-
-  /* Create the key sequence string to pass to rl_generic_bind */
-  kseq = substring (line, kstart, i);
-
-  for ( ; line[i] && line[i] != ':'; i++)
-    ;
-  if (line[i] != ':')
-    {
-      builtin_error (_("%s: missing colon separator"), line);
-      FREE (kseq);
-      return -1;
-    }
-
-  i = isolate_sequence (line, i + 1, 0, &kstart);
-  if (i < 0)
-    {
-      FREE (kseq);
-      return -1;
-    }
-
-  /* Create the value string containing the command to execute. */
-  value = substring (line, kstart, i);
-
-  /* Save the command to execute and the key sequence in the CMD_XMAP */
-  rl_generic_bind (ISMACR, kseq, value, cmd_xmap);
-
-  /* and bind the key sequence in the current keymap to a function that
-     understands how to execute from CMD_XMAP */
-  rl_bind_keyseq_in_map (kseq, bash_execute_unix_command, kmap);
-
-  free (kseq);  
-  return 0;
-}
-
-/* Used by the programmable completion code.  Complete TEXT as a filename,
-   but return only directories as matches.  Dequotes the filename before
-   attempting to find matches. */
-char **
-bash_directory_completion_matches (text)
-     const char *text;
-{
-  char **m1;
-  char *dfn;
-  int qc;
-
-  qc = rl_dispatching ? rl_completion_quote_character : 0;  
-  dfn = bash_dequote_filename ((char *)text, qc);
-  m1 = rl_completion_matches (dfn, rl_filename_completion_function);
-  free (dfn);
-
-  if (m1 == 0 || m1[0] == 0)
-    return m1;
-  /* We don't bother recomputing the lcd of the matches, because it will just
-     get thrown away by the programmable completion code and recomputed
-     later. */
-  (void)bash_ignore_filenames (m1);
-  return m1;
-}
-
-char *
-bash_dequote_text (text)
-     const char *text;
-{
-  char *dtxt;
-  int qc;
-
-  qc = (text[0] == '"' || text[0] == '\'') ? text[0] : 0;
-  dtxt = bash_dequote_filename ((char *)text, qc);
-  return (dtxt);
-}
-
-/* This event hook is designed to be called after readline receives a signal
-   that interrupts read(2).  It gives reasonable responsiveness to interrupts
-   and fatal signals without executing too much code in a signal handler
-   context. */
-static int
-bash_event_hook ()
-{
-#if defined (DEBUG)
-itrace("bash_event_hook");
-#endif
-
-  /* If we're going to longjmp to top_level, make sure we clean up readline */
-  if (interrupt_state && signal_is_trapped (SIGINT) == 0)
-    rl_cleanup_after_signal ();
-
-  bashline_reset_event_hook ();
-  check_signals_and_traps ();  /* XXX */
-}
-
-#endif /* READLINE */
diff --git a/builtins/mapfile.def~ b/builtins/mapfile.def~
deleted file mode 100644 (file)
index 8de8a87..0000000
+++ /dev/null
@@ -1,359 +0,0 @@
-This file is mapfile.def, from which is created mapfile.c.
-It implements the builtin "mapfile" in Bash.
-
-Copyright (C) 2005-2006 Rocky Bernstein for Free Software Foundation, Inc.
-Copyright (C) 2008-2012 Free Software Foundation, Inc.
-
-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 mapfile.c
-
-$BUILTIN mapfile
-$FUNCTION mapfile_builtin
-$SHORT_DOC mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
-Read lines from the standard input into an indexed array variable.
-
-Read lines from the standard input into the indexed array variable ARRAY, or
-from file descriptor FD if the -u option is supplied.  The variable MAPFILE
-is the default ARRAY.
-
-Options:
-  -n count     Copy at most COUNT lines.  If COUNT is 0, all lines are copied.
-  -O origin    Begin assigning to ARRAY at index ORIGIN.  The default index is 0.
-  -s count     Discard the first COUNT lines read.
-  -t           Remove a trailing newline from each line read.
-  -u fd                Read lines from file descriptor FD instead of the standard input.
-  -C callback  Evaluate CALLBACK each time QUANTUM lines are read.
-  -c quantum   Specify the number of lines read between each call to CALLBACK.
-
-Arguments:
-  ARRAY                Array variable name to use for file data.
-
-If -C is supplied without -c, the default quantum is 5000.  When
-CALLBACK is evaluated, it is supplied the index of the next array
-element to be assigned and the line to be assigned to that element
-as additional arguments.
-
-If not supplied with an explicit origin, mapfile will clear ARRAY before
-assigning to it.
-
-Exit Status:
-Returns success unless an invalid option is given or ARRAY is readonly or
-not an indexed array.
-$END
-
-$BUILTIN readarray
-$FUNCTION mapfile_builtin
-$SHORT_DOC readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
-Read lines from a file into an array variable.
-
-A synonym for `mapfile'.
-$END
-
-#include <config.h>
-
-#include "builtins.h"
-#include "posixstat.h"
-
-#if defined (HAVE_UNISTD_H)
-#  include <unistd.h>
-#endif
-
-#include "bashansi.h"
-#include "bashintl.h"
-
-#include <stdio.h>
-#include <errno.h>
-
-#include "../bashintl.h"
-#include "../shell.h"
-#include "common.h"
-#include "bashgetopt.h"
-
-#if !defined (errno)
-extern int errno;
-#endif
-
-#if defined (ARRAY_VARS)
-
-static int run_callback __P((const char *, unsigned int, const char *));
-
-#define DEFAULT_ARRAY_NAME     "MAPFILE"
-#define DEFAULT_VARIABLE_NAME  "MAPLINE"       /* not used right now */
-
-/* The value specifying how frequently `mapfile'  calls the callback. */
-#define DEFAULT_QUANTUM 5000
-
-/* Values for FLAGS */
-#define MAPF_CLEARARRAY        0x01
-#define MAPF_CHOP      0x02
-
-static int
-run_callback (callback, curindex, curline)
-     const char *callback;
-     unsigned int curindex;
-     const char *curline;
-{
-  unsigned int execlen;
-  char  *execstr, *qline;
-  int flags;
-
-  qline = sh_single_quote (curline);
-  execlen = strlen (callback) + strlen (qline) + 10;
-  /* 1 for each space between %s and %d,
-     another 1 for the last nul char for C string. */
-  execlen += 3;
-  execstr = xmalloc (execlen);
-
-  flags = SEVAL_NOHIST;
-#if 0
-  if (interactive)
-    flags |= SEVAL_INTERACT;
-#endif
-  snprintf (execstr, execlen, "%s %d %s", callback, curindex, qline);
-  free (qline);
-  return evalstring (execstr, NULL, flags);
-}
-
-static void
-do_chop(line)
-     char * line;
-{
-  int length;
-
-  length = strlen (line);
-  if (length && line[length-1] == '\n') 
-    line[length-1] = '\0';
-}
-
-static int
-mapfile (fd, line_count_goal, origin, nskip, callback_quantum, callback, array_name, flags)
-     int fd;
-     long line_count_goal, origin, nskip, callback_quantum;
-     char *callback, *array_name;
-     int flags;
-{
-  char *line;
-  size_t line_length;
-  unsigned int array_index, line_count;
-  SHELL_VAR *entry;
-  int unbuffered_read;
-  
-  line = NULL;
-  line_length = 0;
-  unbuffered_read = 0;
-
-  /* The following check should be done before reading any lines.  Doing it
-     here allows us to call bind_array_element instead of bind_array_variable
-     and skip the variable lookup on every call. */
-  entry = find_or_make_array_variable (array_name, 1);
-  if (entry == 0 || readonly_p (entry) || noassign_p (entry))
-    {
-      if (entry && readonly_p (entry))
-       err_readonly (array_name);
-       
-      return (EXECUTION_FAILURE);
-    }
-  else if (array_p (entry) == 0)
-    {
-      builtin_error (_("%s: not an indexed array"), array_name);
-      return (EXECUTION_FAILURE);
-    }
-  else if (invisible_p (entry))
-    VUNSETATTR (entry, att_invisible); /* no longer invisible */
-      
-  if (flags & MAPF_CLEARARRAY)
-    array_flush (array_cell (entry));
-
-#ifndef __CYGWIN__
-  unbuffered_read = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE);
-#else
-  unbuffered_read = 1;
-#endif
-
-  zreset ();
-
-  /* Skip any lines at beginning of file? */
-  for (line_count = 0; line_count < nskip; line_count++)
-    if (zgetline (fd, &line, &line_length, unbuffered_read) < 0)
-      break;
-
-  line = 0;
-  line_length = 0;    
-
-  /* Reset the buffer for bash own stream */
-  for (array_index = origin, line_count = 1; 
-       zgetline (fd, &line, &line_length, unbuffered_read) != -1;
-       array_index++) 
-    {
-      /* Remove trailing newlines? */
-      if (flags & MAPF_CHOP)
-       do_chop (line);
-         
-      /* Has a callback been registered and if so is it time to call it? */
-      if (callback && line_count && (line_count % callback_quantum) == 0) 
-       {
-         run_callback (callback, array_index, line);
-
-         /* Reset the buffer for bash own stream. */
-         if (unbuffered_read == 0)
-           zsyncfd (fd);
-       }
-
-      bind_array_element (entry, array_index, line, 0);
-
-      /* Have we exceeded # of lines to store? */
-      line_count++;
-      if (line_count_goal != 0 && line_count > line_count_goal) 
-       break;
-    }
-
-  xfree (line);
-
-  if (unbuffered_read == 0)
-    zsyncfd (fd);
-
-  return EXECUTION_SUCCESS;
-}
-
-int
-mapfile_builtin (list)
-     WORD_LIST *list;
-{
-  int opt, code, fd, clear_array, flags;
-  intmax_t intval;
-  long lines, origin, nskip, callback_quantum;
-  char *array_name, *callback;
-
-  clear_array = 1;
-  fd = 0;
-  lines = origin = nskip = 0;
-  flags = MAPF_CLEARARRAY;
-  callback_quantum = DEFAULT_QUANTUM;
-  callback = 0;
-
-  reset_internal_getopt ();
-  while ((opt = internal_getopt (list, "u:n:O:tC:c:s:")) != -1)
-    {
-      switch (opt)
-       {
-       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 'n':
-         code = legal_number (list_optarg, &intval);
-         if (code == 0 || intval < 0 || intval != (unsigned)intval)
-           {
-             builtin_error (_("%s: invalid line count"), list_optarg);
-             return (EXECUTION_FAILURE);
-           }
-         else
-           lines = intval;
-         break;
-
-       case 'O':
-         code = legal_number (list_optarg, &intval);
-         if (code == 0 || intval < 0 || intval != (unsigned)intval)
-           {
-             builtin_error (_("%s: invalid array origin"), list_optarg);
-             return (EXECUTION_FAILURE);
-           }
-         else
-           origin = intval;
-         flags &= ~MAPF_CLEARARRAY;
-         break;
-       case 't':
-         flags |= MAPF_CHOP;
-         break;
-       case 'C':
-         callback = list_optarg;
-         break;
-       case 'c':
-         code = legal_number (list_optarg, &intval);
-         if (code == 0 || intval <= 0 || intval != (unsigned)intval)
-           {
-             builtin_error (_("%s: invalid callback quantum"), list_optarg);
-             return (EXECUTION_FAILURE);
-           }
-         else
-           callback_quantum = intval;
-         break;
-       case 's':
-         code = legal_number (list_optarg, &intval);
-         if (code == 0 || intval < 0 || intval != (unsigned)intval)
-           {
-             builtin_error (_("%s: invalid line count"), list_optarg);
-             return (EXECUTION_FAILURE);
-           }
-         else
-           nskip = intval;
-         break;
-       default:
-         builtin_usage ();
-         return (EX_USAGE);
-       }
-    }
-  list = loptend;
-
-  if (list == 0) 
-    array_name = DEFAULT_ARRAY_NAME;
-  else if (list->word == 0 || list->word->word == 0)
-    {
-      builtin_error ("internal error: getting variable name");
-      return (EXECUTION_FAILURE);
-    }
-  else if (list->word->word[0] == '\0')
-    {
-      builtin_error (_("empty array variable name"));
-      return (EX_USAGE);
-    } 
-  else
-    array_name = list->word->word;
-  
-  if (legal_identifier (array_name) == 0 && valid_array_reference (array_name) == 0)
-    {
-      sh_invalidid (array_name);
-      return (EXECUTION_FAILURE);
-    }
-
-  return mapfile (fd, lines, origin, nskip, callback_quantum, callback, array_name, flags);
-}
-
-#else
-
-int
-mapfile_builtin (list)
-     WORD_LIST *list;
-{
-  builtin_error (_("array variable support required"));
-  return (EXECUTION_FAILURE);
-}
-
-#endif  /* ARRAY_VARS */
diff --git a/command.h~ b/command.h~
deleted file mode 100644 (file)
index 8f5ce7d..0000000
+++ /dev/null
@@ -1,391 +0,0 @@
-/* command.h -- The structures used internally to represent commands, and
-   the extern declarations of the functions used to create them. */
-
-/* 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 (_COMMAND_H_)
-#define _COMMAND_H_
-
-#include "stdc.h"
-
-/* Instructions describing what kind of thing to do for a redirection. */
-enum r_instruction {
-  r_output_direction, r_input_direction, r_inputa_direction,
-  r_appending_to, r_reading_until, r_reading_string,
-  r_duplicating_input, r_duplicating_output, r_deblank_reading_until,
-  r_close_this, r_err_and_out, r_input_output, r_output_force,
-  r_duplicating_input_word, r_duplicating_output_word,
-  r_move_input, r_move_output, r_move_input_word, r_move_output_word,
-  r_append_err_and_out
-};
-
-/* Redirection flags; values for rflags */
-#define REDIR_VARASSIGN                0x01
-
-/* Redirection errors. */
-#define AMBIGUOUS_REDIRECT  -1
-#define NOCLOBBER_REDIRECT  -2
-#define RESTRICTED_REDIRECT -3 /* can only happen in restricted shells. */
-#define HEREDOC_REDIRECT    -4  /* here-doc temp file can't be created */
-#define BADVAR_REDIRECT            -5  /* something wrong with {varname}redir */
-
-#define CLOBBERING_REDIRECT(ri) \
-  (ri == r_output_direction || ri == r_err_and_out)
-
-#define OUTPUT_REDIRECT(ri) \
-  (ri == r_output_direction || ri == r_input_output || ri == r_err_and_out || ri == r_append_err_and_out)
-
-#define INPUT_REDIRECT(ri) \
-  (ri == r_input_direction || ri == r_inputa_direction || ri == r_input_output)
-
-#define WRITE_REDIRECT(ri) \
-  (ri == r_output_direction || \
-       ri == r_input_output || \
-       ri == r_err_and_out || \
-       ri == r_appending_to || \
-       ri == r_append_err_and_out || \
-       ri == r_output_force)
-
-/* redirection needs translation */
-#define TRANSLATE_REDIRECT(ri) \
-  (ri == r_duplicating_input_word || ri == r_duplicating_output_word || \
-   ri == r_move_input_word || ri == r_move_output_word)
-
-/* Command Types: */
-enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
-                   cm_connection, cm_function_def, cm_until, cm_group,
-                   cm_arith, cm_cond, cm_arith_for, cm_subshell, cm_coproc };
-
-/* Possible values for the `flags' field of a WORD_DESC. */
-#define W_HASDOLLAR    0x000001        /* Dollar sign present. */
-#define W_QUOTED       0x000002        /* Some form of quote character is present. */
-#define W_ASSIGNMENT   0x000004        /* This word is a variable assignment. */
-#define W_GLOBEXP      0x000008        /* This word is the result of a glob expansion. */
-#define W_NOSPLIT      0x000010        /* Do not perform word splitting on this word because ifs is empty string. */
-#define W_NOGLOB       0x000020        /* Do not perform globbing on this word. */
-#define W_NOSPLIT2     0x000040        /* Don't split word except for $@ expansion (using spaces) because context does not allow it. */
-#define W_TILDEEXP     0x000080        /* Tilde expand this assignment word */
-#define W_DOLLARAT     0x000100        /* $@ and its special handling */
-#define W_DOLLARSTAR   0x000200        /* $* and its special handling */
-#define W_NOCOMSUB     0x000400        /* Don't perform command substitution on this word */
-#define W_ASSIGNRHS    0x000800        /* Word is rhs of an assignment statement */
-#define W_NOTILDE      0x001000        /* Don't perform tilde expansion on this word */
-#define W_ITILDE       0x002000        /* Internal flag for word expansion */
-#define W_NOEXPAND     0x004000        /* Don't expand at all -- do quote removal */
-#define W_COMPASSIGN   0x008000        /* Compound assignment */
-#define W_ASSNBLTIN    0x010000        /* word is a builtin command that takes assignments */
-#define W_ASSIGNARG    0x020000        /* word is assignment argument to command */
-#define W_HASQUOTEDNULL        0x040000        /* word contains a quoted null character */
-#define W_DQUOTE       0x080000        /* word should be treated as if double-quoted */
-#define W_NOPROCSUB    0x100000        /* don't perform process substitution */
-#define W_HASCTLESC    0x200000        /* word contains literal CTLESC characters */
-#define W_ASSIGNASSOC  0x400000        /* word looks like associative array assignment */
-#define W_ASSIGNARRAY  0x800000        /* word looks like a compound indexed array assignment */
-#define W_ARRAYIND     0x1000000       /* word is an array index being expanded */
-#define W_ASSNGLOBAL   0x2000000       /* word is a global assignment to declare (declare/typeset -g) */
-#define W_NOBRACE      0x4000000       /* Don't perform brace expansion */
-
-/* Possible values for subshell_environment */
-#define SUBSHELL_ASYNC 0x01    /* subshell caused by `command &' */
-#define SUBSHELL_PAREN 0x02    /* subshell caused by ( ... ) */
-#define SUBSHELL_COMSUB        0x04    /* subshell caused by `command` or $(command) */
-#define SUBSHELL_FORK  0x08    /* subshell caused by executing a disk command */
-#define SUBSHELL_PIPE  0x10    /* subshell from a pipeline element */
-#define SUBSHELL_PROCSUB 0x20  /* subshell caused by <(command) or >(command) */
-#define SUBSHELL_COPROC        0x40    /* subshell from a coproc pipeline */
-#define SUBSHELL_RESETTRAP 0x80        /* subshell needs to reset trap strings on first call to trap */
-
-/* A structure which represents a word. */
-typedef struct word_desc {
-  char *word;          /* Zero terminated string. */
-  int flags;           /* Flags associated with this word. */
-} WORD_DESC;
-
-/* A linked list of words. */
-typedef struct word_list {
-  struct word_list *next;
-  WORD_DESC *word;
-} WORD_LIST;
-
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Shell Command Structs                       */
-/*                                                                 */
-/* **************************************************************** */
-
-/* What a redirection descriptor looks like.  If the redirection instruction
-   is ri_duplicating_input or ri_duplicating_output, use DEST, otherwise
-   use the file in FILENAME.  Out-of-range descriptors are identified by a
-   negative DEST. */
-
-typedef union {
-  int dest;                    /* Place to redirect REDIRECTOR to, or ... */
-  WORD_DESC *filename;         /* filename to redirect to. */
-} REDIRECTEE;
-
-/* Structure describing a redirection.  If REDIRECTOR is negative, the parser
-   (or translator in redir.c) encountered an out-of-range file descriptor. */
-typedef struct redirect {
-  struct redirect *next;       /* Next element, or NULL. */
-  REDIRECTEE redirector;       /* Descriptor or varname to be redirected. */
-  int rflags;                  /* Private flags for this redirection */
-  int flags;                   /* Flag value for `open'. */
-  enum r_instruction  instruction; /* What to do with the information. */
-  REDIRECTEE redirectee;       /* File descriptor or filename */
-  char *here_doc_eof;          /* The word that appeared in <<foo. */
-} REDIRECT;
-
-/* An element used in parsing.  A single word or a single redirection.
-   This is an ephemeral construct. */
-typedef struct element {
-  WORD_DESC *word;
-  REDIRECT *redirect;
-} ELEMENT;
-
-/* Possible values for command->flags. */
-#define CMD_WANT_SUBSHELL  0x01        /* User wants a subshell: ( command ) */
-#define CMD_FORCE_SUBSHELL 0x02        /* Shell needs to force a subshell. */
-#define CMD_INVERT_RETURN  0x04        /* Invert the exit value. */
-#define CMD_IGNORE_RETURN  0x08        /* Ignore the exit value.  For set -e. */
-#define CMD_NO_FUNCTIONS   0x10 /* Ignore functions during command lookup. */
-#define CMD_INHIBIT_EXPANSION 0x20 /* Do not expand the command words. */
-#define CMD_NO_FORK       0x40 /* Don't fork; just call execve */
-#define CMD_TIME_PIPELINE  0x80 /* Time a pipeline */
-#define CMD_TIME_POSIX    0x100 /* time -p; use POSIX.2 time output spec. */
-#define CMD_AMPERSAND     0x200 /* command & */
-#define CMD_STDIN_REDIR           0x400 /* async command needs implicit </dev/null */
-#define CMD_COMMAND_BUILTIN 0x0800 /* command executed by `command' builtin */
-#define CMD_COPROC_SUBSHELL 0x1000
-#define CMD_LASTPIPE       0x2000
-
-/* What a command looks like. */
-typedef struct command {
-  enum command_type type;      /* FOR CASE WHILE IF CONNECTION or SIMPLE. */
-  int flags;                   /* Flags controlling execution environment. */
-  int line;                    /* line number the command starts on */
-  REDIRECT *redirects;         /* Special redirects for FOR CASE, etc. */
-  union {
-    struct for_com *For;
-    struct case_com *Case;
-    struct while_com *While;
-    struct if_com *If;
-    struct connection *Connection;
-    struct simple_com *Simple;
-    struct function_def *Function_def;
-    struct group_com *Group;
-#if defined (SELECT_COMMAND)
-    struct select_com *Select;
-#endif
-#if defined (DPAREN_ARITHMETIC)
-    struct arith_com *Arith;
-#endif
-#if defined (COND_COMMAND)
-    struct cond_com *Cond;
-#endif
-#if defined (ARITH_FOR_COMMAND)
-    struct arith_for_com *ArithFor;
-#endif
-    struct subshell_com *Subshell;
-    struct coproc_com *Coproc;
-  } value;
-} COMMAND;
-
-/* Structure used to represent the CONNECTION type. */
-typedef struct connection {
-  int ignore;                  /* Unused; simplifies make_command (). */
-  COMMAND *first;              /* Pointer to the first command. */
-  COMMAND *second;             /* Pointer to the second command. */
-  int connector;               /* What separates this command from others. */
-} CONNECTION;
-
-/* Structures used to represent the CASE command. */
-
-/* Values for FLAGS word in a PATTERN_LIST */
-#define CASEPAT_FALLTHROUGH    0x01
-#define CASEPAT_TESTNEXT       0x02
-
-/* Pattern/action structure for CASE_COM. */
-typedef struct pattern_list {
-  struct pattern_list *next;   /* Clause to try in case this one failed. */
-  WORD_LIST *patterns;         /* Linked list of patterns to test. */
-  COMMAND *action;             /* Thing to execute if a pattern matches. */
-  int flags;
-} PATTERN_LIST;
-
-/* The CASE command. */
-typedef struct case_com {
-  int flags;                   /* See description of CMD flags. */
-  int line;                    /* line number the `case' keyword appears on */
-  WORD_DESC *word;             /* The thing to test. */
-  PATTERN_LIST *clauses;       /* The clauses to test against, or NULL. */
-} CASE_COM;
-
-/* FOR command. */
-typedef struct for_com {
-  int flags;           /* See description of CMD flags. */
-  int line;            /* line number the `for' keyword appears on */
-  WORD_DESC *name;     /* The variable name to get mapped over. */
-  WORD_LIST *map_list; /* The things to map over.  This is never NULL. */
-  COMMAND *action;     /* The action to execute.
-                          During execution, NAME is bound to successive
-                          members of MAP_LIST. */
-} FOR_COM;
-
-#if defined (ARITH_FOR_COMMAND)
-typedef struct arith_for_com {
-  int flags;
-  int line;    /* generally used for error messages */
-  WORD_LIST *init;
-  WORD_LIST *test;
-  WORD_LIST *step;
-  COMMAND *action;
-} ARITH_FOR_COM;
-#endif
-
-#if defined (SELECT_COMMAND)
-/* KSH SELECT command. */
-typedef struct select_com {
-  int flags;           /* See description of CMD flags. */
-  int line;            /* line number the `select' keyword appears on */
-  WORD_DESC *name;     /* The variable name to get mapped over. */
-  WORD_LIST *map_list; /* The things to map over.  This is never NULL. */
-  COMMAND *action;     /* The action to execute.
-                          During execution, NAME is bound to the member of
-                          MAP_LIST chosen by the user. */
-} SELECT_COM;
-#endif /* SELECT_COMMAND */
-
-/* IF command. */
-typedef struct if_com {
-  int flags;                   /* See description of CMD flags. */
-  COMMAND *test;               /* Thing to test. */
-  COMMAND *true_case;          /* What to do if the test returned non-zero. */
-  COMMAND *false_case;         /* What to do if the test returned zero. */
-} IF_COM;
-
-/* WHILE command. */
-typedef struct while_com {
-  int flags;                   /* See description of CMD flags. */
-  COMMAND *test;               /* Thing to test. */
-  COMMAND *action;             /* Thing to do while test is non-zero. */
-} WHILE_COM;
-
-#if defined (DPAREN_ARITHMETIC)
-/* The arithmetic evaluation command, ((...)).  Just a set of flags and
-   a WORD_LIST, of which the first element is the only one used, for the
-   time being. */
-typedef struct arith_com {
-  int flags;
-  int line;
-  WORD_LIST *exp;
-} ARITH_COM;
-#endif /* DPAREN_ARITHMETIC */
-
-/* The conditional command, [[...]].  This is a binary tree -- we slippped
-   a recursive-descent parser into the YACC grammar to parse it. */
-#define COND_AND       1
-#define COND_OR                2
-#define COND_UNARY     3
-#define COND_BINARY    4
-#define COND_TERM      5
-#define COND_EXPR      6
-
-typedef struct cond_com {
-  int flags;
-  int line;
-  int type;
-  WORD_DESC *op;
-  struct cond_com *left, *right;
-} COND_COM;
-
-/* The "simple" command.  Just a collection of words and redirects. */
-typedef struct simple_com {
-  int flags;                   /* See description of CMD flags. */
-  int line;                    /* line number the command starts on */
-  WORD_LIST *words;            /* The program name, the arguments,
-                                  variable assignments, etc. */
-  REDIRECT *redirects;         /* Redirections to perform. */
-} SIMPLE_COM;
-
-/* The "function definition" command. */
-typedef struct function_def {
-  int flags;                   /* See description of CMD flags. */
-  int line;                    /* Line number the function def starts on. */
-  WORD_DESC *name;             /* The name of the function. */
-  COMMAND *command;            /* The parsed execution tree. */
-  char *source_file;           /* file in which function was defined, if any */
-} FUNCTION_DEF;
-
-/* A command that is `grouped' allows pipes and redirections to affect all
-   commands in the group. */
-typedef struct group_com {
-  int ignore;                  /* See description of CMD flags. */
-  COMMAND *command;
-} GROUP_COM;
-
-typedef struct subshell_com {
-  int flags;
-  COMMAND *command;
-} SUBSHELL_COM;
-
-#define COPROC_RUNNING 0x01
-#define COPROC_DEAD    0x02
-
-typedef struct coproc {
-  char *c_name;
-  pid_t c_pid;
-  int c_rfd;
-  int c_wfd;
-  int c_rsave;
-  int c_wsave;
-  int c_flags;
-  int c_status;
-  int c_lock;
-} Coproc;
-
-typedef struct coproc_com {
-  int flags;
-  char *name;
-  COMMAND *command;
-} COPROC_COM;
-
-extern COMMAND *global_command;
-extern Coproc sh_coproc;
-
-/* Possible command errors */
-#define CMDERR_DEFAULT 0
-#define CMDERR_BADTYPE 1
-#define CMDERR_BADCONN 2
-#define CMDERR_BADJUMP 3
-
-#define CMDERR_LAST    3
-
-/* Forward declarations of functions declared in copy_cmd.c. */
-
-extern FUNCTION_DEF *copy_function_def_contents __P((FUNCTION_DEF *, FUNCTION_DEF *));
-extern FUNCTION_DEF *copy_function_def __P((FUNCTION_DEF *));
-
-extern WORD_DESC *copy_word __P((WORD_DESC *));
-extern WORD_LIST *copy_word_list __P((WORD_LIST *));
-extern REDIRECT *copy_redirect __P((REDIRECT *));
-extern REDIRECT *copy_redirects __P((REDIRECT *));
-extern COMMAND *copy_command __P((COMMAND *));
-
-#endif /* _COMMAND_H_ */
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/doc/bash.1~ b/doc/bash.1~
deleted file mode 100644 (file)
index 828b7ca..0000000
+++ /dev/null
@@ -1,10270 +0,0 @@
-.\"
-.\" MAN PAGE COMMENTS to
-.\"
-.\"    Chet Ramey
-.\"    Case Western Reserve University
-.\"    chet@po.cwru.edu
-.\"
-.\"    Last Change: Sat Jan  5 17:38:02 EST 2013
-.\"
-.\" bash_builtins, strip all but Built-Ins section
-.if \n(zZ=1 .ig zZ
-.if \n(zY=1 .ig zY
-.TH BASH 1 "2013 January 5" "GNU Bash 4.2"
-.\"
-.\" There's some problem with having a `@'
-.\" in a tagged paragraph with the BSD man macros.
-.\" It has to do with `@' appearing in the }1 macro.
-.\" This is a problem on 4.3 BSD and Ultrix, but Sun
-.\" appears to have fixed it.
-.\" If you're seeing the characters
-.\" `@u-3p' appearing before the lines reading
-.\" `possible-hostname-completions
-.\" and `complete-hostname' down in READLINE,
-.\" then uncomment this redefinition.
-.\"
-.de }1
-.ds ]X \&\\*(]B\\
-.nr )E 0
-.if !"\\$1"" .nr )I \\$1n
-.}f
-.ll \\n(LLu
-.in \\n()Ru+\\n(INu+\\n()Iu
-.ti \\n(INu
-.ie !\\n()Iu+\\n()Ru-\w\a\\*(]X\au-3p \{\\*(]X
-.br\}
-.el \\*(]X\h\a|\\n()Iu+\\n()Ru\a\c
-.}f
-..
-.\"
-.\" File Name macro.  This used to be `.PN', for Path Name,
-.\" but Sun doesn't seem to like that very much.
-.\"
-.de FN
-\fI\|\\$1\|\fP
-..
-.SH NAME
-bash \- GNU Bourne-Again SHell
-.SH SYNOPSIS
-.B bash
-[options]
-[command_string | file]
-.SH COPYRIGHT
-.if n Bash is Copyright (C) 1989-2013 by the Free Software Foundation, Inc.
-.if t Bash is Copyright \(co 1989-2013 by the Free Software Foundation, Inc.
-.SH DESCRIPTION
-.B Bash
-is an \fBsh\fR-compatible command language interpreter that
-executes commands read from the standard input or from a file.
-.B Bash
-also incorporates useful features from the \fIKorn\fP and \fIC\fP
-shells (\fBksh\fP and \fBcsh\fP).
-.PP
-.B Bash
-is intended to be a conformant implementation of the
-Shell and Utilities portion of the IEEE POSIX specification
-(IEEE Standard 1003.1).
-.B Bash
-can be configured to be POSIX-conformant by default.
-.SH OPTIONS
-All of the  single-character shell options documented in the
-description of the \fBset\fR builtin command can be used as options
-when the shell is invoked.
-In addition, \fBbash\fR
-interprets the following options when it is invoked:
-.PP
-.PD 0
-.TP 10
-.B \-c
-If the
-.B \-c
-option is present, then commands are read from the first non-option argument
-.IR command_string .
-If there are arguments after the
-.IR command_string ,
-they are assigned to the positional parameters, starting with
-.BR $0 .
-.TP
-.B \-i
-If the
-.B \-i
-option is present, the shell is
-.IR interactive .
-.TP
-.B \-l
-Make
-.B bash
-act as if it had been invoked as a login shell (see
-.SM
-.B INVOCATION
-below).
-.TP
-.B \-r
-If the
-.B \-r
-option is present, the shell becomes
-.I restricted
-(see
-.SM
-.B "RESTRICTED SHELL"
-below).
-.TP
-.B \-s
-If the
-.B \-s
-option is present, or if no arguments remain after option
-processing, then commands are read from the standard input.
-This option allows the positional parameters to be set
-when invoking an interactive shell.
-.TP
-.B \-D
-A list of all double-quoted strings preceded by \fB$\fP
-is printed on the standard output.
-These are the strings that
-are subject to language translation when the current locale
-is not \fBC\fP or \fBPOSIX\fP.
-This implies the \fB\-n\fP option; no commands will be executed.
-.TP
-.B [\-+]O [\fIshopt_option\fP]
-\fIshopt_option\fP is one of the shell options accepted by the
-\fBshopt\fP builtin (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-If \fIshopt_option\fP is present, \fB\-O\fP sets the value of that option;
-\fB+O\fP unsets it.
-If \fIshopt_option\fP is not supplied, the names and values of the shell
-options accepted by \fBshopt\fP are printed on the standard output.
-If the invocation option is \fB+O\fP, the output is displayed in a format
-that may be reused as input.
-.TP
-.B \-\-
-A
-.B \-\-
-signals the end of options and disables further option processing.
-Any arguments after the
-.B \-\-
-are treated as filenames and arguments.  An argument of
-.B \-
-is equivalent to \fB\-\-\fP.
-.PD
-.PP
-.B Bash
-also interprets a number of multi-character options.
-These options must appear on the command line before the
-single-character options to be recognized.
-.PP
-.PD 0
-.TP
-.B \-\-debugger
-Arrange for the debugger profile to be executed before the shell
-starts.
-Turns on extended debugging mode (see the description of the
-.B extdebug
-option to the
-.B shopt
-builtin below).
-.TP
-.B \-\-dump\-po\-strings
-Equivalent to \fB\-D\fP, but the output is in the GNU \fIgettext\fP
-\fBpo\fP (portable object) file format.
-.TP
-.B \-\-dump\-strings
-Equivalent to \fB\-D\fP.
-.TP
-.B \-\-help
-Display a usage message on standard output and exit successfully.
-.TP
-\fB\-\-init\-file\fP \fIfile\fP
-.PD 0
-.TP
-\fB\-\-rcfile\fP \fIfile\fP
-.PD
-Execute commands from
-.I file
-instead of the standard personal initialization file
-.I ~/.bashrc
-if the shell is interactive (see
-.SM
-.B INVOCATION
-below).
-.TP
-.B \-\-login
-Equivalent to \fB\-l\fP.
-.TP
-.B \-\-noediting
-Do not use the GNU
-.B readline
-library to read command lines when the shell is interactive.
-.TP
-.B \-\-noprofile
-Do not read either the system-wide startup file
-.FN /etc/profile
-or any of the personal initialization files
-.IR ~/.bash_profile ,
-.IR ~/.bash_login ,
-or
-.IR ~/.profile .
-By default,
-.B bash
-reads these files when it is invoked as a login shell (see
-.SM
-.B INVOCATION
-below).
-.TP
-.B \-\-norc
-Do not read and execute the personal initialization file
-.I ~/.bashrc
-if the shell is interactive.
-This option is on by default if the shell is invoked as
-.BR sh .
-.TP
-.B \-\-posix
-Change the behavior of \fBbash\fP where the default operation differs
-from the POSIX standard to match the standard (\fIposix mode\fP).
-.TP
-.B \-\-restricted
-The shell becomes restricted (see
-.SM
-.B "RESTRICTED SHELL"
-below).
-.TP
-.B \-\-verbose
-Equivalent to  \fB\-v\fP.
-.TP
-.B \-\-version
-Show version information for this instance of
-.B bash
-on the standard output and exit successfully.
-.PD
-.SH ARGUMENTS
-If arguments remain after option processing, and neither the
-.B \-c
-nor the
-.B \-s
-option has been supplied, the first argument is assumed to
-be the name of a file containing shell commands.
-If
-.B bash
-is invoked in this fashion, 
-.B $0
-is set to the name of the file, and the positional parameters
-are set to the remaining arguments.
-.B Bash
-reads and executes commands from this file, then exits.
-\fBBash\fP's exit status is the exit status of the last command
-executed in the script.
-If no commands are executed, the exit status is 0.
-An attempt is first made to open the file in the current directory, and,
-if no file is found, then the shell searches the directories in
-.SM
-.B PATH
-for the script.
-.SH INVOCATION
-A \fIlogin shell\fP is one whose first character of argument zero is a
-.BR \- ,
-or one started with the 
-.B \-\-login
-option.
-.PP
-An \fIinteractive\fP shell is one started without non-option arguments
-and without the
-.B \-c
-option
-whose standard input and error are
-both connected to terminals (as determined by
-.IR isatty (3)),
-or one started with the
-.B \-i
-option.
-.SM
-.B PS1
-is set and
-.B $\-
-includes
-.B i
-if
-.B bash
-is interactive,
-allowing a shell script or a startup file to test this state.
-.PP
-The following paragraphs describe how
-.B bash
-executes its startup files.
-If any of the files exist but cannot be read,
-.B bash
-reports an error.
-Tildes are expanded in filenames as described below under
-.B "Tilde Expansion"
-in the
-.SM
-.B EXPANSION
-section.
-.PP
-When
-.B bash
-is invoked as an interactive login shell, or as a non-interactive shell
-with the \fB\-\-login\fP option, it first reads and
-executes commands from the file \fI/etc/profile\fP, if that
-file exists.
-After reading that file, it looks for \fI~/.bash_profile\fP,
-\fI~/.bash_login\fP, and \fI~/.profile\fP, in that order, and reads
-and executes commands from the first one that exists and is readable.
-The
-.B \-\-noprofile
-option may be used when the shell is started to inhibit this behavior.
-.PP
-When a login shell exits,
-.B bash
-reads and executes commands from the file \fI~/.bash_logout\fP, if it
-exists.
-.PP
-When an interactive shell that is not a login shell is started,
-.B bash
-reads and executes commands from \fI~/.bashrc\fP, if that file exists.
-This may be inhibited by using the
-.B \-\-norc
-option.
-The \fB\-\-rcfile\fP \fIfile\fP option will force
-.B bash
-to read and execute commands from \fIfile\fP instead of \fI~/.bashrc\fP.
-.PP
-When
-.B bash
-is started non-interactively, to run a shell script, for example, it
-looks for the variable
-.SM
-.B BASH_ENV
-in the environment, expands its value if it appears there, and uses the
-expanded value as the name of a file to read and execute.
-.B Bash
-behaves as if the following command were executed:
-.sp .5
-.RS
-.if t \f(CWif [ \-n "$BASH_ENV" ]; then . "$BASH_ENV"; fi\fP
-.if n if [ \-n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
-.RE
-.sp .5
-but the value of the
-.SM
-.B PATH
-variable is not used to search for the filename.
-.PP
-If
-.B bash
-is invoked with the name
-.BR sh ,
-it tries to mimic the startup behavior of historical versions of
-.B sh
-as closely as possible,
-while conforming to the POSIX standard as well.
-When invoked as an interactive login shell, or a non-interactive
-shell with the \fB\-\-login\fP option, it first attempts to
-read and execute commands from
-.I /etc/profile
-and
-.IR ~/.profile ,
-in that order.
-The
-.B \-\-noprofile
-option may be used to inhibit this behavior.
-When invoked as an interactive shell with the name
-.BR sh ,
-.B bash
-looks for the variable
-.SM
-.BR ENV ,
-expands its value if it is defined, and uses the
-expanded value as the name of a file to read and execute.
-Since a shell invoked as
-.B sh
-does not attempt to read and execute commands from any other startup
-files, the
-.B \-\-rcfile
-option has no effect.
-A non-interactive shell invoked with the name
-.B sh
-does not attempt to read any other startup files. 
-When invoked as
-.BR sh ,
-.B bash
-enters
-.I posix
-mode after the startup files are read.
-.PP
-When
-.B bash
-is started in
-.I posix
-mode, as with the
-.B \-\-posix
-command line option, it follows the POSIX standard for startup files.
-In this mode, interactive shells expand the
-.SM
-.B ENV
-variable and commands are read and executed from the file
-whose name is the expanded value.
-No other startup files are read.
-.PP
-.B Bash
-attempts to determine when it is being run with its standard input
-connected to a network connection, as when executed by the remote shell
-daemon, usually \fIrshd\fP, or the secure shell daemon \fIsshd\fP.
-If
-.B bash
-determines it is being run in this fashion, it reads and executes
-commands from \fI~/.bashrc\fP, if that file exists and is readable.
-It will not do this if invoked as \fBsh\fP.
-The
-.B \-\-norc
-option may be used to inhibit this behavior, and the
-.B \-\-rcfile
-option may be used to force another file to be read, but
-\fIrshd\fP does not generally invoke the shell with those options
-or allow them to be specified.
-.PP
-If the shell is started with the effective user (group) id not equal to the
-real user (group) id, and the \fB\-p\fP option is not supplied, no startup
-files are read, shell functions are not inherited from the environment, the
-.SM
-.BR SHELLOPTS ,
-.SM
-.BR BASHOPTS ,
-.SM
-.BR CDPATH ,
-and
-.SM
-.B GLOBIGNORE
-variables, if they appear in the environment, are ignored,
-and the effective user id is set to the real user id.
-If the \fB\-p\fP option is supplied at invocation, the startup behavior is
-the same, but the effective user id is not reset.
-.SH DEFINITIONS
-.PP
-The following definitions are used throughout the rest of this
-document.
-.PD 0
-.TP
-.B blank 
-A space or tab.
-.TP
-.B word
-A sequence of characters considered as a single unit by the shell.
-Also known as a
-.BR token .
-.TP
-.B name
-A 
-.I word
-consisting only of alphanumeric characters and underscores, and
-beginning with an alphabetic character or an underscore.  Also
-referred to as an
-.BR identifier .
-.TP
-.B metacharacter
-A character that, when unquoted, separates words.  One of the following:
-.br
-.RS
-.PP
-.if t \fB|  &  ;  (  )  <  >  space  tab\fP
-.if n \fB|  & ; ( ) < > space tab\fP
-.RE
-.PP
-.TP
-.B control operator
-A \fItoken\fP that performs a control function.  It is one of the following
-symbols:
-.RS
-.PP
-.if t \fB||  &  &&  ;  ;;  (  )  |  |&    <newline>\fP
-.if n \fB|| & && ; ;; ( ) | |& <newline>\fP
-.RE
-.PD
-.SH "RESERVED WORDS"
-\fIReserved words\fP are words that have a special meaning to the shell.
-The following words are recognized as reserved when unquoted and either
-the first word of a simple command (see
-.SM
-.B SHELL GRAMMAR
-below) or the third word of a 
-.B case 
-or
-.B for
-command:
-.if t .RS
-.PP
-.B
-.if n ! case  coproc  do done elif else esac fi for function if in select then until while { } time [[ ]]
-.if t !    case    coproc    do    done    elif    else    esac    fi    for    function    if    in    select    then    until    while    {    }    time    [[    ]]
-.if t .RE
-.SH "SHELL GRAMMAR"
-.SS Simple Commands
-.PP
-A \fIsimple command\fP is a sequence of optional variable assignments
-followed by \fBblank\fP-separated words and redirections, and
-terminated by a \fIcontrol operator\fP.  The first word
-specifies the command to be executed, and is passed as argument zero.
-The remaining words are passed as arguments to the invoked command.
-.PP
-The return value of a \fIsimple command\fP is its exit status, or
-128+\fIn\^\fP if the command is terminated by signal
-.IR n .
-.SS Pipelines
-.PP
-A \fIpipeline\fP is a sequence of one or more commands separated by
-one of the control operators
-.B |
-or \fB|&\fP.
-The format for a pipeline is:
-.RS
-.PP
-[\fBtime\fP [\fB\-p\fP]] [ ! ] \fIcommand\fP [ [\fB|\fP\(bv\fB|&\fP] \fIcommand2\fP ... ]
-.RE
-.PP
-The standard output of
-.I command
-is connected via a pipe to the standard input of
-.IR command2 .
-This connection is performed before any redirections specified by the
-command (see
-.SM
-.B REDIRECTION
-below).
-If \fB|&\fP is used, \fIcommand\fP's standard output and standard error
-are connected to
-\fIcommand2\fP's standard input through the pipe;
-it is shorthand for \fB2>&1 |\fP.
-This implicit redirection of the standard error is
-performed after any redirections specified by the command.
-.PP
-The return status of a pipeline is the exit status of the last
-command, unless the \fBpipefail\fP option is enabled.
-If \fBpipefail\fP is enabled, the pipeline's return status is the
-value of the last (rightmost) command to exit with a non-zero status,
-or zero if all commands exit successfully.
-If the reserved word
-.B !
-precedes a pipeline, the exit status of that pipeline is the logical
-negation of the exit status as described above.
-The shell waits for all commands in the pipeline to
-terminate before returning a value.
-.PP
-If the
-.B time
-reserved word precedes a pipeline, the elapsed as well as user and
-system time consumed by its execution are reported when the pipeline
-terminates.
-The \fB\-p\fP option changes the output format to that specified by POSIX.
-When the shell is in \fIposix mode\fP, it does not recognize
-\fBtime\fP as a reserved word if the next token begins with a `-'.
-The
-.SM
-.B TIMEFORMAT
-variable may be set to a format string that specifies how the timing
-information should be displayed; see the description of
-.SM
-.B TIMEFORMAT
-under
-.B "Shell Variables"
-below.
-.PP
-When the shell is in \fIposix mode\fP, \fBtime\fP
-may be followed by a newline.  In this case, the shell displays the
-total user and system time consumed by the shell and its children.
-The
-.SM
-.B TIMEFORMAT
-variable may be used to specify the format of
-the time information.
-.PP
-Each command in a pipeline is executed as a separate process (i.e., in a
-subshell).
-.SS Lists
-.PP
-A \fIlist\fP is a sequence of one or more pipelines separated by one
-of the operators
-.BR ; ,
-.BR & ,
-.BR && ,
-or
-.BR || ,
-and optionally terminated by one of
-.BR ; ,
-.BR & ,
-or
-.BR <newline> .
-.PP
-Of these list operators,
-.B &&
-and
-.B ||
-have equal precedence, followed by
-.B ;
-and
-.BR & ,
-which have equal precedence.
-.PP
-A sequence of one or more newlines may appear in a \fIlist\fP instead
-of a semicolon to delimit commands.
-.PP
-If a command is terminated by the control operator
-.BR & ,
-the shell executes the command in the \fIbackground\fP
-in a subshell.  The shell does not wait for the command to
-finish, and the return status is 0.  Commands separated by a
-.B ;
-are executed sequentially; the shell waits for each
-command to terminate in turn.  The return status is the
-exit status of the last command executed.
-.PP
-AND and OR lists are sequences of one of more pipelines separated by the
-\fB&&\fP and \fB||\fP control operators, respectively.
-AND and OR lists are executed with left associativity.
-An AND list has the form
-.RS
-.PP
-\fIcommand1\fP \fB&&\fP \fIcommand2\fP
-.RE
-.PP
-.I command2
-is executed if, and only if,
-.I command1
-returns an exit status of zero.
-.PP
-An OR list has the form
-.RS
-.PP
-\fIcommand1\fP \fB||\fP \fIcommand2\fP
-.PP
-.RE
-.PP
-.I command2
-is executed if and only if
-.I command1
-returns a non-zero exit status.
-The return status of
-AND and OR lists is the exit status of the last command
-executed in the list.
-.SS Compound Commands
-.PP
-A \fIcompound command\fP is one of the following.
-In most cases a \fIlist\fP in a command's description may be separated from
-the rest of the command by one or more newlines, and may be followed by a
-newline in place of a semicolon.
-.TP
-(\fIlist\fP)
-\fIlist\fP is executed in a subshell environment (see
-.SM
-\fBCOMMAND EXECUTION ENVIRONMENT\fP
-below).
-Variable assignments and builtin
-commands that affect the shell's environment do not remain in effect
-after the command completes.  The return status is the exit status of
-\fIlist\fP.
-.TP
-{ \fIlist\fP; }
-\fIlist\fP is simply executed in the current shell environment.
-\fIlist\fP must be terminated with a newline or semicolon.
-This is known as a \fIgroup command\fP.
-The return status is the exit status of
-\fIlist\fP.
-Note that unlike the metacharacters \fB(\fP and \fB)\fP, \fB{\fP and
-\fB}\fP are \fIreserved words\fP and must occur where a reserved
-word is permitted to be recognized.  Since they do not cause a word
-break, they must be separated from \fIlist\fP by whitespace or another
-shell metacharacter.
-.TP
-((\fIexpression\fP))
-The \fIexpression\fP is evaluated according to the rules described
-below under
-.SM
-.BR "ARITHMETIC EVALUATION" .
-If the value of the expression is non-zero, the return status is 0;
-otherwise the return status is 1.  This is exactly equivalent to
-\fBlet "\fIexpression\fP"\fR.
-.TP
-\fB[[\fP \fIexpression\fP \fB]]\fP
-Return a status of 0 or 1 depending on the evaluation of
-the conditional expression \fIexpression\fP.
-Expressions are composed of the primaries described below under
-.SM
-.BR "CONDITIONAL EXPRESSIONS" .
-Word splitting and pathname expansion are not performed on the words
-between the \fB[[\fP and \fB]]\fP; tilde expansion,
-parameter and variable expansion,
-arithmetic expansion, command substitution, process
-substitution, and quote removal are performed.
-Conditional operators such as \fB\-f\fP must be unquoted to be recognized
-as primaries.
-.if t .sp 0.5
-.if n .sp 1
-When used with \fB[[\fP, the \fB<\fP and \fB>\fP operators sort
-lexicographically using the current locale.
-.if t .sp 0.5
-.if n .sp 1
-When the \fB==\fP and \fB!=\fP operators are used, the string to the
-right of the operator is considered a pattern and matched according
-to the rules described below under \fBPattern Matching\fP.
-The \fB=\fP operator is equivalent to \fB==\fP.
-If the shell option
-.B nocasematch
-is enabled, the match is performed without regard to the case
-of alphabetic characters.
-The return value is 0 if the string matches (\fB==\fP) or does not match
-(\fB!=\fP) the pattern, and 1 otherwise.
-Any part of the pattern may be quoted to force the quoted portion
-to be matched as a string.
-.if t .sp 0.5
-.if n .sp 1
-An additional binary operator, \fB=~\fP, is available, with the same
-precedence as \fB==\fP and \fB!=\fP.
-When it is used, the string to the right of the operator is considered
-an extended regular expression and matched accordingly (as in \fIregex\fP(3)).  
-The return value is 0 if the string matches
-the pattern, and 1 otherwise.
-If the regular expression is syntactically incorrect, the conditional
-expression's return value is 2.
-If the shell option
-.B nocasematch
-is enabled, the match is performed without regard to the case
-of alphabetic characters.
-Any part of the pattern may be quoted to force the quoted portion
-to be matched as a string.
-Bracket expressions in regular expressions must be treated carefully,
-since normal quoting characters lose their meanings between brackets.
-If the pattern is stored in a shell variable, quoting the variable
-expansion forces the entire pattern to be matched as a string.
-Substrings matched by parenthesized subexpressions within the regular
-expression are saved in the array variable
-.SM
-.BR BASH_REMATCH .
-The element of
-.SM
-.B BASH_REMATCH
-with index 0 is the portion of the string
-matching the entire regular expression.
-The element of
-.SM
-.B BASH_REMATCH
-with index \fIn\fP is the portion of the
-string matching the \fIn\fPth parenthesized subexpression.
-.if t .sp 0.5
-.if n .sp 1
-Expressions may be combined using the following operators, listed
-in decreasing order of precedence:
-.if t .sp 0.5
-.if n .sp 1
-.RS
-.PD 0
-.TP
-.B ( \fIexpression\fP )
-Returns the value of \fIexpression\fP.
-This may be used to override the normal precedence of operators.
-.TP
-.B ! \fIexpression\fP
-True if
-.I expression
-is false.
-.TP
-\fIexpression1\fP \fB&&\fP \fIexpression2\fP
-True if both
-.I expression1
-and
-.I expression2
-are true.
-.TP
-\fIexpression1\fP \fB||\fP \fIexpression2\fP
-True if either
-.I expression1
-or
-.I expression2
-is true.
-.PD
-.LP
-The \fB&&\fP and \fB||\fP
-operators do not evaluate \fIexpression2\fP if the value of
-\fIexpression1\fP is sufficient to determine the return value of
-the entire conditional expression.
-.RE
-.TP
-\fBfor\fP \fIname\fP [ [ \fBin\fP [ \fIword ...\fP ] ] ; ] \fBdo\fP \fIlist\fP ; \fBdone\fP
-The list of words following \fBin\fP is expanded, generating a list
-of items.
-The variable \fIname\fP is set to each element of this list
-in turn, and \fIlist\fP is executed each time.
-If the \fBin\fP \fIword\fP is omitted, the \fBfor\fP command executes
-\fIlist\fP once for each positional parameter that is set (see
-.SM
-.B PARAMETERS
-below).
-The return status is the exit status of the last command that executes.
-If the expansion of the items following \fBin\fP results in an empty
-list, no commands are executed, and the return status is 0.
-.TP
-\fBfor\fP (( \fIexpr1\fP ; \fIexpr2\fP ; \fIexpr3\fP )) ; \fBdo\fP \fIlist\fP ; \fBdone\fP
-First, the arithmetic expression \fIexpr1\fP is evaluated according
-to the rules described below under
-.SM
-.BR "ARITHMETIC EVALUATION" .
-The arithmetic expression \fIexpr2\fP is then evaluated repeatedly
-until it evaluates to zero.
-Each time \fIexpr2\fP evaluates to a non-zero value, \fIlist\fP is
-executed and the arithmetic expression \fIexpr3\fP is evaluated.
-If any expression is omitted, it behaves as if it evaluates to 1.
-The return value is the exit status of the last command in \fIlist\fP
-that is executed, or false if any of the expressions is invalid.
-.TP
-\fBselect\fP \fIname\fP [ \fBin\fP \fIword\fP ] ; \fBdo\fP \fIlist\fP ; \fBdone\fP
-The list of words following \fBin\fP is expanded, generating a list
-of items.  The set of expanded words is printed on the standard
-error, each preceded by a number.  If the \fBin\fP
-\fIword\fP is omitted, the positional parameters are printed (see
-.SM
-.B PARAMETERS
-below).  The
-.SM
-.B PS3
-prompt is then displayed and a line read from the standard input.
-If the line consists of a number corresponding to one of
-the displayed words, then the value of
-.I name
-is set to that word.  If the line is empty, the words and prompt
-are displayed again.  If EOF is read, the command completes.  Any
-other value read causes
-.I name
-to be set to null.  The line read is saved in the variable
-.SM
-.BR REPLY .
-The
-.I list
-is executed after each selection until a
-.B break
-command is executed.
-The exit status of
-.B select
-is the exit status of the last command executed in
-.IR list ,
-or zero if no commands were executed.
-.TP
-\fBcase\fP \fIword\fP \fBin\fP [ [(] \fIpattern\fP [ \fB|\fP \fIpattern\fP ] \
-... ) \fIlist\fP ;; ] ... \fBesac\fP
-A \fBcase\fP command first expands \fIword\fP, and tries to match
-it against each \fIpattern\fP in turn, using the same matching rules
-as for pathname expansion (see
-.B Pathname Expansion
-below).
-The \fIword\fP is expanded using tilde
-expansion, parameter and variable expansion, arithmetic substitution,
-command substitution, process substitution and quote removal.
-Each \fIpattern\fP examined is expanded using tilde
-expansion, parameter and variable expansion, arithmetic substitution,
-command substitution, and process substitution.
-If the shell option
-.B nocasematch
-is enabled, the match is performed without regard to the case
-of alphabetic characters.
-When a match is found, the corresponding \fIlist\fP is executed.
-If the \fB;;\fP operator is used, no subsequent matches are attempted after
-the first pattern match.
-Using \fB;&\fP in place of \fB;;\fP causes execution to continue with
-the \fIlist\fP associated with the next set of patterns.
-Using \fB;;&\fP in place of \fB;;\fP causes the shell to test the next
-pattern list in the statement, if any, and execute any associated \fIlist\fP
-on a successful match.
-The exit status is zero if no
-pattern matches.  Otherwise, it is the exit status of the
-last command executed in \fIlist\fP.
-.TP
-\fBif\fP \fIlist\fP; \fBthen\fP \fIlist;\fP \
-[ \fBelif\fP \fIlist\fP; \fBthen\fP \fIlist\fP; ] ... \
-[ \fBelse\fP \fIlist\fP; ] \fBfi\fP
-The
-.B if 
-.I list
-is executed.  If its exit status is zero, the
-\fBthen\fP \fIlist\fP is executed.  Otherwise, each \fBelif\fP
-\fIlist\fP is executed in turn, and if its exit status is zero,
-the corresponding \fBthen\fP \fIlist\fP is executed and the
-command completes.  Otherwise, the \fBelse\fP \fIlist\fP is
-executed, if present.  The exit status is the exit status of the
-last command executed, or zero if no condition tested true.
-.TP
-\fBwhile\fP \fIlist-1\fP; \fBdo\fP \fIlist-2\fP; \fBdone\fP
-.PD 0
-.TP
-\fBuntil\fP \fIlist-1\fP; \fBdo\fP \fIlist-2\fP; \fBdone\fP
-.PD
-The \fBwhile\fP command continuously executes the list
-\fIlist-2\fP as long as the last command in the list \fIlist-1\fP returns
-an exit status of zero.  The \fBuntil\fP command is identical
-to the \fBwhile\fP command, except that the test is negated;
-.I list-2
-is executed as long as the last command in
-.I list-1
-returns a non-zero exit status.
-The exit status of the \fBwhile\fP and \fBuntil\fP commands
-is the exit status
-of the last command executed in \fIlist-2\fP, or zero if
-none was executed.
-.SS Coprocesses
-.PP
-A \fIcoprocess\fP is a shell command preceded by the \fBcoproc\fP reserved
-word.
-A coprocess is executed asynchronously in a subshell, as if the command
-had been terminated with the \fB&\fP control operator, with a two-way pipe
-established between the executing shell and the coprocess.
-.PP
-The format for a coprocess is:
-.RS
-.PP
-\fBcoproc\fP [\fINAME\fP] \fIcommand\fP [\fIredirections\fP]
-.RE
-.PP
-This creates a coprocess named \fINAME\fP.
-If \fINAME\fP is not supplied, the default name is \fBCOPROC\fP.
-\fINAME\fP must not be supplied if \fIcommand\fP is a \fIsimple
-command\fP (see above); otherwise, it is interpreted as the first word
-of the simple command.
-When the coprocess is executed, the shell creates an array variable (see
-.B Arrays
-below) named \fINAME\fP in the context of the executing shell.
-The standard output of
-.I command
-is connected via a pipe to a file descriptor in the executing shell,
-and that file descriptor is assigned to \fINAME\fP[0].
-The standard input of
-.I command
-is connected via a pipe to a file descriptor in the executing shell,
-and that file descriptor is assigned to \fINAME\fP[1].
-This pipe is established before any redirections specified by the
-command (see
-.SM
-.B REDIRECTION
-below).
-The file descriptors can be utilized as arguments to shell commands
-and redirections using standard word expansions.
-The file descriptors are not available in subshells.
-The process ID of the shell spawned to execute the coprocess is
-available as the value of the variable \fINAME\fP_PID.
-The \fBwait\fP
-builtin command may be used to wait for the coprocess to terminate.
-.PP
-Since the coprocess is created as an asynchronous command,
-the \fBcoproc\fP command always returns success.
-The return status of a coprocess is the exit status of \fIcommand\fP.
-.SS Shell Function Definitions
-.PP
-A shell function is an object that is called like a simple command and
-executes a compound command with a new set of positional parameters.
-Shell functions are declared as follows:
-.TP
-\fIname\fP () \fIcompound\-command\fP [\fIredirection\fP]
-.PD 0
-.TP
-\fBfunction\fP \fIname\fP [()] \fIcompound\-command\fP [\fIredirection\fP]
-.PD
-This defines a function named \fIname\fP.
-The reserved word \fBfunction\fP is optional.
-If the \fBfunction\fP reserved word is supplied, the parentheses are optional.
-The \fIbody\fP of the function is the compound command
-.I compound\-command 
-(see \fBCompound Commands\fP above).
-That command is usually a \fIlist\fP of commands between { and }, but
-may be any command listed under \fBCompound Commands\fP above.
-\fIcompound\-command\fP is executed whenever \fIname\fP is specified as the
-name of a simple command.
-When in \fIposix mode\fP, \fIname\fP may not be the name of one of the
-POSIX \fIspecial builtins\fP.
-Any redirections (see
-.SM
-.B REDIRECTION
-below) specified when a function is defined are performed
-when the function is executed.
-The exit status of a function definition is zero unless a syntax error
-occurs or a readonly function with the same name already exists.
-When executed, the exit status of a function is the exit status of the
-last command executed in the body.  (See
-.SM
-.B FUNCTIONS
-below.)
-.SH COMMENTS
-In a non-interactive shell, or an interactive shell in which the
-.B interactive_comments
-option to the
-.B shopt
-builtin is enabled (see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below), a word beginning with
-.B #
-causes that word and all remaining characters on that line to
-be ignored.  An interactive shell without the
-.B interactive_comments
-option enabled does not allow comments.  The
-.B interactive_comments
-option is on by default in interactive shells.
-.SH QUOTING
-\fIQuoting\fP is used to remove the special meaning of certain
-characters or words to the shell.  Quoting can be used to 
-disable special treatment for special characters, to prevent
-reserved words from being recognized as such, and to prevent
-parameter expansion.
-.PP
-Each of the \fImetacharacters\fP listed above under
-.SM
-.B DEFINITIONS
-has special meaning to the shell and must be quoted if it is to
-represent itself.
-.PP
-When the command history expansion facilities are being used
-(see
-.SM
-.B HISTORY EXPANSION
-below), the
-\fIhistory expansion\fP character, usually \fB!\fP, must be quoted
-to prevent history expansion.
-.PP
-There are three quoting mechanisms: the
-.IR "escape character" ,
-single quotes, and double quotes.
-.PP
-A non-quoted backslash (\fB\e\fP) is the
-.IR "escape character" .
-It preserves the literal value of the next character that follows,
-with the exception of <newline>.  If a \fB\e\fP<newline> pair
-appears, and the backslash is not itself quoted, the \fB\e\fP<newline>
-is treated as a line continuation (that is, it is removed from the
-input stream and effectively ignored).
-.PP
-Enclosing characters in single quotes preserves the literal value
-of each character within the quotes.  A single quote may not occur
-between single quotes, even when preceded by a backslash.
-.PP
-Enclosing characters in double quotes preserves the literal value
-of all characters within the quotes, with the exception of
-.BR $ ,
-.BR \` ,
-.BR \e ,
-and, when history expansion is enabled,
-.BR ! .
-The characters
-.B $
-and
-.B \`
-retain their special meaning within double quotes.  The backslash
-retains its special meaning only when followed by one of the following
-characters:
-.BR $ ,
-.BR \` ,
-\^\fB"\fP\^,
-.BR \e ,
-or
-.BR <newline> .
-A double quote may be quoted within double quotes by preceding it with
-a backslash.
-If enabled, history expansion will be performed unless an
-.B !
-appearing in double quotes is escaped using a backslash.
-The backslash preceding the
-.B !
-is not removed.
-.PP
-The special parameters
-.B *
-and
-.B @
-have special meaning when in double
-quotes (see
-.SM
-.B PARAMETERS
-below).
-.PP
-Words of the form \fB$\fP\(aq\fIstring\fP\(aq are treated specially.  The
-word expands to \fIstring\fP, with backslash-escaped characters replaced
-as specified by the ANSI C standard.  Backslash escape sequences, if
-present, are decoded as follows:
-.RS
-.PD 0
-.TP
-.B \ea
-alert (bell)
-.TP
-.B \eb
-backspace
-.TP
-.B \ee
-.TP
-.B \eE
-an escape character
-.TP   
-.B \ef
-form feed
-.TP  
-.B \en
-new line
-.TP     
-.B \er
-carriage return
-.TP
-.B \et
-horizontal tab
-.TP   
-.B \ev
-vertical tab
-.TP
-.B \e\e
-backslash
-.TP
-.B \e\(aq
-single quote
-.TP
-.B \e\(dq
-double quote
-.TP   
-.B \e\fInnn\fP
-the eight-bit character whose value is the octal value \fInnn\fP
-(one to three digits)
-.TP
-.B \ex\fIHH\fP
-the eight-bit character whose value is the hexadecimal value \fIHH\fP
-(one or two hex digits)
-.TP
-.B \eu\fIHHHH\fP
-the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
-\fIHHHH\fP (one to four hex digits)
-.TP
-.B \eU\fIHHHHHHHH\fP
-the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
-\fIHHHHHHHH\fP (one to eight hex digits)
-.TP
-.B \ec\fIx\fP
-a control-\fIx\fP character
-.PD
-.RE
-.LP
-The expanded result is single-quoted, as if the dollar sign had
-not been present.
-.PP
-A double-quoted string preceded by a dollar sign (\fB$\fP\(dq\fIstring\fP\(dq)
-will cause the string to be translated according to the current locale.
-If the current locale is \fBC\fP or \fBPOSIX\fP, the dollar sign
-is ignored.
-If the string is translated and replaced, the replacement is
-double-quoted.
-.SH PARAMETERS
-A
-.I parameter
-is an entity that stores values.
-It can be a
-.IR name ,
-a number, or one of the special characters listed below under
-.BR "Special Parameters" .
-A
-.I variable
-is a parameter denoted by a
-.IR name .
-A variable has a \fIvalue\fP and zero or more \fIattributes\fP.
-Attributes are assigned using the
-.B declare
-builtin command (see
-.B declare
-below in
-.SM
-.BR "SHELL BUILTIN COMMANDS" ).
-.PP
-A parameter is set if it has been assigned a value.  The null string is
-a valid value.  Once a variable is set, it may be unset only by using
-the
-.B unset
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.PP
-A
-.I variable
-may be assigned to by a statement of the form
-.RS
-.PP
-\fIname\fP=[\fIvalue\fP]
-.RE
-.PP
-If
-.I value
-is not given, the variable is assigned the null string.  All
-.I values
-undergo tilde expansion, parameter and variable expansion,
-command substitution, arithmetic expansion, and quote
-removal (see
-.SM
-.B EXPANSION
-below).  If the variable has its
-.B integer
-attribute set, then
-.I value
-is evaluated as an arithmetic expression even if the $((...)) expansion is
-not used (see
-.B "Arithmetic Expansion"
-below).
-Word splitting is not performed, with the exception
-of \fB"$@"\fP as explained below under
-.BR "Special Parameters" .
-Pathname expansion is not performed.
-Assignment statements may also appear as arguments to the
-.BR alias ,
-.BR declare ,
-.BR typeset ,
-.BR export ,
-.BR readonly ,
-and
-.B local
-builtin commands.
-When in \fIposix mode\fP, these builtins may appear in a command after
-one or more instances of the \fBcommand\fP builtin and retain these
-assignment statement properties.
-.PP
-In the context where an assignment statement is assigning a value
-to a shell variable or array index, the += operator can be used to
-append to or add to the variable's previous value.
-When += is applied to a variable for which the \fIinteger\fP attribute has been
-set, \fIvalue\fP is evaluated as an arithmetic expression and added to the
-variable's current value, which is also evaluated.
-When += is applied to an array variable using compound assignment (see
-.B Arrays
-below), the
-variable's value is not unset (as it is when using =), and new values are
-appended to the array beginning at one greater than the array's maximum index
-(for indexed arrays) or added as additional key\-value pairs in an
-associative array.
-When applied to a string-valued variable, \fIvalue\fP is expanded and
-appended to the variable's value.
-.PP
-A variable can be assigned the \fInameref\fP attribute using the
-\fB\-n\fP option to the \fBdeclare\fP or \fBlocal\fP builtin commands
-(see the descriptions of \fBdeclare\fP and \fBlocal\fP below)
-to create a \fInameref\fP, or a reference to another variable.
-This allows variables to be manipulated indirectly.
-Whenever the nameref variable is referenced or assigned to, the operation
-is actually performed on the variable specified by the nameref variable's
-value.
-A nameref is commonly used within shell functions to refer to a variable
-whose name is passed as an argument to the function.
-For instance, if a variable name is passed to a shell function as its first
-argument, running
-.sp .5
-.RS
-.if t \f(CWdeclare -n ref=$1\fP
-.if n declare -n ref=$1
-.RE
-.sp .5
-inside the function creates a nameref variable \fBref\fP whose value is
-the variable name passed as the first argument.
-References and assignments to \fBref\fP are treated as references and
-assignments to the variable whose name was passed as \fB$1\fP.
-If the control variable in a \fBfor\fP loop has the nameref attribute,
-the list of words can be a list of shell variables, and a name reference
-will be established for each word in the list, in turn, when the loop is
-executed.
-Array variables cannot be given the \fB\-n\fP attribute.
-However, nameref variables can reference array variables and subscripted
-array variables.
-Namerefs can be unset using the \fB\-n\fP option to the \fBunset\fP builtin.
-Otherwise, if \fBunset\fP is executed with the name of a nameref variable
-as an argument, the variable referenced by the nameref variable will be unset.
-.SS Positional Parameters
-.PP
-A
-.I positional parameter
-is a parameter denoted by one or more
-digits, other than the single digit 0.  Positional parameters are
-assigned from the shell's arguments when it is invoked,
-and may be reassigned using the
-.B set
-builtin command.  Positional parameters may not be assigned to
-with assignment statements.  The positional parameters are
-temporarily replaced when a shell function is executed (see
-.SM
-.B FUNCTIONS
-below).
-.PP
-When a positional parameter consisting of more than a single
-digit is expanded, it must be enclosed in braces (see
-.SM
-.B EXPANSION
-below).
-.SS Special Parameters
-.PP
-The shell treats several parameters specially.  These parameters may
-only be referenced; assignment to them is not allowed.
-.PD 0
-.TP
-.B *
-Expands to the positional parameters, starting from one.  When the
-expansion occurs within double quotes, it expands to a single word
-with the value of each parameter separated by the first character
-of the 
-.SM
-.B IFS
-special variable.  That is, "\fB$*\fP" is equivalent
-to "\fB$1\fP\fIc\fP\fB$2\fP\fIc\fP\fB...\fP", where
-.I c
-is the first character of the value of the
-.SM
-.B IFS
-variable.  If
-.SM
-.B IFS
-is unset, the parameters are separated by spaces.
-If
-.SM
-.B IFS
-is null, the parameters are joined without intervening separators.
-.TP
-.B @
-Expands to the positional parameters, starting from one.  When the
-expansion occurs within double quotes, each parameter expands to a
-separate word.  That is, "\fB$@\fP" is equivalent to
-"\fB$1\fP" "\fB$2\fP" ...
-If the double-quoted expansion occurs within a word, the expansion of
-the first parameter is joined with the beginning part of the original
-word, and the expansion of the last parameter is joined with the last
-part of the original word.
-When there are no positional parameters, "\fB$@\fP" and 
-.B $@
-expand to nothing (i.e., they are removed).
-.TP
-.B #
-Expands to the number of positional parameters in decimal.
-.TP
-.B ?
-Expands to the exit status of the most recently executed foreground
-pipeline.
-.TP
-.B \-
-Expands to the current option flags as specified upon invocation, 
-by the
-.B set
-builtin command, or those set by the shell itself
-(such as the
-.B \-i
-option).
-.TP
-.B $
-Expands to the process ID of the shell.  In a () subshell, it
-expands to the process ID of the current shell, not the
-subshell.
-.TP
-.B !
-Expands to the process ID of the most recently executed background
-(asynchronous) command.
-.TP
-.B 0
-Expands to the name of the shell or shell script.  This is set at
-shell initialization.  If
-.B bash
-is invoked with a file of commands,
-.B $0
-is set to the name of that file.  If
-.B bash
-is started with the
-.B \-c
-option, then
-.B $0
-is set to the first argument after the string to be
-executed, if one is present.  Otherwise, it is set
-to the filename used to invoke
-.BR bash ,
-as given by argument zero.
-.TP
-.B _
-At shell startup, set to the absolute pathname used to invoke the
-shell or shell script being executed as passed in the environment
-or argument list.
-Subsequently, expands to the last argument to the previous command,
-after expansion.
-Also set to the full pathname used to invoke each command executed
-and placed in the environment exported to that command.
-When checking mail, this parameter holds the name of the mail file
-currently being checked.
-.PD
-.SS Shell Variables
-.PP
-The following variables are set by the shell:
-.PP
-.PD 0
-.TP
-.B BASH
-Expands to the full filename used to invoke this instance of
-.BR bash .
-.TP
-.B BASHOPTS
-A colon-separated list of enabled shell options.  Each word in
-the list is a valid argument for the
-.B \-s
-option to the
-.B shopt
-builtin command (see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below).  The options appearing in
-.SM
-.B BASHOPTS
-are those reported as
-.I on
-by \fBshopt\fP.
-If this variable is in the environment when
-.B bash
-starts up, each shell option in the list will be enabled before
-reading any startup files.
-This variable is read-only.
-.TP
-.B BASHPID
-Expands to the process ID of the current \fBbash\fP process.
-This differs from \fB$$\fP under certain circumstances, such as subshells
-that do not require \fBbash\fP to be re-initialized.
-.TP
-.B BASH_ALIASES
-An associative array variable whose members correspond to the internal
-list of aliases as maintained by the \fBalias\fP builtin.
-Elements added to this array appear in the alias list; unsetting array
-elements cause aliases to be removed from the alias list.
-.TP
-.B BASH_ARGC
-An array variable whose values are the number of parameters in each
-frame of the current \fBbash\fP execution call stack.
-The number of
-parameters to the current subroutine (shell function or script executed
-with \fB.\fP or \fBsource\fP) is at the top of the stack.
-When a subroutine is executed, the number of parameters passed is pushed onto
-.SM
-.BR BASH_ARGC .
-The shell sets
-.SM
-.B BASH_ARGC
-only when in extended debugging mode (see the description of the
-.B extdebug
-option to the
-.B shopt
-builtin below)
-.TP
-.B BASH_ARGV
-An array variable containing all of the parameters in the current \fBbash\fP
-execution call stack.  The final parameter of the last subroutine call
-is at the top of the stack; the first parameter of the initial call is
-at the bottom.  When a subroutine is executed, the parameters supplied
-are pushed onto
-.SM
-.BR BASH_ARGV .
-The shell sets
-.SM
-.B BASH_ARGV
-only when in extended debugging mode
-(see the description of the
-.B extdebug
-option to the
-.B shopt
-builtin below)
-.TP
-.B BASH_CMDS
-An associative array variable whose members correspond to the internal
-hash table of commands as maintained by the \fBhash\fP builtin.
-Elements added to this array appear in the hash table; unsetting array
-elements cause commands to be removed from the hash table.
-.TP
-.B BASH_COMMAND
-The command currently being executed or about to be executed, unless the
-shell is executing a command as the result of a trap,
-in which case it is the command executing at the time of the trap.
-.TP
-.B BASH_EXECUTION_STRING
-The command argument to the \fB\-c\fP invocation option.
-.TP
-.B BASH_LINENO
-An array variable whose members are the line numbers in source files
-where each corresponding member of
-.SM
-.B FUNCNAME
-was invoked.
-\fB${BASH_LINENO[\fP\fI$i\fP\fB]}\fP is the line number in the source
-file (\fB${BASH_SOURCE[\fP\fI$i+1\fP\fB]}\fP) where
-\fB${FUNCNAME[\fP\fI$i\fP\fB]}\fP was called
-(or \fB${BASH_LINENO[\fP\fI$i-1\fP\fB]}\fP if referenced within another
-shell function).
-Use
-.SM
-.B LINENO
-to obtain the current line number.
-.TP
-.B BASH_REMATCH
-An array variable whose members are assigned by the \fB=~\fP binary
-operator to the \fB[[\fP conditional command.
-The element with index 0 is the portion of the string
-matching the entire regular expression.
-The element with index \fIn\fP is the portion of the
-string matching the \fIn\fPth parenthesized subexpression.
-This variable is read-only.
-.TP
-.B BASH_SOURCE
-An array variable whose members are the source filenames
-where the corresponding shell function names in the
-.SM
-.B FUNCNAME
-array variable are defined.
-The shell function
-\fB${FUNCNAME[\fP\fI$i\fP\fB]}\fP is defined in the file
-\fB${BASH_SOURCE[\fP\fI$i\fP\fB]}\fP and called from
-\fB${BASH_SOURCE[\fP\fI$i+1\fP\fB]}\fP.
-.TP
-.B BASH_SUBSHELL
-Incremented by one within each subshell or subshell environment when
-the shell begins executing in that environment.
-The initial value is 0.
-.TP
-.B BASH_VERSINFO
-A readonly array variable whose members hold version information for
-this instance of
-.BR bash .
-The values assigned to the array members are as follows:
-.sp .5
-.RS
-.TP 24
-.B BASH_VERSINFO[\fR0\fP]
-The major version number (the \fIrelease\fP).
-.TP
-.B BASH_VERSINFO[\fR1\fP]
-The minor version number (the \fIversion\fP).
-.TP
-.B BASH_VERSINFO[\fR2\fP]
-The patch level.
-.TP
-.B BASH_VERSINFO[\fR3\fP]
-The build version.
-.TP
-.B BASH_VERSINFO[\fR4\fP]
-The release status (e.g., \fIbeta1\fP).
-.TP
-.B BASH_VERSINFO[\fR5\fP]
-The value of
-.SM
-.BR MACHTYPE .
-.RE
-.TP
-.B BASH_VERSION
-Expands to a string describing the version of this instance of
-.BR bash .
-.TP
-.B COMP_CWORD
-An index into \fB${COMP_WORDS}\fP of the word containing the current
-cursor position.
-This variable is available only in shell functions invoked by the
-programmable completion facilities (see \fBProgrammable Completion\fP
-below).
-.TP
-.B COMP_KEY
-The key (or final key of a key sequence) used to invoke the current
-completion function.
-.TP
-.B COMP_LINE
-The current command line.
-This variable is available only in shell functions and external
-commands invoked by the
-programmable completion facilities (see \fBProgrammable Completion\fP
-below).
-.TP
-.B COMP_POINT
-The index of the current cursor position relative to the beginning of
-the current command.
-If the current cursor position is at the end of the current command,
-the value of this variable is equal to \fB${#COMP_LINE}\fP.
-This variable is available only in shell functions and external
-commands invoked by the
-programmable completion facilities (see \fBProgrammable Completion\fP
-below).
-.TP
-.B COMP_TYPE
-Set to an integer value corresponding to the type of completion attempted
-that caused a completion function to be called:
-\fITAB\fP, for normal completion,
-\fI?\fP, for listing completions after successive tabs,
-\fI!\fP, for listing alternatives on partial word completion,
-\fI@\fP, to list completions if the word is not unmodified,
-or
-\fI%\fP, for menu completion.
-This variable is available only in shell functions and external
-commands invoked by the
-programmable completion facilities (see \fBProgrammable Completion\fP
-below).
-.TP
-.B COMP_WORDBREAKS
-The set of characters that the \fBreadline\fP library treats as word
-separators when performing word completion.
-If
-.SM
-.B COMP_WORDBREAKS
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B COMP_WORDS
-An array variable (see \fBArrays\fP below) consisting of the individual
-words in the current command line.
-The line is split into words as \fBreadline\fP would split it, using
-.SM
-.B COMP_WORDBREAKS
-as described above.
-This variable is available only in shell functions invoked by the
-programmable completion facilities (see \fBProgrammable Completion\fP
-below).
-.TP
-.B COPROC
-An array variable (see \fBArrays\fP below) created to hold the file descriptors
-for output from and input to an unnamed coprocess (see \fBCoprocesses\fP
-above).
-.TP
-.B DIRSTACK
-An array variable (see
-.B Arrays
-below) containing the current contents of the directory stack.
-Directories appear in the stack in the order they are displayed by the
-.B dirs
-builtin.
-Assigning to members of this array variable may be used to modify
-directories already in the stack, but the
-.B pushd
-and
-.B popd
-builtins must be used to add and remove directories.
-Assignment to this variable will not change the current directory.
-If
-.SM
-.B DIRSTACK
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B EUID
-Expands to the effective user ID of the current user, initialized at
-shell startup.  This variable is readonly.
-.TP
-.B FUNCNAME
-An array variable containing the names of all shell functions
-currently in the execution call stack.
-The element with index 0 is the name of any currently-executing
-shell function.
-The bottom-most element (the one with the highest index) is
-.if t \f(CW"main"\fP.
-.if n "main".
-This variable exists only when a shell function is executing.
-Assignments to
-.SM
-.B FUNCNAME
-have no effect and return an error status.
-If
-.SM
-.B FUNCNAME
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.if t .sp 0.5
-.if n .sp 1
-This variable can be used with \fBBASH_LINENO\fP and \fBBASH_SOURCE\fP.
-Each element of \fBFUNCNAME\fP has corresponding elements in
-\fBBASH_LINENO\fP and \fBBASH_SOURCE\fP to describe the call stack.
-For instance, \fB${FUNCNAME[\fP\fI$i\fP\fB]}\fP was called from the file
-\fB${BASH_SOURCE[\fP\fI$i+1\fP\fB]}\fP at line number
-\fB${BASH_LINENO[\fP\fI$i\fP\fB]}\fP.
-The \fBcaller\fP builtin displays the current call stack using this
-information.
-.TP
-.B GROUPS
-An array variable containing the list of groups of which the current
-user is a member.
-Assignments to    
-.SM
-.B GROUPS
-have no effect and return an error status.
-If
-.SM
-.B GROUPS
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B HISTCMD
-The history number, or index in the history list, of the current
-command.
-If
-.SM
-.B HISTCMD
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B HOSTNAME
-Automatically set to the name of the current host.
-.TP
-.B HOSTTYPE
-Automatically set to a string that uniquely
-describes the type of machine on which
-.B bash
-is executing.
-The default is system-dependent.
-.TP
-.B LINENO
-Each time this parameter is referenced, the shell substitutes
-a decimal number representing the current sequential line number
-(starting with 1) within a script or function.  When not in a
-script or function, the value substituted is not guaranteed to
-be meaningful.
-If
-.SM
-.B LINENO
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B MACHTYPE
-Automatically set to a string that fully describes the system
-type on which
-.B bash
-is executing, in the standard GNU \fIcpu-company-system\fP format.
-The default is system-dependent.
-.TP
-.B MAPFILE
-An array variable (see \fBArrays\fP below) created to hold the text
-read by the \fBmapfile\fP builtin when no variable name is supplied.
-.TP
-.B OLDPWD
-The previous working directory as set by the
-.B cd
-command.
-.TP
-.B OPTARG
-The value of the last option argument processed by the
-.B getopts
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.TP
-.B OPTIND
-The index of the next argument to be processed by the
-.B getopts
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.TP
-.B OSTYPE
-Automatically set to a string that
-describes the operating system on which
-.B bash
-is executing.
-The default is system-dependent.
-.TP
-.B PIPESTATUS
-An array variable (see
-.B Arrays
-below) containing a list of exit status values from the processes
-in the most-recently-executed foreground pipeline (which may
-contain only a single command).
-.TP
-.B PPID
-The process ID of the shell's parent.  This variable is readonly.
-.TP
-.B PWD
-The current working directory as set by the
-.B cd
-command.
-.TP
-.B RANDOM
-Each time this parameter is referenced, a random integer between
-0 and 32767 is
-generated.  The sequence of random numbers may be initialized by assigning
-a value to
-.SM
-.BR RANDOM .
-If
-.SM
-.B RANDOM
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B READLINE_LINE
-The contents of the
-.B readline
-line buffer, for use with
-.if t \f(CWbind -x\fP
-.if n "bind -x"
-(see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below).
-.TP
-.B READLINE_POINT
-The position of the insertion point in the
-.B readline
-line buffer, for use with
-.if t \f(CWbind -x\fP
-.if n "bind -x"
-(see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below).
-.TP
-.B REPLY
-Set to the line of input read by the
-.B read
-builtin command when no arguments are supplied.
-.TP
-.B SECONDS
-Each time this parameter is
-referenced, the number of seconds since shell invocation is returned.  If a
-value is assigned to 
-.SM
-.BR SECONDS ,
-the value returned upon subsequent
-references is
-the number of seconds since the assignment plus the value assigned.
-If
-.SM
-.B SECONDS
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B SHELLOPTS
-A colon-separated list of enabled shell options.  Each word in
-the list is a valid argument for the
-.B \-o
-option to the
-.B set
-builtin command (see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below).  The options appearing in
-.SM
-.B SHELLOPTS
-are those reported as
-.I on
-by \fBset \-o\fP.
-If this variable is in the environment when
-.B bash
-starts up, each shell option in the list will be enabled before
-reading any startup files.
-This variable is read-only.
-.TP
-.B SHLVL
-Incremented by one each time an instance of
-.B bash
-is started.
-.TP
-.B UID
-Expands to the user ID of the current user, initialized at shell startup.
-This variable is readonly.
-.PD
-.PP
-The following variables are used by the shell.  In some cases,
-.B bash
-assigns a default value to a variable; these cases are noted
-below.
-.PP
-.PD 0
-.TP
-.B BASH_COMPAT
-The value is used to set the shell's compatibility level.
-See the description of the \fBshopt\fB builtin below under
-\fBSHELL BUILTIN COMMANDS\fP  for a description of the various compatibility
-levels and their effects.
-The value may be a decimal number (e.g., 4.2) or an integer (e.g., 42)
-corresponding to the desired compatibility level.
-If \fBBASH_COMPAT\fP is unset or set to the empty string, the compatibility
-level is set to the default for the current version.
-If \fBBASH_COMPAT\fP is set to a value that is not one of the valid
-compatibility levels, the shell prints an error message and sets the
-compatibility level to the default for the current version.
-The valid compatibility levels correspond to the compatibility options
-accepted by the \fBshopt\fP builtin described below (for example,
-\fBcompat42\fP means that 4.2 and 42 are valid values).
-The current version is also a valid value.
-.TP
-.B BASH_ENV
-If this parameter is set when \fBbash\fP is executing a shell script,
-its value is interpreted as a filename containing commands to
-initialize the shell, as in
-.IR ~/.bashrc .
-The value of
-.SM
-.B BASH_ENV
-is subjected to parameter expansion, command substitution, and arithmetic
-expansion before being interpreted as a filename.
-.SM
-.B PATH
-is not used to search for the resultant filename.
-.TP
-.B BASH_XTRACEFD
-If set to an integer corresponding to a valid file descriptor, \fBbash\fP
-will write the trace output generated when
-.if t \f(CWset -x\fP
-.if n \fIset -x\fP
-is enabled to that file descriptor.
-The file descriptor is closed when
-.SM
-.B BASH_XTRACEFD
-is unset or assigned a new value.
-Unsetting
-.SM
-.B BASH_XTRACEFD
-or assigning it the empty string causes the
-trace output to be sent to the standard error.
-Note that setting
-.SM
-.B BASH_XTRACEFD
-to 2 (the standard error file
-descriptor) and then unsetting it will result in the standard error
-being closed.
-.TP
-.B CDPATH
-The search path for the
-.B cd
-command.
-This is a colon-separated list of directories in which the shell looks
-for destination directories specified by the
-.B cd
-command.
-A sample value is
-.if t \f(CW".:~:/usr"\fP.
-.if n ".:~:/usr".
-.TP
-.B CHILD_MAX
-Set the number of exited child status values for the shell to remember.
-Bash will not allow this value to be decreased below a Posix-mandated
-minimum, and there is a maximum value (currently 8192) that this may
-not exceed.
-The minimum value is system-dependent.
-.TP
-.B COLUMNS
-Used by the \fBselect\fP compound command to determine the terminal width
-when printing selection lists.  Automatically set in an interactive shell
-upon receipt of a
-.SM
-.BR SIGWINCH .
-.TP
-.B COMPREPLY
-An array variable from which \fBbash\fP reads the possible completions
-generated by a shell function invoked by the programmable completion
-facility (see \fBProgrammable Completion\fP below).
-Each array element contains one possible completion.
-.TP
-.B EMACS
-If \fBbash\fP finds this variable in the environment when the shell starts
-with value
-.if t \f(CWt\fP,
-.if n "t",
-it assumes that the shell is running in an Emacs shell buffer and disables
-line editing.
-.TP
-.B ENV
-Similar to
-.SM
-.BR BASH_ENV ;
-used when the shell is invoked in POSIX mode.
-.TP
-.B FCEDIT
-The default editor for the
-.B fc
-builtin command.
-.TP
-.B FIGNORE
-A colon-separated list of suffixes to ignore when performing
-filename completion (see
-.SM
-.B READLINE
-below).
-A filename whose suffix matches one of the entries in 
-.SM
-.B FIGNORE
-is excluded from the list of matched filenames.
-A sample value is
-.if t \f(CW".o:~"\fP.
-.if n ".o:~".
-.TP
-.B FUNCNEST
-If set to a numeric value greater than 0, defines a maximum function
-nesting level.  Function invocations that exceed this nesting level
-will cause the current command to abort.
-.TP
-.B GLOBIGNORE
-A colon-separated list of patterns defining the set of filenames to
-be ignored by pathname expansion.
-If a filename matched by a pathname expansion pattern also matches one
-of the patterns in
-.SM
-.BR GLOBIGNORE ,
-it is removed from the list of matches.
-.TP
-.B HISTCONTROL
-A colon-separated list of values controlling how commands are saved on
-the history list.
-If the list of values includes
-.IR ignorespace ,
-lines which begin with a
-.B space
-character are not saved in the history list.
-A value of 
-.I ignoredups
-causes lines matching the previous history entry to not be saved.
-A value of
-.I ignoreboth
-is shorthand for \fIignorespace\fP and \fIignoredups\fP.
-A value of
-.IR erasedups
-causes all previous lines matching the current line to be removed from
-the history list before that line is saved.
-Any value not in the above list is ignored.
-If
-.SM
-.B HISTCONTROL
-is unset, or does not include a valid value,
-all lines read by the shell parser are saved on the history list,
-subject to the value of
-.SM
-.BR HISTIGNORE .
-The second and subsequent lines of a multi-line compound command are
-not tested, and are added to the history regardless of the value of
-.SM
-.BR HISTCONTROL .
-.TP
-.B HISTFILE
-The name of the file in which command history is saved (see
-.SM
-.B HISTORY
-below).  The default value is \fI~/.bash_history\fP.  If unset, the
-command history is not saved when a shell exits.
-.TP
-.B HISTFILESIZE
-The maximum number of lines contained in the history file.  When this
-variable is assigned a value, the history file is truncated, if
-necessary,
-to contain no more than that number of lines by removing the oldest entries.
-The history file is also truncated to this size after
-writing it when a shell exits.
-If the value is 0, the history file is truncated to zero size.
-Non-numeric values and numeric values less than zero inhibit truncation.
-The shell sets the default value to the value of \fBHISTSIZE\fP
-after reading any startup files.
-.TP
-.B HISTIGNORE
-A colon-separated list of patterns used to decide which command lines
-should be saved on the history list.  Each pattern is anchored at the
-beginning of the line and must match the complete line (no implicit
-`\fB*\fP' is appended).  Each pattern is tested against the line
-after the checks specified by
-.SM
-.B HISTCONTROL
-are applied.
-In addition to the normal shell pattern matching characters, `\fB&\fP'
-matches the previous history line.  `\fB&\fP' may be escaped using a
-backslash; the backslash is removed before attempting a match.
-The second and subsequent lines of a multi-line compound command are
-not tested, and are added to the history regardless of the value of
-.SM
-.BR HISTIGNORE .
-.TP
-.B HISTSIZE
-The number of commands to remember in the command history (see
-.SM
-.B HISTORY
-below).
-If the value is 0, commands are not saved in the history list.
-Numeric values less than zero result in every command being saved
-on the history list (there is no limit).
-The shell sets the default value to 500 after reading any startup files.
-.TP
-.B HISTTIMEFORMAT
-If this variable is set and not null, its value is used as a format string
-for \fIstrftime\fP(3) to print the time stamp associated with each history
-entry displayed by the \fBhistory\fP builtin.
-If this variable is set, time stamps are written to the history file so
-they may be preserved across shell sessions.
-This uses the history comment character to distinguish timestamps from
-other history lines.
-.TP
-.B HOME
-The home directory of the current user; the default argument for the
-\fBcd\fP builtin command.
-The value of this variable is also used when performing tilde expansion.
-.TP
-.B HOSTFILE
-Contains the name of a file in the same format as
-.FN /etc/hosts
-that should be read when the shell needs to complete a
-hostname.
-The list of possible hostname completions may be changed while the
-shell is running;
-the next time hostname completion is attempted after the
-value is changed,
-.B bash
-adds the contents of the new file to the existing list.
-If
-.SM
-.B HOSTFILE
-is set, but has no value, or does not name a readable file,
-\fBbash\fP attempts to read
-.FN /etc/hosts
-to obtain the list of possible hostname completions.
-When
-.SM
-.B HOSTFILE
-is unset, the hostname list is cleared.
-.TP
-.B IFS
-The
-.I Internal Field Separator
-that is used
-for word splitting after expansion and to
-split lines into words with the
-.B read
-builtin command.  The default value is
-``<space><tab><newline>''.
-.TP
-.B IGNOREEOF
-Controls the
-action of an interactive shell on receipt of an
-.SM
-.B EOF
-character as the sole input.  If set, the value is the number of
-consecutive
-.SM
-.B EOF
-characters which must be
-typed as the first characters on an input line before
-.B bash
-exits.  If the variable exists but does not have a numeric value, or
-has no value, the default value is 10.  If it does not exist,
-.SM
-.B EOF
-signifies the end of input to the shell.
-.TP
-.B INPUTRC
-The filename for the
-.B readline
-startup file, overriding the default of
-.FN ~/.inputrc
-(see
-.SM
-.B READLINE
-below).
-.TP
-.B LANG
-Used to determine the locale category for any category not specifically
-selected with a variable starting with \fBLC_\fP.
-.TP
-.B LC_ALL
-This variable overrides the value of
-.SM
-.B LANG
-and any other
-\fBLC_\fP variable specifying a locale category.
-.TP
-.B LC_COLLATE
-This variable determines the collation order used when sorting the
-results of pathname expansion, and determines the behavior of range
-expressions, equivalence classes, and collating sequences within
-pathname expansion and pattern matching.
-.TP
-.B LC_CTYPE
-This variable determines the interpretation of characters and the
-behavior of character classes within pathname expansion and pattern
-matching.
-.TP
-.B LC_MESSAGES
-This variable determines the locale used to translate double-quoted
-strings preceded by a \fB$\fP.
-.TP
-.B LC_NUMERIC
-This variable determines the locale category used for number formatting.
-.TP
-.B LINES
-Used by the \fBselect\fP compound command to determine the column length
-for printing selection lists.  Automatically set by an interactive shell
-upon receipt of a
-.SM
-.BR SIGWINCH .
-.TP
-.B MAIL
-If this parameter is set to a file or directory name and the
-.SM
-.B MAILPATH
-variable is not set,
-.B bash
-informs the user of the arrival of mail in the specified file or
-Maildir-format directory.
-.TP
-.B MAILCHECK
-Specifies how
-often (in seconds)
-.B bash
-checks for mail.  The default is 60 seconds.  When it is time to check
-for mail, the shell does so before displaying the primary prompt.
-If this variable is unset, or set to a value that is not a number
-greater than or equal to zero, the shell disables mail checking.
-.TP
-.B MAILPATH
-A colon-separated list of filenames to be checked for mail. 
-The message to be printed when mail arrives in a particular file
-may be specified by separating the filename from the message with a `?'.
-When used in the text of the message, \fB$_\fP expands to the name of
-the current mailfile. 
-Example:
-.RS
-.PP
-\fBMAILPATH\fP=\(aq/var/mail/bfox?"You have mail":~/shell\-mail?"$_ has mail!"\(aq
-.PP
-.B Bash
-supplies a default value for this variable, but the location of the user
-mail files that it uses is system dependent (e.g., /var/mail/\fB$USER\fP).
-.RE
-.TP
-.B OPTERR
-If set to the value 1,
-.B bash
-displays error messages generated by the
-.B getopts
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.SM
-.B OPTERR
-is initialized to 1 each time the shell is invoked or a shell
-script is executed.
-.TP
-.B PATH
-The search path for commands.  It
-is a colon-separated list of directories in which
-the shell looks for commands (see
-.SM
-.B COMMAND EXECUTION
-below).
-A zero-length (null) directory name in the value of
-.SM
-.B PATH
-indicates the current directory.
-A null directory name may appear as two adjacent colons, or as an initial
-or trailing colon.
-The default path is system-dependent,
-and is set by the administrator who installs
-.BR bash .
-A common value is
-.if t \f(CW/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin\fP.
-.if n ``/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin''.
-.TP
-.B POSIXLY_CORRECT
-If this variable is in the environment when \fBbash\fP starts, the shell
-enters \fIposix mode\fP before reading the startup files, as if the
-.B \-\-posix
-invocation option had been supplied.  If it is set while the shell is
-running, \fBbash\fP enables \fIposix mode\fP, as if the command
-.if t \f(CWset -o posix\fP
-.if n \fIset -o posix\fP
-had been executed.
-.TP
-.B PROMPT_COMMAND
-If set, the value is executed as a command prior to issuing each primary
-prompt.
-.TP
-.B PROMPT_DIRTRIM
-If set to a number greater than zero, the value is used as the number of
-trailing directory components to retain when expanding the \fB\ew\fP and
-\fB\eW\fP prompt string escapes (see
-.SM
-.B PROMPTING
-below).  Characters removed are replaced with an ellipsis.
-.TP
-.B PS1
-The value of this parameter is expanded (see
-.SM
-.B PROMPTING
-below) and used as the primary prompt string.  The default value is
-``\fB\es\-\ev\e$ \fP''.
-.TP
-.B PS2
-The value of this parameter is expanded as with
-.SM
-.B PS1
-and used as the secondary prompt string.  The default is
-``\fB> \fP''.
-.TP
-.B PS3
-The value of this parameter is used as the prompt for the
-.B select
-command (see
-.SM
-.B SHELL GRAMMAR
-above).
-.TP
-.B PS4
-The value of this parameter is expanded as with
-.SM
-.B PS1
-and the value is printed before each command
-.B bash
-displays during an execution trace.  The first character of
-.SM
-.B PS4
-is replicated multiple times, as necessary, to indicate multiple
-levels of indirection.  The default is ``\fB+ \fP''.
-.TP
-.B SHELL
-The full pathname to the shell is kept in this environment variable.
-If it is not set when the shell starts,
-.B bash
-assigns to it the full pathname of the current user's login shell.
-.TP
-.B TIMEFORMAT
-The value of this parameter is used as a format string specifying
-how the timing information for pipelines prefixed with the
-.B time
-reserved word should be displayed.
-The \fB%\fP character introduces an escape sequence that is
-expanded to a time value or other information.
-The escape sequences and their meanings are as follows; the
-braces denote optional portions.
-.sp .5
-.RS
-.PD 0
-.TP 10
-.B %%
-A literal \fB%\fP.
-.TP
-.B %[\fIp\fP][l]R
-The elapsed time in seconds.
-.TP
-.B %[\fIp\fP][l]U
-The number of CPU seconds spent in user mode.
-.TP
-.B %[\fIp\fP][l]S
-The number of CPU seconds spent in system mode.
-.TP
-.B %P
-The CPU percentage, computed as (%U + %S) / %R.
-.PD
-.RE
-.IP
-The optional \fIp\fP is a digit specifying the \fIprecision\fP,
-the number of fractional digits after a decimal point.
-A value of 0 causes no decimal point or fraction to be output.
-At most three places after the decimal point may be specified;
-values of \fIp\fP greater than 3 are changed to 3.
-If \fIp\fP is not specified, the value 3 is used.
-.IP
-The optional \fBl\fP specifies a longer format, including
-minutes, of the form \fIMM\fPm\fISS\fP.\fIFF\fPs.
-The value of \fIp\fP determines whether or not the fraction is
-included.
-.IP
-If this variable is not set, \fBbash\fP acts as if it had the
-value \fB$\(aq\enreal\et%3lR\enuser\et%3lU\ensys\e\t%3lS\(aq\fP.
-If the value is null, no timing information is displayed.
-A trailing newline is added when the format string is displayed.
-.PD 0
-.TP
-.B TMOUT
-If set to a value greater than zero,
-.SM
-.B TMOUT
-is treated as the
-default timeout for the \fBread\fP builtin.
-The \fBselect\fP command terminates if input does not arrive
-after
-.SM
-.B TMOUT
-seconds when input is coming from a terminal.
-In an interactive shell, the value is interpreted as the
-number of seconds to wait for a line of input after issuing the
-primary prompt.
-.B Bash
-terminates after waiting for that number of seconds if a complete
-line of input does not arrive.
-.TP
-.B TMPDIR
-If set, \fBbash\fP uses its value as the name of a directory in which
-\fBbash\fP creates temporary files for the shell's use.
-.TP
-.B auto_resume
-This variable controls how the shell interacts with the user and
-job control.  If this variable is set, single word simple
-commands without redirections are treated as candidates for resumption
-of an existing stopped job.  There is no ambiguity allowed; if there is
-more than one job beginning with the string typed, the job most recently
-accessed is selected.  The
-.I name
-of a stopped job, in this context, is the command line used to
-start it.
-If set to the value
-.IR exact ,
-the string supplied must match the name of a stopped job exactly;
-if set to
-.IR substring ,
-the string supplied needs to match a substring of the name of a
-stopped job.  The
-.I substring
-value provides functionality analogous to the
-.B %?
-job identifier (see
-.SM
-.B JOB CONTROL
-below).  If set to any other value, the supplied string must
-be a prefix of a stopped job's name; this provides functionality
-analogous to the \fB%\fP\fIstring\fP job identifier.
-.TP
-.B histchars
-The two or three characters which control history expansion
-and tokenization (see
-.SM
-.B HISTORY EXPANSION
-below).  The first character is the \fIhistory expansion\fP character,
-the character which signals the start of a history
-expansion, normally `\fB!\fP'.
-The second character is the \fIquick substitution\fP
-character, which is used as shorthand for re-running the previous
-command entered, substituting one string for another in the command.
-The default is `\fB^\fP'.
-The optional third character is the character
-which indicates that the remainder of the line is a comment when found
-as the first character of a word, normally `\fB#\fP'.  The history
-comment character causes history substitution to be skipped for the
-remaining words on the line.  It does not necessarily cause the shell
-parser to treat the rest of the line as a comment.
-.PD
-.SS Arrays
-.B Bash
-provides one-dimensional indexed and associative array variables.
-Any variable may be used as an indexed array; the
-.B declare
-builtin will explicitly declare an array.
-There is no maximum
-limit on the size of an array, nor any requirement that members
-be indexed or assigned contiguously.
-Indexed arrays are referenced using integers (including arithmetic
-expressions)  and are zero-based; associative arrays are referenced
-using arbitrary strings.
-Unless otherwise noted, indexed array indices must be non-negative integers.
-.PP
-An indexed array is created automatically if any variable is assigned to
-using the syntax \fIname\fP[\fIsubscript\fP]=\fIvalue\fP.  The
-.I subscript
-is treated as an arithmetic expression that must evaluate to a number.
-To explicitly declare an indexed array, use
-.B declare \-a \fIname\fP
-(see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.B declare \-a \fIname\fP[\fIsubscript\fP]
-is also accepted; the \fIsubscript\fP is ignored.
-.PP
-Associative arrays are created using
-.BR "declare \-A \fIname\fP" .
-.PP
-Attributes may be
-specified for an array variable using the
-.B declare
-and
-.B readonly
-builtins.  Each attribute applies to all members of an array.
-.PP
-Arrays are assigned to using compound assignments of the form
-\fIname\fP=\fB(\fPvalue\fI1\fP ... value\fIn\fP\fB)\fP, where each
-\fIvalue\fP is of the form [\fIsubscript\fP]=\fIstring\fP.
-Indexed array assignments do not require anything but \fIstring\fP.
-When assigning to indexed arrays, if the optional brackets and subscript
-are supplied, that index is assigned to;
-otherwise the index of the element assigned is the last index assigned
-to by the statement plus one.  Indexing starts at zero.
-.PP
-When assigning to an associative array, the subscript is required.
-.PP
-This syntax is also accepted by the
-.B declare
-builtin.  Individual array elements may be assigned to using the
-\fIname\fP[\fIsubscript\fP]=\fIvalue\fP syntax introduced above.
-When assigning to an indexed array, if
-.I name
-is subscripted by a negative number, that number is
-interpreted as relative to one greater than the maximum index of
-\fIname\fP, so negative indices count back from the end of the
-array, and an index of \-1 references the last element.
-.PP
-Any element of an array may be referenced using
-${\fIname\fP[\fIsubscript\fP]}.  The braces are required to avoid
-conflicts with pathname expansion.  If
-\fIsubscript\fP is \fB@\fP or \fB*\fP, the word expands to
-all members of \fIname\fP.  These subscripts differ only when the
-word appears within double quotes.  If the word is double-quoted,
-${\fIname\fP[*]} expands to a single
-word with the value of each array member separated by the first
-character of the
-.SM
-.B IFS
-special variable, and ${\fIname\fP[@]} expands each element of
-\fIname\fP to a separate word.  When there are no array members,
-${\fIname\fP[@]} expands to nothing.
-If the double-quoted expansion occurs within a word, the expansion of
-the first parameter is joined with the beginning part of the original
-word, and the expansion of the last parameter is joined with the last
-part of the original word.
-This is analogous to the expansion
-of the special parameters \fB*\fP and \fB@\fP (see
-.B Special Parameters
-above).  ${#\fIname\fP[\fIsubscript\fP]} expands to the length of
-${\fIname\fP[\fIsubscript\fP]}.  If \fIsubscript\fP is \fB*\fP or
-\fB@\fP, the expansion is the number of elements in the array.
-Referencing an array variable without a subscript is equivalent to
-referencing the array with a subscript of 0.
-If the
-.I subscript
-used to reference an element of an indexed array
-evaluates to a number less than zero, it is 
-interpreted as relative to one greater than the maximum index of the array,
-so negative indices count back from the end of the
-array, and an index of \-1 references the last element.
-.PP
-An array variable is considered set if a subscript has been assigned a
-value.  The null string is a valid value.
-.PP
-The
-.B unset
-builtin is used to destroy arrays.  \fBunset\fP \fIname\fP[\fIsubscript\fP]
-destroys the array element at index \fIsubscript\fP.
-Negative subscripts to indexed arrays are interpreted as described above.
-Care must be taken to avoid unwanted side effects caused by pathname
-expansion.
-\fBunset\fP \fIname\fP, where \fIname\fP is an array, or
-\fBunset\fP \fIname\fP[\fIsubscript\fP], where
-\fIsubscript\fP is \fB*\fP or \fB@\fP, removes the entire array.
-.PP
-The
-.BR declare ,
-.BR local ,
-and
-.B readonly
-builtins each accept a
-.B \-a
-option to specify an indexed array and a
-.B \-A
-option to specify an associative array.
-If both options are supplied, 
-.B \-A
-takes precedence.
-The
-.B read
-builtin accepts a
-.B \-a
-option to assign a list of words read from the standard input
-to an array.  The
-.B set
-and
-.B declare
-builtins display array values in a way that allows them to be
-reused as assignments.
-.SH EXPANSION
-Expansion is performed on the command line after it has been split into
-words.  There are seven kinds of expansion performed:
-.IR "brace expansion" ,
-.IR "tilde expansion" ,
-.IR "parameter and variable expansion" ,
-.IR "command substitution" ,
-.IR "arithmetic expansion" ,
-.IR "word splitting" ,
-and
-.IR "pathname expansion" .
-.PP
-The order of expansions is: brace expansion, tilde expansion,
-parameter, variable and arithmetic expansion and
-command substitution
-(done in a left-to-right fashion), word splitting, and pathname
-expansion.
-.PP
-On systems that can support it, there is an additional expansion
-available: \fIprocess substitution\fP.
-.PP
-Only brace expansion, word splitting, and pathname expansion
-can change the number of words of the expansion; other expansions
-expand a single word to a single word.
-The only exceptions to this are the expansions of
-"\fB$@\fP" and "\fB${\fP\fIname\fP\fB[@]}\fP"
-as explained above (see
-.SM
-.BR PARAMETERS ).
-.SS Brace Expansion
-.PP
-.I "Brace expansion"
-is a mechanism by which arbitrary strings
-may be generated.  This mechanism is similar to
-\fIpathname expansion\fP, but the filenames generated
-need not exist.  Patterns to be brace expanded take
-the form of an optional
-.IR preamble ,
-followed by either a series of comma-separated strings or
-a sequence expression between a pair of braces, followed by
-an optional
-.IR postscript .
-The preamble is prefixed to each string contained
-within the braces, and the postscript is then appended
-to each resulting string, expanding left to right.
-.PP
-Brace expansions may be nested.  The results of each expanded
-string are not sorted; left to right order is preserved.
-For example, a\fB{\fPd,c,b\fB}\fPe expands into `ade ace abe'.
-.PP
-A sequence expression takes the form
-\fB{\fP\fIx\fP\fB..\fP\fIy\fP\fB[..\fP\fIincr\fP\fB]}\fP,
-where \fIx\fP and \fIy\fP are either integers or single characters,
-and \fIincr\fP, an optional increment, is an integer.
-When integers are supplied, the expression expands to each number between
-\fIx\fP and \fIy\fP, inclusive.
-Supplied integers may be prefixed with \fI0\fP to force each term to have the
-same width.
-When either \fIx\fP or \fPy\fP begins with a zero, the shell
-attempts to force all generated terms to contain the same number of digits,
-zero-padding where necessary.
-When characters are supplied, the expression expands to each character
-lexicographically between \fIx\fP and \fIy\fP, inclusive,
-using the default C locale.
-Note that both \fIx\fP and \fIy\fP must be of the same type.
-When the increment is supplied, it is used as the difference between
-each term.  The default increment is 1 or -1 as appropriate.
-.PP
-Brace expansion is performed before any other expansions,
-and any characters special to other expansions are preserved
-in the result.  It is strictly textual.
-.B Bash
-does not apply any syntactic interpretation to the context of the
-expansion or the text between the braces.
-.PP
-A correctly-formed brace expansion must contain unquoted opening
-and closing braces, and at least one unquoted comma or a valid
-sequence expression.
-Any incorrectly formed brace expansion is left unchanged.
-A \fB{\fP or \fB,\fP may be quoted with a backslash to prevent its
-being considered part of a brace expression.
-To avoid conflicts with parameter expansion, the string \fB${\fP
-is not considered eligible for brace expansion.
-.PP
-This construct is typically used as shorthand when the common
-prefix of the strings to be generated is longer than in the
-above example:
-.RS
-.PP
-mkdir /usr/local/src/bash/{old,new,dist,bugs}
-.RE
-or
-.RS
-chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
-.RE
-.PP
-Brace expansion introduces a slight incompatibility with
-historical versions of
-.BR sh .
-.B sh
-does not treat opening or closing braces specially when they
-appear as part of a word, and preserves them in the output.
-.B Bash
-removes braces from words as a consequence of brace
-expansion.  For example, a word entered to
-.B sh
-as \fIfile{1,2}\fP
-appears identically in the output.  The same word is
-output as
-.I file1 file2
-after expansion by
-.BR bash .
-If strict compatibility with
-.B sh
-is desired, start
-.B bash
-with the
-.B +B 
-option or disable brace expansion with the
-.B +B
-option to the
-.B set
-command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.SS Tilde Expansion
-.PP
-If a word begins with an unquoted tilde character (`\fB~\fP'), all of
-the characters preceding the first unquoted slash (or all characters,
-if there is no unquoted slash) are considered a \fItilde-prefix\fP.
-If none of the characters in the tilde-prefix are quoted, the
-characters in the tilde-prefix following the tilde are treated as a
-possible \fIlogin name\fP.
-If this login name is the null string, the tilde is replaced with the
-value of the shell parameter
-.SM
-.BR HOME .
-If
-.SM
-.B HOME
-is unset, the home directory of the user executing the shell is
-substituted instead.
-Otherwise, the tilde-prefix is replaced with the home directory
-associated with the specified login name.
-.PP
-If the tilde-prefix is a `~+', the value of the shell variable
-.SM
-.B PWD
-replaces the tilde-prefix.
-If the tilde-prefix is a `~\-', the value of the shell variable
-.SM
-.BR OLDPWD ,
-if it is set, is substituted.
-If the characters following the tilde in the tilde-prefix consist
-of a number \fIN\fP, optionally prefixed
-by a `+' or a `\-', the tilde-prefix is replaced with the corresponding
-element from the directory stack, as it would be displayed by the
-.B dirs
-builtin invoked with the tilde-prefix as an argument.
-If the characters following the tilde in the tilde-prefix consist of a
-number without a leading `+' or `\-', `+' is assumed.
-.PP
-If the login name is invalid, or the tilde expansion fails, the word
-is unchanged.
-.PP
-Each variable assignment is checked for unquoted tilde-prefixes immediately
-following a
-.B :
-or the first
-.BR = .
-In these cases, tilde expansion is also performed.
-Consequently, one may use filenames with tildes in assignments to
-.SM
-.BR PATH ,
-.SM
-.BR MAILPATH ,
-and
-.SM
-.BR CDPATH ,
-and the shell assigns the expanded value.
-.SS Parameter Expansion
-.PP
-The `\fB$\fP' character introduces parameter expansion,
-command substitution, or arithmetic expansion.  The parameter name
-or symbol to be expanded may be enclosed in braces, which
-are optional but serve to protect the variable to be expanded from
-characters immediately following it which could be
-interpreted as part of the name.
-.PP
-When braces are used, the matching ending brace is the first `\fB}\fP'
-not escaped by a backslash or within a quoted string, and not within an
-embedded arithmetic expansion, command substitution, or parameter
-expansion.
-.PP
-.PD 0
-.TP
-${\fIparameter\fP}
-The value of \fIparameter\fP is substituted.  The braces are required
-when
-.I parameter
-is a positional parameter with more than one digit,
-or when
-.I parameter
-is followed by a character which is not to be
-interpreted as part of its name.
-The \fIparameter\fP is a shell parameter as described above
-\fBPARAMETERS\fP) or an array reference (\fBArrays\fP).
-.PD
-.PP
-If the first character of \fIparameter\fP is an exclamation point (\fB!\fP),
-it introduces a level of variable indirection.
-\fBBash\fP uses the value of the variable formed from the rest of
-\fIparameter\fP as the name of the variable; this variable is then
-expanded and that value is used in the rest of the substitution, rather
-than the value of \fIparameter\fP itself.
-This is known as \fIindirect expansion\fP.
-The exceptions to this are the expansions of ${\fB!\fP\fIprefix\fP\fB*\fP} and
-${\fB!\fP\fIname\fP[\fI@\fP]} described below.
-The exclamation point must immediately follow the left brace in order to
-introduce indirection.
-.PP
-In each of the cases below, \fIword\fP is subject to tilde expansion,
-parameter expansion, command substitution, and arithmetic expansion.
-.PP
-When not performing substring expansion, using the forms documented below
-(e.g., \fB:-\fP),
-\fBbash\fP tests for a parameter that is unset or null.  Omitting the colon
-results in a test only for a parameter that is unset.
-.PP
-.PD 0
-.TP
-${\fIparameter\fP\fB:\-\fP\fIword\fP}
-\fBUse Default Values\fP.  If
-.I parameter
-is unset or null, the expansion of
-.I word
-is substituted.  Otherwise, the value of
-.I parameter
-is substituted.
-.TP
-${\fIparameter\fP\fB:=\fP\fIword\fP}
-\fBAssign Default Values\fP.
-If
-.I parameter
-is unset or null, the expansion of
-.I word
-is assigned to
-.IR parameter .
-The value of
-.I parameter
-is then substituted.  Positional parameters and special parameters may
-not be assigned to in this way.
-.TP
-${\fIparameter\fP\fB:?\fP\fIword\fP}
-\fBDisplay Error if Null or Unset\fP.
-If
-.I parameter
-is null or unset, the expansion of \fIword\fP (or a message to that effect
-if
-.I word
-is not present) is written to the standard error and the shell, if it
-is not interactive, exits.  Otherwise, the value of \fIparameter\fP is
-substituted.
-.TP
-${\fIparameter\fP\fB:+\fP\fIword\fP}
-\fBUse Alternate Value\fP.
-If
-.I parameter
-is null or unset, nothing is substituted, otherwise the expansion of
-.I word
-is substituted.
-.TP
-${\fIparameter\fP\fB:\fP\fIoffset\fP}
-.PD 0
-.TP
-${\fIparameter\fP\fB:\fP\fIoffset\fP\fB:\fP\fIlength\fP}
-.PD
-\fBSubstring Expansion\fP.
-Expands to up to \fIlength\fP characters of the value of \fIparameter\fP
-starting at the character specified by \fIoffset\fP.
-If \fIparameter\fP is \fB@\fP, an indexed array subscripted by
-\fB@\fP or \fB*\fP, or an associative array name, the results differ as
-described below.
-If \fIlength\fP is omitted, expands to the substring of the value of
-\fIparameter\fP starting at the character specified by \fIoffset\fP
-and extending to the end of the value.
-\fIlength\fP and \fIoffset\fP are arithmetic expressions (see
-.SM
-.B
-ARITHMETIC EVALUATION
-below).
-.sp 1
-If \fIoffset\fP evaluates to a number less than zero, the value
-is used as an offset in characters
-from the end of the value of \fIparameter\fP.
-If \fIlength\fP evaluates to a number less than zero,
-it is interpreted as an offset in characters
-from the end of the value of \fIparameter\fP rather than
-a number of characters, and the expansion is the characters between
-\fIoffset\fP and that result.
-Note that a negative offset must be separated from the colon by at least
-one space to avoid being confused with the \fB:-\fP expansion.
-.sp 1
-If \fIparameter\fP is \fB@\fP, the result is \fIlength\fP positional
-parameters beginning at \fIoffset\fP.
-A negative \fIoffset\fP is taken relative to one greater than the greatest
-positional parameter, so an offset of -1 evaluates to the last positional
-parameter.
-It is an expansion error if \fIlength\fP evaluates to a number less than
-zero.
-.sp 1
-If \fIparameter\fP is an indexed array name subscripted by @ or *,
-the result is the \fIlength\fP
-members of the array beginning with ${\fIparameter\fP[\fIoffset\fP]}.
-A negative \fIoffset\fP is taken relative to one greater than the maximum
-index of the specified array.
-It is an expansion error if \fIlength\fP evaluates to a number less than
-zero.
-.sp 1
-Substring expansion applied to an associative array produces undefined
-results.
-.sp 1
-Substring indexing is zero-based unless the positional parameters 
-are used, in which case the indexing starts at 1 by default.
-If \fIoffset\fP is 0, and the positional parameters are used, \fB$0\fP is
-prefixed to the list.
-.TP
-${\fB!\fP\fIprefix\fP\fB*\fP}
-.PD 0
-.TP
-${\fB!\fP\fIprefix\fP\fB@\fP}
-.PD
-\fBNames matching prefix\fP.
-Expands to the names of variables whose names begin with \fIprefix\fP,
-separated by the first character of the
-.SM
-.B IFS
-special variable.
-When \fI@\fP is used and the expansion appears within double quotes, each
-variable name expands to a separate word.
-.TP
-${\fB!\fP\fIname\fP[\fI@\fP]}
-.PD 0
-.TP
-${\fB!\fP\fIname\fP[\fI*\fP]}
-.PD
-\fBList of array keys\fP.
-If \fIname\fP is an array variable, expands to the list of array indices
-(keys) assigned in \fIname\fP.
-If \fIname\fP is not an array, expands to 0 if \fIname\fP is set and null
-otherwise.
-When \fI@\fP is used and the expansion appears within double quotes, each
-key expands to a separate word.
-.TP
-${\fB#\fP\fIparameter\fP}
-\fBParameter length\fP.
-The length in characters of the value of \fIparameter\fP is substituted.
-If
-.I parameter
-is
-.B *
-or 
-.BR @ ,
-the value substituted is the number of positional parameters.
-If
-.I parameter
-is an array name subscripted by
-.B *
-or
-.BR @ ,
-the value substituted is the number of elements in the array.
-If
-.I parameter
-is an indexed array name subscripted by a negative number, that number is
-interpreted as relative to one greater than the maximum index of
-\fIparameter\fP, so negative indices count back from the end of the
-array, and an index of \-1 references the last element.
-.TP
-${\fIparameter\fP\fB#\fP\fIword\fP}
-.PD 0
-.TP
-${\fIparameter\fP\fB##\fP\fIword\fP}
-.PD
-\fBRemove matching prefix pattern\fP.
-The 
-.I word
-is expanded to produce a pattern just as in pathname
-expansion.  If the pattern matches the beginning of
-the value of
-.IR parameter ,
-then the result of the expansion is the expanded value of
-.I parameter
-with the shortest matching pattern (the ``\fB#\fP'' case) or the
-longest matching pattern (the ``\fB##\fP'' case) deleted.
-If
-.I parameter
-is
-.B @
-or
-.BR * ,
-the pattern removal operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If
-.I parameter
-is an array variable subscripted with
-.B @
-or
-.BR * ,
-the pattern removal operation is applied to each member of the
-array in turn, and the expansion is the resultant list.
-.TP
-${\fIparameter\fP\fB%\fP\fIword\fP}
-.PD 0
-.TP
-${\fIparameter\fP\fB%%\fP\fIword\fP}
-.PD
-\fBRemove matching suffix pattern\fP.
-The \fIword\fP is expanded to produce a pattern just as in
-pathname expansion.
-If the pattern matches a trailing portion of the expanded value of
-.IR parameter ,
-then the result of the expansion is the expanded value of
-.I parameter
-with the shortest matching pattern (the ``\fB%\fP'' case) or the
-longest matching pattern (the ``\fB%%\fP'' case) deleted.
-If
-.I parameter
-is
-.B @
-or
-.BR * ,
-the pattern removal operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If
-.I parameter
-is an array variable subscripted with
-.B @
-or
-.BR * ,
-the pattern removal operation is applied to each member of the
-array in turn, and the expansion is the resultant list.
-.TP
-${\fIparameter\fP\fB/\fP\fIpattern\fP\fB/\fP\fIstring\fP}
-\fBPattern substitution\fP.
-The \fIpattern\fP is expanded to produce a pattern just as in
-pathname expansion.
-\fIParameter\fP is expanded and the longest match of \fIpattern\fP
-against its value is replaced with \fIstring\fP.
-If \fIpattern\fP begins with \fB/\fP, all matches of \fIpattern\fP are
-replaced with \fIstring\fP.  Normally only the first match is replaced.
-If \fIpattern\fP begins with \fB#\fP, it must match at the beginning
-of the expanded value of \fIparameter\fP.
-If \fIpattern\fP begins with \fB%\fP, it must match at the end
-of the expanded value of \fIparameter\fP.
-If \fIstring\fP is null, matches of \fIpattern\fP are deleted
-and the \fB/\fP following \fIpattern\fP may be omitted.
-If
-.I parameter
-is
-.B @
-or
-.BR * ,
-the substitution operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If
-.I parameter
-is an array variable subscripted with
-.B @
-or
-.BR * ,
-the substitution operation is applied to each member of the
-array in turn, and the expansion is the resultant list.
-.TP
-${\fIparameter\fP\fB^\fP\fIpattern\fP}
-.PD 0
-.TP
-${\fIparameter\fP\fB^^\fP\fIpattern\fP}
-.TP
-${\fIparameter\fP\fB,\fP\fIpattern\fP}
-.TP
-${\fIparameter\fP\fB,,\fP\fIpattern\fP}
-.PD
-\fBCase modification\fP.
-This expansion modifies the case of alphabetic characters in \fIparameter\fP.
-The \fIpattern\fP is expanded to produce a pattern just as in
-pathname expansion.
-Each character in the expanded value of \fIparameter\fP is tested against
-\fIpattern\fP, and, if it matches the pattern, its case is converted.
-The pattern should not attempt to match more than one character.
-The \fB^\fP operator converts lowercase letters matching \fIpattern\fP
-to uppercase; the \fB,\fP operator converts matching uppercase letters
-to lowercase.
-The \fB^^\fP and \fB,,\fP expansions convert each matched character in the
-expanded value; the \fB^\fP and \fB,\fP expansions match and convert only
-the first character in the expanded value.
-If \fIpattern\fP is omitted, it is treated like a \fB?\fP, which matches
-every character.
-If
-.I parameter
-is
-.B @
-or
-.BR * ,
-the case modification operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If
-.I parameter
-is an array variable subscripted with
-.B @
-or
-.BR * ,
-the case modification operation is applied to each member of the
-array in turn, and the expansion is the resultant list.
-.SS Command Substitution
-.PP
-\fICommand substitution\fP allows the output of a command to replace
-the command name.  There are two forms:
-.RS
-.PP
-\fB$(\fP\fIcommand\fP\|\fB)\fP
-.RE
-or
-.RS
-\fB\`\fP\fIcommand\fP\fB\`\fP
-.RE
-.PP
-.B Bash
-performs the expansion by executing \fIcommand\fP and
-replacing the command substitution with the standard output of the
-command, with any trailing newlines deleted.
-Embedded newlines are not deleted, but they may be removed during
-word splitting.
-The command substitution \fB$(cat \fIfile\fP)\fR can be replaced by
-the equivalent but faster \fB$(< \fIfile\fP)\fR.
-.PP
-When the old-style backquote form of substitution is used,
-backslash retains its literal meaning except when followed by
-.BR $ ,
-.BR \` ,
-or
-.BR \e .
-The first backquote not preceded by a backslash terminates the
-command substitution.
-When using the $(\^\fIcommand\fP\|) form, all characters between the
-parentheses make up the command; none are treated specially.
-.PP
-Command substitutions may be nested.  To nest when using the backquoted form,
-escape the inner backquotes with backslashes.
-.PP
-If the substitution appears within double quotes, word splitting and
-pathname expansion are not performed on the results.
-.SS Arithmetic Expansion
-.PP
-Arithmetic expansion allows the evaluation of an arithmetic expression
-and the substitution of the result.  The format for arithmetic expansion is:
-.RS
-.PP
-\fB$((\fP\fIexpression\fP\fB))\fP
-.RE
-.PP
-The
-.I expression
-is treated as if it were within double quotes, but a double quote
-inside the parentheses is not treated specially.
-All tokens in the expression undergo parameter expansion, string
-expansion, command substitution, and quote removal.
-Arithmetic expansions may be nested.
-.PP
-The evaluation is performed according to the rules listed below under
-.SM
-.BR "ARITHMETIC EVALUATION" .
-If
-.I expression
-is invalid,
-.B bash
-prints a message indicating failure and no substitution occurs.
-.SS Process Substitution
-.PP
-\fIProcess substitution\fP is supported on systems that support named
-pipes (\fIFIFOs\fP) or the \fB/dev/fd\fP method of naming open files.
-It takes the form of
-\fB<(\fP\fIlist\^\fP\fB)\fP
-or
-\fB>(\fP\fIlist\^\fP\fB)\fP.
-The process \fIlist\fP is run with its input or output connected to a
-\fIFIFO\fP or some file in \fB/dev/fd\fP.  The name of this file is
-passed as an argument to the current command as the result of the
-expansion.  If the \fB>(\fP\fIlist\^\fP\fB)\fP form is used, writing to
-the file will provide input for \fIlist\fP.  If the
-\fB<(\fP\fIlist\^\fP\fB)\fP form is used, the file passed as an
-argument should be read to obtain the output of \fIlist\fP.
-.PP
-When available, process substitution is performed
-simultaneously with parameter and variable expansion, 
-command substitution,
-and arithmetic expansion.
-.SS Word Splitting
-.PP
-The shell scans the results of
-parameter expansion,
-command substitution,
-and
-arithmetic expansion
-that did not occur within double quotes for
-.IR "word splitting" .
-.PP
-The shell treats each character of
-.SM
-.B IFS
-as a delimiter, and splits the results of the other
-expansions into words on these characters.  If
-.SM
-.B IFS
-is unset, or its
-value is exactly
-.BR <space><tab><newline> ,
-the default, then
-sequences of
-.BR <space> ,
-.BR <tab> ,
-and
-.B <newline>
-at the beginning and end of the results of the previous
-expansions are ignored, and
-any sequence of
-.SM
-.B IFS
-characters not at the beginning or end serves to delimit words.
-If
-.SM
-.B IFS
-has a value other than the default, then sequences of
-the whitespace characters
-.B space
-and
-.B tab
-are ignored at the beginning and end of the
-word, as long as the whitespace character is in the
-value of
-.SM
-.BR IFS
-(an
-.SM
-.B IFS
-whitespace character).
-Any character in
-.SM
-.B IFS
-that is not
-.SM
-.B IFS
-whitespace, along with any adjacent
-.SM
-.B IFS
-whitespace characters, delimits a field.
-A sequence of
-.SM
-.B IFS
-whitespace characters is also treated as a delimiter.
-If the value of
-.SM
-.B IFS
-is null, no word splitting occurs.
-.PP
-Explicit null arguments (\^\f3"\^"\fP or \^\f3\(aq\^\(aq\fP\^) are retained.
-Unquoted implicit null arguments, resulting from the expansion of
-parameters that have no values, are removed.
-If a parameter with no value is expanded within double quotes, a
-null argument results and is retained.
-.PP
-Note that if no expansion occurs, no splitting
-is performed.
-.SS Pathname Expansion
-.PP
-After word splitting,
-unless the
-.B \-f
-option has been set,
-.B bash
-scans each word for the characters
-.BR * ,
-.BR ? ,
-and
-.BR [ .
-If one of these characters appears, then the word is
-regarded as a
-.IR pattern ,
-and replaced with an alphabetically sorted list of
-filenames matching the pattern
-(see
-.SM
-.B "Pattern Matching"
-below).
-If no matching filenames are found,
-and the shell option
-.B nullglob
-is not enabled, the word is left unchanged.
-If the 
-.B nullglob
-option is set, and no matches are found,
-the word is removed.
-If the
-.B failglob
-shell option is set, and no matches are found, an error message
-is printed and the command is not executed.
-If the shell option
-.B nocaseglob
-is enabled, the match is performed without regard to the case
-of alphabetic characters.
-When a pattern is used for pathname expansion,
-the character
-.B ``.''
-at the start of a name or immediately following a slash
-must be matched explicitly, unless the shell option
-.B dotglob
-is set.
-When matching a pathname, the slash character must always be
-matched explicitly.
-In other cases, the
-.B ``.''
-character is not treated specially.
-See the description of
-.B shopt
-below under
-.SM
-.B SHELL BUILTIN COMMANDS
-for a description of the
-.BR nocaseglob ,
-.BR nullglob ,
-.BR failglob ,
-and
-.B dotglob
-shell options.
-.PP
-The
-.SM
-.B GLOBIGNORE
-shell variable may be used to restrict the set of filenames matching a
-.IR pattern .
-If
-.SM
-.B GLOBIGNORE
-is set, each matching filename that also matches one of the patterns in
-.SM
-.B GLOBIGNORE
-is removed from the list of matches.
-The filenames
-.B ``.''
-and
-.B ``..''
-are always ignored when
-.SM
-.B GLOBIGNORE
-is set and not null.  However, setting
-.SM
-.B GLOBIGNORE
-to a non-null value has the effect of enabling the
-.B dotglob
-shell option, so all other filenames beginning with a
-.B ``.''
-will match.
-To get the old behavior of ignoring filenames beginning with a
-.BR ``.'' ,
-make
-.B ``.*''
-one of the patterns in
-.SM
-.BR GLOBIGNORE .
-The
-.B dotglob
-option is disabled when
-.SM
-.B GLOBIGNORE
-is unset.
-.PP
-\fBPattern Matching\fP
-.PP
-Any character that appears in a pattern, other than the special pattern
-characters described below, matches itself.  The NUL character may not
-occur in a pattern.  A backslash escapes the following character; the
-escaping backslash is discarded when matching.
-The special pattern characters must be quoted if
-they are to be matched literally.
-.PP
-The special pattern characters have the following meanings:
-.PP
-.PD 0
-.RS
-.TP
-.B *
-Matches any string, including the null string.
-When the \fBglobstar\fP shell option is enabled, and \fB*\fP is used in
-a pathname expansion context, two adjacent \fB*\fPs used as a single
-pattern will match all files and zero or more directories and
-subdirectories.
-If followed by a \fB/\fP, two adjacent \fB*\fPs will match only directories
-and subdirectories.
-.TP
-.B ?
-Matches any single character.
-.TP
-.B [...]
-Matches any one of the enclosed characters.  A pair of characters
-separated by a hyphen denotes a
-\fIrange expression\fP;
-any character that falls between those two characters, inclusive,
-using the current locale's collating sequence and character set,
-is matched.  If the first character following the
-.B [
-is a
-.B !
-or a
-.B ^
-then any character not enclosed is matched.
-The sorting order of characters in range expressions is determined by
-the current locale and the values of the
-.SM
-.B LC_COLLATE
-or
-.SM
-.B LC_ALL
-shell variables, if set.
-To obtain the traditional interpretation of range expressions, where
-.B [a\-d]
-is equivalent to
-.BR [abcd] ,
-set value of the
-.B LC_ALL
-shell variable to
-.BR C ,
-or enable the
-.B globasciiranges
-shell option.
-A 
-.B \-
-may be matched by including it as the first or last character
-in the set.
-A
-.B ]
-may be matched by including it as the first character
-in the set.
-.br
-.if t .sp 0.5
-.if n .sp 1
-Within
-.B [
-and
-.BR ] ,
-\fIcharacter classes\fP can be specified using the syntax
-\fB[:\fP\fIclass\fP\fB:]\fP, where \fIclass\fP is one of the
-following classes defined in the POSIX standard:
-.PP
-.RS
-.B
-.if n alnum alpha ascii blank cntrl digit graph lower print punct space upper word xdigit
-.if t alnum   alpha   ascii   blank   cntrl   digit   graph   lower   print   punct   space   upper   word   xdigit
-.br
-A character class matches any character belonging to that class.
-The \fBword\fP character class matches letters, digits, and the character _.
-.br
-.if t .sp 0.5
-.if n .sp 1
-Within
-.B [
-and 
-.BR ] ,
-an \fIequivalence class\fP can be specified using the syntax
-\fB[=\fP\fIc\fP\fB=]\fP, which matches all characters with the
-same collation weight (as defined by the current locale) as
-the character \fIc\fP.
-.br
-.if t .sp 0.5
-.if n .sp 1
-Within
-.B [
-and 
-.BR ] ,
-the syntax \fB[.\fP\fIsymbol\fP\fB.]\fP matches the collating symbol
-\fIsymbol\fP.
-.RE
-.RE
-.PD
-.PP
-If the \fBextglob\fP shell option is enabled using the \fBshopt\fP
-builtin, several extended pattern matching operators are recognized.
-In the following description, a \fIpattern-list\fP is a list of one
-or more patterns separated by a \fB|\fP.
-Composite patterns may be formed using one or more of the following
-sub-patterns:
-.sp 1
-.PD 0
-.RS
-.TP
-\fB?(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches zero or one occurrence of the given patterns
-.TP
-\fB*(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches zero or more occurrences of the given patterns
-.TP
-\fB+(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches one or more occurrences of the given patterns
-.TP
-\fB@(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches one of the given patterns
-.TP
-\fB!(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches anything except one of the given patterns
-.RE
-.PD
-.SS Quote Removal
-.PP
-After the preceding expansions, all unquoted occurrences of the
-characters
-.BR \e ,
-.BR \(aq ,
-and \^\f3"\fP\^ that did not result from one of the above
-expansions are removed.
-.SH REDIRECTION
-Before a command is executed, its input and output
-may be
-.I redirected
-using a special notation interpreted by the shell.
-Redirection allows commands' file handles to be
-duplicated, opened, closed,
-made to refer to different files,
-and can change the files the command reads from and writes to.
-Redirection may also be used to modify file handles in the
-current shell execution environment.
-The following redirection
-operators may precede or appear anywhere within a
-.I simple command
-or may follow a
-.IR command .
-Redirections are processed in the order they appear, from
-left to right.
-.PP
-Each redirection that may be preceded by a file descriptor number
-may instead be preceded by a word of the form {\fIvarname\fP}.
-In this case, for each redirection operator except
->&- and <&-, the shell will allocate a file descriptor greater
-than or equal to 10 and assign it to \fIvarname\fP.
-If >&- or <&- is preceded
-by {\fIvarname\fP}, the value of \fIvarname\fP defines the file
-descriptor to close.
-.PP
-In the following descriptions, if the file descriptor number is
-omitted, and the first character of the redirection operator is
-.BR < ,
-the redirection refers to the standard input (file descriptor
-0).  If the first character of the redirection operator is
-.BR > ,
-the redirection refers to the standard output (file descriptor
-1).
-.PP
-The word following the redirection operator in the following
-descriptions, unless otherwise noted, is subjected to
-brace expansion, tilde expansion, parameter and variable expansion,
-command substitution, arithmetic expansion, quote removal,
-pathname expansion, and word splitting.
-If it expands to more than one word,
-.B bash
-reports an error.
-.PP
-Note that the order of redirections is significant.  For example, 
-the command
-.RS
-.PP
-ls \fB>\fP dirlist 2\fB>&\fP1
-.RE
-.PP
-directs both standard output and standard error to the file 
-.IR dirlist ,
-while the command
-.RS
-.PP
-ls 2\fB>&\fP1 \fB>\fP dirlist
-.RE
-.PP
-directs only the standard output to file
-.IR dirlist ,
-because the standard error was duplicated from the standard output
-before the standard output was redirected to
-.IR dirlist .
-.PP
-\fBBash\fP handles several filenames specially when they are used in
-redirections, as described in the following table:
-.RS
-.PP
-.PD 0
-.TP
-.B /dev/fd/\fIfd\fP
-If \fIfd\fP is a valid integer, file descriptor \fIfd\fP is duplicated.
-.TP
-.B /dev/stdin
-File descriptor 0 is duplicated.
-.TP
-.B /dev/stdout
-File descriptor 1 is duplicated.
-.TP
-.B /dev/stderr
-File descriptor 2 is duplicated.
-.TP
-.B /dev/tcp/\fIhost\fP/\fIport\fP
-If \fIhost\fP is a valid hostname or Internet address, and \fIport\fP
-is an integer port number or service name, \fBbash\fP attempts to open
-the corresponding TCP socket.
-.TP
-.B /dev/udp/\fIhost\fP/\fIport\fP
-If \fIhost\fP is a valid hostname or Internet address, and \fIport\fP
-is an integer port number or service name, \fBbash\fP attempts to open
-the corresponding UDP socket.
-.PD
-.RE
-.PP
-A failure to open or create a file causes the redirection to fail.
-.PP
-Redirections using file descriptors greater than 9 should be used with
-care, as they may conflict with file descriptors the shell uses
-internally.
-.SS Redirecting Input
-.PP
-Redirection of input causes the file whose name results from
-the expansion of
-.I word
-to be opened for reading on file descriptor
-.IR n ,
-or the standard input (file descriptor 0) if
-.I n
-is not specified.
-.PP
-The general format for redirecting input is:
-.RS
-.PP
-[\fIn\fP]\fB<\fP\fIword\fP
-.RE
-.SS Redirecting Output
-.PP
-Redirection of output causes the file whose name results from
-the expansion of
-.I word
-to be opened for writing on file descriptor
-.IR n ,
-or the standard output (file descriptor 1) if
-.I n
-is not specified.  If the file does not exist it is created;
-if it does exist it is truncated to zero size.
-.PP
-The general format for redirecting output is:
-.RS
-.PP
-[\fIn\fP]\fB>\fP\fIword\fP
-.RE
-.PP
-If the redirection operator is
-.BR > ,
-and the
-.B noclobber
-option to the
-.B set
-builtin has been enabled, the redirection will fail if the file
-whose name results from the expansion of \fIword\fP exists and is
-a regular file.
-If the redirection operator is
-.BR >| ,
-or the redirection operator is
-.B >
-and the
-.B noclobber
-option to the
-.B set
-builtin command is not enabled, the redirection is attempted even
-if the file named by \fIword\fP exists.
-.SS Appending Redirected Output
-.PP
-Redirection of output in this fashion
-causes the file whose name results from
-the expansion of
-.I word
-to be opened for appending on file descriptor
-.IR n ,
-or the standard output (file descriptor 1) if
-.I n
-is not specified.  If the file does not exist it is created.
-.PP
-The general format for appending output is:
-.RS
-.PP
-[\fIn\fP]\fB>>\fP\fIword\fP
-.RE
-.PP
-.SS Redirecting Standard Output and Standard Error
-.PP
-This construct allows both the
-standard output (file descriptor 1) and
-the standard error output (file descriptor 2)
-to be redirected to the file whose name is the
-expansion of
-.IR word .
-.PP
-There are two formats for redirecting standard output and
-standard error:
-.RS
-.PP
-\fB&>\fP\fIword\fP
-.RE
-and
-.RS
-\fB>&\fP\fIword\fP
-.RE
-.PP
-Of the two forms, the first is preferred.
-This is semantically equivalent to
-.RS
-.PP
-\fB>\fP\fIword\fP 2\fB>&\fP1
-.RE
-.PP
-When using the second form, \fIword\fP may not expand to a number or
-\fB\-\fP.  If it does, other redirection operators apply
-(see \fBDuplicating File Descriptors\fP below) for compatibility
-reasons.
-.SS Appending Standard Output and Standard Error
-.PP
-This construct allows both the
-standard output (file descriptor 1) and
-the standard error output (file descriptor 2)
-to be appended to the file whose name is the
-expansion of
-.IR word .
-.PP
-The format for appending standard output and standard error is:
-.RS
-.PP
-\fB&>>\fP\fIword\fP
-.RE
-.PP
-This is semantically equivalent to
-.RS
-.PP
-\fB>>\fP\fIword\fP 2\fB>&\fP1
-.RE
-.PP
-(see \fBDuplicating File Descriptors\fP below).
-.SS Here Documents
-.PP
-This type of redirection instructs the shell to read input from the
-current source until a line containing only
-.I delimiter
-(with no trailing blanks)
-is seen.  All of
-the lines read up to that point are then used as the standard
-input for a command.
-.PP
-The format of here-documents is:
-.RS
-.PP
-.nf
-\fB<<\fP[\fB\-\fP]\fIword\fP
-        \fIhere-document\fP
-\fIdelimiter\fP
-.fi
-.RE
-.PP
-No parameter and variable expansion, command substitution,
-arithmetic expansion, or pathname expansion is performed on
-.IR word .
-If any characters in
-.I word
-are quoted, the
-.I delimiter
-is the result of quote removal on
-.IR word ,
-and the lines in the here-document are not expanded.
-If \fIword\fP is unquoted,
-all lines of the here-document are subjected to
-parameter expansion, command substitution, and arithmetic expansion,
-the character sequence
-.B \e<newline>
-is ignored, and
-.B \e
-must be used to quote the characters
-.BR \e ,
-.BR $ ,
-and
-.BR \` .
-.PP
-If the redirection operator is
-.BR <<\- ,
-then all leading tab characters are stripped from input lines and the
-line containing
-.IR delimiter .
-This allows
-here-documents within shell scripts to be indented in a
-natural fashion.
-.SS "Here Strings"
-A variant of here documents, the format is:
-.RS
-.PP
-.nf
-\fB<<<\fP\fIword\fP
-.fi
-.RE
-.PP
-The \fIword\fP undergoes
-brace expansion, tilde expansion, parameter and variable expansion,
-command substitution, arithmetic expansion, and quote removal.
-Pathname expansion and word splitting are not performed.
-The result is supplied as a single string to the command on its
-standard input.
-.SS "Duplicating File Descriptors"
-.PP
-The redirection operator
-.RS
-.PP
-[\fIn\fP]\fB<&\fP\fIword\fP
-.RE
-.PP
-is used to duplicate input file descriptors.
-If
-.I word
-expands to one or more digits, the file descriptor denoted by
-.I n
-is made to be a copy of that file descriptor.
-If the digits in
-.I word
-do not specify a file descriptor open for input, a redirection error occurs.
-If
-.I word
-evaluates to
-.BR \- ,
-file descriptor
-.I n
-is closed.  If
-.I n
-is not specified, the standard input (file descriptor 0) is used.
-.PP
-The operator
-.RS
-.PP
-[\fIn\fP]\fB>&\fP\fIword\fP
-.RE
-.PP
-is used similarly to duplicate output file descriptors.  If
-.I n
-is not specified, the standard output (file descriptor 1) is used.
-If the digits in
-.I word
-do not specify a file descriptor open for output, a redirection error occurs.
-If
-.I word
-evaluates to
-.BR \- ,
-file descriptor
-.I n
-is closed.
-As a special case, if \fIn\fP is omitted, and \fIword\fP does not
-expand to one or more digits or \fB\-\fP, the standard output and standard
-error are redirected as described previously.
-.SS "Moving File Descriptors"
-.PP
-The redirection operator
-.RS
-.PP
-[\fIn\fP]\fB<&\fP\fIdigit\fP\fB\-\fP
-.RE
-.PP
-moves the file descriptor \fIdigit\fP to file descriptor
-.IR n ,
-or the standard input (file descriptor 0) if \fIn\fP is not specified.
-\fIdigit\fP is closed after being duplicated to \fIn\fP.
-.PP
-Similarly, the redirection operator
-.RS
-.PP
-[\fIn\fP]\fB>&\fP\fIdigit\fP\fB\-\fP
-.RE
-.PP
-moves the file descriptor \fIdigit\fP to file descriptor
-.IR n ,
-or the standard output (file descriptor 1) if \fIn\fP is not specified.
-.SS "Opening File Descriptors for Reading and Writing"
-.PP
-The redirection operator
-.RS
-.PP
-[\fIn\fP]\fB<>\fP\fIword\fP
-.RE
-.PP
-causes the file whose name is the expansion of
-.I word
-to be opened for both reading and writing on file descriptor
-.IR n ,
-or on file descriptor 0 if
-.I n
-is not specified.  If the file does not exist, it is created.
-.SH ALIASES
-\fIAliases\fP allow a string to be substituted for a word when it is used
-as the first word of a simple command.
-The shell maintains a list of aliases that may be set and unset with the
-.B alias
-and
-.B unalias
-builtin commands (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-The first word of each simple command, if unquoted,
-is checked to see if it has an
-alias.  If so, that word is replaced by the text of the alias.
-The characters \fB/\fP, \fB$\fP, \fB\`\fP, and \fB=\fP and
-any of the shell \fImetacharacters\fP or quoting characters
-listed above may not appear in an alias name.
-The replacement text may contain any valid shell input,
-including shell metacharacters.
-The first word of the replacement text is tested
-for aliases, but a word that is identical to an alias being expanded
-is not expanded a second time.
-This means that one may alias
-.B ls
-to
-.BR "ls \-F" ,
-for instance, and
-.B bash
-does not try to recursively expand the replacement text.
-If the last character of the alias value is a
-.IR blank ,
-then the next command
-word following the alias is also checked for alias expansion.
-.PP
-Aliases are created and listed with the
-.B alias
-command, and removed with the
-.B unalias
-command.
-.PP
-There is no mechanism for using arguments in the replacement text.
-If arguments are needed, a shell function should be used (see
-.SM
-.B FUNCTIONS
-below).
-.PP
-Aliases are not expanded when the shell is not interactive, unless
-the
-.B expand_aliases
-shell option is set using
-.B shopt
-(see the description of
-.B shopt
-under
-.SM
-\fBSHELL BUILTIN COMMANDS\fP
-below).
-.PP
-The rules concerning the definition and use of aliases are
-somewhat confusing.
-.B Bash
-always reads at least one complete line
-of input before executing any
-of the commands on that line.  Aliases are expanded when a
-command is read, not when it is executed.  Therefore, an
-alias definition appearing on the same line as another
-command does not take effect until the next line of input is read.
-The commands following the alias definition
-on that line are not affected by the new alias.
-This behavior is also an issue when functions are executed.
-Aliases are expanded when a function definition is read,
-not when the function is executed, because a function definition
-is itself a compound command.  As a consequence, aliases
-defined in a function are not available until after that
-function is executed.  To be safe, always put
-alias definitions on a separate line, and do not use
-.B alias
-in compound commands.
-.PP
-For almost every purpose, aliases are superseded by
-shell functions.
-.SH FUNCTIONS
-A shell function, defined as described above under
-.SM
-.BR "SHELL GRAMMAR" ,
-stores a series of commands for later execution.
-When the name of a shell function is used as a simple command name,
-the list of commands associated with that function name is executed.
-Functions are executed in the context of the
-current shell; no new process is created to interpret
-them (contrast this with the execution of a shell script).
-When a function is executed, the arguments to the
-function become the positional parameters
-during its execution.
-The special parameter
-.B #
-is updated to reflect the change.  Special parameter \fB0\fP
-is unchanged.
-The first element of the
-.SM
-.B FUNCNAME
-variable is set to the name of the function while the function
-is executing.
-.PP
-All other aspects of the shell execution
-environment are identical between a function and its caller
-with these exceptions:  the
-.SM
-.B DEBUG
-and
-.B RETURN
-traps (see the description of the
-.B trap
-builtin under
-.SM
-.B SHELL BUILTIN COMMANDS
-below) are not inherited unless the function has been given the
-\fBtrace\fP attribute (see the description of the
-.SM
-.B declare
-builtin below) or the
-\fB\-o functrace\fP shell option has been enabled with
-the \fBset\fP builtin
-(in which case all functions inherit the \fBDEBUG\fP and \fBRETURN\fP traps),
-and the
-.SM
-.B ERR
-trap is not inherited unless the \fB\-o errtrace\fP shell option has
-been enabled.
-.PP
-Variables local to the function may be declared with the
-.B local
-builtin command.  Ordinarily, variables and their values
-are shared between the function and its caller.
-.PP
-The \fBFUNCNEST\fP variable, if set to a numeric value greater
-than 0, defines a maximum function nesting level.  Function
-invocations that exceed the limit cause the entire command to
-abort.
-.PP
-If the builtin command
-.B return
-is executed in a function, the function completes and
-execution resumes with the next command after the function
-call.
-Any command associated with the \fBRETURN\fP trap is executed
-before execution resumes.
-When a function completes, the values of the
-positional parameters and the special parameter
-.B #
-are restored to the values they had prior to the function's
-execution.
-.PP
-Function names and definitions may be listed with the
-.B \-f
-option to the
-.B declare
-or
-.B typeset
-builtin commands.  The
-.B \-F
-option to
-.B declare
-or
-.B typeset
-will list the function names only
-(and optionally the source file and line number, if the \fBextdebug\fP
-shell option is enabled).
-Functions may be exported so that subshells
-automatically have them defined with the
-.B \-f
-option to the 
-.B export
-builtin.
-A function definition may be deleted using the \fB\-f\fP option to
-the
-.B unset
-builtin.
-Note that shell functions and variables with the same name may result
-in multiple identically-named entries in the environment passed to the
-shell's children.
-Care should be taken in cases where this may cause a problem.
-.PP
-Functions may be recursive.
-The \fBFUNCNEST\fP variable may be used to limit the depth of the
-function call stack and restrict the number of function invocations.
-By default, no limit is imposed on the number of recursive calls.
-.SH "ARITHMETIC EVALUATION"
-The shell allows arithmetic expressions to be evaluated, under
-certain circumstances (see the \fBlet\fP and \fBdeclare\fP builtin
-commands and \fBArithmetic Expansion\fP).
-Evaluation is done in fixed-width integers with no check for overflow,
-though division by 0 is trapped and flagged as an error.
-The operators and their precedence, associativity, and values
-are the same as in the C language.
-The following list of operators is grouped into levels of
-equal-precedence operators.
-The levels are listed in order of decreasing precedence.
-.PP
-.PD 0
-.TP
-.B \fIid\fP++ \fIid\fP\-\-
-variable post-increment and post-decrement
-.TP
-.B ++\fIid\fP \-\-\fIid\fP
-variable pre-increment and pre-decrement
-.TP
-.B \- +
-unary minus and plus
-.TP
-.B ! ~
-logical and bitwise negation
-.TP
-.B **
-exponentiation
-.TP
-.B * / %
-multiplication, division, remainder
-.TP
-.B + \-
-addition, subtraction
-.TP
-.B << >>
-left and right bitwise shifts
-.TP
-.B <= >= < >
-comparison
-.TP
-.B == !=
-equality and inequality
-.TP
-.B &
-bitwise AND
-.TP
-.B ^
-bitwise exclusive OR
-.TP
-.B |
-bitwise OR
-.TP
-.B &&
-logical AND
-.TP
-.B ||
-logical OR
-.TP
-.B \fIexpr\fP?\fIexpr\fP:\fIexpr\fP
-conditional operator
-.TP
-.B = *= /= %= += \-= <<= >>= &= ^= |=
-assignment
-.TP
-.B \fIexpr1\fP , \fIexpr2\fP
-comma
-.PD
-.PP
-Shell variables are allowed as operands; parameter expansion is
-performed before the expression is evaluated.
-Within an expression, shell variables may also be referenced by name
-without using the parameter expansion syntax.
-A shell variable that is null or unset evaluates to 0 when referenced
-by name without using the parameter expansion syntax.
-The value of a variable is evaluated as an arithmetic expression
-when it is referenced, or when a variable which has been given the
-\fIinteger\fP attribute using \fBdeclare -i\fP is assigned a value.
-A null value evaluates to 0.
-A shell variable need not have its \fIinteger\fP attribute
-turned on to be used in an expression.
-.PP
-Constants with a leading 0 are interpreted as octal numbers.
-A leading 0x or 0X denotes hexadecimal.
-Otherwise, numbers take the form [\fIbase#\fP]n, where the optional \fIbase\fP
-is a decimal number between 2 and 64 representing the arithmetic
-base, and \fIn\fP is a number in that base.
-If \fIbase#\fP is omitted, then base 10 is used.
-When specifying \fIn\fP,
-the digits greater< than 9 are represented by the lowercase letters,
-the uppercase letters, @, and _, in that order.
-If \fIbase\fP is less than or equal to 36, lowercase and uppercase
-letters may be used interchangeably to represent numbers between 10
-and 35.
-.PP
-Operators are evaluated in order of precedence.  Sub-expressions in
-parentheses are evaluated first and may override the precedence
-rules above.
-.SH "CONDITIONAL EXPRESSIONS"
-Conditional expressions are used by the \fB[[\fP compound command and
-the \fBtest\fP and \fB[\fP builtin commands to test file attributes
-and perform string and arithmetic comparisons.
-Expressions are formed from the following unary or binary primaries.
-If any \fIfile\fP argument to one of the primaries is of the form
-\fI/dev/fd/n\fP, then file descriptor \fIn\fP is checked.
-If the \fIfile\fP argument to one of the primaries is one of
-\fI/dev/stdin\fP, \fI/dev/stdout\fP, or \fI/dev/stderr\fP, file
-descriptor 0, 1, or 2, respectively, is checked.
-.PP
-Unless otherwise specified, primaries that operate on files follow symbolic
-links and operate on the target of the link, rather than the link itself.
-.if t .sp 0.5
-.if n .sp 1
-When used with \fB[[\fP, the \fB<\fP and \fB>\fP operators sort
-lexicographically using the current locale.
-The \fBtest\fP command sorts using ASCII ordering.
-.sp 1
-.PD 0
-.TP
-.B \-a \fIfile\fP
-True if \fIfile\fP exists.
-.TP
-.B \-b \fIfile\fP
-True if \fIfile\fP exists and is a block special file.
-.TP
-.B \-c \fIfile\fP
-True if \fIfile\fP exists and is a character special file.
-.TP
-.B \-d \fIfile\fP
-True if \fIfile\fP exists and is a directory.
-.TP
-.B \-e \fIfile\fP
-True if \fIfile\fP exists.
-.TP
-.B \-f \fIfile\fP
-True if \fIfile\fP exists and is a regular file.
-.TP
-.B \-g \fIfile\fP
-True if \fIfile\fP exists and is set-group-id.
-.TP
-.B \-h \fIfile\fP
-True if \fIfile\fP exists and is a symbolic link.
-.TP
-.B \-k \fIfile\fP
-True if \fIfile\fP exists and its ``sticky'' bit is set.
-.TP
-.B \-p \fIfile\fP
-True if \fIfile\fP exists and is a named pipe (FIFO).
-.TP
-.B \-r \fIfile\fP
-True if \fIfile\fP exists and is readable.
-.TP
-.B \-s \fIfile\fP
-True if \fIfile\fP exists and has a size greater than zero.
-.TP
-.B \-t \fIfd\fP
-True if file descriptor
-.I fd
-is open and refers to a terminal.
-.TP
-.B \-u \fIfile\fP
-True if \fIfile\fP exists and its set-user-id bit is set.
-.TP
-.B \-w \fIfile\fP
-True if \fIfile\fP exists and is writable.
-.TP
-.B \-x \fIfile\fP
-True if \fIfile\fP exists and is executable.
-.TP
-.B \-G \fIfile\fP
-True if \fIfile\fP exists and is owned by the effective group id.
-.TP
-.B \-L \fIfile\fP
-True if \fIfile\fP exists and is a symbolic link.
-.TP
-.B \-N \fIfile\fP
-True if \fIfile\fP exists and has been modified since it was last read.
-.TP
-.B \-O \fIfile\fP
-True if \fIfile\fP exists and is owned by the effective user id.
-.TP
-.B \-S \fIfile\fP
-True if \fIfile\fP exists and is a socket.
-.TP
-\fIfile1\fP \fB\-ef\fP \fIfile2\fP
-True if \fIfile1\fP and \fIfile2\fP refer to the same device and
-inode numbers.
-.TP
-\fIfile1\fP \-\fBnt\fP \fIfile2\fP
-True if \fIfile1\fP is newer (according to modification date) than \fIfile2\fP,
-or if \fIfile1\fP exists and \fPfile2\fP does not.
-.TP
-\fIfile1\fP \-\fBot\fP \fIfile2\fP
-True if \fIfile1\fP is older than \fIfile2\fP, or if \fIfile2\fP exists
-and \fIfile1\fP does not.
-.TP
-.B \-o \fIoptname\fP
-True if the shell option
-.I optname
-is enabled.
-See the list of options under the description of the
-.B \-o
-option to the
-.B set
-builtin below.
-.TP
-.B \-v \fIvarname\fP
-True if the shell variable
-.I varname
-is set (has been assigned a value).
-.TP
-.B \-R \fIvarname\fP
-True if the shell variable
-.I varname
-is set and is a name reference.
-.TP
-.B \-z \fIstring\fP
-True if the length of \fIstring\fP is zero.
-.TP
-\fIstring\fP
-.PD 0
-.TP
-.B \-n \fIstring\fP
-.PD
-True if the length of
-.I string
-is non-zero.
-.TP
-\fIstring1\fP \fB==\fP \fIstring2\fP
-.PD 0
-.TP
-\fIstring1\fP \fB=\fP \fIstring2\fP
-.PD
-True if the strings are equal.  \fB=\fP should be used
-with the \fBtest\fP command for POSIX conformance.
-When used with the \fB[[\fP command, this performs pattern matching as
-described above (\fBCompound Commands\fP).
-.TP
-\fIstring1\fP \fB!=\fP \fIstring2\fP
-True if the strings are not equal.
-.TP
-\fIstring1\fP \fB<\fP \fIstring2\fP
-True if \fIstring1\fP sorts before \fIstring2\fP lexicographically.
-.TP
-\fIstring1\fP \fB>\fP \fIstring2\fP
-True if \fIstring1\fP sorts after \fIstring2\fP lexicographically.
-.TP
-.I \fIarg1\fP \fBOP\fP \fIarg2\fP
-.SM
-.B OP
-is one of
-.BR \-eq ,
-.BR \-ne ,
-.BR \-lt ,
-.BR \-le ,
-.BR \-gt ,
-or
-.BR \-ge .
-These arithmetic binary operators return true if \fIarg1\fP
-is equal to, not equal to, less than, less than or equal to,
-greater than, or greater than or equal to \fIarg2\fP, respectively.
-.I Arg1
-and
-.I arg2
-may be positive or negative integers.
-.PD
-.SH "SIMPLE COMMAND EXPANSION"
-When a simple command is executed, the shell performs the following
-expansions, assignments, and redirections, from left to right.
-.IP 1.
-The words that the parser has marked as variable assignments (those
-preceding the command name) and redirections are saved for later
-processing.
-.IP 2.
-The words that are not variable assignments or redirections are
-expanded.  If any words remain after expansion, the first word
-is taken to be the name of the command and the remaining words are
-the arguments.
-.IP 3.
-Redirections are performed as described above under
-.SM
-.BR REDIRECTION .
-.IP 4.
-The text after the \fB=\fP in each variable assignment undergoes tilde
-expansion, parameter expansion, command substitution, arithmetic expansion,
-and quote removal before being assigned to the variable.
-.PP
-If no command name results, the variable assignments affect the current
-shell environment.  Otherwise, the variables are added to the environment
-of the executed command and do not affect the current shell environment.
-If any of the assignments attempts to assign a value to a readonly variable,
-an error occurs, and the command exits with a non-zero status.
-.PP
-If no command name results, redirections are performed, but do not
-affect the current shell environment.  A redirection error causes the
-command to exit with a non-zero status.
-.PP
-If there is a command name left after expansion, execution proceeds as
-described below.  Otherwise, the command exits.  If one of the expansions
-contained a command substitution, the exit status of the command is
-the exit status of the last command substitution performed.  If there
-were no command substitutions, the command exits with a status of zero.
-.SH "COMMAND EXECUTION"
-After a command has been split into words, if it results in a
-simple command and an optional list of arguments, the following
-actions are taken.
-.PP
-If the command name contains no slashes, the shell attempts to
-locate it.  If there exists a shell function by that name, that
-function is invoked as described above in
-.SM
-.BR FUNCTIONS .
-If the name does not match a function, the shell searches for
-it in the list of shell builtins.  If a match is found, that
-builtin is invoked.
-.PP
-If the name is neither a shell function nor a builtin,
-and contains no slashes,
-.B bash
-searches each element of the
-.SM
-.B PATH
-for a directory containing an executable file by that name.
-.B Bash
-uses a hash table to remember the full pathnames of executable
-files (see
-.B hash
-under
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below).
-A full search of the directories in
-.SM
-.B PATH
-is performed only if the command is not found in the hash table.
-If the search is unsuccessful, the shell searches for a defined shell
-function named \fBcommand_not_found_handle\fP.
-If that function exists, it is invoked with the original command and
-the original command's arguments as its arguments, and the function's
-exit status becomes the exit status of the shell.
-If that function is not defined, the shell prints an error
-message and returns an exit status of 127.
-.PP
-If the search is successful, or if the command name contains
-one or more slashes, the shell executes the named program in a
-separate execution environment.
-Argument 0 is set to the name given, and the remaining arguments
-to the command are set to the arguments given, if any.
-.PP
-If this execution fails because the file is not in executable
-format, and the file is not a directory, it is assumed to be
-a \fIshell script\fP, a file
-containing shell commands.  A subshell is spawned to execute
-it.  This subshell reinitializes itself, so
-that the effect is as if a new shell had been invoked
-to handle the script, with the exception that the locations of
-commands remembered by the parent (see
-.B hash
-below under
-.SM
-\fBSHELL BUILTIN COMMANDS\fP)
-are retained by the child.
-.PP
-If the program is a file beginning with
-.BR #! ,
-the remainder of the first line specifies an interpreter
-for the program.  The shell executes the
-specified interpreter on operating systems that do not
-handle this executable format themselves.  The arguments to the 
-interpreter consist of a single optional argument following the
-interpreter name on the first line of the program, followed
-by the name of the program, followed by the command
-arguments, if any.
-.SH COMMAND EXECUTION ENVIRONMENT
-The shell has an \fIexecution environment\fP, which consists of the
-following:
-.IP \(bu
-open files inherited by the shell at invocation, as modified by
-redirections supplied to the \fBexec\fP builtin
-.IP \(bu
-the current working directory as set by \fBcd\fP, \fBpushd\fP, or
-\fBpopd\fP, or inherited by the shell at invocation
-.IP \(bu
-the file creation mode mask as set by \fBumask\fP or inherited from
-the shell's parent
-.IP \(bu
-current traps set by \fBtrap\fP
-.IP \(bu
-shell parameters that are set by variable assignment or with \fBset\fP
-or inherited from the shell's parent in the environment
-.IP \(bu
-shell functions defined during execution or inherited from the shell's
-parent in the environment
-.IP \(bu
-options enabled at invocation (either by default or with command-line
-arguments) or by \fBset\fP
-.IP \(bu
-options enabled by \fBshopt\fP
-.IP \(bu
-shell aliases defined with \fBalias\fP
-.IP \(bu
-various process IDs, including those of background jobs, the value
-of \fB$$\fP, and the value of
-.SM
-.B PPID
-.PP
-When a simple command other than a builtin or shell function
-is to be executed, it
-is invoked in a separate execution environment that consists of
-the following.  Unless otherwise noted, the values are inherited
-from the shell.
-.if n .sp 1
-.IP \(bu
-the shell's open files, plus any modifications and additions specified
-by redirections to the command
-.IP \(bu
-the current working directory
-.IP \(bu
-the file creation mode mask
-.IP \(bu
-shell variables and functions marked for export, along with variables
-exported for the command, passed in the environment
-.IP \(bu
-traps caught by the shell are reset to the values inherited from the
-shell's parent, and traps ignored by the shell are ignored
-.PP
-A command invoked in this separate environment cannot affect the
-shell's execution environment. 
-.PP
-Command substitution, commands grouped with parentheses,
-and asynchronous commands are invoked in a
-subshell environment that is a duplicate of the shell environment,
-except that traps caught by the shell are reset to the values
-that the shell inherited from its parent at invocation.  Builtin
-commands that are invoked as part of a pipeline are also executed in a
-subshell environment.  Changes made to the subshell environment
-cannot affect the shell's execution environment.
-.PP
-Subshells spawned to execute command substitutions inherit the value of
-the \fB\-e\fP option from the parent shell.  When not in \fIposix\fP mode,
-\fBbash\fP clears the \fB\-e\fP option in such subshells.
-.PP
-If a command is followed by a \fB&\fP and job control is not active, the
-default standard input for the command is the empty file \fI/dev/null\fP.
-Otherwise, the invoked command inherits the file descriptors of the calling
-shell as modified by redirections.
-.SH ENVIRONMENT
-When a program is invoked it is given an array of strings
-called the
-.IR environment .
-This is a list of 
-\fIname\fP\-\fIvalue\fP pairs, of the form
-.IR "name\fR=\fPvalue" .
-.PP
-The shell provides several ways to manipulate the environment.
-On invocation, the shell scans its own environment and
-creates a parameter for each name found, automatically marking
-it for
-.I export
-to child processes.  Executed commands inherit the environment.
-The
-.B export
-and
-.B declare \-x
-commands allow parameters and functions to be added to and
-deleted from the environment.  If the value of a parameter
-in the environment is modified, the new value becomes part
-of the environment, replacing the old.  The environment
-inherited by any executed command consists of the shell's
-initial environment, whose values may be modified in the shell,
-less any pairs removed by the
-.B unset
-command, plus any additions via the
-.B export
-and
-.B declare \-x
-commands.
-.PP
-The environment for any
-.I simple command
-or function may be augmented temporarily by prefixing it with
-parameter assignments, as described above in
-.SM
-.BR PARAMETERS .
-These assignment statements affect only the environment seen
-by that command.
-.PP
-If the 
-.B \-k
-option is set (see the
-.B set
-builtin command below), then
-.I all
-parameter assignments are placed in the environment for a command,
-not just those that precede the command name.
-.PP
-When
-.B bash
-invokes an external command, the variable
-.B _
-is set to the full filename of the command and passed to that
-command in its environment.
-.SH "EXIT STATUS"
-.PP
-The exit status of an executed command is the value returned by the
-\fIwaitpid\fP system call or equivalent function.  Exit statuses
-fall between 0 and 255, though, as explained below, the shell may
-use values above 125 specially.  Exit statuses from shell builtins and
-compound commands are also limited to this range. Under certain
-circumstances, the shell will use special values to indicate specific
-failure modes.
-.PP
-For the shell's purposes, a command which exits with a 
-zero exit status has succeeded.  An exit status of zero
-indicates success.  A non-zero exit status indicates failure.
-When a command terminates on a fatal signal \fIN\fP, \fBbash\fP uses
-the value of 128+\fIN\fP as the exit status.
-.PP
-If a command is not found, the child process created to
-execute it returns a status of 127.  If a command is found
-but is not executable, the return status is 126.
-.PP
-If a command fails because of an error during expansion or redirection,
-the exit status is greater than zero.
-.PP
-Shell builtin commands return a status of 0 (\fItrue\fP) if
-successful, and non-zero (\fIfalse\fP) if an error occurs
-while they execute. 
-All builtins return an exit status of 2 to indicate incorrect usage.
-.PP
-\fBBash\fP itself returns the exit status of the last command
-executed, unless a syntax error occurs, in which case it exits
-with a non-zero value.  See also the \fBexit\fP builtin
-command below.
-.SH SIGNALS
-When \fBbash\fP is interactive, in the absence of any traps, it ignores
-.SM
-.B SIGTERM
-(so that \fBkill 0\fP does not kill an interactive shell),
-and
-.SM
-.B SIGINT
-is caught and handled (so that the \fBwait\fP builtin is interruptible).
-In all cases, \fBbash\fP ignores
-.SM
-.BR SIGQUIT .
-If job control is in effect,
-.B bash
-ignores
-.SM
-.BR SIGTTIN ,
-.SM
-.BR SIGTTOU ,
-and
-.SM
-.BR SIGTSTP .
-.PP
-Non-builtin commands run by \fBbash\fP have signal handlers
-set to the values inherited by the shell from its parent.
-When job control is not in effect, asynchronous commands
-ignore
-.SM
-.B SIGINT
-and
-.SM
-.B SIGQUIT
-in addition to these inherited handlers.
-Commands run as a result of command substitution ignore the
-keyboard-generated job control signals
-.SM
-.BR SIGTTIN ,
-.SM
-.BR SIGTTOU ,
-and
-.SM
-.BR SIGTSTP .
-.PP
-The shell exits by default upon receipt of a
-.SM
-.BR SIGHUP .
-Before exiting, an interactive shell resends the
-.SM
-.B SIGHUP
-to all jobs, running or stopped.
-Stopped jobs are sent
-.SM
-.B SIGCONT
-to ensure that they receive the
-.SM
-.BR SIGHUP .
-To prevent the shell from
-sending the signal to a particular job, it should be removed from the
-jobs table with the 
-.B disown
-builtin (see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below) or marked 
-to not receive
-.SM
-.B SIGHUP
-using
-.BR "disown \-h" .
-.PP
-If the
-.B huponexit
-shell option has been set with
-.BR shopt ,
-.B bash
-sends a 
-.SM
-.B SIGHUP
-to all jobs when an interactive login shell exits.
-.PP
-If \fBbash\fP is waiting for a command to complete and receives a signal
-for which a trap has been set, the trap will not be executed until
-the command completes. 
-When \fBbash\fP is waiting for an asynchronous command via the \fBwait\fP
-builtin, the reception of a signal for which a trap has been set will
-cause the \fBwait\fP builtin to return immediately with an exit status
-greater than 128, immediately after which the trap is executed.
-.SH "JOB CONTROL"
-.I Job control
-refers to the ability to selectively stop (\fIsuspend\fP)
-the execution of processes and continue (\fIresume\fP)
-their execution at a later point.  A user typically employs
-this facility via an interactive interface supplied jointly
-by the operating system kernel's terminal driver and
-.BR bash .
-.PP
-The shell associates a
-.I job
-with each pipeline.  It keeps a table of currently executing
-jobs, which may be listed with the
-.B jobs
-command.  When
-.B bash
-starts a job asynchronously (in the
-.IR background ),
-it prints a line that looks like:
-.RS
-.PP
-[1] 25647
-.RE
-.PP
-indicating that this job is job number 1 and that the process ID
-of the last process in the pipeline associated with this job is 25647.
-All of the processes in a single pipeline are members of the same job.
-.B Bash
-uses the
-.I job
-abstraction as the basis for job control.
-.PP
-To facilitate the implementation of the user interface to job
-control, the operating system maintains the notion of a \fIcurrent terminal
-process group ID\fP.  Members of this process group (processes whose
-process group ID is equal to the current terminal process group ID)
-receive keyboard-generated signals such as
-.SM
-.BR SIGINT .
-These processes are said to be in the
-.IR foreground .
-.I Background
-processes are those whose process group ID differs from the terminal's;
-such processes are immune to keyboard-generated signals.
-Only foreground processes are allowed to read from or, if the
-user so specifies with \f(CWstty tostop\fP, write to the
-terminal.
-Background processes which attempt to read from (write to when
-\f(CWstty tostop\fP is in effect) the
-terminal are sent a 
-.SM
-.B SIGTTIN (SIGTTOU)
-signal by the kernel's terminal driver, 
-which, unless caught, suspends the process.
-.PP
-If the operating system on which
-.B bash
-is running supports
-job control,
-.B bash
-contains facilities to use it.
-Typing the
-.I suspend
-character (typically
-.BR ^Z ,
-Control-Z) while a process is running
-causes that process to be stopped and returns control to 
-.BR bash .
-Typing the
-.I "delayed suspend"
-character (typically
-.BR ^Y ,
-Control-Y) causes the process to be stopped when it
-attempts to read input from the terminal, and control to
-be returned to
-.BR bash .
-The user may then manipulate the state of this job, using the
-.B bg
-command to continue it in the background, the
-.B fg
-command to continue it in the foreground, or
-the
-.B kill
-command to kill it.  A \fB^Z\fP takes effect immediately,
-and has the additional side effect of causing pending output
-and typeahead to be discarded.
-.PP
-There are a number of ways to refer to a job in the shell.
-The character
-.B %
-introduces a job specification (\fIjobspec\fP).  Job number
-.I n
-may be referred to as
-.BR %n .
-A job may also be referred to using a prefix of the name used to
-start it, or using a substring that appears in its command line.
-For example,
-.B %ce
-refers to a stopped
-.B ce
-job.  If a prefix matches more than one job,
-.B bash
-reports an error.  Using
-.BR %?ce ,
-on the other hand, refers to any job containing the string
-.B ce
-in its command line.  If the substring matches more than one job,
-.B bash
-reports an error.  The symbols
-.B %%
-and
-.B %+
-refer to the shell's notion of the
-.IR "current job" ,
-which is the last job stopped while it was in
-the foreground or started in the background.
-The 
-.I "previous job"
-may be referenced using
-.BR %\- .
-If there is only a single job, \fB%+\fP and \fB%\-\fP can both be used
-to refer to that job.
-In output pertaining to jobs (e.g., the output of the
-.B jobs
-command), the current job is always flagged with a
-.BR + ,
-and the previous job with a
-.BR \- .
-A single % (with no accompanying job specification) also refers to the
-current job.
-.PP
-Simply naming a job can be used to bring it into the
-foreground:
-.B %1
-is a synonym for
-\fB``fg %1''\fP,
-bringing job 1 from the background into the foreground.
-Similarly,
-.B ``%1 &''
-resumes job 1 in the background, equivalent to
-\fB``bg %1''\fP.
-.PP
-The shell learns immediately whenever a job changes state.
-Normally,
-.B bash
-waits until it is about to print a prompt before reporting
-changes in a job's status so as to not interrupt
-any other output.  If the 
-.B \-b
-option to the
-.B set
-builtin command
-is enabled,
-.B bash
-reports such changes immediately.
-Any trap on
-.SM
-.B SIGCHLD
-is executed for each child that exits.
-.PP
-If an attempt to exit
-.B bash
-is made while jobs are stopped (or, if the \fBcheckjobs\fP shell option has
-been enabled using the \fBshopt\fP builtin, running), the shell prints a
-warning message, and, if the \fBcheckjobs\fP option is enabled, lists the
-jobs and their statuses.
-The
-.B jobs
-command may then be used to inspect their status. 
-If a second attempt to exit is made without an intervening command,
-the shell does not print another warning, and any stopped
-jobs are terminated.
-.SH PROMPTING
-When executing interactively, 
-.B bash
-displays the primary prompt
-.SM
-.B PS1
-when it is ready to read a command, and the secondary prompt
-.SM
-.B PS2
-when it needs more input to complete a command.
-.B Bash
-allows these prompt strings to be customized by inserting a number of
-backslash-escaped special characters that are decoded as follows:
-.RS
-.PD 0
-.TP
-.B \ea
-an ASCII bell character (07)
-.TP
-.B \ed
-the date in "Weekday Month Date" format (e.g., "Tue May 26")
-.TP
-.B \eD{\fIformat\fP}
-the \fIformat\fP is passed to \fIstrftime\fP(3) and the result is inserted
-into the prompt string; an empty \fIformat\fP results in a locale-specific
-time representation.  The braces are required
-.TP
-.B \ee
-an ASCII escape character (033)
-.TP
-.B \eh
-the hostname up to the first `.'
-.TP
-.B \eH
-the hostname
-.TP
-.B \ej
-the number of jobs currently managed by the shell
-.TP
-.B \el
-the basename of the shell's terminal device name
-.TP
-.B \en
-newline
-.TP
-.B \er
-carriage return
-.TP
-.B \es
-the name of the shell, the basename of
-.B $0
-(the portion following the final slash)
-.TP
-.B \et
-the current time in 24-hour HH:MM:SS format
-.TP
-.B \eT
-the current time in 12-hour HH:MM:SS format
-.TP
-.B \e@
-the current time in 12-hour am/pm format
-.TP
-.B \eA
-the current time in 24-hour HH:MM format
-.TP
-.B \eu
-the username of the current user
-.TP
-.B \ev
-the version of \fBbash\fP (e.g., 2.00)
-.TP
-.B \eV
-the release of \fBbash\fP, version + patch level (e.g., 2.00.0)
-.TP
-.B \ew
-the current working directory, with
-.SM
-.B $HOME
-abbreviated with a tilde
-(uses the value of the
-.SM
-.B PROMPT_DIRTRIM
-variable)
-.TP
-.B \eW
-the basename of the current working directory, with
-.SM
-.B $HOME
-abbreviated with a tilde
-.TP
-.B \e!
-the history number of this command
-.TP
-.B \e#
-the command number of this command
-.TP
-.B \e$
-if the effective UID is 0, a
-.BR # ,
-otherwise a
-.B $
-.TP
-.B \e\fInnn\fP
-the character corresponding to the octal number \fInnn\fP
-.TP
-.B \e\e
-a backslash
-.TP
-.B \e[
-begin a sequence of non-printing characters, which could be used to
-embed a terminal control sequence into the prompt
-.TP
-.B \e]
-end a sequence of non-printing characters
-.PD
-.RE
-.PP
-The command number and the history number are usually different:
-the history number of a command is its position in the history
-list, which may include commands restored from the history file
-(see
-.SM
-.B HISTORY
-below), while the command number is the position in the sequence
-of commands executed during the current shell session.
-After the string is decoded, it is expanded via
-parameter expansion, command substitution, arithmetic
-expansion, and quote removal, subject to the value of the
-.B promptvars
-shell option (see the description of the
-.B shopt
-command under
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below).
-.SH READLINE
-This is the library that handles reading input when using an interactive
-shell, unless the
-.B \-\-noediting
-option is given at shell invocation.
-Line editing is also used when using the \fB\-e\fP option to the
-\fBread\fP builtin.
-By default, the line editing commands are similar to those of Emacs.
-A vi-style line editing interface is also available.
-Line editing can be enabled at any time using the
-.B \-o emacs
-or
-.B \-o vi
-options to the
-.B set
-builtin (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-To turn off line editing after the shell is running, use the
-.B +o emacs
-or
-.B +o vi
-options to the
-.B set
-builtin.
-.SS "Readline Notation"
-.PP
-In this section, the Emacs-style notation is used to denote
-keystrokes.  Control keys are denoted by C\-\fIkey\fR, e.g., C\-n
-means Control\-N.  Similarly, 
-.I meta
-keys are denoted by M\-\fIkey\fR, so M\-x means Meta\-X.  (On keyboards
-without a 
-.I meta
-key, M\-\fIx\fP means ESC \fIx\fP, i.e., press the Escape key
-then the
-.I x
-key.  This makes ESC the \fImeta prefix\fP.
-The combination M\-C\-\fIx\fP means ESC\-Control\-\fIx\fP,
-or press the Escape key
-then hold the Control key while pressing the
-.I x
-key.)
-.PP
-Readline commands may be given numeric
-.IR arguments ,
-which normally act as a repeat count.
-Sometimes, however, it is the sign of the argument that is significant.
-Passing a negative argument to a command that acts in the forward
-direction (e.g., \fBkill\-line\fP) causes that command to act in a
-backward direction. 
-Commands whose behavior with arguments deviates from this are noted
-below.
-.PP
-When a command is described as \fIkilling\fP text, the text
-deleted is saved for possible future retrieval
-(\fIyanking\fP).  The killed text is saved in a
-\fIkill ring\fP.  Consecutive kills cause the text to be
-accumulated into one unit, which can be yanked all at once. 
-Commands which do not kill text separate the chunks of text
-on the kill ring.
-.SS "Readline Initialization"
-.PP
-Readline is customized by putting commands in an initialization
-file (the \fIinputrc\fP file).
-The name of this file is taken from the value of the
-.SM
-.B INPUTRC
-variable.  If that variable is unset, the default is
-.IR ~/.inputrc .
-When a program which uses the readline library starts up, the
-initialization file is read, and the key bindings and variables
-are set.
-There are only a few basic constructs allowed in the
-readline initialization file.
-Blank lines are ignored.
-Lines beginning with a \fB#\fP are comments.
-Lines beginning with a \fB$\fP indicate conditional constructs.
-Other lines denote key bindings and variable settings.
-.PP
-The default key-bindings may be changed with an
-.I inputrc 
-file.
-Other programs that use this library may add their own commands
-and bindings.
-.PP
-For example, placing
-.RS
-.PP
-M\-Control\-u: universal\-argument
-.RE
-or
-.RS
-C\-Meta\-u: universal\-argument
-.RE
-into the 
-.I inputrc
-would make M\-C\-u execute the readline command
-.IR universal\-argument .
-.PP
-The following symbolic character names are recognized:
-.IR RUBOUT ,
-.IR DEL ,
-.IR ESC ,
-.IR LFD ,
-.IR NEWLINE ,
-.IR RET ,
-.IR RETURN ,
-.IR SPC ,
-.IR SPACE ,
-and
-.IR TAB .
-.PP
-In addition to command names, readline allows keys to be bound
-to a string that is inserted when the key is pressed (a \fImacro\fP).
-.SS "Readline Key Bindings"
-.PP
-The syntax for controlling key bindings in the
-.I inputrc
-file is simple.  All that is required is the name of the
-command or the text of a macro and a key sequence to which
-it should be bound. The name may be specified in one of two ways:
-as a symbolic key name, possibly with \fIMeta\-\fP or \fIControl\-\fP
-prefixes, or as a key sequence.
-.PP
-When using the form \fBkeyname\fP:\^\fIfunction\-name\fP or \fImacro\fP,
-.I keyname
-is the name of a key spelled out in English.  For example:
-.sp
-.RS
-Control-u: universal\-argument
-.br
-Meta-Rubout: backward-kill-word
-.br
-Control-o: "> output"
-.RE
-.LP
-In the above example,
-.I C\-u
-is bound to the function
-.BR universal\-argument ,
-.I M\-DEL
-is bound to the function
-.BR backward\-kill\-word ,
-and
-.I C\-o
-is bound to run the macro
-expressed on the right hand side (that is, to insert the text
-.if t \f(CW> output\fP
-.if n ``> output''
-into the line).
-.PP
-In the second form, \fB"keyseq"\fP:\^\fIfunction\-name\fP or \fImacro\fP,
-.B keyseq
-differs from
-.B keyname
-above in that strings denoting
-an entire key sequence may be specified by placing the sequence
-within double quotes.  Some GNU Emacs style key escapes can be
-used, as in the following example, but the symbolic character names
-are not recognized.
-.sp
-.RS
-"\eC\-u": universal\-argument
-.br
-"\eC\-x\eC\-r": re\-read\-init\-file
-.br
-"\ee[11~": "Function Key 1"
-.RE
-.PP
-In this example,
-.I C\-u
-is again bound to the function
-.BR universal\-argument .
-.I "C\-x C\-r"
-is bound to the function
-.BR re\-read\-init\-file ,
-and 
-.I "ESC [ 1 1 ~"
-is bound to insert the text
-.if t \f(CWFunction Key 1\fP.
-.if n ``Function Key 1''.
-.PP
-The full set of GNU Emacs style escape sequences is
-.RS
-.PD 0
-.TP
-.B \eC\-
-control prefix
-.TP
-.B \eM\-
-meta prefix
-.TP
-.B \ee
-an escape character
-.TP
-.B \e\e
-backslash
-.TP
-.B \e"
-literal "
-.TP
-.B \e\(aq
-literal \(aq
-.RE
-.PD
-.PP
-In addition to the GNU Emacs style escape sequences, a second
-set of backslash escapes is available:
-.RS
-.PD 0
-.TP
-.B \ea
-alert (bell)
-.TP
-.B \eb
-backspace
-.TP
-.B \ed
-delete
-.TP
-.B \ef
-form feed
-.TP
-.B \en
-newline
-.TP
-.B \er
-carriage return
-.TP
-.B \et
-horizontal tab
-.TP
-.B \ev
-vertical tab
-.TP
-.B \e\fInnn\fP
-the eight-bit character whose value is the octal value \fInnn\fP
-(one to three digits)
-.TP
-.B \ex\fIHH\fP
-the eight-bit character whose value is the hexadecimal value \fIHH\fP
-(one or two hex digits)
-.RE
-.PD
-.PP
-When entering the text of a macro, single or double quotes must
-be used to indicate a macro definition.
-Unquoted text is assumed to be a function name.
-In the macro body, the backslash escapes described above are expanded.
-Backslash will quote any other character in the macro text,
-including " and \(aq.
-.PP
-.B Bash
-allows the current readline key bindings to be displayed or modified
-with the
-.B bind
-builtin command.  The editing mode may be switched during interactive
-use by using the
-.B \-o
-option to the
-.B set
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.SS "Readline Variables"
-.PP
-Readline has variables that can be used to further customize its
-behavior.  A variable may be set in the
-.I inputrc
-file with a statement of the form
-.RS
-.PP
-\fBset\fP \fIvariable\-name\fP \fIvalue\fP
-.RE
-.PP
-Except where noted, readline variables can take the values
-.B On
-or
-.B Off
-(without regard to case).
-Unrecognized variable names are ignored.
-When a variable value is read, empty or null values, "on" (case-insensitive),
-and "1" are equivalent to \fBOn\fP.  All other values are equivalent to
-\fBOff\fP.
-The variables and their default values are:
-.PP
-.PD 0
-.TP
-.B bell\-style (audible)
-Controls what happens when readline wants to ring the terminal bell.
-If set to \fBnone\fP, readline never rings the bell.  If set to
-\fBvisible\fP, readline uses a visible bell if one is available.
-If set to \fBaudible\fP, readline attempts to ring the terminal's bell.
-.TP
-.B bind\-tty\-special\-chars (On)
-If set to \fBOn\fP, readline attempts to bind the control characters
-treated specially by the kernel's terminal driver to their readline
-equivalents.
-.TP
-.B colored\-stats (Off)
-If set to \fBOn\fP, readline displays possible completions using different
-colors to indicate their file type.     
-The color definitions are taken from the value of the \fBLS_COLORS\fP
-environment variable.
-.TP
-.B comment\-begin (``#'')
-The string that is inserted when the readline
-.B insert\-comment
-command is executed.
-This command is bound to
-.B M\-#
-in emacs mode and to
-.B #
-in vi command mode.
-.TP
-.B completion\-ignore\-case (Off)
-If set to \fBOn\fP, readline performs filename matching and completion
-in a case\-insensitive fashion.
-.TP
-.B completion\-prefix\-display\-length (0)
-The length in characters of the common prefix of a list of possible
-completions that is displayed without modification.  When set to a
-value greater than zero, common prefixes longer than this value are
-replaced with an ellipsis when displaying possible completions.
-.TP
-.B completion\-query\-items (100)
-This determines when the user is queried about viewing
-the number of possible completions
-generated by the \fBpossible\-completions\fP command.
-It may be set to any integer value greater than or equal to
-zero.  If the number of possible completions is greater than
-or equal to the value of this variable, the user is asked whether
-or not he wishes to view them; otherwise they are simply listed
-on the terminal.
-.TP
-.B convert\-meta (On)
-If set to \fBOn\fP, readline will convert characters with the
-eighth bit set to an ASCII key sequence
-by stripping the eighth bit and prefixing an
-escape character (in effect, using escape as the \fImeta prefix\fP).
-.TP
-.B disable\-completion (Off)
-If set to \fBOn\fP, readline will inhibit word completion.  Completion
-characters will be inserted into the line as if they had been
-mapped to \fBself-insert\fP.
-.TP
-.B editing\-mode (emacs)
-Controls whether readline begins with a set of key bindings similar
-to \fIEmacs\fP or \fIvi\fP.
-.B editing\-mode
-can be set to either
-.B emacs
-or
-.BR vi .
-.TP
-.B echo\-control\-characters (On)
-When set to \fBOn\fP, on operating systems that indicate they support it,
-readline echoes a character corresponding to a signal generated from the
-keyboard.
-.TP
-.B enable\-keypad (Off)
-When set to \fBOn\fP, readline will try to enable the application
-keypad when it is called.  Some systems need this to enable the
-arrow keys.
-.TP
-.B enable\-meta\-key (On)
-When set to \fBOn\fP, readline will try to enable any meta modifier
-key the terminal claims to support when it is called.  On many terminals,
-the meta key is used to send eight-bit characters.
-.TP
-.B expand\-tilde (Off)
-If set to \fBOn\fP, tilde expansion is performed when readline
-attempts word completion.
-.TP
-.B history\-preserve\-point (Off)
-If set to \fBOn\fP, the history code attempts to place point at the
-same location on each history line retrieved with \fBprevious-history\fP
-or \fBnext-history\fP.
-.TP
-.B history\-size (0)
-Set the maximum number of history entries saved in the history list.
-If set to zero, any existing history entries are deleted and no new entries
-are saved.
-If set to a value less than zero, the number of history entries is not
-limited.
-By default, the number of history entries is not limited.
-.TP
-.B horizontal\-scroll\-mode (Off)
-When set to \fBOn\fP, makes readline use a single line for display,
-scrolling the input horizontally on a single screen line when it
-becomes longer than the screen width rather than wrapping to a new line.
-.TP
-.B input\-meta (Off)
-If set to \fBOn\fP, readline will enable eight-bit input (that is,
-it will not strip the high bit from the characters it reads),
-regardless of what the terminal claims it can support.  The name
-.B meta\-flag
-is a synonym for this variable.
-.TP
-.B isearch\-terminators (``C\-[C\-J'')
-The string of characters that should terminate an incremental
-search without subsequently executing the character as a command.
-If this variable has not been given a value, the characters
-\fIESC\fP and \fIC\-J\fP will terminate an incremental search.
-.TP
-.B keymap (emacs)
-Set the current readline keymap.  The set of valid keymap names is
-\fIemacs, emacs\-standard, emacs\-meta, emacs\-ctlx, vi,
-vi\-command\fP, and
-.IR vi\-insert .
-\fIvi\fP is equivalent to \fIvi\-command\fP; \fIemacs\fP is
-equivalent to \fIemacs\-standard\fP.  The default value is
-.IR emacs ;
-the value of
-.B editing\-mode
-also affects the default keymap.
-.TP
-.B keyseq\-timeout (500)
-Specifies the duration \fIreadline\fP will wait for a character when reading an
-ambiguous key sequence (one that can form a complete key sequence using
-the input read so far, or can take additional input to complete a longer
-key sequence).
-If no input is received within the timeout, \fIreadline\fP will use the shorter
-but complete key sequence.
-The value is specified in milliseconds, so a value of 1000 means that
-\fIreadline\fP will wait one second for additional input.
-If this variable is set to a value less than or equal to zero, or to a
-non-numeric value, \fIreadline\fP will wait until another key is pressed to
-decide which key sequence to complete.
-.TP
-.B mark\-directories (On)
-If set to \fBOn\fP, completed directory names have a slash
-appended.
-.TP
-.B mark\-modified\-lines (Off)
-If set to \fBOn\fP, history lines that have been modified are displayed
-with a preceding asterisk (\fB*\fP).
-.TP
-.B mark\-symlinked\-directories (Off)
-If set to \fBOn\fP, completed names which are symbolic links to directories
-have a slash appended (subject to the value of
-\fBmark\-directories\fP).
-.TP
-.B match\-hidden\-files (On)
-This variable, when set to \fBOn\fP, causes readline to match files whose
-names begin with a `.' (hidden files) when performing filename 
-completion.
-If set to \fBOff\fP, the leading `.' must be
-supplied by the user in the filename to be completed.
-.TP
-.B menu\-complete\-display\-prefix (Off)
-If set to \fBOn\fP, menu completion displays the common prefix of the
-list of possible completions (which may be empty) before cycling through
-the list.
-.TP
-.B output\-meta (Off)
-If set to \fBOn\fP, readline will display characters with the
-eighth bit set directly rather than as a meta-prefixed escape
-sequence.
-.TP
-.B page\-completions (On)
-If set to \fBOn\fP, readline uses an internal \fImore\fP-like pager
-to display a screenful of possible completions at a time.
-.TP
-.B print\-completions\-horizontally (Off)
-If set to \fBOn\fP, readline will display completions with matches
-sorted horizontally in alphabetical order, rather than down the screen.
-.TP 
-.B revert\-all\-at\-newline (Off)
-If set to \fBOn\fP, readline will undo all changes to history lines 
-before returning when \fBaccept\-line\fP is executed.  By default,
-history lines may be modified and retain individual undo lists across
-calls to \fBreadline\fP.
-.TP
-.B show\-all\-if\-ambiguous (Off)
-This alters the default behavior of the completion functions.  If
-set to
-.BR On ,
-words which have more than one possible completion cause the
-matches to be listed immediately instead of ringing the bell.
-.TP
-.B show\-all\-if\-unmodified (Off)
-This alters the default behavior of the completion functions in
-a fashion similar to \fBshow\-all\-if\-ambiguous\fP.
-If set to
-.BR On ,
-words which have more than one possible completion without any
-possible partial completion (the possible completions don't share
-a common prefix) cause the matches to be listed immediately instead
-of ringing the bell.
-.TP
-.B show\-mode\-in\-prompt (Off)
-If set to \fBOn\fP, add a character to the beginning of the prompt
-indicating the editing mode: emacs (@), vi command (:) or vi
-insertion (+).
-.TP
-.B skip\-completed\-text (Off)
-If set to \fBOn\fP, this alters the default completion behavior when
-inserting a single match into the line.  It's only active when
-performing completion in the middle of a word.  If enabled, readline
-does not insert characters from the completion that match characters
-after point in the word being completed, so portions of the word
-following the cursor are not duplicated.
-.TP
-.B visible\-stats (Off)
-If set to \fBOn\fP, a character denoting a file's type as reported
-by \fIstat\fP(2) is appended to the filename when listing possible
-completions.
-.PD
-.SS "Readline Conditional Constructs"
-.PP
-Readline implements a facility similar in spirit to the conditional
-compilation features of the C preprocessor which allows key
-bindings and variable settings to be performed as the result
-of tests.  There are four parser directives used.
-.IP \fB$if\fP
-The 
-.B $if
-construct allows bindings to be made based on the
-editing mode, the terminal being used, or the application using
-readline.  The text of the test extends to the end of the line;
-no characters are required to isolate it.
-.RS
-.IP \fBmode\fP
-The \fBmode=\fP form of the \fB$if\fP directive is used to test
-whether readline is in emacs or vi mode.
-This may be used in conjunction
-with the \fBset keymap\fP command, for instance, to set bindings in
-the \fIemacs\-standard\fP and \fIemacs\-ctlx\fP keymaps only if
-readline is starting out in emacs mode.
-.IP \fBterm\fP
-The \fBterm=\fP form may be used to include terminal-specific
-key bindings, perhaps to bind the key sequences output by the
-terminal's function keys.  The word on the right side of the
-.B =
-is tested against the both full name of the terminal and the portion
-of the terminal name before the first \fB\-\fP.  This allows
-.I sun
-to match both
-.I sun
-and
-.IR sun\-cmd ,
-for instance.
-.IP \fBapplication\fP
-The \fBapplication\fP construct is used to include
-application-specific settings.  Each program using the readline
-library sets the \fIapplication name\fP, and an initialization
-file can test for a particular value.
-This could be used to bind key sequences to functions useful for
-a specific program.  For instance, the following command adds a
-key sequence that quotes the current or previous word in \fBbash\fP:
-.sp 1
-.RS
-.nf
-\fB$if\fP Bash
-# Quote the current or previous word
-"\eC\-xq": "\eeb\e"\eef\e""
-\fB$endif\fP
-.fi
-.RE
-.RE
-.IP \fB$endif\fP
-This command, as seen in the previous example, terminates an
-\fB$if\fP command.
-.IP \fB$else\fP
-Commands in this branch of the \fB$if\fP directive are executed if
-the test fails.
-.IP \fB$include\fP
-This directive takes a single filename as an argument and reads commands
-and bindings from that file.  For example, the following directive
-would read \fI/etc/inputrc\fP:
-.sp 1
-.RS
-.nf
-\fB$include\fP \^ \fI/etc/inputrc\fP
-.fi
-.RE
-.SS Searching
-.PP
-Readline provides commands for searching through the command history
-(see
-.SM
-.B HISTORY
-below) for lines containing a specified string.
-There are two search modes:
-.I incremental
-and
-.IR non-incremental .
-.PP
-Incremental searches begin before the user has finished typing the
-search string.
-As each character of the search string is typed, readline displays
-the next entry from the history matching the string typed so far.
-An incremental search requires only as many characters as needed to
-find the desired history entry.
-The characters present in the value of the \fBisearch-terminators\fP
-variable are used to terminate an incremental search.
-If that variable has not been assigned a value the Escape and
-Control-J characters will terminate an incremental search.
-Control-G will abort an incremental search and restore the original
-line.
-When the search is terminated, the history entry containing the
-search string becomes the current line.
-.PP
-To find other matching entries in the history list, type Control-S or
-Control-R as appropriate.
-This will search backward or forward in the history for the next
-entry matching the search string typed so far.
-Any other key sequence bound to a readline command will terminate
-the search and execute that command.
-For instance, a \fInewline\fP will terminate the search and accept
-the line, thereby executing the command from the history list.
-.PP
-Readline remembers the last incremental search string.  If two
-Control-Rs are typed without any intervening characters defining a
-new search string, any remembered search string is used.
-.PP
-Non-incremental searches read the entire search string before starting
-to search for matching history lines.  The search string may be
-typed by the user or be part of the contents of the current line.
-.SS "Readline Command Names"
-.PP
-The following is a list of the names of the commands and the default
-key sequences to which they are bound.
-Command names without an accompanying key sequence are unbound by default.
-In the following descriptions, \fIpoint\fP refers to the current cursor
-position, and \fImark\fP refers to a cursor position saved by the
-\fBset\-mark\fP command.
-The text between the point and mark is referred to as the \fIregion\fP.
-.SS Commands for Moving
-.PP
-.PD 0
-.TP
-.B beginning\-of\-line (C\-a)
-Move to the start of the current line.
-.TP
-.B end\-of\-line (C\-e)
-Move to the end of the line.
-.TP
-.B forward\-char (C\-f)
-Move forward a character.
-.TP
-.B backward\-char (C\-b)
-Move back a character.
-.TP
-.B forward\-word (M\-f)
-Move forward to the end of the next word.  Words are composed of
-alphanumeric characters (letters and digits).
-.TP
-.B backward\-word (M\-b)
-Move back to the start of the current or previous word.
-Words are composed of alphanumeric characters (letters and digits).
-.TP
-.B shell\-forward\-word
-Move forward to the end of the next word.
-Words are delimited by non-quoted shell metacharacters.
-.TP
-.B shell\-backward\-word
-Move back to the start of the current or previous word.
-Words are delimited by non-quoted shell metacharacters.
-.TP
-.B clear\-screen (C\-l)
-Clear the screen leaving the current line at the top of the screen.
-With an argument, refresh the current line without clearing the
-screen.
-.TP
-.B redraw\-current\-line
-Refresh the current line.
-.PD
-.SS Commands for Manipulating the History
-.PP
-.PD 0
-.TP
-.B accept\-line (Newline, Return)
-Accept the line regardless of where the cursor is.  If this line is
-non-empty, add it to the history list according to the state of the
-.SM
-.B HISTCONTROL
-variable.  If the line is a modified history
-line, then restore the history line to its original state.
-.TP
-.B previous\-history (C\-p)
-Fetch the previous command from the history list, moving back in
-the list.
-.TP
-.B next\-history (C\-n)
-Fetch the next command from the history list, moving forward in the
-list.
-.TP
-.B beginning\-of\-history (M\-<)
-Move to the first line in the history.
-.TP
-.B end\-of\-history (M\->)
-Move to the end of the input history, i.e., the line currently being
-entered.
-.TP
-.B reverse\-search\-history (C\-r)
-Search backward starting at the current line and moving `up' through
-the history as necessary.  This is an incremental search.
-.TP
-.B forward\-search\-history (C\-s)
-Search forward starting at the current line and moving `down' through
-the history as necessary.  This is an incremental search.
-.TP
-.B non\-incremental\-reverse\-search\-history (M\-p)
-Search backward through the history starting at the current line
-using a non-incremental search for a string supplied by the user.
-.TP
-.B non\-incremental\-forward\-search\-history (M\-n)
-Search forward through the history using a non-incremental search for
-a string supplied by the user.
-.TP
-.B history\-search\-forward
-Search forward through the history for the string of characters
-between the start of the current line and the point.
-This is a non-incremental search.
-.TP
-.B history\-search\-backward
-Search backward through the history for the string of characters
-between the start of the current line and the point.
-This is a non-incremental search.
-.TP
-.B yank\-nth\-arg (M\-C\-y)
-Insert the first argument to the previous command (usually
-the second word on the previous line) at point.
-With an argument
-.IR n ,
-insert the \fIn\fPth word from the previous command (the words
-in the previous command begin with word 0).  A negative argument
-inserts the \fIn\fPth word from the end of the previous command.
-Once the argument \fIn\fP is computed, the argument is extracted
-as if the "!\fIn\fP" history expansion had been specified.
-.TP
-.B
-yank\-last\-arg (M\-.\^, M\-_\^)
-Insert the last argument to the previous command (the last word of
-the previous history entry).
-With a numeric argument, behave exactly like \fByank\-nth\-arg\fP.
-Successive calls to \fByank\-last\-arg\fP move back through the history
-list, inserting the last word (or the word specified by the argument to
-the first call) of each line in turn.
-Any numeric argument supplied to these successive calls determines
-the direction to move through the history.  A negative argument switches
-the direction through the history (back or forward).
-The history expansion facilities are used to extract the last argument,
-as if the "!$" history expansion had been specified.
-.TP
-.B shell\-expand\-line (M\-C\-e)
-Expand the line as the shell does.  This
-performs alias and history expansion as well as all of the shell
-word expansions.  See
-.SM
-.B HISTORY EXPANSION
-below for a description of history expansion.
-.TP
-.B history\-expand\-line (M\-^)
-Perform history expansion on the current line.
-See
-.SM
-.B HISTORY EXPANSION
-below for a description of history expansion.
-.TP
-.B magic\-space
-Perform history expansion on the current line and insert a space.
-See
-.SM
-.B HISTORY EXPANSION
-below for a description of history expansion.
-.TP
-.B alias\-expand\-line
-Perform alias expansion on the current line.
-See
-.SM
-.B ALIASES
-above for a description of alias expansion.
-.TP
-.B history\-and\-alias\-expand\-line
-Perform history and alias expansion on the current line.
-.TP
-.B insert\-last\-argument (M\-.\^, M\-_\^)
-A synonym for \fByank\-last\-arg\fP.
-.TP
-.B operate\-and\-get\-next (C\-o)
-Accept the current line for execution and fetch the next line
-relative to the current line from the history for editing.  Any
-argument is ignored.
-.TP
-.B edit\-and\-execute\-command (C\-xC\-e)
-Invoke an editor on the current command line, and execute the result as shell
-commands.
-\fBBash\fP attempts to invoke
-.SM
-.BR $VISUAL ,
-.SM
-.BR $EDITOR ,
-and \fIemacs\fP as the editor, in that order.
-.PD
-.SS Commands for Changing Text
-.PP
-.PD 0
-.TP
-.B delete\-char (C\-d)
-Delete the character at point.  If point is at the
-beginning of the line, there are no characters in the line, and
-the last character typed was not bound to \fBdelete\-char\fP,
-then return
-.SM
-.BR EOF .
-.TP
-.B backward\-delete\-char (Rubout)
-Delete the character behind the cursor.  When given a numeric argument,
-save the deleted text on the kill ring.
-.TP
-.B forward\-backward\-delete\-char
-Delete the character under the cursor, unless the cursor is at the
-end of the line, in which case the character behind the cursor is
-deleted.
-.TP
-.B quoted\-insert (C\-q, C\-v)
-Add the next character typed to the line verbatim.  This is
-how to insert characters like \fBC\-q\fP, for example.
-.TP
-.B tab\-insert (C\-v TAB)
-Insert a tab character.
-.TP
-.B self\-insert (a,\ b,\ A,\ 1,\ !,\ ...)
-Insert the character typed.
-.TP
-.B transpose\-chars (C\-t)
-Drag the character before point forward over the character at point,
-moving point forward as well.
-If point is at the end of the line, then this transposes
-the two characters before point.
-Negative arguments have no effect.
-.TP
-.B transpose\-words (M\-t)
-Drag the word before point past the word after point,
-moving point over that word as well.
-If point is at the end of the line, this transposes
-the last two words on the line.   
-.TP
-.B upcase\-word (M\-u)
-Uppercase the current (or following) word.  With a negative argument,
-uppercase the previous word, but do not move point.
-.TP
-.B downcase\-word (M\-l)
-Lowercase the current (or following) word.  With a negative argument,
-lowercase the previous word, but do not move point.
-.TP
-.B capitalize\-word (M\-c)
-Capitalize the current (or following) word.  With a negative argument,
-capitalize the previous word, but do not move point.
-.TP
-.B overwrite\-mode
-Toggle overwrite mode.  With an explicit positive numeric argument,
-switches to overwrite mode.  With an explicit non-positive numeric
-argument, switches to insert mode.  This command affects only
-\fBemacs\fP mode; \fBvi\fP mode does overwrite differently.
-Each call to \fIreadline()\fP starts in insert mode.
-In overwrite mode, characters bound to \fBself\-insert\fP replace   
-the text at point rather than pushing the text to the right.
-Characters bound to \fBbackward\-delete\-char\fP replace the character
-before point with a space.  By default, this command is unbound.
-.PD
-.SS Killing and Yanking
-.PP
-.PD 0
-.TP
-.B kill\-line (C\-k)
-Kill the text from point to the end of the line.
-.TP
-.B backward\-kill\-line (C\-x Rubout)
-Kill backward to the beginning of the line.
-.TP
-.B unix\-line\-discard (C\-u)
-Kill backward from point to the beginning of the line.
-The killed text is saved on the kill-ring.
-.\" There is no real difference between this and backward-kill-line
-.TP
-.B kill\-whole\-line
-Kill all characters on the current line, no matter where point is.
-.TP
-.B kill\-word  (M\-d)
-Kill from point to the end of the current word, or if between
-words, to the end of the next word.
-Word boundaries are the same as those used by \fBforward\-word\fP.
-.TP
-.B backward\-kill\-word (M\-Rubout)
-Kill the word behind point.
-Word boundaries are the same as those used by \fBbackward\-word\fP.
-.TP
-.B shell\-kill\-word  (M\-d)
-Kill from point to the end of the current word, or if between
-words, to the end of the next word.
-Word boundaries are the same as those used by \fBshell\-forward\-word\fP.
-.TP
-.B shell\-backward\-kill\-word (M\-Rubout)
-Kill the word behind point.
-Word boundaries are the same as those used by \fBshell\-backward\-word\fP.
-.TP
-.B unix\-word\-rubout (C\-w)
-Kill the word behind point, using white space as a word boundary.
-The killed text is saved on the kill-ring.
-.TP
-.B unix\-filename\-rubout
-Kill the word behind point, using white space and the slash character
-as the word boundaries.
-The killed text is saved on the kill-ring.
-.TP
-.B delete\-horizontal\-space (M\-\e)
-Delete all spaces and tabs around point.
-.TP
-.B kill\-region
-Kill the text in the current region.
-.TP
-.B copy\-region\-as\-kill
-Copy the text in the region to the kill buffer.
-.TP
-.B copy\-backward\-word
-Copy the word before point to the kill buffer.
-The word boundaries are the same as \fBbackward\-word\fP.
-.TP
-.B copy\-forward\-word
-Copy the word following point to the kill buffer.
-The word boundaries are the same as \fBforward\-word\fP.
-.TP
-.B yank (C\-y)
-Yank the top of the kill ring into the buffer at point.
-.TP
-.B yank\-pop (M\-y)
-Rotate the kill ring, and yank the new top.  Only works following
-.B yank
-or
-.BR yank\-pop .
-.PD
-.SS Numeric Arguments
-.PP
-.PD 0
-.TP
-.B digit\-argument (M\-0, M\-1, ..., M\-\-)
-Add this digit to the argument already accumulating, or start a new
-argument.  M\-\- starts a negative argument.
-.TP
-.B universal\-argument
-This is another way to specify an argument.
-If this command is followed by one or more digits, optionally with a
-leading minus sign, those digits define the argument.
-If the command is followed by digits, executing
-.B universal\-argument
-again ends the numeric argument, but is otherwise ignored.
-As a special case, if this command is immediately followed by a
-character that is neither a digit or minus sign, the argument count
-for the next command is multiplied by four.
-The argument count is initially one, so executing this function the
-first time makes the argument count four, a second time makes the
-argument count sixteen, and so on.
-.PD
-.SS Completing
-.PP
-.PD 0
-.TP
-.B complete (TAB)
-Attempt to perform completion on the text before point.
-.B Bash
-attempts completion treating the text as a variable (if the
-text begins with \fB$\fP), username (if the text begins with
-\fB~\fP), hostname (if the text begins with \fB@\fP), or
-command (including aliases and functions) in turn.  If none
-of these produces a match, filename completion is attempted.
-.TP
-.B possible\-completions (M\-?)
-List the possible completions of the text before point.
-.TP
-.B insert\-completions (M\-*)
-Insert all completions of the text before point
-that would have been generated by
-\fBpossible\-completions\fP.
-.TP
-.B menu\-complete
-Similar to \fBcomplete\fP, but replaces the word to be completed
-with a single match from the list of possible completions.
-Repeated execution of \fBmenu\-complete\fP steps through the list
-of possible completions, inserting each match in turn.
-At the end of the list of completions, the bell is rung
-(subject to the setting of \fBbell\-style\fP)
-and the original text is restored.
-An argument of \fIn\fP moves \fIn\fP positions forward in the list
-of matches; a negative argument may be used to move backward
-through the list.
-This command is intended to be bound to \fBTAB\fP, but is unbound
-by default.
-.TP
-.B menu\-complete\-backward
-Identical to \fBmenu\-complete\fP, but moves backward through the list
-of possible completions, as if \fBmenu\-complete\fP had been given a
-negative argument.  This command is unbound by default.
-.TP
-.B delete\-char\-or\-list
-Deletes the character under the cursor if not at the beginning or
-end of the line (like \fBdelete\-char\fP).
-If at the end of the line, behaves identically to
-\fBpossible\-completions\fP.
-This command is unbound by default.
-.TP
-.B complete\-filename (M\-/)
-Attempt filename completion on the text before point.
-.TP
-.B possible\-filename\-completions (C\-x /)
-List the possible completions of the text before point,
-treating it as a filename.
-.TP
-.B complete\-username (M\-~)
-Attempt completion on the text before point, treating
-it as a username.
-.TP
-.B possible\-username\-completions (C\-x ~)
-List the possible completions of the text before point,
-treating it as a username.
-.TP
-.B complete\-variable (M\-$)
-Attempt completion on the text before point, treating
-it as a shell variable.
-.TP
-.B possible\-variable\-completions (C\-x $)
-List the possible completions of the text before point,
-treating it as a shell variable.
-.TP
-.B complete\-hostname (M\-@)
-Attempt completion on the text before point, treating
-it as a hostname.
-.TP
-.B possible\-hostname\-completions (C\-x @)
-List the possible completions of the text before point,
-treating it as a hostname.
-.TP
-.B complete\-command (M\-!)
-Attempt completion on the text before point, treating
-it as a command name.  Command completion attempts to
-match the text against aliases, reserved words, shell
-functions, shell builtins, and finally executable filenames,
-in that order.
-.TP
-.B possible\-command\-completions (C\-x !)
-List the possible completions of the text before point,
-treating it as a command name.
-.TP
-.B dynamic\-complete\-history (M\-TAB)
-Attempt completion on the text before point, comparing
-the text against lines from the history list for possible
-completion matches.
-.TP
-.B dabbrev\-expand
-Attempt menu completion on the text before point, comparing
-the text against lines from the history list for possible
-completion matches.
-.TP
-.B complete\-into\-braces (M\-{)
-Perform filename completion and insert the list of possible completions
-enclosed within braces so the list is available to the shell (see
-.B Brace Expansion
-above).
-.PD
-.SS Keyboard Macros
-.PP
-.PD 0
-.TP
-.B start\-kbd\-macro (C\-x (\^)
-Begin saving the characters typed into the current keyboard macro.
-.TP
-.B end\-kbd\-macro (C\-x )\^)
-Stop saving the characters typed into the current keyboard macro
-and store the definition.
-.TP
-.B call\-last\-kbd\-macro (C\-x e)
-Re-execute the last keyboard macro defined, by making the characters
-in the macro appear as if typed at the keyboard.
-.B print\-last\-kbd\-macro ()
-Print the last keyboard macro defined in a format suitable for the
-\fIinputrc\fP file.
-.PD
-.SS Miscellaneous
-.PP
-.PD 0
-.TP
-.B re\-read\-init\-file (C\-x C\-r)
-Read in the contents of the \fIinputrc\fP file, and incorporate
-any bindings or variable assignments found there.
-.TP
-.B abort (C\-g)
-Abort the current editing command and
-ring the terminal's bell (subject to the setting of
-.BR bell\-style ).
-.TP
-.B do\-uppercase\-version (M\-a, M\-b, M\-\fIx\fP, ...)
-If the metafied character \fIx\fP is lowercase, run the command
-that is bound to the corresponding uppercase character.
-.TP
-.B prefix\-meta (ESC)
-Metafy the next character typed.
-.SM
-.B ESC
-.B f
-is equivalent to
-.BR Meta\-f .
-.TP
-.B undo (C\-_, C\-x C\-u)
-Incremental undo, separately remembered for each line.
-.TP
-.B revert\-line (M\-r)
-Undo all changes made to this line.  This is like executing the
-.B undo
-command enough times to return the line to its initial state.
-.TP
-.B tilde\-expand (M\-&)
-Perform tilde expansion on the current word.
-.TP
-.B set\-mark (C\-@, M\-<space>)
-Set the mark to the point.  If a
-numeric argument is supplied, the mark is set to that position.
-.TP
-.B exchange\-point\-and\-mark (C\-x C\-x)
-Swap the point with the mark.  The current cursor position is set to
-the saved position, and the old cursor position is saved as the mark.
-.TP
-.B character\-search (C\-])
-A character is read and point is moved to the next occurrence of that
-character.  A negative count searches for previous occurrences.
-.TP
-.B character\-search\-backward (M\-C\-])
-A character is read and point is moved to the previous occurrence of that
-character.  A negative count searches for subsequent occurrences.
-.TP
-.B skip\-csi\-sequence
-Read enough characters to consume a multi-key sequence such as those
-defined for keys like Home and End.  Such sequences begin with a
-Control Sequence Indicator (CSI), usually ESC\-[.  If this sequence is
-bound to "\e[", keys producing such sequences will have no effect
-unless explicitly bound to a readline command, instead of inserting
-stray characters into the editing buffer.  This is unbound by default,
-but usually bound to ESC\-[.
-.TP
-.B insert\-comment (M\-#)
-Without a numeric argument, the value of the readline
-.B comment\-begin
-variable is inserted at the beginning of the current line.
-If a numeric argument is supplied, this command acts as a toggle:  if
-the characters at the beginning of the line do not match the value
-of \fBcomment\-begin\fP, the value is inserted, otherwise
-the characters in \fBcomment\-begin\fP are deleted from the beginning of 
-the line.
-In either case, the line is accepted as if a newline had been typed.
-The default value of
-\fBcomment\-begin\fP causes this command to make the current line
-a shell comment.
-If a numeric argument causes the comment character to be removed, the line
-will be executed by the shell.
-.TP
-.B glob\-complete\-word (M\-g)
-The word before point is treated as a pattern for pathname expansion,
-with an asterisk implicitly appended.  This pattern is used to
-generate a list of matching filenames for possible completions.
-.TP
-.B glob\-expand\-word (C\-x *)
-The word before point is treated as a pattern for pathname expansion,
-and the list of matching filenames is inserted, replacing the word.
-If a numeric argument is supplied, an asterisk is appended before
-pathname expansion.
-.TP
-.B glob\-list\-expansions (C\-x g)
-The list of expansions that would have been generated by
-.B glob\-expand\-word
-is displayed, and the line is redrawn.
-If a numeric argument is supplied, an asterisk is appended before
-pathname expansion.
-.TP
-.B dump\-functions
-Print all of the functions and their key bindings to the
-readline output stream.  If a numeric argument is supplied,
-the output is formatted in such a way that it can be made part
-of an \fIinputrc\fP file.
-.TP
-.B dump\-variables
-Print all of the settable readline variables and their values to the
-readline output stream.  If a numeric argument is supplied,
-the output is formatted in such a way that it can be made part
-of an \fIinputrc\fP file.
-.TP
-.B dump\-macros
-Print all of the readline key sequences bound to macros and the
-strings they output.  If a numeric argument is supplied,
-the output is formatted in such a way that it can be made part
-of an \fIinputrc\fP file.
-.TP
-.B display\-shell\-version (C\-x C\-v)
-Display version information about the current instance of
-.BR bash .
-.PD
-.SS Programmable Completion
-.PP
-When word completion is attempted for an argument to a command for
-which a completion specification (a \fIcompspec\fP) has been defined
-using the \fBcomplete\fP builtin (see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below), the programmable completion facilities are invoked.
-.PP
-First, the command name is identified.
-If the command word is the empty string (completion attempted at the
-beginning of an empty line), any compspec defined with
-the \fB\-E\fP option to \fBcomplete\fP is used.
-If a compspec has been defined for that command, the
-compspec is used to generate the list of possible completions for the word.
-If the command word is a full pathname, a compspec for the full
-pathname is searched for first.
-If no compspec is found for the full pathname, an attempt is made to
-find a compspec for the portion following the final slash.
-If those searches do not result in a compspec, any compspec defined with
-the \fB\-D\fP option to \fBcomplete\fP is used as the default.
-.PP
-Once a compspec has been found, it is used to generate the list of
-matching words.
-If a compspec is not found, the default \fBbash\fP completion as
-described above under \fBCompleting\fP is performed.
-.PP
-First, the actions specified by the compspec are used.
-Only matches which are prefixed by the word being completed are
-returned.
-When the
-.B \-f
-or
-.B \-d
-option is used for filename or directory name completion, the shell
-variable
-.SM
-.B FIGNORE
-is used to filter the matches.
-.PP
-Any completions specified by a pathname expansion pattern to the
-\fB\-G\fP option are generated next.
-The words generated by the pattern need not match the word
-being completed.
-The
-.SM
-.B GLOBIGNORE
-shell variable is not used to filter the matches, but the
-.SM
-.B FIGNORE
-variable is used.
-.PP
-Next, the string specified as the argument to the \fB\-W\fP option
-is considered.
-The string is first split using the characters in the
-.SM
-.B IFS
-special variable as delimiters.
-Shell quoting is honored.
-Each word is then expanded using
-brace expansion, tilde expansion, parameter and variable expansion,
-command substitution, and arithmetic expansion,
-as described above under 
-.SM
-.BR EXPANSION .
-The results are split using the rules described above under
-\fBWord Splitting\fP.
-The results of the expansion are prefix-matched against the word being
-completed, and the matching words become the possible completions.
-.PP
-After these matches have been generated, any shell function or command
-specified with the \fB\-F\fP and \fB\-C\fP options is invoked.
-When the command or function is invoked, the
-.SM
-.BR COMP_LINE ,
-.SM
-.BR COMP_POINT ,
-.SM
-.BR COMP_KEY ,
-and
-.SM
-.B COMP_TYPE
-variables are assigned values as described above under
-\fBShell Variables\fP.
-If a shell function is being invoked, the 
-.SM
-.B COMP_WORDS
-and
-.SM
-.B COMP_CWORD
-variables are also set.
-When the function or command is invoked,
-the first argument (\fB$1\fP) is the name of the command whose arguments are
-being completed,
-the second argument (\fB$2\fP) is the word being completed,
-and the third argument (\fB$3\fP) is the word preceding the word being
-completed on the current command line.
-No filtering of the generated completions against the word being completed
-is performed; the function or command has complete freedom in generating
-the matches.
-.PP
-Any function specified with \fB\-F\fP is invoked first.
-The function may use any of the shell facilities, including the
-\fBcompgen\fP builtin described below, to generate the matches.
-It must put the possible completions in the
-.SM
-.B COMPREPLY
-array variable, one per array element.
-.PP
-Next, any command specified with the \fB\-C\fP option is invoked
-in an environment equivalent to command substitution.
-It should print a list of completions, one per line, to the
-standard output.
-Backslash may be used to escape a newline, if necessary.
-.PP
-After all of the possible completions are generated, any filter
-specified with the \fB\-X\fP option is applied to the list.
-The filter is a pattern as used for pathname expansion; a \fB&\fP
-in the pattern is replaced with the text of the word being completed.
-A literal \fB&\fP may be escaped with a backslash; the backslash
-is removed before attempting a match.
-Any completion that matches the pattern will be removed from the list.
-A leading \fB!\fP negates the pattern; in this case any completion
-not matching the pattern will be removed.
-.PP
-Finally, any prefix and suffix specified with the \fB\-P\fP and \fB\-S\fP
-options are added to each member of the completion list, and the result is
-returned to the readline completion code as the list of possible
-completions.
-.PP
-If the previously-applied actions do not generate any matches, and the
-\fB\-o dirnames\fP option was supplied to \fBcomplete\fP when the
-compspec was defined, directory name completion is attempted.
-.PP
-If the \fB\-o plusdirs\fP option was supplied to \fBcomplete\fP when the
-compspec was defined, directory name completion is attempted and any
-matches are added to the results of the other actions.
-.PP
-By default, if a compspec is found, whatever it generates is returned
-to the completion code as the full set of possible completions.
-The default \fBbash\fP completions are not attempted, and the readline
-default of filename completion is disabled.
-If the \fB\-o bashdefault\fP option was supplied to \fBcomplete\fP when
-the compspec was defined, the \fBbash\fP default completions are attempted
-if the compspec generates no matches.
-If the \fB\-o default\fP option was supplied to \fBcomplete\fP when the
-compspec was defined, readline's default completion will be performed
-if the compspec (and, if attempted, the default \fBbash\fP completions)
-generate no matches.
-.PP
-When a compspec indicates that directory name completion is desired,
-the programmable completion functions force readline to append a slash
-to completed names which are symbolic links to directories, subject to  
-the value of the \fBmark\-directories\fP readline variable, regardless
-of the setting of the \fBmark-symlinked\-directories\fP readline variable.
-.PP
-There is some support for dynamically modifying completions.  This is
-most useful when used in combination with a default completion specified
-with \fBcomplete -D\fP.
-It's possible for shell functions executed as completion
-handlers to indicate that completion should be retried by returning an
-exit status of 124.  If a shell function returns 124, and changes
-the compspec associated with the command on which completion is being
-attempted (supplied as the first argument when the function is executed),
-programmable completion restarts from the beginning, with an
-attempt to find a new compspec for that command.  This allows a set of
-completions to be built dynamically as completion is attempted, rather than
-being loaded all at once.
-.PP
-For instance, assuming that there is a library of compspecs, each kept in a
-file corresponding to the name of the command, the following default
-completion function would load completions dynamically:
-.PP
-\f(CW_completion_loader()
-.br
-{
-.br
-       . "/etc/bash_completion.d/$1.sh" >/dev/null 2>&1 && return 124
-.br
-}
-.br
-complete -D -F _completion_loader
-.br
-\fP
-.SH HISTORY
-When the
-.B \-o history
-option to the
-.B set
-builtin is enabled, the shell provides access to the
-\fIcommand history\fP,
-the list of commands previously typed.
-The value of the
-.SM
-.B HISTSIZE
-variable is used as the
-number of commands to save in a history list.
-The text of the last
-.SM
-.B HISTSIZE
-commands (default 500) is saved.  The shell
-stores each command in the history list prior to parameter and
-variable expansion (see
-.SM
-.B EXPANSION
-above) but after history expansion is performed, subject to the
-values of the shell variables
-.SM
-.B HISTIGNORE
-and
-.SM
-.BR HISTCONTROL .
-.PP
-On startup, the history is initialized from the file named by
-the variable
-.SM
-.B HISTFILE
-(default \fI~/.bash_history\fP).
-The file named by the value of
-.SM
-.B HISTFILE
-is truncated, if necessary, to contain no more than
-the number of lines specified by the value of
-.SM
-.BR HISTFILESIZE .
-If \fBHISTFILESIZE\fP is unset, or set to null, a non-numeric value,
-or a numeric value less than zero, the history file is not truncated.
-When the history file is read,
-lines beginning with the history comment character followed immediately
-by a digit are interpreted as timestamps for the preceding history line.
-These timestamps are optionally displayed depending on the value of the
-.SM
-.B HISTTIMEFORMAT
-variable.
-When a shell with history enabled exits, the last
-.SM
-.B $HISTSIZE
-lines are copied from the history list to
-.SM
-.BR $HISTFILE .
-If the
-.B histappend
-shell option is enabled
-(see the description of
-.B shopt
-under
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below), the lines are appended to the history file,
-otherwise the history file is overwritten.
-If
-.SM
-.B HISTFILE
-is unset, or if the history file is unwritable, the history is
-not saved.
-If the
-.SM
-.B HISTTIMEFORMAT
-variable is set, time stamps are written to the history file, marked
-with the history comment character, so
-they may be preserved across shell sessions.
-This uses the history comment character to distinguish timestamps from
-other history lines.
-After saving the history, the history file is truncated
-to contain no more than
-.SM
-.B HISTFILESIZE
-lines.  If
-.SM
-.B HISTFILESIZE
-is unset, or set to null, a non-numeric value,
-or a numeric value less than zero, the history file is not truncated.
-.PP
-The builtin command
-.B fc
-(see
-.SM
-.B SHELL BUILTIN COMMANDS
-below) may be used to list or edit and re-execute a portion of
-the history list.
-The
-.B history
-builtin may be used to display or modify the history list and
-manipulate the history file.
-When using command-line editing, search commands
-are available in each editing mode that provide access to the
-history list.
-.PP
-The shell allows control over which commands are saved on the history
-list.  The
-.SM
-.B HISTCONTROL
-and
-.SM
-.B HISTIGNORE
-variables may be set to cause the shell to save only a subset of the
-commands entered.
-The
-.B cmdhist
-shell option, if enabled, causes the shell to attempt to save each
-line of a multi-line command in the same history entry, adding
-semicolons where necessary to preserve syntactic correctness.
-The
-.B lithist
-shell option causes the shell to save the command with embedded newlines
-instead of semicolons.  See the description of the
-.B shopt
-builtin below under
-.SM
-.B "SHELL BUILTIN COMMANDS"
-for information on setting and unsetting shell options.
-.SH "HISTORY EXPANSION"
-.PP
-The shell supports a history expansion feature that
-is similar to the history expansion in
-.BR csh.
-This section describes what syntax features are available.  This
-feature is enabled by default for interactive shells, and can be
-disabled using the
-.B +H
-option to the
-.B set
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).  Non-interactive shells do not perform history expansion
-by default.
-.PP
-History expansions introduce words from the history list into
-the input stream, making it easy to repeat commands, insert the
-arguments to a previous command into the current input line, or
-fix errors in previous commands quickly.
-.PP
-History expansion is performed immediately after a complete line
-is read, before the shell breaks it into words.
-It takes place in two parts.
-The first is to determine which line from the history list
-to use during substitution.
-The second is to select portions of that line for inclusion into
-the current one.
-The line selected from the history is the \fIevent\fP,
-and the portions of that line that are acted upon are \fIwords\fP.
-Various \fImodifiers\fP are available to manipulate the selected words.
-The line is broken into words in the same fashion as when reading input,
-so that several \fImetacharacter\fP-separated words surrounded by
-quotes are considered one word.
-History expansions are introduced by the appearance of the
-history expansion character, which is \^\fB!\fP\^ by default.
-Only backslash (\^\fB\e\fP\^) and single quotes can quote
-the history expansion character.
-.PP
-Several characters inhibit history expansion if found immediately
-following the history expansion character, even if it is unquoted:
-space, tab, newline, carriage return, and \fB=\fP.
-If the \fBextglob\fP shell option is enabled, \fB(\fP will also
-inhibit expansion.
-.PP
-Several shell options settable with the
-.B shopt
-builtin may be used to tailor the behavior of history expansion.
-If the
-.B histverify
-shell option is enabled (see the description of the
-.B shopt
-builtin below), and
-.B readline
-is being used, history substitutions are not immediately passed to
-the shell parser.
-Instead, the expanded line is reloaded into the
-.B readline
-editing buffer for further modification.
-If
-.B readline
-is being used, and the
-.B histreedit
-shell option is enabled, a failed history substitution will be reloaded
-into the
-.B readline
-editing buffer for correction.
-The
-.B \-p
-option to the
-.B history
-builtin command may be used to see what a history expansion will
-do before using it.
-The
-.B \-s
-option to the
-.B history
-builtin may be used to add commands to the end of the history list
-without actually executing them, so that they are available for
-subsequent recall.
-.PP
-The shell allows control of the various characters used by the
-history expansion mechanism (see the description of
-.B histchars
-above under
-.BR "Shell Variables" ).
-The shell uses
-the history comment character to mark history timestamps when
-writing the history file.
-.SS Event Designators
-.PP
-An event designator is a reference to a command line entry in the
-history list.
-Unless the reference is absolute, events are relative to the current
-position in the history list.
-.PP
-.PD 0
-.TP
-.B !
-Start a history substitution, except when followed by a
-.BR blank ,
-newline, carriage return, =
-or ( (when the \fBextglob\fP shell option is enabled using
-the \fBshopt\fP builtin).
-.TP
-.B !\fIn\fR
-Refer to command line
-.IR n .
-.TP
-.B !\-\fIn\fR
-Refer to the current command minus
-.IR n .
-.TP
-.B !!
-Refer to the previous command.  This is a synonym for `!\-1'.
-.TP
-.B !\fIstring\fR
-Refer to the most recent command preceding the current position in the
-history list starting with
-.IR string .
-.TP
-.B !?\fIstring\fR\fB[?]\fR
-Refer to the most recent command preceding the current position in the
-history list containing
-.IR string .
-The trailing \fB?\fP may be omitted if
-.I string
-is followed immediately by a newline.
-.TP
-.B \d\s+2^\s-2\u\fIstring1\fP\d\s+2^\s-2\u\fIstring2\fP\d\s+2^\s-2\u
-Quick substitution.  Repeat the previous command, replacing
-.I string1
-with
-.IR string2 .
-Equivalent to
-``!!:s/\fIstring1\fP/\fIstring2\fP/''
-(see \fBModifiers\fP below).
-.TP
-.B !#
-The entire command line typed so far.
-.PD
-.SS Word Designators
-.PP
-Word designators are used to select desired words from the event.
-A 
-.B :
-separates the event specification from the word designator.
-It may be omitted if the word designator begins with a
-.BR ^ ,
-.BR $ ,
-.BR * ,
-.BR \- ,
-or
-.BR % .
-Words are numbered from the beginning of the line,
-with the first word being denoted by 0 (zero).
-Words are inserted into the current line separated by single spaces.
-.PP
-.PD 0
-.TP
-.B 0 (zero)
-The zeroth word.  For the shell, this is the command
-word.
-.TP
-.I n
-The \fIn\fRth word.
-.TP
-.B ^
-The first argument.  That is, word 1.
-.TP
-.B $
-The last argument.
-.TP
-.B %
-The word matched by the most recent `?\fIstring\fR?' search.
-.TP
-.I x\fB\-\fPy
-A range of words; `\-\fIy\fR' abbreviates `0\-\fIy\fR'.
-.TP
-.B *
-All of the words but the zeroth.  This is a synonym
-for `\fI1\-$\fP'.  It is not an error to use
-.B *
-if there is just one
-word in the event; the empty string is returned in that case.
-.TP
-.B x*
-Abbreviates \fIx\-$\fP.
-.TP
-.B x\-
-Abbreviates \fIx\-$\fP like \fBx*\fP, but omits the last word.
-.PD
-.PP
-If a word designator is supplied without an event specification, the
-previous command is used as the event.
-.SS Modifiers
-.PP
-After the optional word designator, there may appear a sequence of
-one or more of the following modifiers, each preceded by a `:'.
-.PP
-.PD 0
-.PP
-.TP
-.B h
-Remove a trailing filename component, leaving only the head.
-.TP
-.B t
-Remove all leading filename components, leaving the tail.
-.TP
-.B r
-Remove a trailing suffix of the form \fI.xxx\fP, leaving the
-basename.
-.TP
-.B e
-Remove all but the trailing suffix.
-.TP
-.B p
-Print the new command but do not execute it.
-.TP
-.B q
-Quote the substituted words, escaping further substitutions.
-.TP
-.B x
-Quote the substituted words as with
-.BR q ,
-but break into words at
-.B blanks
-and newlines.
-.TP
-.B s/\fIold\fP/\fInew\fP/
-Substitute
-.I new
-for the first occurrence of
-.I old
-in the event line.  Any delimiter can be used in place of /.  The
-final delimiter is optional if it is the last character of the
-event line.  The delimiter may be quoted in
-.I old
-and
-.I new
-with a single backslash.  If & appears in
-.IR new ,
-it is replaced by
-.IR old .
-A single backslash will quote the &.  If
-.I old
-is null, it is set to the last
-.I old
-substituted, or, if no previous history substitutions took place,
-the last
-.I string
-in a
-.B !?\fIstring\fR\fB[?]\fR
-search.
-.TP
-.B &
-Repeat the previous substitution.
-.TP
-.B g
-Cause changes to be applied over the entire event line.  This is
-used in conjunction with `\fB:s\fP' (e.g., `\fB:gs/\fIold\fP/\fInew\fP/\fR')
-or `\fB:&\fP'.  If used with
-`\fB:s\fP', any delimiter can be used
-in place of /, and the final delimiter is optional
-if it is the last character of the event line.
-An \fBa\fP may be used as a synonym for \fBg\fP.
-.TP
-.B G
-Apply the following `\fBs\fP' modifier once to each word in the event line.
-.PD
-.SH "SHELL BUILTIN COMMANDS"
-.\" start of bash_builtins
-.zZ
-.PP
-Unless otherwise noted, each builtin command documented in this
-section as accepting options preceded by
-.B \-
-accepts
-.B \-\-
-to signify the end of the options.
-The \fB:\fP, \fBtrue\fP, \fBfalse\fP, and \fBtest\fP builtins
-do not accept options and do not treat \fB\-\-\fP specially.
-The \fBexit\fP, \fBlogout\fP, \fBbreak\fP, \fBcontinue\fP, \fBlet\fP,
-and \fBshift\fP builtins accept and process arguments beginning with
-\fB\-\fP without requiring \fB\-\-\fP.
-Other builtins that accept arguments but are not specified as accepting
-options interpret arguments beginning with \fB\-\fP as invalid options and
-require \fB\-\-\fP to prevent this interpretation.
-.sp .5
-.PD 0
-.TP
-\fB:\fP [\fIarguments\fP]
-.PD
-No effect; the command does nothing beyond expanding
-.I arguments
-and performing any specified
-redirections.  A zero exit code is returned.
-.TP
-\fB .\| \fP \fIfilename\fP [\fIarguments\fP]
-.PD 0
-.TP
-\fBsource\fP \fIfilename\fP [\fIarguments\fP]
-.PD
-Read and execute commands from
-.I filename
-in the current
-shell environment and return the exit status of the last command
-executed from
-.IR filename .
-If
-.I filename
-does not contain a slash, filenames in
-.SM
-.B PATH
-are used to find the directory containing
-.IR filename .
-The file searched for in
-.SM
-.B PATH
-need not be executable.
-When \fBbash\fP is not in \fIposix mode\fP, the current directory is
-searched if no file is found in
-.SM
-.BR PATH .
-If the
-.B sourcepath
-option to the
-.B shopt
-builtin command is turned off, the
-.SM
-.B PATH
-is not searched.
-If any \fIarguments\fP are supplied, they become the positional
-parameters when \fIfilename\fP is executed.  Otherwise the positional
-parameters are unchanged.
-The return status is the status of the last command exited within
-the script (0 if no commands are executed), and false if
-.I filename
-is not found or cannot be read.
-.TP
-\fBalias\fP [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
-\fBAlias\fP with no arguments or with the
-.B \-p
-option prints the list of aliases in the form
-\fBalias\fP \fIname\fP=\fIvalue\fP on standard output.
-When arguments are supplied, an alias is defined for
-each \fIname\fP whose \fIvalue\fP is given.
-A trailing space in  \fIvalue\fP causes the next word to be
-checked for alias substitution when the alias is expanded.
-For each \fIname\fP in the argument list for which no \fIvalue\fP
-is supplied, the name and value of the alias is printed.
-\fBAlias\fP returns true unless a \fIname\fP is given for which
-no alias has been defined.
-.TP
-\fBbg\fP [\fIjobspec\fP ...]
-Resume each suspended job \fIjobspec\fP in the background, as if it
-had been started with
-.BR & .
-If
-.I jobspec
-is not present, the shell's notion of the \fIcurrent job\fP is used.
-.B bg
-.I jobspec
-returns 0 unless run when job control is disabled or, when run with
-job control enabled, any specified \fIjobspec\fP was not found
-or was started without job control.
-.TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lpsvPSVX\fP]
-.PD 0
-.TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-q\fP \fIfunction\fP] [\fB\-u\fP \fIfunction\fP] [\fB\-r\fP \fIkeyseq\fP]
-.TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] \fB\-f\fP \fIfilename\fP
-.TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] \fB\-x\fP \fIkeyseq\fP:\fIshell\-command\fP
-.TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] \fIkeyseq\fP:\fIfunction\-name\fP
-.TP
-\fBbind\fP \fIreadline\-command\fP
-.PD
-Display current
-.B readline
-key and function bindings, bind a key sequence to a
-.B readline
-function or macro, or set a
-.B readline
-variable.
-Each non-option argument is a command as it would appear in
-.IR .inputrc ,
-but each binding or command must be passed as a separate argument;
-e.g., '"\eC\-x\eC\-r": re\-read\-init\-file'.
-Options, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-.B \-m \fIkeymap\fP
-Use
-.I keymap
-as the keymap to be affected by the subsequent bindings.
-Acceptable
-.I keymap
-names are
-\fIemacs, emacs\-standard, emacs\-meta, emacs\-ctlx, vi,
-vi\-move, vi\-command\fP, and
-.IR vi\-insert .
-\fIvi\fP is equivalent to \fIvi\-command\fP; \fIemacs\fP is
-equivalent to \fIemacs\-standard\fP.
-.TP
-.B \-l
-List the names of all \fBreadline\fP functions.
-.TP
-.B \-p
-Display \fBreadline\fP function names and bindings in such a way
-that they can be re-read.
-.TP
-.B \-P
-List current \fBreadline\fP function names and bindings.
-.TP
-.B \-s
-Display \fBreadline\fP key sequences bound to macros and the strings
-they output in such a way that they can be re-read.
-.TP
-.B \-S
-Display \fBreadline\fP key sequences bound to macros and the strings
-they output.
-.TP
-.B \-v
-Display \fBreadline\fP variable names and values in such a way that they
-can be re-read.
-.TP
-.B \-V
-List current \fBreadline\fP variable names and values.
-.TP
-.B \-f \fIfilename\fP
-Read key bindings from \fIfilename\fP.
-.TP
-.B \-q \fIfunction\fP
-Query about which keys invoke the named \fIfunction\fP.
-.TP
-.B \-u \fIfunction\fP
-Unbind all keys bound to the named \fIfunction\fP.
-.TP
-.B \-r \fIkeyseq\fP
-Remove any current binding for \fIkeyseq\fP.
-.TP
-.B \-x \fIkeyseq\fP:\fIshell\-command\fP
-Cause \fIshell\-command\fP to be executed whenever \fIkeyseq\fP is
-entered.
-When \fIshell\-command\fP is executed, the shell sets the
-.SM
-.B READLINE_LINE
-variable to the contents of the \fBreadline\fP line buffer and the
-.SM
-.B READLINE_POINT
-variable to the current location of the insertion point.
-If the executed command changes the value of
-.SM
-.B READLINE_LINE
-or
-.SM
-.BR READLINE_POINT ,
-those new values will be reflected in the editing state.
-.TP
-.B \-X
-List all key sequences bound to shell commands and the associated commands
-in a format that can be reused as input.
-.PD
-.PP
-The return value is 0 unless an unrecognized option is given or an
-error occurred.
-.RE
-.TP
-\fBbreak\fP [\fIn\fP]
-Exit from within a
-.BR for ,
-.BR while ,
-.BR until ,
-or
-.B select
-loop.  If \fIn\fP is specified, break \fIn\fP levels.
-.I n
-must be \(>= 1.  If
-.I n
-is greater than the number of enclosing loops, all enclosing loops
-are exited.
-The return value is 0 unless \fIn\fP is not greater than or equal to 1.
-.TP
-\fBbuiltin\fP \fIshell\-builtin\fP [\fIarguments\fP]
-Execute the specified shell builtin, passing it
-.IR arguments ,
-and return its exit status.
-This is useful when defining a
-function whose name is the same as a shell builtin,
-retaining the functionality of the builtin within the function.
-The \fBcd\fP builtin is commonly redefined this way.
-The return status is false if
-.I shell\-builtin
-is not a shell builtin command.
-.TP
-\fBcaller\fP [\fIexpr\fP]
-Returns the context of any active subroutine call (a shell function or
-a script executed with the \fB.\fP or \fBsource\fP builtins).
-Without \fIexpr\fP, \fBcaller\fP displays the line number and source
-filename of the current subroutine call.
-If a non-negative integer is supplied as \fIexpr\fP, \fBcaller\fP 
-displays the line number, subroutine name, and source file corresponding
-to that position in the current execution call stack.  This extra
-information may be used, for example, to print a stack trace.  The
-current frame is frame 0.
-The return value is 0 unless the shell is not executing a subroutine
-call or \fIexpr\fP does not correspond to a valid position in the
-call stack.
-.TP
-\fBcd\fP [\fB\-L\fP|[\fB\-P\fP [\fB\-e\fP]]] [\fIdir\fP]
-Change the current directory to \fIdir\fP.
-if \fIdir\fP is not supplied, the value of the
-.SM
-.B HOME
-shell variable is the default.
-Any additional arguments following \fIdir\fP are ignored.
-The variable
-.SM
-.B CDPATH
-defines the search path for the directory containing
-.IR dir :
-each directory name in
-.SM
-.B CDPATH
-is searched for \fIdir\fP.
-Alternative directory names in
-.SM
-.B CDPATH
-are separated by a colon (:).  A null directory name in
-.SM
-.B CDPATH
-is the same as the current directory, i.e., ``\fB.\fP''.  If
-.I dir
-begins with a slash (/),
-then
-.SM
-.B CDPATH
-is not used. The
-.B \-P
-option causes \fBcd\fP to use the physical directory structure
-by resolving symbolic links while traversing \fIdir\fP and
-before processing instances of \fI..\fP in \fIdir\fP (see also the
-.B \-P
-option to the
-.B set
-builtin command); the
-.B \-L
-option forces symbolic links to be followed by resolving the link
-after processing instances of \fI..\fP in \fIdir\fP.
-If \fI..\fP appears in \fIdir\fP, it is processed by removing the
-immediately previous pathname component from \fIdir\fP, back to a slash
-or the beginning of \fIdir\fP.
-If the
-.B \-e
-option is supplied with
-.BR \-P ,
-and the current working directory cannot be successfully determined
-after a successful directory change, \fBcd\fP will return an unsuccessful
-status.
-An argument of
-.B \-
-is converted to
-.SM
-.B $OLDPWD
-before the directory change is attempted.
-If a non-empty directory name from
-.SM
-.B CDPATH
-is used, or if
-\fB\-\fP is the first argument, and the directory change is
-successful, the absolute pathname of the new working directory is
-written to the standard output.
-The return value is true if the directory was successfully changed;
-false otherwise.
-.TP
-\fBcommand\fP [\fB\-pVv\fP] \fIcommand\fP [\fIarg\fP ...]
-Run
-.I command
-with
-.I args
-suppressing the normal shell function lookup. Only builtin
-commands or commands found in the
-.SM
-.B PATH
-are executed.  If the
-.B \-p
-option is given, the search for
-.I command
-is performed using a default value for
-.SM
-.B PATH
-that is guaranteed to find all of the standard utilities.
-If either the
-.B \-V
-or
-.B \-v
-option is supplied, a description of
-.I command
-is printed.  The
-.B \-v
-option causes a single word indicating the command or filename
-used to invoke
-.I command
-to be displayed; the
-.B \-V
-option produces a more verbose description.
-If the
-.B \-V
-or
-.B \-v
-option is supplied, the exit status is 0 if
-.I command
-was found, and 1 if not.  If neither option is supplied and
-an error occurred or
-.I command
-cannot be found, the exit status is 127.  Otherwise, the exit status of the
-.B command
-builtin is the exit status of
-.IR command .
-.TP
-\fBcompgen\fP [\fIoption\fP] [\fIword\fP]
-Generate possible completion matches for \fIword\fP according to
-the \fIoption\fPs, which may be any option accepted by the
-.B complete
-builtin with the exception of \fB\-p\fP and \fB\-r\fP, and write
-the matches to the standard output.
-When using the \fB\-F\fP or \fB\-C\fP options, the various shell variables
-set by the programmable completion facilities, while available, will not
-have useful values.
-.sp 1
-The matches will be generated in the same way as if the programmable
-completion code had generated them directly from a completion specification
-with the same flags.
-If \fIword\fP is specified, only those completions matching \fIword\fP
-will be displayed.
-.sp 1
-The return value is true unless an invalid option is supplied, or no
-matches were generated.
-.TP
-\fBcomplete\fP [\fB\-abcdefgjksuv\fP] [\fB\-o\fP \fIcomp-option\fP] [\fB\-DE\fP] [\fB\-A\fP \fIaction\fP] [\fB\-G\fP \fIglobpat\fP] [\fB\-W\fP \fIwordlist\fP] [\fB\-F\fP \fIfunction\fP] [\fB\-C\fP \fIcommand\fP]
-.br
-[\fB\-X\fP \fIfilterpat\fP] [\fB\-P\fP \fIprefix\fP] [\fB\-S\fP \fIsuffix\fP] \fIname\fP [\fIname ...\fP]
-.PD 0
-.TP
-\fBcomplete\fP \fB\-pr\fP [\fB\-DE\fP] [\fIname\fP ...]
-.PD
-Specify how arguments to each \fIname\fP should be completed.
-If the \fB\-p\fP option is supplied, or if no options are supplied,
-existing completion specifications are printed in a way that allows
-them to be reused as input.
-The \fB\-r\fP option removes a completion specification for
-each \fIname\fP, or, if no \fIname\fPs are supplied, all
-completion specifications.
-The \fB\-D\fP option indicates that the remaining options and actions should
-apply to the ``default'' command completion; that is, completion attempted
-on a command for which no completion has previously been defined.
-The \fB\-E\fP option indicates that the remaining options and actions should
-apply to ``empty'' command completion; that is, completion attempted on a
-blank line.
-.sp 1
-The process of applying these completion specifications when word completion
-is attempted is described above under \fBProgrammable Completion\fP.
-.sp 1
-Other options, if specified, have the following meanings.
-The arguments to the \fB\-G\fP, \fB\-W\fP, and \fB\-X\fP options
-(and, if necessary, the \fB\-P\fP and \fB\-S\fP options)
-should be quoted to protect them from expansion before the
-.B complete
-builtin is invoked.
-.RS
-.PD 0
-.TP 8
-\fB\-o\fP \fIcomp-option\fP
-The \fIcomp-option\fP controls several aspects of the compspec's behavior
-beyond the simple generation of completions.
-\fIcomp-option\fP may be one of:
-.RS
-.TP 8
-.B bashdefault
-Perform the rest of the default \fBbash\fP completions if the compspec
-generates no matches.
-.TP 8
-.B default
-Use readline's default filename completion if the compspec generates
-no matches.
-.TP 8
-.B dirnames
-Perform directory name completion if the compspec generates no matches.
-.TP 8
-.B filenames
-Tell readline that the compspec generates filenames, so it can perform any
-filename\-specific processing (like adding a slash to directory names,
-quoting special characters, or suppressing trailing spaces).
-Intended to be used with shell functions.
-.TP 8
-.B noquote
-Tell readline not to quote the completed words if they are filenames
-(quoting filenames is the default).
-.TP 8
-.B nospace
-Tell readline not to append a space (the default) to words completed at
-the end of the line.
-.TP 8
-.B plusdirs
-After any matches defined by the compspec are generated, 
-directory name completion is attempted and any
-matches are added to the results of the other actions.
-.RE
-.TP 8
-\fB\-A\fP \fIaction\fP
-The \fIaction\fP may be one of the following to generate a list of possible
-completions:
-.RS
-.TP 8
-.B alias
-Alias names.  May also be specified as \fB\-a\fP.
-.TP 8
-.B arrayvar
-Array variable names.
-.TP 8
-.B binding
-\fBReadline\fP key binding names.
-.TP 8
-.B builtin
-Names of shell builtin commands.  May also be specified as \fB\-b\fP.
-.TP 8
-.B command
-Command names.  May also be specified as \fB\-c\fP.
-.TP 8
-.B directory
-Directory names.  May also be specified as \fB\-d\fP.
-.TP 8
-.B disabled
-Names of disabled shell builtins.
-.TP 8
-.B enabled
-Names of enabled shell builtins.
-.TP 8
-.B export
-Names of exported shell variables.  May also be specified as \fB\-e\fP.
-.TP 8
-.B file
-File names.  May also be specified as \fB\-f\fP.
-.TP 8
-.B function
-Names of shell functions.
-.TP 8
-.B group
-Group names.  May also be specified as \fB\-g\fP.
-.TP 8
-.B helptopic
-Help topics as accepted by the \fBhelp\fP builtin.
-.TP 8
-.B hostname
-Hostnames, as taken from the file specified by the
-.SM
-.B HOSTFILE
-shell variable.
-.TP 8
-.B job
-Job names, if job control is active.  May also be specified as \fB\-j\fP.
-.TP 8
-.B keyword
-Shell reserved words.  May also be specified as \fB\-k\fP.
-.TP 8
-.B running
-Names of running jobs, if job control is active.
-.TP 8
-.B service
-Service names.  May also be specified as \fB\-s\fP.
-.TP 8
-.B setopt
-Valid arguments for the \fB\-o\fP option to the \fBset\fP builtin.
-.TP 8
-.B shopt
-Shell option names as accepted by the \fBshopt\fP builtin.
-.TP 8
-.B signal
-Signal names.
-.TP 8
-.B stopped
-Names of stopped jobs, if job control is active.
-.TP 8
-.B user
-User names.  May also be specified as \fB\-u\fP.
-.TP 8
-.B variable
-Names of all shell variables.  May also be specified as \fB\-v\fP.
-.RE
-.TP 8
-\fB\-C\fP \fIcommand\fP
-\fIcommand\fP is executed in a subshell environment, and its output is
-used as the possible completions.
-.TP 8
-\fB\-F\fP \fIfunction\fP
-The shell function \fIfunction\fP is executed in the current shell
-environment.
-When the function is executed,
-the first argument (\fB$1\fP) is the name of the command whose arguments are
-being completed,
-the second argument (\fB$2\fP) is the word being completed,
-and the third argument (\fB$3\fP) is the word preceding the word being
-completed on the current command line.
-When it finishes, the possible completions are retrieved from the value
-of the
-.SM
-.B COMPREPLY
-array variable.
-.TP 8
-\fB\-G\fP \fIglobpat\fP
-The pathname expansion pattern \fIglobpat\fP is expanded to generate
-the possible completions.
-.TP 8
-\fB\-P\fP \fIprefix\fP
-\fIprefix\fP is added at the beginning of each possible completion
-after all other options have been applied.
-.TP 8
-\fB\-S\fP \fIsuffix\fP
-\fIsuffix\fP is appended to each possible completion
-after all other options have been applied.
-.TP 8
-\fB\-W\fP \fIwordlist\fP
-The \fIwordlist\fP is split using the characters in the
-.SM
-.B IFS
-special variable as delimiters, and each resultant word is expanded.
-The possible completions are the members of the resultant list which
-match the word being completed.
-.TP 8
-\fB\-X\fP \fIfilterpat\fP
-\fIfilterpat\fP is a pattern as used for pathname expansion.
-It is applied to the list of possible completions generated by the
-preceding options and arguments, and each completion matching
-\fIfilterpat\fP is removed from the list.
-A leading \fB!\fP in \fIfilterpat\fP negates the pattern; in this
-case, any completion not matching \fIfilterpat\fP is removed.
-.PD
-.PP
-The return value is true unless an invalid option is supplied, an option
-other than \fB\-p\fP or \fB\-r\fP is supplied without a \fIname\fP
-argument, an attempt is made to remove a completion specification for
-a \fIname\fP for which no specification exists, or
-an error occurs adding a completion specification.
-.RE
-.TP
-\fBcompopt\fP [\fB\-o\fP \fIoption\fP] [\fB\-DE\fP] [\fB+o\fP \fIoption\fP] [\fIname\fP]
-Modify completion options for each \fIname\fP according to the
-\fIoption\fPs, or for the
-currently-executing completion if no \fIname\fPs are supplied.
-If no \fIoption\fPs are given, display the completion options for each
-\fIname\fP or the current completion.
-The possible values of \fIoption\fP are those valid for the \fBcomplete\fP
-builtin described above.
-The \fB\-D\fP option indicates that the remaining options should
-apply to the ``default'' command completion; that is, completion attempted
-on a command for which no completion has previously been defined.
-The \fB\-E\fP option indicates that the remaining options should
-apply to ``empty'' command completion; that is, completion attempted on a
-blank line.
-.sp 1
-The return value is true unless an invalid option is supplied, an attempt
-is made to modify the options for a \fIname\fP for which no completion
-specification exists, or an output error occurs.
-.TP
-\fBcontinue\fP [\fIn\fP]
-Resume the next iteration of the enclosing
-.BR for ,
-.BR while ,
-.BR until ,
-or
-.B select
-loop.
-If
-.I n
-is specified, resume at the \fIn\fPth enclosing loop.
-.I n
-must be \(>= 1.  If
-.I n
-is greater than the number of enclosing loops, the last enclosing loop
-(the ``top-level'' loop) is resumed.
-The return value is 0 unless \fIn\fP is not greater than or equal to 1.
-.TP
-\fBdeclare\fP [\fB\-aAfFgilnrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
-.PD 0
-.TP
-\fBtypeset\fP [\fB\-aAfFgilnrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
-.PD
-Declare variables and/or give them attributes.
-If no \fIname\fPs are given then display the values of variables.
-The
-.B \-p
-option will display the attributes and values of each
-.IR name .
-When
-.B \-p
-is used with \fIname\fP arguments, additional options are ignored.
-When
-.B \-p
-is supplied without \fIname\fP arguments, it will display the attributes
-and values of all variables having the attributes specified by the
-additional options.
-If no other options are supplied with \fB\-p\fP, \fBdeclare\fP will display
-the attributes and values of all shell variables.  The \fB\-f\fP option
-will restrict the display to shell functions.
-The
-.B \-F
-option inhibits the display of function definitions; only the
-function name and attributes are printed.
-If the \fBextdebug\fP shell option is enabled using \fBshopt\fP,
-the source file name and line number where the function is defined
-are displayed as well.  The
-.B \-F
-option implies
-.BR \-f .
-The
-.B \-g
-option forces variables to be created or modified at the global scope,
-even when \fBdeclare\fP is executed in a shell function.
-It is ignored in all other cases.
-The following options can
-be used to restrict output to variables with the specified attribute or
-to give variables attributes:
-.RS
-.PD 0
-.TP
-.B \-a
-Each \fIname\fP is an indexed array variable (see
-.B Arrays
-above).
-.TP
-.B \-A
-Each \fIname\fP is an associative array variable (see
-.B Arrays
-above).
-.TP
-.B \-f
-Use function names only.
-.TP
-.B \-i
-The variable is treated as an integer; arithmetic evaluation (see
-.SM
-.B "ARITHMETIC EVALUATION"
-above) is performed when the variable is assigned a value.
-.TP
-.B \-l
-When the variable is assigned a value, all upper-case characters are
-converted to lower-case.
-The upper-case attribute is disabled.
-.TP
-.B \-n
-Give each \fIname\fP the \fInameref\fP attribute, making
-it a name reference to another variable.
-That other variable is defined by the value of \fIname\fP.
-All references and assignments to \fIname\fP, except for changing the
-\fB\-n\fP attribute itself, are performed on the variable referenced by
-\fIname\fP's value.
-The \fB\-n\fP attribute cannot be applied to array variables.
-.TP
-.B \-r
-Make \fIname\fPs readonly.  These names cannot then be assigned values
-by subsequent assignment statements or unset.
-.TP
-.B \-t
-Give each \fIname\fP the \fItrace\fP attribute.
-Traced functions inherit the \fBDEBUG\fP and \fBRETURN\fP traps from
-the calling shell.
-The trace attribute has no special meaning for variables.
-.TP
-.B \-u
-When the variable is assigned a value, all lower-case characters are
-converted to upper-case.
-The lower-case attribute is disabled.
-.TP
-.B \-x
-Mark \fIname\fPs for export to subsequent commands via the environment.
-.PD
-.PP
-Using `+' instead of `\-'
-turns off the attribute instead,
-with the exceptions that \fB+a\fP
-may not be used to destroy an array variable and \fB+r\fP will not
-remove the readonly attribute.
-When used in a function,
-.B declare
-and
-.B typeset
-make each
-\fIname\fP local, as with the
-.B local
-command,
-unless the \fB\-g\fP option is supplied.
-If a variable name is followed by =\fIvalue\fP, the value of
-the variable is set to \fIvalue\fP.
-The return value is 0 unless an invalid option is encountered,
-an attempt is made to define a function using
-.if n ``\-f foo=bar'',
-.if t \f(CW\-f foo=bar\fP,
-an attempt is made to assign a value to a readonly variable,
-an attempt is made to assign a value to an array variable without
-using the compound assignment syntax (see
-.B Arrays
-above), one of the \fInames\fP is not a valid shell variable name,
-an attempt is made to turn off readonly status for a readonly variable,
-an attempt is made to turn off array status for an array variable,
-or an attempt is made to display a non-existent function with \fB\-f\fP.
-.RE
-.TP
-.B dirs [\fB\-clpv\fP] [+\fIn\fP] [\-\fIn\fP]
-Without options, displays the list of currently remembered directories.
-The default display is on a single line with directory names separated
-by spaces.
-Directories are added to the list with the 
-.B pushd
-command; the
-.B popd
-command removes entries from the list.
-.RS
-.PD 0
-.TP
-.B \-c
-Clears the directory stack by deleting all of the entries.
-.TP
-.B \-l
-Produces a listing using full pathnames;
-the default listing format uses a tilde to denote the home directory.
-.TP
-.B \-p
-Print the directory stack with one entry per line.
-.TP
-.B \-v
-Print the directory stack with one entry per line,
-prefixing each entry with its index in the stack.
-.TP
-\fB+\fP\fIn\fP
-Displays the \fIn\fPth entry counting from the left of the list
-shown by
-.B dirs
-when invoked without options, starting with zero.
-.TP
-\fB\-\fP\fIn\fP
-Displays the \fIn\fPth entry counting from the right of the list
-shown by
-.B dirs
-when invoked without options, starting with zero.
-.PD
-.PP
-The return value is 0 unless an
-invalid option is supplied or \fIn\fP indexes beyond the end
-of the directory stack.
-.RE
-.TP
-\fBdisown\fP [\fB\-ar\fP] [\fB\-h\fP] [\fIjobspec\fP ...]
-Without options, remove each
-.I jobspec
-from the table of active jobs.
-If
-.I jobspec
-is not present, and neither \fB\-a\fP nor \fB\-r\fP is supplied,
-the shell's notion of the \fIcurrent job\fP is used.
-If the \fB\-h\fP option is given, each
-.I jobspec
-is not removed from the table, but is marked so that
-.SM
-.B SIGHUP
-is not sent to the job if the shell receives a
-.SM
-.BR SIGHUP .
-If no
-.I jobspec
-is present, and neither the
-.B \-a
-nor the
-.B \-r
-option is supplied, the \fIcurrent job\fP is used.
-If no
-.I jobspec
-is supplied, the
-.B \-a
-option means to remove or mark all jobs; the
-.B \-r
-option without a
-.I jobspec
-argument restricts operation to running jobs.
-The return value is 0 unless a
-.I jobspec
-does not specify a valid job.
-.TP
-\fBecho\fP [\fB\-neE\fP] [\fIarg\fP ...]
-Output the \fIarg\fPs, separated by spaces, followed by a newline.
-The return status is 0 unless a write error occurs.
-If \fB\-n\fP is specified, the trailing newline is
-suppressed.  If the \fB\-e\fP option is given, interpretation of
-the following backslash-escaped characters is enabled.  The
-.B \-E
-option disables the interpretation of these escape characters,
-even on systems where they are interpreted by default.
-The \fBxpg_echo\fP shell option may be used to
-dynamically determine whether or not \fBecho\fP expands these
-escape characters by default.
-.B echo
-does not interpret \fB\-\-\fP to mean the end of options.
-.B echo
-interprets the following escape sequences:
-.RS
-.PD 0
-.TP
-.B \ea
-alert (bell)
-.TP
-.B \eb
-backspace
-.TP
-.B \ec
-suppress further output
-.TP
-.B \ee
-.TP
-.B \eE
-an escape character
-.TP
-.B \ef
-form feed
-.TP
-.B \en
-new line
-.TP
-.B \er
-carriage return
-.TP
-.B \et
-horizontal tab
-.TP
-.B \ev
-vertical tab
-.TP
-.B \e\e
-backslash
-.TP
-.B \e0\fInnn\fP
-the eight-bit character whose value is the octal value \fInnn\fP
-(zero to three octal digits)
-.TP
-.B \ex\fIHH\fP
-the eight-bit character whose value is the hexadecimal value \fIHH\fP
-(one or two hex digits)
-.TP
-.B \eu\fIHHHH\fP
-the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
-\fIHHHH\fP (one to four hex digits)
-.TP
-.B \eU\fIHHHHHHHH\fP
-the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
-\fIHHHHHHHH\fP (one to eight hex digits)
-.PD
-.RE
-.TP
-\fBenable\fP [\fB\-a\fP] [\fB\-dnps\fP] [\fB\-f\fP \fIfilename\fP] [\fIname\fP ...]
-Enable and disable builtin shell commands.
-Disabling a builtin allows a disk command which has the same name
-as a shell builtin to be executed without specifying a full pathname,
-even though the shell normally searches for builtins before disk commands.
-If \fB\-n\fP is used, each \fIname\fP
-is disabled; otherwise,
-\fInames\fP are enabled.  For example, to use the
-.B test
-binary found via the
-.SM
-.B PATH
-instead of the shell builtin version, run
-.if t \f(CWenable -n test\fP.
-.if n ``enable -n test''.
-The
-.B \-f
-option means to load the new builtin command
-.I name
-from shared object
-.IR filename ,
-on systems that support dynamic loading.  The
-.B \-d
-option will delete a builtin previously loaded with
-.BR \-f .
-If no \fIname\fP arguments are given, or if the
-.B \-p
-option is supplied, a list of shell builtins is printed.
-With no other option arguments, the list consists of all enabled
-shell builtins.
-If \fB\-n\fP is supplied, only disabled builtins are printed.
-If \fB\-a\fP is supplied, the list printed includes all builtins, with an
-indication of whether or not each is enabled.
-If \fB\-s\fP is supplied, the output is restricted to the POSIX
-\fIspecial\fP builtins.
-The return value is 0 unless a
-.I name
-is not a shell builtin or there is an error loading a new builtin
-from a shared object.
-.TP
-\fBeval\fP [\fIarg\fP ...]
-The \fIarg\fPs are read and concatenated together into a single
-command.  This command is then read and executed by the shell, and
-its exit status is returned as the value of
-.BR eval .
-If there are no
-.IR args ,
-or only null arguments,
-.B eval
-returns 0.
-.TP
-\fBexec\fP [\fB\-cl\fP] [\fB\-a\fP \fIname\fP] [\fIcommand\fP [\fIarguments\fP]]
-If
-.I command
-is specified, it replaces the shell.
-No new process is created.  The
-.I arguments
-become the arguments to \fIcommand\fP.
-If the
-.B \-l
-option is supplied,
-the shell places a dash at the beginning of the zeroth argument passed to 
-.IR command .
-This is what
-.IR login (1)
-does.  The
-.B \-c
-option causes
-.I command
-to be executed with an empty environment.  If
-.B \-a
-is supplied, the shell passes
-.I name
-as the zeroth argument to the executed command.
-If
-.I command
-cannot be executed for some reason, a non-interactive shell exits,
-unless the
-.B execfail
-shell option
-is enabled.  In that case, it returns failure.
-An interactive shell returns failure if the file cannot be executed.
-If
-.I command
-is not specified, any redirections take effect in the current shell,
-and the return status is 0.  If there is a redirection error, the
-return status is 1.
-.TP
-\fBexit\fP [\fIn\fP]
-Cause the shell to exit
-with a status of \fIn\fP.  If
-.I n
-is omitted, the exit status
-is that of the last command executed.
-A trap on
-.SM
-.B EXIT
-is executed before the shell terminates.
-.TP
-\fBexport\fP [\fB\-fn\fP\^] [\fIname\fP[=\fIword\fP]] ...
-.PD 0
-.TP
-.B export \-p
-.PD
-The supplied
-.I names
-are marked for automatic export to the environment of
-subsequently executed commands.  If the 
-.B \-f
-option is given,
-the 
-.I names
-refer to functions.
-If no
-.I names
-are given, or if the
-.B \-p
-option is supplied, a list
-of names of all exported variables is printed.
-The
-.B \-n
-option causes the export property to be removed from each
-\fIname\fP.
-If a variable name is followed by =\fIword\fP, the value of
-the variable is set to \fIword\fP.
-.B export
-returns an exit status of 0 unless an invalid option is
-encountered,
-one of the \fInames\fP is not a valid shell variable name, or
-.B \-f
-is supplied with a
-.I name
-that is not a function.
-.TP
-\fBfc\fP [\fB\-e\fP \fIename\fP] [\fB\-lnr\fP] [\fIfirst\fP] [\fIlast\fP]
-.PD 0
-.TP
-\fBfc\fP \fB\-s\fP [\fIpat\fP=\fIrep\fP] [\fIcmd\fP]
-.PD
-The first form selects a range of commands from
-.I first
-to
-.I last
-from the history list and displays or edits and re-executes them.
-.I First
-and
-.I last
-may be specified as a string (to locate the last command beginning
-with that string) or as a number (an index into the history list,
-where a negative number is used as an offset from the current
-command number).  If 
-.I last
-is not specified it is set to
-the current command for listing (so that
-.if n ``fc \-l \-10''
-.if t \f(CWfc \-l \-10\fP
-prints the last 10 commands) and to
-.I first
-otherwise.
-If
-.I first
-is not specified it is set to the previous
-command for editing and \-16 for listing.
-.sp 1
-The
-.B \-n
-option suppresses
-the command numbers when listing.  The
-.B \-r
-option reverses the order of
-the commands.  If the
-.B \-l
-option is given,
-the commands are listed on
-standard output.  Otherwise, the editor given by
-.I ename
-is invoked
-on a file containing those commands.  If
-.I ename
-is not given, the
-value of the
-.SM
-.B FCEDIT
-variable is used, and
-the value of
-.SM
-.B EDITOR
-if
-.SM
-.B FCEDIT
-is not set.  If neither variable is set,
-.FN vi
-is used.  When editing is complete, the edited commands are
-echoed and executed.
-.sp 1
-In the second form, \fIcommand\fP is re-executed after each instance
-of \fIpat\fP is replaced by \fIrep\fP.
-\fICommand\fP is intepreted the same as \fIfirst\fP above.
-A useful alias to use with this is
-.if n ``r="fc -s"'',
-.if t \f(CWr='fc \-s'\fP,
-so that typing
-.if n ``r cc''
-.if t \f(CWr cc\fP
-runs the last command beginning with
-.if n ``cc''
-.if t \f(CWcc\fP
-and typing
-.if n ``r''
-.if t \f(CWr\fP
-re-executes the last command.
-.sp 1
-If the first form is used, the return value is 0 unless an invalid
-option is encountered or
-.I first
-or
-.I last
-specify history lines out of range.
-If the
-.B \-e
-option is supplied, the return value is the value of the last
-command executed or failure if an error occurs with the temporary
-file of commands.  If the second form is used, the return status
-is that of the command re-executed, unless
-.I cmd
-does not specify a valid history line, in which case
-.B fc
-returns failure.
-.TP
-\fBfg\fP [\fIjobspec\fP]
-Resume
-.I jobspec
-in the foreground, and make it the current job.
-If
-.I jobspec
-is not present, the shell's notion of the \fIcurrent job\fP is used.
-The return value is that of the command placed into the foreground,
-or failure if run when job control is disabled or, when run with
-job control enabled, if
-.I jobspec
-does not specify a valid job or
-.I jobspec
-specifies a job that was started without job control.
-.TP
-\fBgetopts\fP \fIoptstring\fP \fIname\fP [\fIargs\fP]
-.B getopts
-is used by shell procedures to parse positional parameters.
-.I optstring
-contains the option characters to be recognized; if a character
-is followed by a colon, the option is expected to have an
-argument, which should be separated from it by white space.
-The colon and question mark characters may not be used as
-option characters.
-Each time it is invoked,
-.B getopts
-places the next option in the shell variable
-.IR name ,
-initializing
-.I name
-if it does not exist,
-and the index of the next argument to be processed into the
-variable
-.SM
-.BR OPTIND .
-.SM
-.B OPTIND
-is initialized to 1 each time the shell or a shell script
-is invoked.  When an option requires an argument,
-.B getopts
-places that argument into the variable
-.SM
-.BR OPTARG .
-The shell does not reset
-.SM
-.B OPTIND
-automatically; it must be manually reset between multiple
-calls to
-.B getopts
-within the same shell invocation if a new set of parameters
-is to be used.
-.sp 1
-When the end of options is encountered, \fBgetopts\fP exits with a
-return value greater than zero.
-.SM
-.B OPTIND
-is set to the index of the first non-option argument,
-and \fIname\fP is set to ?.
-.sp 1
-.B getopts
-normally parses the positional parameters, but if more arguments are
-given in
-.IR args ,
-.B getopts
-parses those instead.
-.sp 1
-.B getopts
-can report errors in two ways.  If the first character of
-.I optstring
-is a colon,
-.I silent
-error reporting is used.  In normal operation, diagnostic messages
-are printed when invalid options or missing option arguments are
-encountered.
-If the variable
-.SM
-.B OPTERR
-is set to 0, no error messages will be displayed, even if the first
-character of 
-.I optstring
-is not a colon.
-.sp 1
-If an invalid option is seen,
-.B getopts
-places ? into
-.I name
-and, if not silent,
-prints an error message and unsets
-.SM
-.BR OPTARG .
-If
-.B getopts
-is silent,
-the option character found is placed in
-.SM
-.B OPTARG
-and no diagnostic message is printed.
-.sp 1
-If a required argument is not found, and
-.B getopts
-is not silent,
-a question mark (\^\fB?\fP\^) is placed in
-.IR name ,
-.SM
-.B OPTARG
-is unset, and a diagnostic message is printed.
-If
-.B getopts
-is silent, then a colon (\^\fB:\fP\^) is placed in
-.I name
-and
-.SM
-.B OPTARG
-is set to the option character found.
-.sp 1
-.B getopts
-returns true if an option, specified or unspecified, is found.
-It returns false if the end of options is encountered or an
-error occurs.
-.TP
-\fBhash\fP [\fB\-lr\fP] [\fB\-p\fP \fIfilename\fP] [\fB\-dt\fP] [\fIname\fP]
-Each time \fBhash\fP is invoked,
-the full pathname of the command 
-.I name
-is determined by searching
-the directories in
-.B $PATH
-and remembered.  Any previously-remembered pathname is discarded.
-If the
-.B \-p
-option is supplied, no path search is performed, and
-.I filename
-is used as the full filename of the command.
-The
-.B \-r
-option causes the shell to forget all
-remembered locations.
-The
-.B \-d
-option causes the shell to forget the remembered location of each \fIname\fP.
-If the
-.B \-t
-option is supplied, the full pathname to which each \fIname\fP corresponds
-is printed.  If multiple \fIname\fP arguments are supplied with \fB\-t\fP,
-the \fIname\fP is printed before the hashed full pathname.
-The
-.B \-l
-option causes output to be displayed in a format that may be reused as input.
-If no arguments are given, or if only \fB\-l\fP is supplied,
-information about remembered commands is printed.
-The return status is true unless a
-.I name
-is not found or an invalid option is supplied.
-.TP
-\fBhelp\fP [\fB\-dms\fP] [\fIpattern\fP]
-Display helpful information about builtin commands.  If
-.I pattern
-is specified,
-.B help
-gives detailed help on all commands matching
-.IR pattern ;
-otherwise help for all the builtins and shell control structures
-is printed.
-.RS
-.PD 0
-.TP
-.B \-d
-Display a short description of each \fIpattern\fP
-.TP
-.B \-m
-Display the description of each \fIpattern\fP in a manpage-like format
-.TP
-.B \-s
-Display only a short usage synopsis for each \fIpattern\fP
-.PD
-.PP
-The return status is 0 unless no command matches
-.IR pattern .
-.RE
-.TP
-\fBhistory [\fIn\fP]
-.PD 0
-.TP
-\fBhistory\fP \fB\-c\fP
-.TP
-\fBhistory \-d\fP \fIoffset\fP
-.TP
-\fBhistory\fP \fB\-anrw\fP [\fIfilename\fP]
-.TP
-\fBhistory\fP \fB\-p\fP \fIarg\fP [\fIarg ...\fP]
-.TP
-\fBhistory\fP \fB\-s\fP \fIarg\fP [\fIarg ...\fP]
-.PD
-With no options, display the command
-history list with line numbers.  Lines listed
-with a 
-.B *
-have been modified.  An argument of
-.I n
-lists only the last
-.I n
-lines.
-If the shell variable
-.SM
-.B HISTTIMEFORMAT
-is set and not null,
-it is used as a format string for \fIstrftime\fP(3) to display
-the time stamp associated with each displayed history entry.
-No intervening blank is printed between the formatted time stamp
-and the history line.
-If \fIfilename\fP is supplied, it is used as the
-name of the history file; if not, the value of
-.SM
-.B HISTFILE
-is used.  Options, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-.B \-c
-Clear the history list by deleting all the entries.
-.TP
-\fB\-d\fP \fIoffset\fP
-Delete the history entry at position \fIoffset\fP.
-.TP
-.B \-a
-Append the ``new'' history lines (history lines entered since the
-beginning of the current \fBbash\fP session) to the history file.
-.TP
-.B \-n
-Read the history lines not already read from the history
-file into the current history list.  These are lines
-appended to the history file since the beginning of the
-current \fBbash\fP session.
-.TP
-.B \-r
-Read the contents of the history file
-and append them to the current history list.
-.TP
-.B \-w
-Write the current history list to the history file, overwriting the
-history file's contents.
-.TP
-.B \-p
-Perform history substitution on the following \fIargs\fP and display
-the result on the standard output.
-Does not store the results in the history list.
-Each \fIarg\fP must be quoted to disable normal history expansion.
-.TP
-.B \-s
-Store the
-.I args
-in the history list as a single entry.  The last command in the
-history list is removed before the
-.I args
-are added.
-.PD
-.PP
-If the
-.SM
-.B HISTTIMEFORMAT
-variable is set, the time stamp information
-associated with each history entry is written to the history file,
-marked with the history comment character.
-When the history file is read, lines beginning with the history
-comment character followed immediately by a digit are interpreted
-as timestamps for the previous history line.
-The return value is 0 unless an invalid option is encountered, an
-error occurs while reading or writing the history file, an invalid
-\fIoffset\fP is supplied as an argument to \fB\-d\fP, or the
-history expansion supplied as an argument to \fB\-p\fP fails.
-.RE
-.TP
-\fBjobs\fP [\fB\-lnprs\fP] [ \fIjobspec\fP ... ]
-.PD 0
-.TP
-\fBjobs\fP \fB\-x\fP \fIcommand\fP [ \fIargs\fP ... ]
-.PD
-The first form lists the active jobs.  The options have the following
-meanings:
-.RS
-.PD 0
-.TP
-.B \-l
-List process IDs
-in addition to the normal information.
-.TP
-.B \-n
-Display information only about jobs that have changed status since
-the user was last notified of their status.
-.TP
-.B \-p
-List only the process ID of the job's process group
-leader.
-.TP
-.B \-r
-Display only running jobs.
-.TP
-.B \-s
-Display only stopped jobs.
-.PD
-.PP
-If
-.I jobspec
-is given, output is restricted to information about that job.
-The return status is 0 unless an invalid option is encountered
-or an invalid
-.I jobspec
-is supplied.
-.PP
-If the
-.B \-x
-option is supplied,
-.B jobs
-replaces any
-.I jobspec
-found in
-.I command
-or
-.I args
-with the corresponding process group ID, and executes
-.I command
-passing it
-.IR args ,
-returning its exit status.
-.RE
-.TP
-\fBkill\fP [\fB\-s\fP \fIsigspec\fP | \fB\-n\fP \fIsignum\fP | \fB\-\fP\fIsigspec\fP] [\fIpid\fP | \fIjobspec\fP] ...
-.PD 0
-.TP
-\fBkill\fP \fB\-l\fP [\fIsigspec\fP | \fIexit_status\fP]
-.PD
-Send the signal named by
-.I sigspec
-or
-.I signum
-to the processes named by
-.I pid
-or
-.IR jobspec .
-.I sigspec
-is either a case-insensitive signal name such as
-.SM
-.B SIGKILL
-(with or without the
-.SM
-.B SIG
-prefix) or a signal number;
-.I signum
-is a signal number.
-If
-.I sigspec
-is not present, then
-.SM
-.B SIGTERM
-is assumed.
-An argument of
-.B \-l
-lists the signal names.
-If any arguments are supplied when
-.B \-l
-is given, the names of the signals corresponding to the arguments are
-listed, and the return status is 0.
-The \fIexit_status\fP argument to
-.B \-l
-is a number specifying either a signal number or the exit status of
-a process terminated by a signal.
-.B kill
-returns true if at least one signal was successfully sent, or false
-if an error occurs or an invalid option is encountered.
-.TP
-\fBlet\fP \fIarg\fP [\fIarg\fP ...]
-Each
-.I arg
-is an arithmetic expression to be evaluated (see
-.SM
-.B "ARITHMETIC EVALUATION"
-above).
-If the last
-.I arg
-evaluates to 0,
-.B let
-returns 1; 0 is returned otherwise.
-.TP
-\fBlocal\fP [\fIoption\fP] [\fIname\fP[=\fIvalue\fP] ...]
-For each argument, a local variable named
-.I name 
-is created, and assigned
-.IR value .
-The \fIoption\fP can be any of the options accepted by \fBdeclare\fP.
-When
-.B local
-is used within a function, it causes the variable
-.I name
-to have a visible scope restricted to that function and its children.
-With no operands,
-.B local
-writes a list of local variables to the standard output.  It is
-an error to use
-.B local
-when not within a function.  The return status is 0 unless
-.B local
-is used outside a function, an invalid
-.I name
-is supplied, or
-\fIname\fP is a readonly variable.
-.TP
-.B logout
-Exit a login shell.
-.TP
-\fBmapfile\fP [\fB\-n\fP \fIcount\fP] [\fB\-O\fP \fIorigin\fP] [\fB\-s\fP \fIcount\fP] [\fB\-t\fP] [\fB\-u\fP \fIfd\fP] [\fB\-C\fP \fIcallback\fP] [\fB\-c\fP \fIquantum\fP] [\fIarray\fP]
-.PD 0
-.TP
-\fBreadarray\fP [\fB\-n\fP \fIcount\fP] [\fB\-O\fP \fIorigin\fP] [\fB\-s\fP \fIcount\fP] [\fB\-t\fP] [\fB\-u\fP \fIfd\fP] [\fB\-C\fP \fIcallback\fP] [\fB\-c\fP \fIquantum\fP] [\fIarray\fP]
-.PD
-Read lines from the standard input into the indexed array variable
-.IR array ,
-or from file descriptor 
-.IR fd
-if the 
-.B \-u
-option is supplied.
-The variable
-.SM
-.B MAPFILE
-is the default \fIarray\fP.
-Options, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-.B \-n
-Copy at most
-.I count
-lines.  If \fIcount\fP is 0, all lines are copied.
-.TP
-.B \-O
-Begin assigning to
-.I array
-at index
-.IR origin .
-The default index is 0.
-.TP
-.B \-s
-Discard the first \fIcount\fP lines read.
-.TP
-.B \-t
-Remove a trailing newline from each line read.
-.TP
-.B \-u
-Read lines from file descriptor \fIfd\fP instead of the standard input.
-.TP
-.B \-C
-Evaluate
-.I callback
-each time \fIquantum\fP lines are read.  The \fB\-c\fP option specifies
-.IR quantum .
-.TP
-.B \-c
-Specify the number of lines read between each call to
-.IR callback .
-.PD
-.PP
-If
-.B \-C
-is specified without 
-.BR \-c ,
-the default quantum is 5000.
-When \fIcallback\fP is evaluated, it is supplied the index of the next
-array element to be assigned and the line to be assigned to that element
-as additional arguments.
-\fIcallback\fP is evaluated after the line is read but before the 
-array element is assigned.
-.PP
-If not supplied with an explicit origin, \fBmapfile\fP will clear \fIarray\fP
-before assigning to it.
-.PP
-\fBmapfile\fP returns successfully unless an invalid option or option
-argument is supplied, \fIarray\fP is invalid or unassignable, or if
-\fIarray\fP is not an indexed array.
-.RE
-.TP
-\fBpopd\fP [\-\fBn\fP] [+\fIn\fP] [\-\fIn\fP]
-Removes entries from the directory stack.  With no arguments,
-removes the top directory from the stack, and performs a
-.B cd
-to the new top directory.
-Arguments, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-.B \-n
-Suppresses the normal change of directory when removing directories
-from the stack, so that only the stack is manipulated.
-.TP
-\fB+\fP\fIn\fP
-Removes the \fIn\fPth entry counting from the left of the list
-shown by
-.BR dirs ,
-starting with zero.  For example:
-.if n ``popd +0''
-.if t \f(CWpopd +0\fP
-removes the first directory,
-.if n ``popd +1''
-.if t \f(CWpopd +1\fP
-the second.
-.TP
-\fB\-\fP\fIn\fP
-Removes the \fIn\fPth entry counting from the right of the list
-shown by
-.BR dirs ,
-starting with zero.  For example:
-.if n ``popd -0''
-.if t \f(CWpopd -0\fP
-removes the last directory,
-.if n ``popd -1''
-.if t \f(CWpopd -1\fP
-the next to last.
-.PD
-.PP
-If the
-.B popd
-command is successful, a 
-.B dirs
-is performed as well, and the return status is 0.
-.B popd
-returns false if an invalid option is encountered, the directory stack
-is empty, a non-existent directory stack entry is specified, or the
-directory change fails.
-.RE
-.TP
-\fBprintf\fP [\fB\-v\fP \fIvar\fP] \fIformat\fP [\fIarguments\fP]
-Write the formatted \fIarguments\fP to the standard output under the
-control of the \fIformat\fP.
-The \fB\-v\fP option causes the output to be assigned to the variable
-\fIvar\fP rather than being printed to the standard output.
-.sp 1
-The \fIformat\fP is a character string which contains three types of objects:
-plain characters, which are simply copied to standard output, character
-escape sequences, which are converted and copied to the standard output, and
-format specifications, each of which causes printing of the next successive
-\fIargument\fP.
-In addition to the standard \fIprintf\fP(1) format specifications,
-\fBprintf\fP interprets the following extensions:
-.RS
-.PD 0
-.TP
-.B %b
-causes
-\fBprintf\fP to expand backslash escape sequences in the corresponding
-\fIargument\fP (except that \fB\ec\fP terminates output, backslashes in
-\fB\e\(aq\fP, \fB\e"\fP, and \fB\e?\fP are not removed, and octal escapes
-beginning with \fB\e0\fP may contain up to four digits).
-.TP
-.B %q
-causes \fBprintf\fP to output the corresponding
-\fIargument\fP in a format that can be reused as shell input.
-.TP
-.B %(\fIdatefmt\fP)T
-causes \fBprintf\fP to output the date-time string resulting from using
-\fIdatefmt\fP as a format string for \fIstrftime\fP(3).
-The corresponding \fIargument\fP is an integer representing the number of
-seconds since the epoch.
-Two special argument values may be used: -1 represents the current
-time, and -2 represents the time the shell was invoked.
-If no argument is specified, conversion behaves as if -1 had been given.
-This is an exception to the usual \fBprintf\fP behavior.
-.PD
-.PP
-Arguments to non-string format specifiers are treated as C constants,
-except that a leading plus or minus sign is allowed, and if the leading
-character is a single or double quote, the value is the ASCII value of
-the following character.
-.PP
-The \fIformat\fP is reused as necessary to consume all of the \fIarguments\fP.
-If the \fIformat\fP requires more \fIarguments\fP than are supplied, the
-extra format specifications behave as if a zero value or null string, as
-appropriate, had been supplied.
-The return value is zero on success, non-zero on failure.
-.RE
-.TP
-\fBpushd\fP [\fB\-n\fP] [+\fIn\fP] [\-\fIn\fP]
-.PD 0
-.TP
-\fBpushd\fP [\fB\-n\fP] [\fIdir\fP]
-.PD
-Adds a directory to the top of the directory stack, or rotates
-the stack, making the new top of the stack the current working
-directory.  With no arguments, exchanges the top two directories
-and returns 0, unless the directory stack is empty.
-Arguments, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-.B \-n
-Suppresses the normal change of directory when adding directories
-to the stack, so that only the stack is manipulated.
-.TP
-\fB+\fP\fIn\fP
-Rotates the stack so that the \fIn\fPth directory
-(counting from the left of the list shown by
-.BR dirs ,
-starting with zero)
-is at the top.
-.TP
-\fB\-\fP\fIn\fP
-Rotates the stack so that the \fIn\fPth directory
-(counting from the right of the list shown by
-.BR dirs ,
-starting with zero) is at the top.
-.TP
-.I dir
-Adds
-.I dir
-to the directory stack at the top, making it the
-new current working directory as if it had been supplied as the argument
-to the \fBcd\fP builtin.
-.PD
-.PP
-If the
-.B pushd
-command is successful, a 
-.B dirs
-is performed as well.
-If the first form is used,
-.B pushd
-returns 0 unless the cd to
-.I dir
-fails.  With the second form,
-.B pushd
-returns 0 unless the directory stack is empty,
-a non-existent directory stack element is specified,
-or the directory change to the specified new current directory
-fails.
-.RE
-.TP
-\fBpwd\fP [\fB\-LP\fP]
-Print the absolute pathname of the current working directory.
-The pathname printed contains no symbolic links if the
-.B \-P
-option is supplied or the 
-.B \-o physical
-option to the
-.B set
-builtin command is enabled.
-If the
-.B \-L
-option is used, the pathname printed may contain symbolic links.
-The return status is 0 unless an error occurs while
-reading the name of the current directory or an
-invalid option is supplied.
-.TP
-\fBread\fP [\fB\-ers\fP] [\fB\-a\fP \fIaname\fP] [\fB\-d\fP \fIdelim\fP] [\fB\-i\fP \fItext\fP] [\fB\-n\fP \fInchars\fP] [\fB\-N\fP \fInchars\fP] [\fB\-p\fP \fIprompt\fP] [\fB\-t\fP \fItimeout\fP] [\fB\-u\fP \fIfd\fP] [\fIname\fP ...]
-One line is read from the standard input, or from the file descriptor
-\fIfd\fP supplied as an argument to the \fB\-u\fP option, and the first word
-is assigned to the first
-.IR name ,
-the second word to the second
-.IR name ,
-and so on, with leftover words and their intervening separators assigned
-to the last
-.IR name .
-If there are fewer words read from the input stream than names,
-the remaining names are assigned empty values.
-The characters in 
-.SM
-.B IFS
-are used to split the line into words.
-The backslash character (\fB\e\fP) may be used to remove any special
-meaning for the next character read and for line continuation.
-Options, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-.B \-a \fIaname\fP
-The words are assigned to sequential indices
-of the array variable
-.IR aname ,
-starting at 0.
-.I aname
-is unset before any new values are assigned.
-Other \fIname\fP arguments are ignored.
-.TP
-.B \-d \fIdelim\fP
-The first character of \fIdelim\fP is used to terminate the input line,
-rather than newline.
-.TP
-.B \-e
-If the standard input
-is coming from a terminal,
-.B readline
-(see
-.SM
-.B READLINE
-above) is used to obtain the line.
-Readline uses the current (or default, if line editing was not previously
-active) editing settings.
-.TP
-.B \-i \fItext\fP
-If
-.B readline
-is being used to read the line, \fItext\fP is placed into the editing
-buffer before editing begins.
-.TP
-.B \-n \fInchars\fP
-\fBread\fP returns after reading \fInchars\fP characters rather than
-waiting for a complete line of input, but honor a delimiter if fewer
-than \fInchars\fP characters are read before the delimiter.
-.TP
-.B \-N \fInchars\fP
-\fBread\fP returns after reading exactly \fInchars\fP characters rather
-than waiting for a complete line of input, unless EOF is encountered or
-\fBread\fP times out.
-Delimiter characters encountered in the input are
-not treated specially and do not cause \fBread\fP to return until
-\fInchars\fP characters are read.
-.TP
-.B \-p \fIprompt\fP
-Display \fIprompt\fP on standard error, without a
-trailing newline, before attempting to read any input.  The prompt
-is displayed only if input is coming from a terminal.
-.TP
-.B \-r
-Backslash does not act as an escape character.
-The backslash is considered to be part of the line.
-In particular, a backslash-newline pair may not be used as a line
-continuation.
-.TP
-.B \-s
-Silent mode.  If input is coming from a terminal, characters are
-not echoed.
-.TP
-.B \-t \fItimeout\fP
-Cause \fBread\fP to time out and return failure if a complete line of
-input (or a specified number of characters)
-is not read within \fItimeout\fP seconds.
-\fItimeout\fP may be a decimal number with a fractional portion following
-the decimal point.
-This option is only effective if \fBread\fP is reading input from a
-terminal, pipe, or other special file; it has no effect when reading
-from regular files.
-If \fBread\fP times out, \fBread\fP saves any partial input read into
-the specified variable \fIname\fP.
-If \fItimeout\fP is 0, \fBread\fP returns immediately, without trying to
-read any data.  The exit status is 0 if input is available on
-the specified file descriptor, non-zero otherwise.
-The exit status is greater than 128 if the timeout is exceeded.
-.TP
-.B \-u \fIfd\fP
-Read input from file descriptor \fIfd\fP.
-.PD
-.PP
-If no
-.I names
-are supplied, the line read is assigned to the variable
-.SM
-.BR REPLY .
-The return code is zero, unless end-of-file is encountered, \fBread\fP
-times out (in which case the return code is greater than 128),
-a variable assignment error (such as assigning to a readonly variable) occurs,
-or an invalid file descriptor is supplied as the argument to \fB\-u\fP.
-.RE
-.TP
-\fBreadonly\fP [\fB\-aAf\fP] [\fB\-p\fP] [\fIname\fP[=\fIword\fP] ...]
-.PD
-The given
-\fInames\fP are marked readonly; the values of these
-.I names
-may not be changed by subsequent assignment.
-If the
-.B \-f
-option is supplied, the functions corresponding to the
-\fInames\fP are so
-marked.
-The
-.B \-a
-option restricts the variables to indexed arrays; the
-.B \-A
-option restricts the variables to associative arrays.
-If both options are supplied,
-.B \-A
-takes precedence.
-If no
-.I name
-arguments are given, or if the
-.B \-p
-option is supplied, a list of all readonly names is printed.
-The other options may be used to restrict the output to a subset of
-the set of readonly names.
-The
-.B \-p
-option causes output to be displayed in a format that
-may be reused as input.
-If a variable name is followed by =\fIword\fP, the value of
-the variable is set to \fIword\fP.
-The return status is 0 unless an invalid option is encountered,
-one of the
-.I names
-is not a valid shell variable name, or
-.B \-f
-is supplied with a
-.I name
-that is not a function.
-.TP
-\fBreturn\fP [\fIn\fP]
-Causes a function to stop executing and return the value specified by
-.I n
-to its caller.
-If 
-.I n
-is omitted, the return status is that of the last command
-executed in the function body.  If
-.B return
-is used outside a function,
-but during execution of a script by the 
-.B .
-(\fBsource\fP) command, it causes the shell to stop executing
-that script and return either
-.I n
-or the exit status of the last command executed within the
-script as the exit status of the script.
-If \fIn\fP is supplied, the return value is its least significant
-8 bits.
-The return status is non-zero if
-.B return
-is supplied a non-numeric argument, or
-is used outside a
-function and not during execution of a script by \fB.\fP\^ or \fBsource\fP.
-Any command associated with the \fBRETURN\fP trap is executed
-before execution resumes after the function or script.
-.TP
-\fBset\fP [\fB\-\-abefhkmnptuvxBCEHPT\fP] [\fB\-o\fP \fIoption\-name\fP] [\fIarg\fP ...]
-.PD 0
-.TP
-\fBset\fP [\fB+abefhkmnptuvxBCEHPT\fP] [\fB+o\fP \fIoption\-name\fP] [\fIarg\fP ...]
-.PD
-Without options, the name and value of each shell variable are displayed
-in a format that can be reused as input
-for setting or resetting the currently-set variables.
-Read-only variables cannot be reset.
-In \fIposix mode\fP, only shell variables are listed.
-The output is sorted according to the current locale.
-When options are specified, they set or unset shell attributes.
-Any arguments remaining after option processing are treated
-as values for the positional parameters and are assigned, in order, to 
-.BR $1 ,
-.BR $2 ,
-.B ...
-.BR $\fIn\fP .
-Options, if specified, have the following meanings:
-.RS
-.PD 0
-.TP 8
-.B \-a
-Automatically mark variables and functions which are modified or
-created for export to the environment of subsequent commands.
-.TP 8
-.B \-b
-Report the status of terminated background jobs
-immediately, rather than before the next primary prompt.  This is
-effective only when job control is enabled.
-.TP 8
-.B \-e
-Exit immediately if a
-\fIpipeline\fP (which may consist of a single \fIsimple command\fP),
-a \fIlist\fP,
-or a \fIcompound command\fP
-(see
-.SM
-.B SHELL GRAMMAR
-above),  exits with a non-zero status.
-The shell does not exit if the
-command that fails is part of the command list immediately following a
-.B while
-or
-.B until
-keyword, 
-part of the test following the
-.B if
-or
-.B elif
-reserved words, part of any command executed in a
-.B &&
-or
-.B ||
-list except the command following the final \fB&&\fP or \fB||\fP,
-any command in a pipeline but the last,
-or if the command's return value is
-being inverted with
-.BR ! .
-If a compound command other than a subshell
-returns a non-zero status because a command failed
-while \fB\-e\fP was being ignored, the shell does not exit.
-A trap on \fBERR\fP, if set, is executed before the shell exits.
-This option applies to the shell environment and each subshell environment
-separately (see
-.SM
-.B "COMMAND EXECUTION ENVIRONMENT"
-above), and may cause
-subshells to exit before executing all the commands in the subshell.
-If a compound command or shell function executes in a context
-where \fB\-e\fP is being ignored,
-none of the commands executed within the compound command or function body
-will be affected by the \fB\-e\fP setting, even if \fB\-e\fP is set
-and a command returns a failure status.
-If a compound command or shell function sets \fB\-e\fP while executing in
-a context where \fB\-e\fP is ignored, that setting will not have any
-effect until the compound command or the command containing the function
-call completes.
-.TP 8
-.B \-f
-Disable pathname expansion.
-.TP 8 
-.B \-h
-Remember the location of commands as they are looked up for execution.
-This is enabled by default.
-.TP 8
-.B \-k
-All arguments in the form of assignment statements
-are placed in the environment for a command, not just
-those that precede the command name.
-.TP 8
-.B \-m
-Monitor mode.  Job control is enabled.  This option is on
-by default for interactive shells on systems that support
-it (see
-.SM
-.B JOB CONTROL
-above).
-All processes run in a separate process group.
-When a background job completes, the shell prints a line
-containing its exit status.
-.TP 8
-.B \-n
-Read commands but do not execute them.  This may be used to 
-check a shell script for syntax errors.  This is ignored by
-interactive shells.
-.TP 8
-.B \-o \fIoption\-name\fP
-The \fIoption\-name\fP can be one of the following:
-.RS
-.TP 8
-.B allexport
-Same as
-.BR \-a .
-.TP 8
-.B braceexpand
-Same as
-.BR \-B .
-.TP 8
-.B emacs
-Use an emacs-style command line editing interface.  This is enabled
-by default when the shell is interactive, unless the shell is started
-with the
-.B \-\-noediting
-option.
-This also affects the editing interface used for \fBread \-e\fP.
-.TP 8
-.B errexit
-Same as
-.BR \-e .
-.TP 8
-.B errtrace
-Same as
-.BR \-E .
-.TP 8
-.B functrace
-Same as
-.BR \-T .
-.TP 8
-.B hashall
-Same as
-.BR \-h .
-.TP 8
-.B histexpand
-Same as
-.BR \-H .
-.TP 8
-.B history
-Enable command history, as described above under
-.SM
-.BR HISTORY .
-This option is on by default in interactive shells.
-.TP 8
-.B ignoreeof
-The effect is as if the shell command
-.if t \f(CWIGNOREEOF=10\fP
-.if n ``IGNOREEOF=10''
-had been executed
-(see
-.B Shell Variables
-above).
-.TP 8
-.B keyword
-Same as
-.BR \-k .
-.TP 8
-.B monitor
-Same as
-.BR \-m .
-.TP 8
-.B noclobber
-Same as
-.BR \-C .
-.TP 8
-.B noexec
-Same as
-.BR \-n .
-.TP 8
-.B noglob
-Same as
-.BR \-f .
-.TP 8
-.B nolog
-Currently ignored.
-.TP 8
-.B notify
-Same as
-.BR \-b .
-.TP 8
-.B nounset
-Same as
-.BR \-u .
-.TP 8
-.B onecmd
-Same as
-.BR \-t .
-.TP 8
-.B physical
-Same as
-.BR \-P .
-.TP 8
-.B pipefail
-If set, the return value of a pipeline is the value of the last
-(rightmost) command to exit with a non-zero status, or zero if all
-commands in the pipeline exit successfully.
-This option is disabled by default.
-.TP 8
-.B posix
-Change the behavior of
-.B bash
-where the default operation differs
-from the POSIX standard to match the standard (\fIposix mode\fP).
-.TP 8
-.B privileged
-Same as
-.BR \-p .
-.TP 8
-.B verbose
-Same as
-.BR \-v .
-.TP 8
-.B vi
-Use a vi-style command line editing interface.
-This also affects the editing interface used for \fBread \-e\fP.
-.TP 8
-.B xtrace
-Same as
-.BR \-x .
-.sp .5
-.PP
-If
-.B \-o
-is supplied with no \fIoption\-name\fP, the values of the current options are
-printed.
-If
-.B +o
-is supplied with no \fIoption\-name\fP, a series of
-.B set
-commands to recreate the current option settings is displayed on
-the standard output.
-.RE
-.TP 8
-.B \-p
-Turn on
-.I privileged
-mode.  In this mode, the
-.SM
-.B $ENV
-and
-.SM
-.B $BASH_ENV
-files are not processed, shell functions are not inherited from the
-environment, and the
-.SM
-.BR SHELLOPTS ,
-.SM
-.BR BASHOPTS ,
-.SM
-.BR CDPATH ,
-and
-.SM
-.B GLOBIGNORE
-variables, if they appear in the environment, are ignored.
-If the shell is started with the effective user (group) id not equal to the
-real user (group) id, and the \fB\-p\fP option is not supplied, these actions
-are taken and the effective user id is set to the real user id.
-If the \fB\-p\fP option is supplied at startup, the effective user id is
-not reset.
-Turning this option off causes the effective user
-and group ids to be set to the real user and group ids.
-.TP 8
-.B \-t
-Exit after reading and executing one command.
-.TP 8
-.B \-u
-Treat unset variables and parameters other than the special
-parameters "@" and "*" as an error when performing
-parameter expansion.  If expansion is attempted on an
-unset variable or parameter, the shell prints an error message, and,
-if not interactive, exits with a non-zero status.
-.TP 8
-.B \-v
-Print shell input lines as they are read.
-.TP 8
-.B \-x
-After expanding each \fIsimple command\fP,
-\fBfor\fP command, \fBcase\fP command, \fBselect\fP command, or
-arithmetic \fBfor\fP command, display the expanded value of
-.SM
-.BR PS4 ,
-followed by the command and its expanded arguments
-or associated word list.
-.TP 8
-.B \-B
-The shell performs brace expansion (see
-.B Brace Expansion
-above).  This is on by default.
-.TP 8
-.B \-C
-If set,
-.B bash
-does not overwrite an existing file with the
-.BR > ,
-.BR >& ,
-and
-.B <>
-redirection operators.  This may be overridden when 
-creating output files by using the redirection operator
-.B >|
-instead of
-.BR > .
-.TP 8
-.B \-E
-If set, any trap on \fBERR\fP is inherited by shell functions, command
-substitutions, and commands executed in a subshell environment.
-The \fBERR\fP trap is normally not inherited in such cases.
-.TP 8
-.B \-H
-Enable
-.B !
-style history substitution.  This option is on by
-default when the shell is interactive.
-.TP 8
-.B \-P
-If set, the shell does not resolve symbolic links when executing
-commands such as
-.B cd
-that change the current working directory.  It uses the
-physical directory structure instead.  By default,
-.B bash
-follows the logical chain of directories when performing commands
-which change the current directory.
-.TP 8
-.B \-T
-If set, any traps on \fBDEBUG\fP and \fBRETURN\fP are inherited by shell
-functions, command substitutions, and commands executed in a
-subshell environment.
-The \fBDEBUG\fP and \fBRETURN\fP traps are normally not inherited
-in such cases.
-.TP 8
-.B \-\-
-If no arguments follow this option, then the positional parameters are
-unset.  Otherwise, the positional parameters are set to the
-\fIarg\fPs, even if some of them begin with a
-.BR \- .
-.TP 8
-.B \-
-Signal the end of options, cause all remaining \fIarg\fPs to be
-assigned to the positional parameters.  The
-.B \-x
-and
-.B \-v
-options are turned off.
-If there are no \fIarg\fPs,
-the positional parameters remain unchanged.
-.PD
-.PP
-The options are off by default unless otherwise noted.
-Using + rather than \- causes these options to be turned off.
-The options can also be specified as arguments to an invocation of
-the shell.
-The current set of options may be found in
-.BR $\- .
-The return status is always true unless an invalid option is encountered.
-.RE
-.TP
-\fBshift\fP [\fIn\fP]
-The positional parameters from \fIn\fP+1 ... are renamed to
-.B $1
-.B ....
-Parameters represented by the numbers \fB$#\fP
-down to \fB$#\fP\-\fIn\fP+1 are unset.
-.I n
-must be a non-negative number less than or equal to \fB$#\fP.
-If
-.I n
-is 0, no parameters are changed.
-If
-.I n 
-is not given, it is assumed to be 1.
-If
-.I n
-is greater than \fB$#\fP, the positional parameters are not changed.
-The return status is greater than zero if
-.I n
-is greater than
-.B $#
-or less than zero; otherwise 0.
-.TP
-\fBshopt\fP [\fB\-pqsu\fP] [\fB\-o\fP] [\fIoptname\fP ...]
-Toggle the values of variables controlling optional shell behavior.
-With no options, or with the
-.B \-p
-option, a list of all settable options is displayed, with
-an indication of whether or not each is set.
-The \fB\-p\fP option causes output to be displayed in a form that
-may be reused as input.
-Other options have the following meanings:
-.RS
-.PD 0
-.TP
-.B \-s
-Enable (set) each \fIoptname\fP.
-.TP
-.B \-u
-Disable (unset) each \fIoptname\fP.
-.TP
-.B \-q
-Suppresses normal output (quiet mode); the return status indicates
-whether the \fIoptname\fP is set or unset.
-If multiple \fIoptname\fP arguments are given with
-.BR \-q ,
-the return status is zero if all \fIoptnames\fP are enabled; non-zero
-otherwise.
-.TP
-.B \-o
-Restricts the values of \fIoptname\fP to be those defined for the
-.B \-o
-option to the
-.B set
-builtin.
-.PD
-.PP
-If either
-.B \-s
-or
-.B \-u
-is used with no \fIoptname\fP arguments,
-.B shopt
-shows only those options which are set or unset, respectively.
-Unless otherwise noted, the \fBshopt\fP options are disabled (unset)
-by default.
-.PP
-The return status when listing options is zero if all \fIoptnames\fP
-are enabled, non-zero otherwise.  When setting or unsetting options,
-the return status is zero unless an \fIoptname\fP is not a valid shell
-option.
-.PP
-The list of \fBshopt\fP options is:
-.if t .sp .5v
-.if n .sp 1v
-.PD 0
-.TP 8
-.B autocd
-If set, a command name that is the name of a directory is executed as if
-it were the argument to the \fBcd\fP command.
-This option is only used by interactive shells.
-.TP 8
-.B cdable_vars
-If set, an argument to the
-.B cd
-builtin command that
-is not a directory is assumed to be the name of a variable whose
-value is the directory to change to.
-.TP 8
-.B cdspell
-If set, minor errors in the spelling of a directory component in a
-.B cd
-command will be corrected.
-The errors checked for are transposed characters,
-a missing character, and one character too many.
-If a correction is found, the corrected filename is printed,
-and the command proceeds.
-This option is only used by interactive shells.
-.TP 8
-.B checkhash
-If set, \fBbash\fP checks that a command found in the hash
-table exists before trying to execute it.  If a hashed command no
-longer exists, a normal path search is performed.
-.TP 8
-.B checkjobs
-If set, \fBbash\fP lists the status of any stopped and running jobs before
-exiting an interactive shell.  If any jobs are running, this causes
-the exit to be deferred until a second exit is attempted without an
-intervening command (see
-.SM
-.B "JOB CONTROL"
-above).  The shell always
-postpones exiting if any jobs are stopped.
-.TP 8
-.B checkwinsize
-If set, \fBbash\fP checks the window size after each command
-and, if necessary, updates the values of
-.SM
-.B LINES
-and
-.SM
-.BR COLUMNS .
-.TP 8
-.B cmdhist
-If set,
-.B bash
-attempts to save all lines of a multiple-line
-command in the same history entry.  This allows
-easy re-editing of multi-line commands.
-.TP 8
-.B compat31
-If set,
-.B bash
-changes its behavior to that of version 3.1 with respect to quoted
-arguments to the \fB[[\fP conditional command's \fB=~\fP operator
-and locale-specific string comparison when using the \fB[[\fP
-conditional command's \fB<\fP and \fB>\fP operators.
-Bash versions prior to bash-4.1 use ASCII collation and
-.IR strcmp (3);
-bash-4.1 and later use the current locale's collation sequence and
-.IR strcoll (3).
-.TP 8
-.B compat32
-If set,
-.B bash
-changes its behavior to that of version 3.2 with respect to
-locale-specific string comparison when using the \fB[[\fP
-conditional command's \fB<\fP and \fB>\fP operators (see previous item).
-.TP 8
-.B compat40
-If set,
-.B bash
-changes its behavior to that of version 4.0 with respect to locale-specific
-string comparison when using the \fB[[\fP
-conditional command's \fB<\fP and \fB>\fP operators (see description of
-\fBcompat31\fP)
-and the effect of interrupting a command list.
-Bash versions 4.0 and later interrupt the list as if the shell received the
-interrupt; previous versions continue with the next command in the list.
-.TP 8
-.B compat41
-If set,
-.BR bash ,
-when in posix mode, treats a single quote in a double-quoted
-parameter expansion as a special character.  The single quotes must match
-(an even number) and the characters between the single quotes are considered
-quoted.  This is the behavior of posix mode through version 4.1.
-The default bash behavior remains as in previous versions.
-.TP 8
-.B compat42
-If set,
-.B bash
-does not process the replacement string in the pattern substitution word
-expansion using quote removal.
-.TP 8
-.B complete_fullquote
-If set,
-.B bash
-quotes all shell metacharacters in filenames and directory names when
-performing completion.
-If not set,
-.B bash
-removes metacharacters such as the dollar sign from the set of
-characters that will be quoted in completed filenames
-when these metacharacters appear in shell variable references in words to be
-completed.
-This means that dollar signs in variable names that expand to directories
-will not be quoted;
-however, any dollar signs appearing in filenames will not be quoted, either.
-This is active only when bash is using backslashes to quote completed
-filenames.
-This variable is set by default, which is the default bash behavior in
-versions through 4.2.
-.TP 8
-.B direxpand
-If set,
-.B bash
-replaces directory names with the results of word expansion when performing
-filename completion.  This changes the contents of the readline editing
-buffer.
-If not set,
-.B bash
-attempts to preserve what the user typed.
-.TP 8
-.B dirspell
-If set,
-.B bash
-attempts spelling correction on directory names during word completion
-if the directory name initially supplied does not exist.
-.TP 8
-.B dotglob
-If set, 
-.B bash
-includes filenames beginning with a `.' in the results of pathname
-expansion.
-.TP 8
-.B execfail
-If set, a non-interactive shell will not exit if
-it cannot execute the file specified as an argument to the
-.B exec
-builtin command.  An interactive shell does not exit if
-.B exec
-fails.
-.TP 8
-.B expand_aliases
-If set, aliases are expanded as described above under
-.SM
-.BR ALIASES .
-This option is enabled by default for interactive shells.
-.TP 8
-.B extdebug
-If set, behavior intended for use by debuggers is enabled:
-.RS
-.TP
-.B 1.
-The \fB\-F\fP option to the \fBdeclare\fP builtin displays the source
-file name and line number corresponding to each function name supplied
-as an argument.
-.TP
-.B 2.
-If the command run by the \fBDEBUG\fP trap returns a non-zero value, the
-next command is skipped and not executed.
-.TP
-.B 3.
-If the command run by the \fBDEBUG\fP trap returns a value of 2, and the
-shell is executing in a subroutine (a shell function or a shell script
-executed by the \fB.\fP or \fBsource\fP builtins), a call to
-\fBreturn\fP is simulated.
-.TP
-.B 4.
-.SM
-.B BASH_ARGC
-and
-.SM
-.B BASH_ARGV
-are updated as described in their descriptions above.
-.TP
-.B 5.
-Function tracing is enabled:  command substitution, shell functions, and
-subshells invoked with \fB(\fP \fIcommand\fP \fB)\fP inherit the
-\fBDEBUG\fP and \fBRETURN\fP traps.
-.TP
-.B 6.
-Error tracing is enabled:  command substitution, shell functions, and
-subshells invoked with \fB(\fP \fIcommand\fP \fB)\fP inherit the
-\fBERR\fP trap.
-.RE
-.TP 8
-.B extglob
-If set, the extended pattern matching features described above under
-\fBPathname Expansion\fP are enabled.
-.TP 8
-.B extquote
-If set, \fB$\fP\(aq\fIstring\fP\(aq and \fB$\fP"\fIstring\fP" quoting is
-performed within \fB${\fP\fIparameter\fP\fB}\fP expansions
-enclosed in double quotes.  This option is enabled by default.
-.TP 8
-.B failglob
-If set, patterns which fail to match filenames during pathname expansion
-result in an expansion error.
-.TP 8
-.B force_fignore
-If set, the suffixes specified by the
-.SM
-.B FIGNORE
-shell variable
-cause words to be ignored when performing word completion even if
-the ignored words are the only possible completions.
-See
-.SM
-\fBSHELL VARIABLES\fP
-above for a description of
-.SM
-.BR FIGNORE .
-This option is enabled by default.
-.TP 8
-.B globasciiranges
-If set, range expressions used in pattern matching (see
-.SM
-.B Pattern Matching
-above) behave as if in the traditional C locale when performing
-comparisons.  That is, the current locale's collating sequence
-is not taken into account, so
-.B b
-will not collate between
-.B A
-and
-.BR B ,
-and upper-case and lower-case ASCII characters will collate together.
-.TP 8
-.B globstar
-If set, the pattern \fB**\fP used in a pathname expansion context will
-match all files and zero or more directories and subdirectories.
-If the pattern is followed by a \fB/\fP, only directories and
-subdirectories match.
-.TP 8
-.B gnu_errfmt
-If set, shell error messages are written in the standard GNU error
-message format.
-.TP 8
-.B histappend
-If set, the history list is appended to the file named by the value
-of the
-.SM
-.B HISTFILE
-variable when the shell exits, rather than overwriting the file.
-.TP 8
-.B histreedit
-If set, and
-.B readline
-is being used, a user is given the opportunity to re-edit a
-failed history substitution.
-.TP 8
-.B histverify
-If set, and 
-.B readline
-is being used, the results of history substitution are not immediately
-passed to the shell parser.  Instead, the resulting line is loaded into
-the \fBreadline\fP editing buffer, allowing further modification.
-.TP 8
-.B hostcomplete
-If set, and
-.B readline
-is being used, \fBbash\fP will attempt to perform hostname completion when a
-word containing a \fB@\fP is being completed (see
-.B Completing
-under
-.SM
-.B READLINE
-above).
-This is enabled by default.
-.TP 8
-.B huponexit
-If set, \fBbash\fP will send
-.SM
-.B SIGHUP
-to all jobs when an interactive login shell exits.
-.TP 8
-.B interactive_comments
-If set, allow a word beginning with
-.B #
-to cause that word and all remaining characters on that
-line to be ignored in an interactive shell (see
-.SM
-.B COMMENTS
-above).  This option is enabled by default.
-.TP 8
-.B lastpipe
-If set, and job control is not active, the shell runs the last command of
-a pipeline not executed in the background in the current shell environment.
-.TP 8
-.B lithist
-If set, and the
-.B cmdhist
-option is enabled, multi-line commands are saved to the history with
-embedded newlines rather than using semicolon separators where possible.
-.TP 8
-.B login_shell
-The shell sets this option if it is started as a login shell (see
-.SM
-.B "INVOCATION"
-above).
-The value may not be changed.
-.TP 8
-.B mailwarn
-If set, and a file that \fBbash\fP is checking for mail has been  
-accessed since the last time it was checked, the message ``The mail in
-\fImailfile\fP has been read'' is displayed.
-.TP 8
-.B no_empty_cmd_completion
-If set, and
-.B readline
-is being used,
-.B bash
-will not attempt to search the
-.SM
-.B PATH
-for possible completions when
-completion is attempted on an empty line.
-.TP 8
-.B nocaseglob
-If set,
-.B bash
-matches filenames in a case\-insensitive fashion when performing pathname
-expansion (see
-.B Pathname Expansion
-above).
-.TP 8
-.B nocasematch
-If set,
-.B bash
-matches patterns in a case\-insensitive fashion when performing matching
-while executing \fBcase\fP or \fB[[\fP conditional commands.
-.TP 8
-.B nullglob
-If set,
-.B bash
-allows patterns which match no
-files (see
-.B Pathname Expansion
-above)
-to expand to a null string, rather than themselves.
-.TP 8
-.B progcomp
-If set, the programmable completion facilities (see
-\fBProgrammable Completion\fP above) are enabled.
-This option is enabled by default.
-.TP 8
-.B promptvars
-If set, prompt strings undergo
-parameter expansion, command substitution, arithmetic
-expansion, and quote removal after being expanded as described in
-.SM
-.B PROMPTING
-above.  This option is enabled by default.
-.TP 8
-.B restricted_shell
-The shell sets this option if it is started in restricted mode (see
-.SM
-.B "RESTRICTED SHELL"
-below).
-The value may not be changed.
-This is not reset when the startup files are executed, allowing
-the startup files to discover whether or not a shell is restricted.
-.TP 8
-.B shift_verbose
-If set, the
-.B shift
-builtin prints an error message when the shift count exceeds the
-number of positional parameters.
-.TP 8
-.B sourcepath
-If set, the
-\fBsource\fP (\fB.\fP) builtin uses the value of
-.SM
-.B PATH
-to find the directory containing the file supplied as an argument.
-This option is enabled by default.
-.TP 8
-.B xpg_echo
-If set, the \fBecho\fP builtin expands backslash-escape sequences
-by default.
-.RE
-.PD
-.TP
-\fBsuspend\fP [\fB\-f\fP]
-Suspend the execution of this shell until it receives a
-.SM
-.B SIGCONT
-signal.  A login shell cannot be suspended; the
-.B \-f
-option can be used to override this and force the suspension.
-The return status is 0 unless the shell is a login shell and
-.B \-f
-is not supplied, or if job control is not enabled.
-.TP
-\fBtest\fP \fIexpr\fP
-.PD 0
-.TP
-\fB[\fP \fIexpr\fP \fB]\fP
-Return a status of 0 (true) or 1 (false) depending on
-the evaluation of the conditional expression
-.IR expr .
-Each operator and operand must be a separate argument.
-Expressions are composed of the primaries described above under
-.SM
-.BR "CONDITIONAL EXPRESSIONS" .
-\fBtest\fP does not accept any options, nor does it accept and ignore
-an argument of \fB\-\-\fP as signifying the end of options.
-.if t .sp 0.5
-.if n .sp 1
-Expressions may be combined using the following operators, listed
-in decreasing order of precedence.
-The evaluation depends on the number of arguments; see below.
-Operator precedence is used when there are five or more arguments.
-.RS
-.PD 0
-.TP
-.B ! \fIexpr\fP
-True if
-.I expr
-is false.
-.TP
-.B ( \fIexpr\fP )
-Returns the value of \fIexpr\fP.
-This may be used to override the normal precedence of operators.
-.TP
-\fIexpr1\fP \-\fBa\fP \fIexpr2\fP
-True if both
-.I expr1
-and
-.I expr2
-are true.
-.TP
-\fIexpr1\fP \-\fBo\fP \fIexpr2\fP
-True if either
-.I expr1
-or
-.I expr2
-is true.
-.PD
-.PP
-\fBtest\fP and \fB[\fP evaluate conditional
-expressions using a set of rules based on the number of arguments.
-.if t .sp 0.5
-.if n .sp 1
-.PD 0
-.TP
-0 arguments
-The expression is false.
-.TP
-1 argument
-The expression is true if and only if the argument is not null.
-.TP
-2 arguments
-If the first argument is \fB!\fP, the expression is true if and
-only if the second argument is null.
-If the first argument is one of the unary conditional operators listed above
-under
-.SM
-.BR "CONDITIONAL EXPRESSIONS" ,
-the expression is true if the unary test is true.
-If the first argument is not a valid unary conditional operator, the expression
-is false.
-.TP
-3 arguments
-The following conditions are applied in the order listed.
-If the second argument is one of the binary conditional operators listed above
-under
-.SM
-.BR "CONDITIONAL EXPRESSIONS" ,
-the result of the expression is the result of the binary test using
-the first and third arguments as operands.
-The \fB\-a\fP and \fB\-o\fP operators are considered binary operators
-when there are three arguments.  
-If the first argument is \fB!\fP, the value is the negation of
-the two-argument test using the second and third arguments.
-If the first argument is exactly \fB(\fP and the third argument is
-exactly \fB)\fP, the result is the one-argument test of the second
-argument.
-Otherwise, the expression is false.
-.TP
-4 arguments
-If the first argument is \fB!\fP, the result is the negation of
-the three-argument expression composed of the remaining arguments.
-Otherwise, the expression is parsed and evaluated according to 
-precedence using the rules listed above.
-.TP
-5 or more arguments
-The expression is parsed and evaluated according to precedence
-using the rules listed above.
-.if t .sp 0.5
-.if n .sp 1
-.LP
-When used with \fBtest\fP or \fB[\fP, the \fB<\fP and \fB>\fP operators
-sort lexicographically using ASCII ordering.
-.RE
-.PD
-.TP
-.B times
-Print the accumulated user and system times for the shell and
-for processes run from the shell.  The return status is 0.
-.TP
-\fBtrap\fP [\fB\-lp\fP] [[\fIarg\fP] \fIsigspec\fP ...]
-The command
-.I arg
-is to be read and executed when the shell receives
-signal(s)
-.IR sigspec .
-If
-.I arg
-is absent (and there is a single \fIsigspec\fP) or
-.BR \- ,
-each specified signal is
-reset to its original disposition (the value it had
-upon entrance to the shell).
-If 
-.I arg
-is the null string the signal specified by each
-.I sigspec
-is ignored by the shell and by the commands it invokes.
-If
-.I arg
-is not present and
-.B \-p
-has been supplied, then the trap commands associated with each
-.I sigspec
-are displayed.
-If no arguments are supplied or if only
-.B \-p
-is given,
-.B trap
-prints the list of commands associated with each signal.
-The
-.B \-l
-option causes the shell to print a list of signal names and
-their corresponding numbers.
-Each
-.I sigspec
-is either
-a signal name defined in <\fIsignal.h\fP>, or a signal number.
-Signal names are case insensitive and the
-.SM
-.B SIG
-prefix is optional.
-.if t .sp 0.5
-.if n .sp 1
-If a
-.I sigspec
-is
-.SM
-.B EXIT
-(0) the command
-.I arg
-is executed on exit from the shell.
-If a
-.I sigspec
-is
-.SM
-.BR DEBUG ,
-the command
-.I arg
-is executed before every \fIsimple command\fP, \fIfor\fP command,
-\fIcase\fP command, \fIselect\fP command, every arithmetic \fIfor\fP
-command, and before the first command executes in a shell function (see
-.SM
-.B SHELL GRAMMAR
-above).
-Refer to the description of the \fBextdebug\fP option to the
-\fBshopt\fP builtin for details of its effect on the \fBDEBUG\fP trap.
-If a
-.I sigspec
-is
-.SM
-.BR RETURN ,
-the command
-.I arg
-is executed each time a shell function or a script executed with
-the \fB.\fP or \fBsource\fP builtins finishes executing.
-.if t .sp 0.5
-.if n .sp 1
-If a
-.I sigspec
-is
-.SM
-.BR ERR ,
-the command
-.I arg
-is executed whenever a simple command has a non\-zero exit status,
-subject to the following conditions.
-The
-.SM
-.B ERR
-trap is not executed if the failed
-command is part of the command list immediately following a
-.B while
-or
-.B until
-keyword, 
-part of the test in an
-.I if
-statement, part of a command executed in a
-.B &&
-or
-.B ||
-list, or if the command's return value is
-being inverted via
-.BR ! .
-These are the same conditions obeyed by the \fBerrexit\fP option.
-.if t .sp 0.5
-.if n .sp 1
-Signals ignored upon entry to the shell cannot be trapped or reset.
-Trapped signals that are not being ignored are reset to their original
-values in a subshell or subshell environment when one is created.
-The return status is false if any
-.I sigspec
-is invalid; otherwise
-.B trap
-returns true.
-.TP
-\fBtype\fP [\fB\-aftpP\fP] \fIname\fP [\fIname\fP ...]
-With no options, 
-indicate how each
-.I name
-would be interpreted if used as a command name.
-If the
-.B \-t
-option is used,
-.B type
-prints a string which is one of
-.IR alias ,
-.IR keyword ,
-.IR function ,
-.IR builtin ,
-or
-.I file 
-if
-.I name
-is an alias, shell reserved word, function, builtin, or disk file,
-respectively.
-If the
-.I name
-is not found, then nothing is printed, and an exit status of false
-is returned.
-If the
-.B \-p
-option is used,
-.B type
-either returns the name of the disk file
-that would be executed if
-.I name
-were specified as a command name,
-or nothing if
-.if t \f(CWtype -t name\fP
-.if n ``type -t name''
-would not return
-.IR file .
-The
-.B \-P
-option forces a
-.SM
-.B PATH
-search for each \fIname\fP, even if
-.if t \f(CWtype -t name\fP
-.if n ``type -t name''
-would not return
-.IR file .
-If a command is hashed,
-.B \-p
-and
-.B \-P
-print the hashed value, which is not necessarily the file that appears
-first in 
-.SM
-.BR PATH .
-If the
-.B \-a
-option is used, 
-.B type
-prints all of the places that contain
-an executable named 
-.IR name .
-This includes aliases and functions,
-if and only if the 
-.B \-p
-option is not also used.
-The table of hashed commands is not consulted
-when using
-.BR \-a .
-The
-.B \-f
-option suppresses shell function lookup, as with the \fBcommand\fP builtin.
-.B type
-returns true if all of the arguments are found, false if
-any are not found.
-.TP
-\fBulimit\fP [\fB\-HSTabcdefilmnpqrstuvx\fP [\fIlimit\fP]]
-Provides control over the resources available to the shell and to
-processes started by it, on systems that allow such control.
-The \fB\-H\fP and \fB\-S\fP options specify that the hard or soft limit is
-set for the given resource.
-A hard limit cannot be increased by a non-root user once it is set;
-a soft limit may be increased up to the value of the hard limit.
-If neither \fB\-H\fP nor \fB\-S\fP is specified, both the soft and hard
-limits are set.
-The value of
-.I limit
-can be a number in the unit specified for the resource
-or one of the special values
-.BR hard ,
-.BR soft ,
-or
-.BR unlimited ,
-which stand for the current hard limit, the current soft limit, and
-no limit, respectively.
-If
-.I limit
-is omitted, the current value of the soft limit of the resource is
-printed, unless the \fB\-H\fP option is given.  When more than one
-resource is specified, the limit name and unit are printed before the value.
-Other options are interpreted as follows:
-.RS
-.PD 0
-.TP
-.B \-a
-All current limits are reported
-.TP
-.B \-b
-The maximum socket buffer size
-.TP
-.B \-c
-The maximum size of core files created
-.TP
-.B \-d
-The maximum size of a process's data segment
-.TP
-.B \-e
-The maximum scheduling priority ("nice")
-.TP
-.B \-f
-The maximum size of files written by the shell and its children
-.TP
-.B \-i
-The maximum number of pending signals
-.TP
-.B \-l
-The maximum size that may be locked into memory
-.TP
-.B \-m
-The maximum resident set size (many systems do not honor this limit)
-.TP
-.B \-n
-The maximum number of open file descriptors (most systems do not
-allow this value to be set)
-.TP
-.B \-p
-The pipe size in 512-byte blocks (this may not be set)
-.TP
-.B \-q
-The maximum number of bytes in POSIX message queues
-.TP
-.B \-r
-The maximum real-time scheduling priority
-.TP
-.B \-s
-The maximum stack size
-.TP
-.B \-t
-The maximum amount of cpu time in seconds
-.TP
-.B \-u
-The maximum number of processes available to a single user
-.TP
-.B \-v
-The maximum amount of virtual memory available to the shell and, on
-some systems, to its children
-.TP
-.B \-x
-The maximum number of file locks
-.TP
-.B \-T
-The maximum number of threads
-.PD
-.PP
-If
-.I limit
-is given, and the
-.B \-a
-option is not used,
-\fIlimit\fP is the new value of the specified resource.
-If no option is given, then
-.B \-f
-is assumed.  Values are in 1024-byte increments, except for
-.BR \-t ,
-which is in seconds;
-.BR \-p ,
-which is in units of 512-byte blocks;
-and
-.BR \-T ,
-.BR \-b ,
-.BR \-n ,
-and
-.BR \-u ,
-which are unscaled values.
-The return status is 0 unless an invalid option or argument is supplied,
-or an error occurs while setting a new limit.
-.RE
-.TP
-\fBumask\fP [\fB\-p\fP] [\fB\-S\fP] [\fImode\fP]
-The user file-creation mask is set to 
-.IR mode .
-If
-.I mode
-begins with a digit, it
-is interpreted as an octal number; otherwise
-it is interpreted as a symbolic mode mask similar
-to that accepted by
-.IR chmod (1).
-If
-.I mode
-is omitted, the current value of the mask is printed.
-The
-.B \-S
-option causes the mask to be printed in symbolic form; the
-default output is an octal number.
-If the
-.B \-p
-option is supplied, and
-.I mode
-is omitted, the output is in a form that may be reused as input.
-The return status is 0 if the mode was successfully changed or if
-no \fImode\fP argument was supplied, and false otherwise.
-.TP
-\fBunalias\fP [\-\fBa\fP] [\fIname\fP ...]
-Remove each \fIname\fP from the list of defined aliases.  If
-.B \-a
-is supplied, all alias definitions are removed.  The return
-value is true unless a supplied
-.I name
-is not a defined alias.
-.TP
-\fBunset\fP [\-\fBfv\fP] [\-\fBn\fP] [\fIname\fP ...]
-For each
-.IR name ,
-remove the corresponding variable or function.
-If the
-.B \-v
-option is given, each
-.I name
-refers to a shell variable, and that variable is removed.
-Read-only variables may not be unset.
-If
-.B \-f
-is specified, each
-.I name
-refers to a shell function, and the function definition
-is removed.
-If the
-.B \-n
-option is supplied, and \fIname\fP is a variable with the \fInameref\fP
-attribute, \fIname\fP will be unset rather than the variable it
-references.
-\fB\-n\fP has no effect if the \fB\-f\fP option is supplied.
-If no options are supplied, each \fIname\fP refers to a variable; if
-there is no variable by that name, any function with that name is
-unset.
-Each unset variable or function is removed from the environment
-passed to subsequent commands.
-If any of
-.SM
-.BR COMP_WORDBREAKS ,
-.SM
-.BR RANDOM ,
-.SM
-.BR SECONDS ,
-.SM
-.BR LINENO ,
-.SM
-.BR HISTCMD ,
-.SM
-.BR FUNCNAME ,
-.SM
-.BR GROUPS ,
-or
-.SM
-.B DIRSTACK
-are unset, they lose their special properties, even if they are
-subsequently reset.  The exit status is true unless a
-.I name
-is readonly.
-.TP
-\fBwait\fP [\fB\--n\fP] [\fIn ...\fP]
-Wait for each specified process and return its termination status.
-Each
-.I n
-may be a process
-ID or a job specification; if a job spec is given, all processes
-in that job's pipeline are waited for.  If
-.I n
-is not given, all currently active child processes
-are waited for, and the return status is zero.
-If the \fB\--n\fP option is supplied, \fBwait\fP waits for any job to
-terminate and returns its exit status.
-If
-.I n
-specifies a non-existent process or job, the return status is
-127.  Otherwise, the return status is the exit status of the last
-process or job waited for.
-.\" bash_builtins
-.if \n(zZ=1 .ig zZ
-.SH "RESTRICTED SHELL"
-.\" rbash.1
-.zY
-.PP
-If
-.B bash
-is started with the name
-.BR rbash ,
-or the
-.B \-r
-option is supplied at invocation,
-the shell becomes restricted.
-A restricted shell is used to
-set up an environment more controlled than the standard shell.
-It behaves identically to
-.B bash
-with the exception that the following are disallowed or not performed:
-.IP \(bu
-changing directories with \fBcd\fP
-.IP \(bu
-setting or unsetting the values of
-.SM
-.BR SHELL ,
-.SM
-.BR PATH ,
-.SM
-.BR ENV ,
-or
-.SM
-.B BASH_ENV
-.IP \(bu
-specifying command names containing
-.B /
-.IP \(bu
-specifying a filename containing a
-.B /
-as an argument to the
-.B .
-builtin command
-.IP \(bu
-specifying a filename containing a slash as an argument to the
-.B \-p
-option to the
-.B hash
-builtin command
-.IP \(bu
-importing function definitions from the shell environment at startup
-.IP \(bu
-parsing the value of
-.SM
-.B SHELLOPTS
-from the shell environment at startup
-.IP \(bu
-redirecting output using the >, >|, <>, >&, &>, and >> redirection operators
-.IP \(bu
-using the
-.B exec
-builtin command to replace the shell with another command
-.IP \(bu
-adding or deleting builtin commands with the
-.B \-f
-and
-.B \-d
-options to the
-.B enable
-builtin command
-.IP \(bu
-using the \fBenable\fP builtin command to enable disabled shell builtins
-.IP \(bu
-specifying the
-.B \-p
-option to the
-.B command
-builtin command
-.IP \(bu
-turning off restricted mode with
-\fBset +r\fP or \fBset +o restricted\fP.
-.PP
-These restrictions are enforced after any startup files are read.
-.PP
-.ie \n(zY=1 When a command that is found to be a shell script is executed,
-.el \{ When a command that is found to be a shell script is executed
-(see
-.SM
-.B "COMMAND EXECUTION"
-above),
-\}
-.B rbash
-turns off any restrictions in the shell spawned to execute the
-script.
-.\" end of rbash.1
-.if \n(zY=1 .ig zY
-.SH "SEE ALSO"
-.PD 0
-.TP
-\fIBash Reference Manual\fP, Brian Fox and Chet Ramey
-.TP
-\fIThe Gnu Readline Library\fP, Brian Fox and Chet Ramey
-.TP
-\fIThe Gnu History Library\fP, Brian Fox and Chet Ramey
-.TP
-\fIPortable Operating System Interface (POSIX) Part 2: Shell and Utilities\fP, IEEE
-.TP
-\fIsh\fP(1), \fIksh\fP(1), \fIcsh\fP(1)
-.TP
-\fIemacs\fP(1), \fIvi\fP(1)
-.TP
-\fIreadline\fP(3)
-.PD
-.SH FILES
-.PD 0
-.TP
-.FN /bin/bash
-The \fBbash\fP executable
-.TP
-.FN /etc/profile
-The systemwide initialization file, executed for login shells
-.TP
-.FN ~/.bash_profile
-The personal initialization file, executed for login shells
-.TP
-.FN ~/.bashrc
-The individual per-interactive-shell startup file
-.TP
-.FN ~/.bash_logout
-The individual login shell cleanup file, executed when a login shell exits
-.TP
-.FN ~/.inputrc
-Individual \fIreadline\fP initialization file
-.PD
-.SH AUTHORS
-Brian Fox, Free Software Foundation
-.br
-bfox@gnu.org
-.PP
-Chet Ramey, Case Western Reserve University
-.br
-chet.ramey@case.edu
-.SH BUG REPORTS
-If you find a bug in
-.B bash,
-you should report it.  But first, you should
-make sure that it really is a bug, and that it appears in the latest
-version of
-.BR bash .
-The latest version is always available from
-\fIftp://ftp.gnu.org/pub/gnu/bash/\fP.
-.PP
-Once you have determined that a bug actually exists, use the
-.I bashbug
-command to submit a bug report.
-If you have a fix, you are encouraged to mail that as well!
-Suggestions and `philosophical' bug reports may be mailed
-to \fIbug-bash@gnu.org\fP or posted to the Usenet
-newsgroup
-.BR gnu.bash.bug .
-.PP
-ALL bug reports should include:
-.PP
-.PD 0
-.TP 20
-The version number of \fBbash\fR
-.TP
-The hardware and operating system
-.TP
-The compiler used to compile
-.TP
-A description of the bug behaviour
-.TP
-A short script or `recipe' which exercises the bug
-.PD
-.PP
-.I bashbug
-inserts the first three items automatically into the template
-it provides for filing a bug report.
-.PP
-Comments and bug reports concerning
-this manual page should be directed to
-.IR chet.ramey@case.edu .
-.SH BUGS
-.PP
-It's too big and too slow.
-.PP
-There are some subtle differences between 
-.B bash
-and traditional versions of
-.BR sh ,
-mostly because of the
-.SM
-.B POSIX
-specification.
-.PP
-Aliases are confusing in some uses.
-.PP
-Shell builtin commands and functions are not stoppable/restartable.
-.PP
-Compound commands and command sequences of the form `a ; b ; c'
-are not handled gracefully when process suspension is attempted.
-When a process is stopped, the shell immediately executes the next
-command in the sequence.
-It suffices to place the sequence of commands between
-parentheses to force it into a subshell, which may be stopped as
-a unit.
-.PP
-Array variables may not (yet) be exported.
-.PP
-There may be only one active coprocess at a time.
-.zZ
-.zY
diff --git a/doc/bashref.texi~ b/doc/bashref.texi~
deleted file mode 100644 (file)
index 5a3664f..0000000
+++ /dev/null
@@ -1,8655 +0,0 @@
-\input texinfo.tex @c -*- texinfo -*-
-@c %**start of header
-@setfilename bashref.info
-@settitle Bash Reference Manual
-
-@include version.texi
-@c %**end of header
-
-@copying
-This text is a brief description of the features that are present in
-the Bash shell (version @value{VERSION}, @value{UPDATED}).
-
-This is Edition @value{EDITION}, last updated @value{UPDATED},
-of @cite{The GNU Bash Reference Manual},
-for @code{Bash}, Version @value{VERSION}.
-
-Copyright @copyright{} 1988--2013 Free Software Foundation, Inc.
-
-@quotation
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.3 or
-any later version published by the Free Software Foundation; with no
-Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-A copy of the license is included in the section entitled
-``GNU Free Documentation License''.
-@end quotation
-@end copying
-
-@defcodeindex bt
-@defcodeindex rw
-@set BashFeatures
-
-@dircategory Basics
-@direntry
-* Bash: (bash).                     The GNU Bourne-Again SHell.
-@end direntry
-
-@finalout
-
-@titlepage
-@title Bash Reference Manual
-@subtitle Reference Documentation for Bash
-@subtitle Edition @value{EDITION}, for @code{Bash} Version @value{VERSION}.
-@subtitle @value{UPDATED-MONTH}
-@author Chet Ramey, Case Western Reserve University
-@author Brian Fox, Free Software Foundation
-
-@page
-@vskip 0pt plus 1filll
-@insertcopying
-
-@end titlepage
-
-@contents
-
-@ifnottex
-@node Top, Introduction, (dir), (dir)
-@top Bash Features
-
-This text is a brief description of the features that are present in
-the Bash shell (version @value{VERSION}, @value{UPDATED}).
-The Bash home page is @url{http://www.gnu.org/software/bash/}.
-
-This is Edition @value{EDITION}, last updated @value{UPDATED},
-of @cite{The GNU Bash Reference Manual},
-for @code{Bash}, Version @value{VERSION}.
-
-Bash contains features that appear in other popular shells, and some
-features that only appear in Bash.  Some of the shells that Bash has
-borrowed concepts from are the Bourne Shell (@file{sh}), the Korn Shell
-(@file{ksh}), and the C-shell (@file{csh} and its successor,
-@file{tcsh}).  The following menu breaks the features up into
-categories, noting which features were inspired by other shells and
-which are specific to Bash.
-
-This manual is meant as a brief introduction to features found in
-Bash.  The Bash manual page should be used as the definitive
-reference on shell behavior.
-
-@menu
-* Introduction::               An introduction to the shell.
-* Definitions::                        Some definitions used in the rest of this
-                               manual.
-* Basic Shell Features::       The shell "building blocks".
-* Shell Builtin Commands::     Commands that are a part of the shell.
-* Shell Variables::            Variables used or set by Bash.
-* Bash Features::              Features found only in Bash.
-* Job Control::                        What job control is and how Bash allows you
-                               to use it.
-* Command Line Editing::       Chapter describing the command line
-                               editing features.
-* Using History Interactively::        Command History Expansion
-* Installing Bash::            How to build and install Bash on your system.
-* Reporting Bugs::             How to report bugs in Bash.
-* Major Differences From The Bourne Shell::    A terse list of the differences
-                                               between Bash and historical
-                                               versions of /bin/sh.
-* GNU Free Documentation License::     Copying and sharing this documentation.
-* Indexes::                    Various indexes for this manual.
-@end menu
-@end ifnottex
-
-@node Introduction
-@chapter Introduction
-@menu
-* What is Bash?::              A short description of Bash.
-* What is a shell?::           A brief introduction to shells.
-@end menu
-
-@node What is Bash?
-@section What is Bash?
-
-Bash is the shell, or command language interpreter,
-for the @sc{gnu} operating system.
-The name is an acronym for the @samp{Bourne-Again SHell},
-a pun on Stephen Bourne, the author of the direct ancestor of
-the current Unix shell @code{sh}, 
-which appeared in the Seventh Edition Bell Labs Research version
-of Unix.
-
-Bash is largely compatible with @code{sh} and incorporates useful
-features from the Korn shell @code{ksh} and the C shell @code{csh}.
-It is intended to be a conformant implementation of the @sc{ieee}
-@sc{posix} Shell and Tools portion of the @sc{ieee} @sc{posix}
-specification (@sc{ieee} Standard 1003.1).
-It offers functional improvements over @code{sh} for both interactive and
-programming use.
-
-While the @sc{gnu} operating system provides other shells, including
-a version of @code{csh}, Bash is the default shell.
-Like other @sc{gnu} software, Bash is quite portable.  It currently runs
-on nearly every version of Unix and a few other operating systems @minus{}
-independently-supported ports exist for @sc{ms-dos}, @sc{os/2},
-and Windows platforms.
-
-@node What is a shell?
-@section What is a shell?
-
-At its base, a shell is simply a macro processor that executes
-commands.  The term macro processor means functionality where text
-and symbols are expanded to create larger expressions.
-
-A Unix shell is both a command interpreter and a programming
-language.  As a command interpreter, the shell provides the user
-interface to the rich set of @sc{gnu} utilities.  The programming
-language features allow these utilities to be combined.
-Files containing commands can be created, and become
-commands themselves.  These new commands have the same status as
-system commands in directories such as @file{/bin}, allowing users
-or groups to establish custom environments to automate their common
-tasks.
-
-Shells may be used interactively or non-interactively.  In
-interactive mode, they accept input typed from the keyboard.
-When executing non-interactively, shells execute commands read
-from a file.
-
-A shell allows execution of @sc{gnu} commands, both synchronously and
-asynchronously.
-The shell waits for synchronous commands to complete before accepting
-more input; asynchronous commands continue to execute in parallel
-with the shell while it reads and executes additional commands.
-The @dfn{redirection} constructs permit
-fine-grained control of the input and output of those commands.
-Moreover, the shell allows control over the contents of commands'
-environments.
-
-Shells also provide a small set of built-in
-commands (@dfn{builtins}) implementing functionality impossible
-or inconvenient to obtain via separate utilities.
-For example, @code{cd}, @code{break}, @code{continue}, and
-@code{exec} cannot be implemented outside of the shell because
-they directly manipulate the shell itself.
-The @code{history}, @code{getopts}, @code{kill}, or @code{pwd}
-builtins, among others, could be implemented in separate utilities,
-but they are more convenient to use as builtin commands.
-All of the shell builtins are described in
-subsequent sections.
-
-While executing commands is essential, most of the power (and
-complexity) of shells is due to their embedded programming
-languages.  Like any high-level language, the shell provides
-variables, flow control constructs, quoting, and functions. 
-
-Shells offer features geared specifically for
-interactive use rather than to augment the programming language. 
-These interactive features include job control, command line
-editing, command history and aliases.  Each of these features is
-described in this manual.
-
-@node Definitions
-@chapter Definitions
-These definitions are used throughout the remainder of this manual.
-
-@table @code
-
-@item POSIX
-@cindex POSIX
-A family of open system standards based on Unix.  Bash
-is primarily concerned with the Shell and Utilities portion of the
-@sc{posix} 1003.1 standard. 
-
-@item blank
-A space or tab character.
-
-@item builtin
-@cindex builtin
-A command that is implemented internally by the shell itself, rather
-than by an executable program somewhere in the file system.
-
-@item control operator
-@cindex control operator
-A @code{token} that performs a control function.  It is a @code{newline}
-or one of the following:
-@samp{||}, @samp{&&}, @samp{&}, @samp{;}, @samp{;;},
-@samp{|}, @samp{|&}, @samp{(}, or @samp{)}.
-
-@item exit status
-@cindex exit status
-The value returned by a command to its caller.  The value is restricted
-to eight bits, so the maximum value is 255.
-
-@item field
-@cindex field
-A unit of text that is the result of one of the shell expansions.  After
-expansion, when executing a command, the resulting fields are used as
-the command name and arguments.
-
-@item filename
-@cindex filename
-A string of characters used to identify a file.
-
-@item job
-@cindex job
-A set of processes comprising a pipeline, and any processes descended
-from it, that are all in the same process group.
-
-@item job control
-@cindex job control
-A mechanism by which users can selectively stop (suspend) and restart
-(resume) execution of processes.
-
-@item metacharacter
-@cindex metacharacter
-A character that, when unquoted, separates words.  A metacharacter is
-a @code{blank} or one of the following characters:
-@samp{|}, @samp{&}, @samp{;}, @samp{(}, @samp{)}, @samp{<}, or
-@samp{>}.
-
-@item name
-@cindex name
-@cindex identifier
-A @code{word} consisting solely of letters, numbers, and underscores,
-and beginning with a letter or underscore.  @code{Name}s are used as
-shell variable and function names.
-Also referred to as an @code{identifier}.
-
-@item operator
-@cindex operator, shell
-A @code{control operator} or a @code{redirection operator}.
-@xref{Redirections}, for a list of redirection operators.
-Operators contain at least one unquoted @code{metacharacter}.
-
-@item process group
-@cindex process group
-A collection of related processes each having the same process
-group @sc{id}.
-
-@item process group ID
-@cindex process group ID
-A unique identifier that represents a @code{process group}
-during its lifetime.
-
-@item reserved word
-@cindex reserved word
-A @code{word} that has a special meaning to the shell.  Most reserved
-words introduce shell flow control constructs, such as @code{for} and
-@code{while}.
-
-@item return status
-@cindex return status
-A synonym for @code{exit status}.
-
-@item signal
-@cindex signal
-A mechanism by which a process may be notified by the kernel
-of an event occurring in the system.
-
-@item special builtin
-@cindex special builtin
-A shell builtin command that has been classified as special by the
-@sc{posix} standard.
-
-@item token
-@cindex token
-A sequence of characters considered a single unit by the shell.
-It is either a @code{word} or an @code{operator}.
-
-@item word
-@cindex word
-A sequence of characters treated as a unit by the shell.
-Words may not include unquoted @code{metacharacters}.
-@end table
-
-@node Basic Shell Features
-@chapter Basic Shell Features
-@cindex Bourne shell
-
-Bash is an acronym for @samp{Bourne-Again SHell}.
-The Bourne shell is
-the traditional Unix shell originally written by Stephen Bourne.
-All of the Bourne shell builtin commands are available in Bash,
-The rules for evaluation and quoting are taken from the @sc{posix}
-specification for the `standard' Unix shell.
-
-This chapter briefly summarizes the shell's `building blocks':
-commands, control structures, shell functions, shell @i{parameters},
-shell expansions,
-@i{redirections}, which are a way to direct input and output from
-and to named files, and how the shell executes commands.
-
-@menu
-* Shell Syntax::               What your input means to the shell.
-* Shell Commands::             The types of commands you can use.
-* Shell Functions::            Grouping commands by name.
-* Shell Parameters::           How the shell stores values.
-* Shell Expansions::           How Bash expands parameters and the various
-                               expansions available.
-* Redirections::               A way to control where input and output go.
-* Executing Commands::         What happens when you run a command.
-* Shell Scripts::              Executing files of shell commands.
-@end menu
-
-@node Shell Syntax
-@section Shell Syntax
-@menu
-* Shell Operation::    The basic operation of the shell.
-* Quoting::            How to remove the special meaning from characters.
-* Comments::           How to specify comments.
-@end menu
-
-When the shell reads input, it proceeds through a
-sequence of operations.  If the input indicates the beginning of a
-comment, the shell ignores the comment symbol (@samp{#}), and the rest
-of that line.
-                                
-Otherwise, roughly speaking,  the shell reads its input and
-divides the input into words and operators, employing the quoting rules
-to select which meanings to assign various words and characters.
-
-The shell then parses these tokens into commands and other constructs,
-removes the special meaning of certain words or characters, expands
-others, redirects input and output as needed, executes the specified
-command, waits for the command's exit status, and makes that exit status
-available for further inspection or processing.
-
-@node Shell Operation
-@subsection Shell Operation
-
-The following is a brief description of the shell's operation when it
-reads and executes a command.  Basically, the shell does the
-following:
-
-@enumerate
-@item
-Reads its input from a file (@pxref{Shell Scripts}), from a string
-supplied as an argument to the @option{-c} invocation option
-(@pxref{Invoking Bash}), or from the user's terminal.
-
-@item
-Breaks the input into words and operators, obeying the quoting rules
-described in @ref{Quoting}.  These tokens are separated by
-@code{metacharacters}.  Alias expansion is performed by this step
-(@pxref{Aliases}).
-
-@item
-Parses the tokens into simple and compound commands
-(@pxref{Shell Commands}).
-
-@item
-Performs the various shell expansions (@pxref{Shell Expansions}), breaking
-the expanded tokens into lists of filenames (@pxref{Filename Expansion})
-and commands and arguments.
-
-@item
-Performs any necessary redirections (@pxref{Redirections}) and removes
-the redirection operators and their operands from the argument list.
-
-@item
-Executes the command (@pxref{Executing Commands}).
-
-@item
-Optionally waits for the command to complete and collects its exit
-status (@pxref{Exit Status}).
-
-@end enumerate
-
-@node Quoting
-@subsection Quoting
-@cindex quoting
-@menu
-* Escape Character::   How to remove the special meaning from a single
-                       character.
-* Single Quotes::      How to inhibit all interpretation of a sequence
-                       of characters.
-* Double Quotes::      How to suppress most of the interpretation of a
-                       sequence of characters.
-* ANSI-C Quoting::     How to expand ANSI-C sequences in quoted strings.
-* Locale Translation:: How to translate strings into different languages.
-@end menu
-
-Quoting is used to remove the special meaning of certain
-characters or words to the shell.  Quoting can be used to
-disable special treatment for special characters, to prevent
-reserved words from being recognized as such, and to prevent
-parameter expansion.
-
-Each of the shell metacharacters (@pxref{Definitions})
-has special meaning to the shell and must be quoted if it is to
-represent itself.
-When the command history expansion facilities are being used
-(@pxref{History Interaction}), the
-@var{history expansion} character, usually @samp{!}, must be quoted
-to prevent history expansion.  @xref{Bash History Facilities}, for
-more details concerning history expansion.
-
-There are three quoting mechanisms: the
-@var{escape character}, single quotes, and double quotes.
-
-@node Escape Character
-@subsubsection Escape Character
-A non-quoted backslash @samp{\} is the Bash escape character.
-It preserves the literal value of the next character that follows,
-with the exception of @code{newline}.  If a @code{\newline} pair
-appears, and the backslash itself is not quoted, the @code{\newline}
-is treated as a line continuation (that is, it is removed from
-the input stream and effectively ignored).
-
-@node Single Quotes
-@subsubsection Single Quotes
-
-Enclosing characters in single quotes (@samp{'}) preserves the literal value
-of each character within the quotes.  A single quote may not occur
-between single quotes, even when preceded by a backslash.
-
-@node Double Quotes
-@subsubsection Double Quotes
-
-Enclosing characters in double quotes (@samp{"}) preserves the literal value
-of all characters within the quotes, with the exception of
-@samp{$}, @samp{`}, @samp{\},
-and, when history expansion is enabled, @samp{!}.
-The characters @samp{$} and @samp{`}
-retain their special meaning within double quotes (@pxref{Shell Expansions}).
-The backslash retains its special meaning only when followed by one of
-the following characters:
-@samp{$}, @samp{`}, @samp{"}, @samp{\}, or @code{newline}.
-Within double quotes, backslashes that are followed by one of these
-characters are removed.  Backslashes preceding characters without a
-special meaning are left unmodified.
-A double quote may be quoted within double quotes by preceding it with
-a backslash.
-If enabled, history expansion will be performed unless an @samp{!}
-appearing in double quotes is escaped using a backslash.
-The backslash preceding the @samp{!} is not removed.
-
-The special parameters @samp{*} and @samp{@@} have special meaning
-when in double quotes (@pxref{Shell Parameter Expansion}).
-
-@node ANSI-C Quoting
-@subsubsection ANSI-C Quoting
-@cindex quoting, ANSI
-
-Words of the form @code{$'@var{string}'} are treated specially.  The
-word expands to @var{string}, with backslash-escaped characters replaced
-as specified by the ANSI C standard.  Backslash escape sequences, if
-present, are decoded as follows:
-
-@table @code
-@item \a
-alert (bell)
-@item \b
-backspace
-@item \e
-@itemx \E
-an escape character (not ANSI C)
-@item \f
-form feed
-@item \n
-newline
-@item \r
-carriage return
-@item \t
-horizontal tab
-@item \v
-vertical tab
-@item \\
-backslash
-@item \'
-single quote
-@item \"
-double quote
-@item \@var{nnn}
-the eight-bit character whose value is the octal value @var{nnn}
-(one to three digits)
-@item \x@var{HH}
-the eight-bit character whose value is the hexadecimal value @var{HH}
-(one or two hex digits)
-@item \u@var{HHHH}
-the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
-@var{HHHH} (one to four hex digits)
-@item \U@var{HHHHHHHH}
-the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
-@var{HHHHHHHH} (one to eight hex digits)
-@item \c@var{x}
-a control-@var{x} character
-@end table
-
-@noindent
-The expanded result is single-quoted, as if the dollar sign had not
-been present.
-
-@node Locale Translation
-@subsubsection Locale-Specific Translation
-@cindex localization
-@cindex internationalization
-@cindex native languages
-@cindex translation, native languages
-
-A double-quoted string preceded by a dollar sign (@samp{$}) will cause
-the string to be translated according to the current locale.
-If the current locale is @code{C} or @code{POSIX}, the dollar sign
-is ignored.
-If the string is translated and replaced, the replacement is
-double-quoted.
-
-@vindex LC_MESSAGES
-@vindex TEXTDOMAIN
-@vindex TEXTDOMAINDIR
-Some systems use the message catalog selected by the @env{LC_MESSAGES}
-shell variable.  Others create the name of the message catalog from the
-value of the @env{TEXTDOMAIN} shell variable, possibly adding a
-suffix of @samp{.mo}.  If you use the @env{TEXTDOMAIN} variable, you
-may need to set the @env{TEXTDOMAINDIR} variable to the location of
-the message catalog files.  Still others use both variables in this
-fashion:
-@env{TEXTDOMAINDIR}/@env{LC_MESSAGES}/LC_MESSAGES/@env{TEXTDOMAIN}.mo.
-
-@node Comments
-@subsection Comments
-@cindex comments, shell
-
-In a non-interactive shell, or an interactive shell in which the
-@code{interactive_comments} option to the @code{shopt}
-builtin is enabled (@pxref{The Shopt Builtin}),
-a word beginning with @samp{#}
-causes that word and all remaining characters on that line to
-be ignored.  An interactive shell without the @code{interactive_comments}
-option enabled does not allow comments.  The @code{interactive_comments}
-option is on by default in interactive shells.
-@xref{Interactive Shells}, for a description of what makes
-a shell interactive.
-
-@node Shell Commands
-@section Shell Commands
-@cindex commands, shell
-
-A simple shell command such as @code{echo a b c} consists of the command
-itself followed by arguments, separated by spaces.
-
-More complex shell commands are composed of simple commands arranged together
-in a variety of ways: in a pipeline in which the output of one command
-becomes the input of a second, in a loop or conditional construct, or in
-some other grouping.
-
-@menu
-* Simple Commands::            The most common type of command.
-* Pipelines::                  Connecting the input and output of several
-                               commands.
-* Lists::                      How to execute commands sequentially.
-* Compound Commands::          Shell commands for control flow.
-* Coprocesses::                        Two-way communication between commands.
-* GNU Parallel::               Running commands in parallel.
-@end menu
-
-@node Simple Commands
-@subsection Simple Commands
-@cindex commands, simple
-
-A simple command is the kind of command encountered most often.
-It's just a sequence of words separated by @code{blank}s, terminated
-by one of the shell's control operators (@pxref{Definitions}).  The
-first word generally specifies a command to be executed, with the
-rest of the words being that command's arguments.
-
-The return status (@pxref{Exit Status}) of a simple command is
-its exit status as provided
-by the @sc{posix} 1003.1 @code{waitpid} function, or 128+@var{n} if
-the command was terminated by signal @var{n}.
-
-@node Pipelines
-@subsection Pipelines
-@cindex pipeline
-@cindex commands, pipelines
-
-A @code{pipeline} is a sequence of simple commands separated by one of
-the control operators @samp{|} or @samp{|&}.
-
-@rwindex time
-@rwindex !
-@cindex command timing
-The format for a pipeline is
-@example
-[time [-p]] [!] @var{command1} [ | or |& @var{command2} ] @dots{}
-@end example
-
-@noindent
-The output of each command in the pipeline is connected via a pipe
-to the input of the next command.
-That is, each command reads the previous command's output.  This
-connection is performed before any redirections specified by the
-command.
-
-If @samp{|&} is used, @var{command1}'s standard output and standard error
-are connected to
-@var{command2}'s standard input through the pipe;
-it is shorthand for @code{2>&1 |}.
-This implicit redirection of the standard error is
-performed after any redirections specified by the command.
-
-The reserved word @code{time} causes timing statistics
-to be printed for the pipeline once it finishes.
-The statistics currently consist of elapsed (wall-clock) time and
-user and system time consumed by the command's execution.
-The @option{-p} option changes the output format to that specified
-by @sc{posix}.
-When the shell is in @sc{posix} mode (@pxref{Bash POSIX Mode}),
-it does not recognize @code{time} as a reserved word if the next
-token begins with a @samp{-}.
-The @env{TIMEFORMAT} variable may be set to a format string that
-specifies how the timing information should be displayed.
-@xref{Bash Variables}, for a description of the available formats.
-The use of @code{time} as a reserved word permits the timing of
-shell builtins, shell functions, and pipelines.  An external
-@code{time} command cannot time these easily.
-
-When the shell is in @sc{posix} mode (@pxref{Bash POSIX Mode}), @code{time}
-may be followed by a newline.  In this case, the shell displays the
-total user and system time consumed by the shell and its children.
-The @env{TIMEFORMAT} variable may be used to specify the format of
-the time information.
-
-If the pipeline is not executed asynchronously (@pxref{Lists}), the
-shell waits for all commands in the pipeline to complete.
-
-Each command in a pipeline is executed in its own subshell
-(@pxref{Command Execution Environment}).  The exit
-status of a pipeline is the exit status of the last command in the
-pipeline, unless the @code{pipefail} option is enabled
-(@pxref{The Set Builtin}).
-If @code{pipefail} is enabled, the pipeline's return status is the
-value of the last (rightmost) command to exit with a non-zero status,
-or zero if all commands exit successfully.
-If the reserved word @samp{!} precedes the pipeline, the
-exit status is the logical negation of the exit status as described
-above.
-The shell waits for all commands in the pipeline to terminate before
-returning a value.
-
-@node Lists
-@subsection Lists of Commands
-@cindex commands, lists
-
-A @code{list} is a sequence of one or more pipelines separated by one
-of the operators @samp{;}, @samp{&}, @samp{&&}, or @samp{||},
-and optionally terminated by one of @samp{;}, @samp{&}, or a
-@code{newline}.
-
-Of these list operators, @samp{&&} and @samp{||}
-have equal precedence, followed by @samp{;} and @samp{&},
-which have equal precedence.
-
-A sequence of one or more newlines may appear in a @code{list}
-to delimit commands, equivalent to a semicolon.
-
-If a command is terminated by the control operator @samp{&},
-the shell executes the command asynchronously in a subshell.
-This is known as executing the command in the @var{background}.
-The shell does not wait for the command to finish, and the return
-status is 0 (true).
-When job control is not active (@pxref{Job Control}),
-the standard input for asynchronous commands, in the absence of any
-explicit redirections, is redirected from @code{/dev/null}.
-
-Commands separated by a @samp{;} are executed sequentially; the shell
-waits for each command to terminate in turn.  The return status is the
-exit status of the last command executed.
-
-@sc{and} and @sc{or} lists are sequences of one or more pipelines
-separated by the control operators @samp{&&} and @samp{||},
-respectively.  @sc{and} and @sc{or} lists are executed with left
-associativity.
-
-An @sc{and} list has the form
-@example
-@var{command1} && @var{command2}
-@end example
-
-@noindent
-@var{command2} is executed if, and only if, @var{command1}
-returns an exit status of zero.
-
-An @sc{or} list has the form
-@example
-@var{command1} || @var{command2}
-@end example
-
-@noindent
-@var{command2} is executed if, and only if, @var{command1}
-returns a non-zero exit status.
-
-The return status of
-@sc{and} and @sc{or} lists is the exit status of the last command
-executed in the list.
-
-@node Compound Commands
-@subsection Compound Commands
-@cindex commands, compound
-
-@menu
-* Looping Constructs::         Shell commands for iterative action.
-* Conditional Constructs::     Shell commands for conditional execution.
-* Command Grouping::           Ways to group commands.
-@end menu
-
-Compound commands are the shell programming constructs.
-Each construct begins with a reserved word or control operator and is
-terminated by a corresponding reserved word or operator.
-Any redirections (@pxref{Redirections}) associated with a compound command
-apply to all commands within that compound command unless explicitly overridden.
-
-In most cases a list of commands in a compound command's description may be
-separated from the rest of the command by one or more newlines, and may be
-followed by a newline in place of a semicolon.
-
-Bash provides looping constructs, conditional commands, and mechanisms
-to group commands and execute them as a unit.
-
-@node Looping Constructs
-@subsubsection Looping Constructs
-@cindex commands, looping
-
-Bash supports the following looping constructs.
-
-Note that wherever a @samp{;} appears in the description of a
-command's syntax, it may be replaced with one or more newlines.
-
-@table @code
-@item until
-@rwindex until
-@rwindex do
-@rwindex done
-The syntax of the @code{until} command is:
-
-@example
-until @var{test-commands}; do @var{consequent-commands}; done
-@end example
-
-Execute @var{consequent-commands} as long as
-@var{test-commands} has an exit status which is not zero.
-The return status is the exit status of the last command executed
-in @var{consequent-commands}, or zero if none was executed.
-
-@item while
-@rwindex while
-The syntax of the @code{while} command is:
-
-@example
-while @var{test-commands}; do @var{consequent-commands}; done
-@end example
-
-Execute @var{consequent-commands} as long as
-@var{test-commands} has an exit status of zero.
-The return status is the exit status of the last command executed
-in @var{consequent-commands}, or zero if none was executed.
-
-@item for
-@rwindex for
-The syntax of the @code{for} command is:
-
-@example
-for @var{name} [ [in [@var{words} @dots{}] ] ; ] do @var{commands}; done
-@end example
-
-Expand @var{words}, and execute @var{commands} once for each member
-in the resultant list, with @var{name} bound to the current member.
-If @samp{in @var{words}} is not present, the @code{for} command
-executes the @var{commands} once for each positional parameter that is
-set, as if @samp{in "$@@"} had been specified
-(@pxref{Special Parameters}).
-The return status is the exit status of the last command that executes.
-If there are no items in the expansion of @var{words}, no commands are
-executed, and the return status is zero.
-
-An alternate form of the @code{for} command is also supported:
-
-@example
-for (( @var{expr1} ; @var{expr2} ; @var{expr3} )) ; do @var{commands} ; done
-@end example
-
-First, the arithmetic expression @var{expr1} is evaluated according
-to the rules described below (@pxref{Shell Arithmetic}).
-The arithmetic expression @var{expr2} is then evaluated repeatedly
-until it evaluates to zero.   
-Each time @var{expr2} evaluates to a non-zero value, @var{commands} are
-executed and the arithmetic expression @var{expr3} is evaluated.       
-If any expression is omitted, it behaves as if it evaluates to 1.
-The return value is the exit status of the last command in @var{commands}
-that is executed, or false if any of the expressions is invalid.
-@end table
-
-The @code{break} and @code{continue} builtins (@pxref{Bourne Shell Builtins})
-may be used to control loop execution.
-
-@node Conditional Constructs
-@subsubsection Conditional Constructs
-@cindex commands, conditional
-
-@table @code
-@item if
-@rwindex if
-@rwindex then
-@rwindex else
-@rwindex elif
-@rwindex fi
-The syntax of the @code{if} command is:
-
-@example
-if @var{test-commands}; then
-  @var{consequent-commands};
-[elif @var{more-test-commands}; then
-  @var{more-consequents};]
-[else @var{alternate-consequents};]
-fi
-@end example
-
-The @var{test-commands} list is executed, and if its return status is zero,
-the @var{consequent-commands} list is executed.
-If @var{test-commands} returns a non-zero status, each @code{elif} list
-is executed in turn, and if its exit status is zero,
-the corresponding @var{more-consequents} is executed and the   
-command completes.
-If @samp{else @var{alternate-consequents}} is present, and
-the final command in the final @code{if} or @code{elif} clause
-has a non-zero exit status, then @var{alternate-consequents} is executed.
-The return status is the exit status of the last command executed, or
-zero if no condition tested true.
-
-@item case
-@rwindex case
-@rwindex in
-@rwindex esac
-The syntax of the @code{case} command is:
-
-@example
-case @var{word} in [ [(] @var{pattern} [| @var{pattern}]@dots{}) @var{command-list} ;;]@dots{} esac
-@end example
-
-@code{case} will selectively execute the @var{command-list} corresponding to
-the first @var{pattern} that matches @var{word}.
-If the shell option @code{nocasematch}
-(see the description of @code{shopt} in @ref{The Shopt Builtin})
-is enabled, the match is performed without regard to the case
-of alphabetic characters.
-The @samp{|} is used to separate multiple patterns, and the @samp{)}
-operator terminates a pattern list.
-A list of patterns and an associated command-list is known
-as a @var{clause}.
-
-Each clause must be terminated with @samp{;;}, @samp{;&}, or @samp{;;&}.
-The @var{word} undergoes tilde expansion, parameter expansion, command
-substitution, arithmetic expansion, and quote removal before matching is
-attempted.  Each @var{pattern} undergoes tilde expansion, parameter
-expansion, command substitution, and arithmetic expansion.
-
-There may be an arbitrary number of @code{case} clauses, each terminated
-by a @samp{;;}, @samp{;&}, or @samp{;;&}.
-The first pattern that matches determines the
-command-list that is executed.
-It's a common idiom to use @samp{*} as the final pattern to define the
-default case, since that pattern will always match.
-
-Here is an example using @code{case} in a script that could be used to
-describe one interesting feature of an animal:
-
-@example
-echo -n "Enter the name of an animal: "
-read ANIMAL
-echo -n "The $ANIMAL has "
-case $ANIMAL in
-  horse | dog | cat) echo -n "four";;
-  man | kangaroo ) echo -n "two";;
-  *) echo -n "an unknown number of";;
-esac
-echo " legs."
-@end example
-
-@noindent
-
-If the @samp{;;} operator is used, no subsequent matches are attempted after
-the first pattern match.
-Using @samp{;&}  in place of @samp{;;} causes execution to continue with
-the @var{command-list} associated with the next clause, if any.
-Using @samp{;;&} in place of @samp{;;} causes the shell to test the patterns
-in the next clause, if any, and execute any associated @var{command-list}
-on a successful match.
-
-The return status is zero if no @var{pattern} is matched.  Otherwise, the
-return status is the exit status of the @var{command-list} executed.
-
-@item select
-@rwindex select
-
-The @code{select} construct allows the easy generation of menus.
-It has almost the same syntax as the @code{for} command:
-
-@example
-select @var{name} [in @var{words} @dots{}]; do @var{commands}; done
-@end example
-
-The list of words following @code{in} is expanded, generating a list
-of items.  The set of expanded words is printed on the standard
-error output stream, each preceded by a number.  If the
-@samp{in @var{words}} is omitted, the positional parameters are printed,
-as if @samp{in "$@@"} had been specified.
-The @env{PS3} prompt is then displayed and a line is read from the
-standard input.
-If the line consists of a number corresponding to one of the displayed
-words, then the value of @var{name} is set to that word.
-If the line is empty, the words and prompt are displayed again.
-If @code{EOF} is read, the @code{select} command completes.
-Any other value read causes @var{name} to be set to null.
-The line read is saved in the variable @env{REPLY}.
-
-The @var{commands} are executed after each selection until a
-@code{break} command is executed, at which
-point the @code{select} command completes.
-
-Here is an example that allows the user to pick a filename from the
-current directory, and displays the name and index of the file
-selected.
-
-@example
-select fname in *;
-do
-       echo you picked $fname \($REPLY\)
-       break;
-done
-@end example
-
-@item ((@dots{}))
-@example
-(( @var{expression} ))
-@end example
-
-The arithmetic @var{expression} is evaluated according to the rules
-described below (@pxref{Shell Arithmetic}).
-If the value of the expression is non-zero, the return status is 0;
-otherwise the return status is 1.  This is exactly equivalent to
-@example
-let "@var{expression}"
-@end example
-@noindent
-@xref{Bash Builtins}, for a full description of the @code{let} builtin.
-
-@item [[@dots{}]]
-@rwindex [[
-@rwindex ]]
-@example
-[[ @var{expression} ]]
-@end example
-
-Return a status of 0 or 1 depending on the evaluation of
-the conditional expression @var{expression}.
-Expressions are composed of the primaries described below in
-@ref{Bash Conditional Expressions}.
-Word splitting and filename expansion are not performed on the words
-between the @code{[[} and @code{]]}; tilde expansion, parameter and
-variable expansion, arithmetic expansion, command substitution, process
-substitution, and quote removal are performed.
-Conditional operators such as @samp{-f} must be unquoted to be recognized
-as primaries.
-
-When used with @code{[[}, the @samp{<} and @samp{>} operators sort
-lexicographically using the current locale.
-
-When the @samp{==} and @samp{!=} operators are used, the string to the
-right of the operator is considered a pattern and matched according
-to the rules described below in @ref{Pattern Matching}.
-The @samp{=} operator is identical to @samp{==}.
-If the shell option @code{nocasematch}
-(see the description of @code{shopt} in @ref{The Shopt Builtin})
-is enabled, the match is performed without regard to the case
-of alphabetic characters.
-The return value is 0 if the string matches (@samp{==}) or does not
-match (@samp{!=})the pattern, and 1 otherwise.
-Any part of the pattern may be quoted to force the quoted portion
-to be matched as a string.
-
-An additional binary operator, @samp{=~}, is available, with the same
-precedence as @samp{==} and @samp{!=}.
-When it is used, the string to the right of the operator is considered
-an extended regular expression and matched accordingly (as in @i{regex}3)).  
-The return value is 0 if the string matches
-the pattern, and 1 otherwise.
-If the regular expression is syntactically incorrect, the conditional
-expression's return value is 2.
-If the shell option @code{nocasematch}
-(see the description of @code{shopt} in @ref{The Shopt Builtin})
-is enabled, the match is performed without regard to the case
-of alphabetic characters.
-Any part of the pattern may be quoted to force the quoted portion
-to be matched as a string.
-Bracket expressions in regular expressions must be treated carefully,
-since normal quoting characters lose their meanings between brackets.
-If the pattern is stored in a shell variable, quoting the variable
-expansion forces the entire pattern to be matched as a string.
-Substrings matched by parenthesized subexpressions within the regular
-expression are saved in the array variable @code{BASH_REMATCH}.
-The element of @code{BASH_REMATCH} with index 0 is the portion of the string
-matching the entire regular expression.
-The element of @code{BASH_REMATCH} with index @var{n} is the portion of the
-string matching the @var{n}th parenthesized subexpression.
-
-For example, the following will match a line
-(stored in the shell variable @var{line})
-if there is a sequence of characters in the value consisting of
-any number, including zero, of 
-space characters, zero or one instances of @samp{a}, then a @samp{b}:
-@example
-[[ $line =~ [[:space:]]*(a)?b ]]
-@end example
-
-@noindent
-That means values like @samp{aab} and @samp{  aaaaaab} will match, as
-will a line containing a @samp{b} anywhere in its value.
-
-Storing the regular expression in a shell variable is often a useful
-way to avoid problems with quoting characters that are special to the
-shell.
-It is sometimes difficult to specify a regular expression literally
-without using quotes, or to keep track of the quoting used by regular
-expressions while paying attention to the shell's quote removal.
-Using a shell variable to store the pattern decreases these problems.
-For example, the following is equivalent to the above:
-@example
-pattern='[[:space:]]*(a)?b'
-[[ $line =~ $pattern ]]
-@end example
-
-@noindent
-If you want to match a character that's special to the regular expression
-grammar, it has to be quoted to remove its special meaning.
-This means that in the pattern @samp{xxx.txt}, the @samp{.} matches any
-character in the string (its usual regular expression meaning), but in the
-pattern @samp{"xxx.txt"} it can only match a literal @samp{.}.
-Shell programmers should take special care with backslashes, since backslashes
-are used both by the shell and regular expressions to remove the special
-meaning from the following character.
-The following two sets of commands are @emph{not} equivalent:
-@example
-pattern='\.'
-
-[[ . =~ $pattern ]]
-[[ . =~ \. ]]
-
-[[ . =~ "$pattern" ]]
-[[ . =~ '\.' ]]
-@end example
-
-@noindent
-The first two matches will succeed, but the second two will not, because
-in the second two the backslash will be part of the pattern to be matched.
-In the first two examples, the backslash removes the special meaning from
-@samp{.}, so the literal @samp{.} matches.
-If the string in the first examples were anything other than @samp{.}, say
-@samp{a}, the pattern would not match, because the quoted @samp{.} in the
-pattern loses its special meaning of matching any single character.
-
-Expressions may be combined using the following operators, listed
-in decreasing order of precedence:
-
-@table @code
-@item ( @var{expression} )
-Returns the value of @var{expression}.
-This may be used to override the normal precedence of operators.
-
-@item ! @var{expression}
-True if @var{expression} is false.
-
-@item @var{expression1} && @var{expression2}
-True if both @var{expression1} and @var{expression2} are true.
-
-@item @var{expression1} || @var{expression2}
-True if either @var{expression1} or @var{expression2} is true.
-@end table
-
-@noindent
-The @code{&&} and @code{||} operators do not evaluate @var{expression2} if the
-value of @var{expression1} is sufficient to determine the return
-value of the entire conditional expression.
-@end table
-
-@node Command Grouping
-@subsubsection Grouping Commands
-@cindex commands, grouping
-
-Bash provides two ways to group a list of commands to be executed
-as a unit.  When commands are grouped, redirections may be applied
-to the entire command list.  For example, the output of all the
-commands in the list may be redirected to a single stream.
-
-@table @code
-@item ()
-@example
-( @var{list} )
-@end example
-
-Placing a list of commands between parentheses causes a subshell
-environment to be created (@pxref{Command Execution Environment}), and each
-of the commands in @var{list} to be executed in that subshell.  Since the
-@var{list} is executed in a subshell, variable assignments do not remain in
-effect after the subshell completes. 
-
-@item @{@}
-@rwindex @{
-@rwindex @}
-@example
-@{ @var{list}; @}
-@end example
-
-Placing a list of commands between curly braces causes the list to
-be executed in the current shell context.  No subshell is created.
-The semicolon (or newline) following @var{list} is required.
-@end table
-
-In addition to the creation of a subshell, there is a subtle difference
-between these two constructs due to historical reasons.  The braces
-are @code{reserved words}, so they must be separated from the @var{list}
-by @code{blank}s or other shell metacharacters.
-The parentheses are @code{operators}, and are
-recognized as separate tokens by the shell even if they are not separated
-from the @var{list} by whitespace.
-
-The exit status of both of these constructs is the exit status of
-@var{list}.
-
-@node Coprocesses
-@subsection Coprocesses
-@cindex coprocess
-
-A @code{coprocess} is a shell command preceded by the @code{coproc}
-reserved word.
-A coprocess is executed asynchronously in a subshell, as if the command
-had been terminated with the @samp{&} control operator, with a two-way pipe
-established between the executing shell and the coprocess.
-
-The format for a coprocess is:
-@example
-coproc [@var{NAME}] @var{command} [@var{redirections}]
-@end example
-
-@noindent
-This creates a coprocess named @var{NAME}.
-If @var{NAME} is not supplied, the default name is @var{COPROC}.
-@var{NAME} must not be supplied if @var{command} is a simple
-command (@pxref{Simple Commands}); otherwise, it is interpreted as
-the first word of the simple command.
-
-When the coprocess is executed, the shell creates an array variable
-(@pxref{Arrays})
-named @env{NAME} in the context of the executing shell.
-The standard output of @var{command}
-is connected via a pipe to a file descriptor in the executing shell,
-and that file descriptor is assigned to @env{NAME}[0].
-The standard input of @var{command}
-is connected via a pipe to a file descriptor in the executing shell,
-and that file descriptor is assigned to @env{NAME}[1].
-This pipe is established before any redirections specified by the
-command (@pxref{Redirections}).
-The file descriptors can be utilized as arguments to shell commands
-and redirections using standard word expansions.
-The file descriptors are not available in subshells.
-
-The process ID of the shell spawned to execute the coprocess is
-available as the value of the variable @env{NAME}_PID.
-The @code{wait}
-builtin command may be used to wait for the coprocess to terminate.
-
-Since the coprocess is created as an asynchronous command,
-the @code{coproc} command always returns success.
-The return status of a coprocess is the exit status of @var{command}.
-
-@node GNU Parallel
-@subsection GNU Parallel
-
-GNU Parallel, as its name suggests, can be used to build and run commands
-in parallel.  You may run the same command with different arguments, whether
-they are filenames, usernames, hostnames, or lines read from files.
-
-For a complete description, refer to the GNU Parallel documentation.  A few
-examples should provide a brief introduction to its use.
-
-For example, it is easy to prefix each line in a text file with a specified
-string:
-@example
-cat file | parallel -k echo prefix_string
-@end example
-@noindent
-The @option{-k} option is required to preserve the lines' order.
-
-Similarly, you can append a specified string to each line in a text file:
-@example
-cat file | parallel -k echo @{@} append_string
-@end example
-
-You can use Parallel to move files from the current directory when the
-number of files is too large to process with one @code{mv} invocation:
-@example
-ls | parallel mv @{@} destdir
-@end example
-
-As you can see, the @{@} is replaced with each line read from standard input.
-This will run as many @code{mv} commands as there are files in the current
-directory.  You can emulate a parallel @code{xargs} by adding the @option{-X}
-option:
-@example
-ls | parallel -X mv @{@} destdir
-@end example
-
-GNU Parallel can replace certain common idioms that operate on lines read
-from a file (in this case, filenames):
-@example
-       for x in $(cat list); do
-               do-something1 $x config-$x
-               do-something2 < $x
-       done | process-output
-@end example
-
-@noindent
-with a more compact syntax reminiscent of lambdas:
-@example
-cat list | parallel "do-something1 @{@} config-@{@} ; do-something2 < @{@}" | process-output
-@end example
-
-Parallel provides a built-in mechanism to remove filename extensions, which
-lends itself to batch file transformations or renaming:
-@example
-ls *.gz | parallel -j+0 "zcat @{@} | bzip2 >@{.@}.bz2 && rm @{@}"
-@end example
-@noindent
-This will recompress all files in the current directory with names ending
-in .gz using bzip2, running one job per CPU (-j+0)  in parallel.
-
-If a command generates output, you may want to preserve the input order in
-the output.  For instance, the following command
-@example
-@{ echo foss.org.my ; echo debian.org; echo freenetproject.org; @} | parallel traceroute
-@end example
-@noindent
-will display as output the traceroute invocation that finishes first.  Using
-the @option{-k} option, as we saw above
-@example
-@{ echo foss.org.my ; echo debian.org; echo freenetproject.org; @} | parallel -k traceroute
-@end example
-@noindent
-will ensure that the output of @code{traceroute foss.org.my} is displayed first.
-
-@node Shell Functions
-@section Shell Functions
-@cindex shell function
-@cindex functions, shell
-
-Shell functions are a way to group commands for later execution
-using a single name for the group.  They are executed just like
-a "regular" command.
-When the name of a shell function is used as a simple command name,
-the list of commands associated with that function name is executed.
-Shell functions are executed in the current
-shell context; no new process is created to interpret them.
-
-Functions are declared using this syntax:
-@rwindex function
-@example
-@var{name} () @var{compound-command} [ @var{redirections} ]
-@end example
-
-or
-
-@example
-function @var{name} [()] @var{compound-command} [ @var{redirections} ]
-@end example
-
-This defines a shell function named @var{name}.  The reserved
-word @code{function} is optional.
-If the @code{function} reserved
-word is supplied, the parentheses are optional.
-The @var{body} of the function is the compound command
-@var{compound-command} (@pxref{Compound Commands}).
-That command is usually a @var{list} enclosed between @{ and @}, but
-may be any compound command listed above.
-@var{compound-command} is executed whenever @var{name} is specified as the
-name of a command.
-When the shell is in @sc{posix} mode (@pxref{Bash POSIX Mode}),
-@var{name} may not be the same as one of the special builtins
-(@pxref{Special Builtins}).
-Any redirections (@pxref{Redirections}) associated with the shell function
-are performed when the function is executed.
-
-A function definition may be deleted using the @option{-f} option to the
-@code{unset} builtin (@pxref{Bourne Shell Builtins}).
-
-The exit status of a function definition is zero unless a syntax error
-occurs or a readonly function with the same name already exists.
-When executed, the exit status of a function is the exit status of the
-last command executed in the body.
-
-Note that for historical reasons, in the most common usage the curly braces
-that surround the body of the function must be separated from the body by
-@code{blank}s or newlines.
-This is because the braces are reserved words and are only recognized
-as such when they are separated from the command list
-by whitespace or another shell metacharacter.
-Also, when using the braces, the @var{list} must be terminated by a semicolon,
-a @samp{&}, or a newline.
-
-When a function is executed, the arguments to the
-function become the positional parameters
-during its execution (@pxref{Positional Parameters}).
-The special parameter @samp{#} that expands to the number of
-positional parameters is updated to reflect the change.
-Special parameter @code{0} is unchanged.
-The first element of the @env{FUNCNAME} variable is set to the
-name of the function while the function is executing.
-
-All other aspects of the shell execution
-environment are identical between a function and its caller
-with these exceptions:
-the @env{DEBUG} and @env{RETURN} traps
-are not inherited unless the function has been given the
-@code{trace} attribute using the @code{declare} builtin or
-the @code{-o functrace} option has been enabled with
-the @code{set} builtin,
-(in which case all functions inherit the @env{DEBUG} and @env{RETURN} traps),
-and the @env{ERR} trap is not inherited unless the @code{-o errtrace}
-shell option has been enabled.
-@xref{Bourne Shell Builtins}, for the description of the
-@code{trap} builtin.
-
-The @env{FUNCNEST} variable, if set to a numeric value greater
-than 0, defines a maximum function nesting level.  Function
-invocations that exceed the limit cause the entire command to
-abort.
-
-If the builtin command @code{return}
-is executed in a function, the function completes and
-execution resumes with the next command after the function
-call.
-Any command associated with the @code{RETURN} trap is executed
-before execution resumes.
-When a function completes, the values of the
-positional parameters and the special parameter @samp{#}
-are restored to the values they had prior to the function's
-execution.  If a numeric argument is given to @code{return},
-that is the function's return status; otherwise the function's
-return status is the exit status of the last command executed
-before the @code{return}.
-
-Variables local to the function may be declared with the
-@code{local} builtin.  These variables are visible only to
-the function and the commands it invokes.
-
-Function names and definitions may be listed with the
-@option{-f} option to the @code{declare} (@code{typeset})
-builtin command (@pxref{Bash Builtins}).
-The @option{-F} option to @code{declare} or @code{typeset}
-will list the function names only
-(and optionally the source file and line number, if the @code{extdebug}
-shell option is enabled).
-Functions may be exported so that subshells
-automatically have them defined with the
-@option{-f} option to the @code{export} builtin
-(@pxref{Bourne Shell Builtins}).
-Note that shell functions and variables with the same name may result
-in multiple identically-named entries in the environment passed to the
-shell's children.
-Care should be taken in cases where this may cause a problem.
-
-Functions may be recursive.
-The @code{FUNCNEST} variable may be used to limit the depth of the
-function call stack and restrict the number of function invocations.
-By default, no limit is placed on the number of recursive  calls.
-
-@node Shell Parameters
-@section Shell Parameters
-@cindex parameters
-@cindex variable, shell
-@cindex shell variable
-
-@menu
-* Positional Parameters::      The shell's command-line arguments.
-* Special Parameters::         Parameters denoted by special characters.
-@end menu
-
-A @var{parameter} is an entity that stores values.
-It can be a @code{name}, a number, or one of the special characters
-listed below.
-A @var{variable} is a parameter denoted by a @code{name}.
-A variable has a @var{value} and zero or more @var{attributes}.
-Attributes are assigned using the @code{declare} builtin command
-(see the description of the @code{declare} builtin in @ref{Bash Builtins}).
-
-A parameter is set if it has been assigned a value.  The null string is
-a valid value.  Once a variable is set, it may be unset only by using
-the @code{unset} builtin command.
-
-A variable may be assigned to by a statement of the form
-@example
-@var{name}=[@var{value}]
-@end example
-@noindent
-If @var{value}
-is not given, the variable is assigned the null string.  All
-@var{value}s undergo tilde expansion, parameter and variable expansion,
-command substitution, arithmetic expansion, and quote
-removal (detailed below).  If the variable has its @code{integer}
-attribute set, then @var{value} 
-is evaluated as an arithmetic expression even if the @code{$((@dots{}))}
-expansion is not used (@pxref{Arithmetic Expansion}).
-Word splitting is not performed, with the exception
-of @code{"$@@"} as explained below.
-Filename expansion is not performed.
-Assignment statements may also appear as arguments to the
-@code{alias}, 
-@code{declare}, @code{typeset}, @code{export}, @code{readonly},
-and @code{local} builtin commands.
-When in @sc{posix} mode (@pxref{Bash POSIX Mode}), these builtins may appear
-in a command after one or more instances of the @code{command} builtin
-and retain these assignment statement properties.
-
-In the context where an assignment statement is assigning a value  
-to a shell variable or array index (@pxref{Arrays}), the @samp{+=}
-operator can be used to   
-append to or add to the variable's previous value.
-When @samp{+=} is applied to a variable for which the @var{integer} attribute
-has been set, @var{value} is evaluated as an arithmetic expression and
-added to the variable's current value, which is also evaluated.
-When @samp{+=} is applied to an array variable using compound assignment
-(@pxref{Arrays}), the
-variable's value is not unset (as it is when using @samp{=}), and new
-values are appended to the array beginning at one greater than the array's
-maximum index (for indexed arrays),  or added as additional key-value pairs
-in an associative array.
-When applied to a string-valued variable, @var{value} is expanded and
-appended to the variable's value.
-
-A variable can be assigned the @var{nameref} attribute using the
-@option{-n} option to the \fBdeclare\fP or \fBlocal\fP builtin commands
-(@pxref{Bash Builtins})
-to create a @var{nameref}, or a reference to another variable.
-This allows variables to be manipulated indirectly.
-Whenever the nameref variable is referenced or assigned to, the operation
-is actually performed on the variable specified by the nameref variable's
-value.
-A nameref is commonly used within shell functions to refer to a variable
-whose name is passed as an argument to the function.
-For instance, if a variable name is passed to a shell function as its first
-argument, running
-@example
-declare -n ref=$1
-@end example
-@noindent
-inside the function creates a nameref variable @var{ref} whose value is
-the variable name passed as the first argument.
-References and assignments to @var{ref} are treated as references and
-assignments to the variable whose name was passed as @code{$1}.
-
-If the control variable in a @code{for} loop has the nameref attribute,
-the list of words can be a list of shell variables, and a name reference
-will be established for each word in the list, in turn, when the loop is
-executed.
-Array variables cannot be given the @option{-n} attribute.
-However, nameref variables can reference array variables and subscripted
-array variables.
-Namerefs can be unset using the @option{-n} option to the @code{unset} builtin
-(@pxref{Bourne Shell Builtins}).
-Otherwise, if @code{unset} is executed with the name of a nameref variable
-as an argument, the variable referenced by the nameref variable will be unset.
-
-@node Positional Parameters
-@subsection Positional Parameters
-@cindex parameters, positional
-
-A @var{positional parameter} is a parameter denoted by one or more
-digits, other than the single digit @code{0}.  Positional parameters are
-assigned from the shell's arguments when it is invoked,
-and may be reassigned using the @code{set} builtin command.
-Positional parameter @code{N} may be referenced as @code{$@{N@}}, or
-as @code{$N} when @code{N} consists of a single digit.
-Positional parameters may not be assigned to with assignment statements.
-The @code{set} and @code{shift} builtins are used to set and
-unset them (@pxref{Shell Builtin Commands}).
-The positional parameters are
-temporarily replaced when a shell function is executed
-(@pxref{Shell Functions}).
-
-When a positional parameter consisting of more than a single
-digit is expanded, it must be enclosed in braces.
-
-@node Special Parameters
-@subsection Special Parameters
-@cindex parameters, special
-
-The shell treats several parameters specially.  These parameters may
-only be referenced; assignment to them is not allowed.
-
-@vtable @code
-
-@item *
-Expands to the positional parameters, starting from one.  When the
-expansion occurs within double quotes, it expands to a single word
-with the value of each parameter separated by the first character
-of the @env{IFS}
-special variable.  That is, @code{"$*"} is equivalent
-to @code{"$1@var{c}$2@var{c}@dots{}"}, where @var{c}
-is the first character of the value of the @code{IFS}
-variable.
-If @env{IFS} is unset, the parameters are separated by spaces.
-If @env{IFS} is null, the parameters are joined without intervening
-separators.
-
-
-@item @@
-Expands to the positional parameters, starting from one.  When the
-expansion occurs within double quotes, each parameter expands to a
-separate word.  That is, @code{"$@@"} is equivalent to
-@code{"$1" "$2" @dots{}}.
-If the double-quoted expansion occurs within a word, the expansion of
-the first parameter is joined with the beginning part of the original
-word, and the expansion of the last parameter is joined with the last
-part of the original word.
-When there are no positional parameters, @code{"$@@"} and
-@code{$@@}
-expand to nothing (i.e., they are removed).
-
-@item #
-Expands to the number of positional parameters in decimal.
-
-@item ?
-Expands to the exit status of the most recently executed foreground
-pipeline.
-
-@item -
-(A hyphen.)  Expands to the current option flags as specified upon
-invocation, by the @code{set}
-builtin command, or those set by the shell itself
-(such as the @option{-i} option).
-
-@item $
-Expands to the process @sc{id} of the shell.  In a @code{()} subshell, it
-expands to the process @sc{id} of the invoking shell, not the subshell.
-
-@item !
-Expands to the process @sc{id} of the most recently executed background
-(asynchronous) command.
-
-@item 0
-Expands to the name of the shell or shell script.  This is set at
-shell initialization.  If Bash is invoked with a file of commands
-(@pxref{Shell Scripts}), @code{$0} is set to the name of that file.
-If Bash is started with the @option{-c} option (@pxref{Invoking Bash}),
-then @code{$0} is set to the first argument after the string to be
-executed, if one is present.  Otherwise, it is set
-to the filename used to invoke Bash, as given by argument zero.
-
-@item _
-(An underscore.)
-At shell startup, set to the absolute pathname used to invoke the
-shell or shell script being executed as passed in the environment
-or argument list.
-Subsequently, expands to the last argument to the previous command,
-after expansion.   
-Also set to the full pathname used to invoke each command executed
-and placed in the environment exported to that command.
-When checking mail, this parameter holds the name of the mail file.
-@end vtable
-
-@node Shell Expansions
-@section Shell Expansions
-@cindex expansion
-
-Expansion is performed on the command line after it has been split into
-@code{token}s.  There are seven kinds of expansion performed:
-
-@itemize @bullet
-@item brace expansion
-@item tilde expansion
-@item parameter and variable expansion
-@item command substitution
-@item arithmetic expansion
-@item word splitting
-@item filename expansion
-@end itemize
-
-@menu
-* Brace Expansion::            Expansion of expressions within braces.
-* Tilde Expansion::            Expansion of the ~ character.
-* Shell Parameter Expansion::  How Bash expands variables to their values.
-* Command Substitution::       Using the output of a command as an argument.
-* Arithmetic Expansion::       How to use arithmetic in shell expansions.
-* Process Substitution::       A way to write and read to and from a
-                               command.
-* Word Splitting::     How the results of expansion are split into separate
-                       arguments.
-* Filename Expansion:: A shorthand for specifying filenames matching patterns.
-* Quote Removal::      How and when quote characters are removed from
-                       words.
-@end menu
-
-The order of expansions is: brace expansion, tilde expansion,
-parameter, variable, and arithmetic expansion and
-command substitution
-(done in a left-to-right fashion), word splitting, and filename
-expansion.
-
-On systems that can support it, there is an additional expansion
-available: @var{process substitution}.  This is performed at the
-same time as parameter, variable, and arithmetic expansion and
-command substitution.
-
-Only brace expansion, word splitting, and filename expansion
-can change the number of words of the expansion; other expansions
-expand a single word to a single word.
-The only exceptions to this are the expansions of
-@code{"$@@"} (@pxref{Special Parameters}) and @code{"$@{@var{name}[@@]@}"}
-(@pxref{Arrays}).
-
-After all expansions, @code{quote removal} (@pxref{Quote Removal})
-is performed.
-
-@node Brace Expansion
-@subsection Brace Expansion
-@cindex brace expansion
-@cindex expansion, brace
-
-Brace expansion is a mechanism by which arbitrary strings may be generated.
-This mechanism is similar to
-@var{filename expansion} (@pxref{Filename Expansion}),
-but the filenames generated need not exist.
-Patterns to be brace expanded take the form of an optional @var{preamble},
-followed by either a series of comma-separated strings or a sequence expression
-between a pair of braces,
-followed by an optional @var{postscript}.
-The preamble is prefixed to each string contained within the braces, and
-the postscript is then appended to each resulting string, expanding left
-to right.
-
-Brace expansions may be nested.
-The results of each expanded string are not sorted; left to right order
-is preserved.
-For example,
-@example
-bash$ echo a@{d,c,b@}e
-ade ace abe
-@end example
-
-A sequence expression takes the form @code{@{@var{x}..@var{y}[..@var{incr}]@}},
-where @var{x} and @var{y} are either integers or single characters,
-and @var{incr}, an optional increment, is an integer.
-When integers are supplied, the expression expands to each number between
-@var{x} and @var{y}, inclusive.
-Supplied integers may be prefixed with @samp{0} to force each term to have the
-same width.
-When either @var{x} or @var{y} begins with a zero, the shell
-attempts to force all generated terms to contain the same number of digits,
-zero-padding where necessary.
-When characters are supplied, the expression expands to each character
-lexicographically between @var{x} and @var{y}, inclusive,
-using the default C locale.
-Note that both @var{x} and @var{y} must be of the same type.
-When the increment is supplied, it is used as the difference between
-each term.  The default increment is 1 or -1 as appropriate.
-
-Brace expansion is performed before any other expansions,
-and any characters special to other expansions are preserved
-in the result.  It is strictly textual.  Bash
-does not apply any syntactic interpretation to the context of the
-expansion or the text between the braces.
-To avoid conflicts with parameter expansion, the string @samp{$@{}
-is not considered eligible for brace expansion.
-
-A correctly-formed brace expansion must contain unquoted opening
-and closing braces, and at least one unquoted comma or a valid
-sequence expression.
-Any incorrectly formed brace expansion is left unchanged.
-
-A @{ or @samp{,} may be quoted with a backslash to prevent its
-being considered part of a brace expression.
-To avoid conflicts with parameter expansion, the string @samp{$@{}
-is not considered eligible for brace expansion.
-
-This construct is typically used as shorthand when the common
-prefix of the strings to be generated is longer than in the
-above example:
-@example
-mkdir /usr/local/src/bash/@{old,new,dist,bugs@}
-@end example
-or
-@example
-chown root /usr/@{ucb/@{ex,edit@},lib/@{ex?.?*,how_ex@}@}
-@end example
-
-@node Tilde Expansion
-@subsection Tilde Expansion
-@cindex tilde expansion
-@cindex expansion, tilde
-
-If a word begins with an unquoted tilde character (@samp{~}), all of the
-characters up to the first unquoted slash (or all characters,
-if there is no unquoted slash) are considered a @var{tilde-prefix}.
-If none of the characters in the tilde-prefix are quoted, the
-characters in the tilde-prefix following the tilde are treated as a
-possible @var{login name}.
-If this login name is the null string, the tilde is replaced with the
-value of the @env{HOME} shell variable.
-If @env{HOME} is unset, the home directory of the user executing the
-shell is substituted instead.
-Otherwise, the tilde-prefix is replaced with the home directory
-associated with the specified login name.
-
-If the tilde-prefix is @samp{~+}, the value of
-the shell variable @env{PWD} replaces the tilde-prefix.
-If the tilde-prefix is @samp{~-}, the value of the shell variable
-@env{OLDPWD}, if it is set, is substituted.
-
-If the characters following the tilde in the tilde-prefix consist of a
-number @var{N}, optionally prefixed by a @samp{+} or a @samp{-},
-the tilde-prefix is replaced with the
-corresponding element from the directory stack, as it would be displayed
-by the @code{dirs} builtin invoked with the characters following tilde
-in the tilde-prefix as an argument (@pxref{The Directory Stack}).
-If the tilde-prefix, sans the tilde, consists of a number without a
-leading @samp{+} or @samp{-}, @samp{+} is assumed.
-
-If the login name is invalid, or the tilde expansion fails, the word is
-left unchanged.
-
-Each variable assignment is checked for unquoted tilde-prefixes immediately
-following a @samp{:} or the first @samp{=}.
-In these cases, tilde expansion is also performed.
-Consequently, one may use filenames with tildes in assignments to
-@env{PATH}, @env{MAILPATH}, and @env{CDPATH},
-and the shell assigns the expanded value.
-
-The following table shows how Bash treats unquoted tilde-prefixes:
-
-@table @code
-@item ~
-The value of @code{$HOME}
-@item ~/foo
-@file{$HOME/foo}
-
-@item ~fred/foo
-The subdirectory @code{foo} of the home directory of the user
-@code{fred}
-
-@item ~+/foo
-@file{$PWD/foo}
-
-@item ~-/foo
-@file{$@{OLDPWD-'~-'@}/foo}
-
-@item ~@var{N}
-The string that would be displayed by @samp{dirs +@var{N}}
-
-@item ~+@var{N}
-The string that would be displayed by @samp{dirs +@var{N}}
-
-@item ~-@var{N}
-The string that would be displayed by @samp{dirs -@var{N}}
-@end table
-
-@node Shell Parameter Expansion
-@subsection Shell Parameter Expansion
-@cindex parameter expansion
-@cindex expansion, parameter
-
-The @samp{$} character introduces parameter expansion,
-command substitution, or arithmetic expansion.  The parameter name
-or symbol to be expanded may be enclosed in braces, which
-are optional but serve to protect the variable to be expanded from
-characters immediately following it which could be
-interpreted as part of the name.
-
-When braces are used, the matching ending brace is the first @samp{@}}
-not escaped by a backslash or within a quoted string, and not within an
-embedded arithmetic expansion, command substitution, or parameter
-expansion.
-
-The basic form of parameter expansion is $@{@var{parameter}@}.
-The value of @var{parameter} is substituted.
-The @var{parameter} is a shell parameter as described above
-(@pxref{Shell Parameters}) or an array reference (@pxref{Arrays}).
-The braces are required when @var{parameter}
-is a positional parameter with more than one digit,
-or when @var{parameter} is followed by a character that is not to be
-interpreted as part of its name.
-
-If the first character of @var{parameter} is an exclamation point (!),
-it introduces a level of variable indirection.
-Bash uses the value of the variable formed from the rest of
-@var{parameter} as the name of the variable; this variable is then
-expanded and that value is used in the rest of the substitution, rather
-than the value of @var{parameter} itself.
-This is known as @code{indirect expansion}.
-The exceptions to this are the expansions of $@{!@var{prefix}*@}
-and $@{!@var{name}[@@]@}
-described below.
-The exclamation point must immediately follow the left brace in order to
-introduce indirection.
-
-In each of the cases below, @var{word} is subject to tilde expansion,
-parameter expansion, command substitution, and arithmetic expansion.
-
-When not performing substring expansion, using the form described
-below (e.g., @samp{:-}), Bash tests for a parameter that is unset or null.
-Omitting the colon results in a test only for a parameter that is unset.
-Put another way, if the colon is included,
-the operator tests for both @var{parameter}'s existence and that its value
-is not null; if the colon is omitted, the operator tests only for existence.
-
-@table @code
-
-@item $@{@var{parameter}:@minus{}@var{word}@}
-If @var{parameter} is unset or null, the expansion of
-@var{word} is substituted.  Otherwise, the value of
-@var{parameter} is substituted.
-
-@item $@{@var{parameter}:=@var{word}@}
-If @var{parameter}
-is unset or null, the expansion of @var{word}
-is assigned to @var{parameter}.
-The value of @var{parameter} is then substituted. 
-Positional parameters and special parameters may not be assigned to
-in this way.
-
-@item $@{@var{parameter}:?@var{word}@}
-If @var{parameter}
-is null or unset, the expansion of @var{word} (or a message
-to that effect if @var{word}
-is not present) is written to the standard error and the shell, if it
-is not interactive, exits.  Otherwise, the value of @var{parameter} is
-substituted.
-
-@item $@{@var{parameter}:+@var{word}@}
-If @var{parameter}
-is null or unset, nothing is substituted, otherwise the expansion of
-@var{word} is substituted.
-
-@item $@{@var{parameter}:@var{offset}@}
-@itemx $@{@var{parameter}:@var{offset}:@var{length}@}
-This is referred to as Substring Expansion.
-It expands to up to @var{length} characters of the value of @var{parameter}
-starting at the character specified by @var{offset}.
-If @var{parameter} is @samp{@@}, an indexed array subscripted by
-@samp{@@} or @samp{*}, or an associative array name, the results differ as
-described below.
-If @var{length} is omitted, it expands to the substring of the value of
-@var{parameter} starting at the character specified by @var{offset}
-and extending to the end of the value.
-@var{length} and @var{offset} are arithmetic expressions
-(@pxref{Shell Arithmetic}).
-
-If @var{offset} evaluates to a number less than zero, the value
-is used as an offset in characters
-from the end of the value of @var{parameter}.
-If @var{length} evaluates to a number less than zero,
-it is interpreted as an offset in characters
-from the end of the value of @var{parameter} rather than
-a number of characters, and the expansion is the characters between
-@var{offset} and that result.
-Note that a negative offset must be separated from the colon by at least
-one space to avoid being confused with the @samp{:-} expansion.
-
-Here are some examples illustrating substring expansion on parameters and
-subscripted arrays:
-
-@verbatim
-$ string=01234567890abcdefgh
-$ echo ${string:7}
-7890abcdefgh
-$ echo ${string:7:0}
-
-$ echo ${string:7:2}
-78
-$ echo ${string:7:-2}
-7890abcdef
-$ echo ${string: -7}
-bcdefgh
-$ echo ${string: -7:0}
-
-$ echo ${string: -7:2}
-bc
-$ echo ${string: -7:-2}
-bcdef
-$ set -- 01234567890abcdefgh
-$ echo ${1:7}
-7890abcdefgh
-$ echo ${1:7:0}
-
-$ echo ${1:7:2}
-78
-$ echo ${1:7:-2}
-7890abcdef
-$ echo ${1: -7}
-bcdefgh
-$ echo ${1: -7:0}
-
-$ echo ${1: -7:2}
-bc
-$ echo ${1: -7:-2}
-bcdef
-$ array[0]=01234567890abcdefgh
-$ echo ${array[0]:7}
-7890abcdefgh
-$ echo ${array[0]:7:0}
-
-$ echo ${array[0]:7:2}
-78
-$ echo ${array[0]:7:-2}
-7890abcdef
-$ echo ${array[0]: -7}
-bcdefgh
-$ echo ${array[0]: -7:0}
-
-$ echo ${array[0]: -7:2}
-bc
-$ echo ${array[0]: -7:-2}
-bcdef
-@end verbatim
-
-If @var{parameter} is @samp{@@}, the result is @var{length} positional
-parameters beginning at @var{offset}.
-A negative @var{offset} is taken relative to one greater than the greatest
-positional parameter, so an offset of -1 evaluates to the last positional
-parameter.
-It is an expansion error if @var{length} evaluates to a number less than zero.
-
-The following examples illustrate substring expansion using positional
-parameters:
-
-@verbatim
-$ set -- 1 2 3 4 5 6 7 8 9 0 a b c d e f g h
-$ echo ${@:7}
-7 8 9 0 a b c d e f g h
-$ echo ${@:7:0}
-
-$ echo ${@:7:2}
-7 8
-$ echo ${@:7:-2}
-bash: -2: substring expression < 0
-$ echo ${@: -7:2}
-b c
-$ echo ${@:0}
-./bash 1 2 3 4 5 6 7 8 9 0 a b c d e f g h
-$ echo ${@:0:2}
-./bash 1
-$ echo ${@: -7:0}
-
-@end verbatim
-
-If @var{parameter} is an indexed array name subscripted
-by @samp{@@} or @samp{*}, the result is the @var{length}
-members of the array beginning with @code{$@{@var{parameter}[@var{offset}]@}}.
-A negative @var{offset} is taken relative to one greater than the maximum
-index of the specified array.
-It is an expansion error if @var{length} evaluates to a number less than zero.
-
-These examples show how you can use substring expansion with indexed
-arrays:
-
-@verbatim
-$ array=(0 1 2 3 4 5 6 7 8 9 0 a b c d e f g h)
-$ echo ${array[@]:7}
-7 8 9 0 a b c d e f g h
-$ echo ${array[@]:7:2}
-7 8
-$ echo ${array[@]: -7:2}
-b c
-$ echo ${array[@]: -7:-2}
-bash: -2: substring expression < 0
-$ echo ${array[@]:0}
-0 1 2 3 4 5 6 7 8 9 0 a b c d e f g h
-$ echo ${array[@]:0:2}
-0 1
-$ echo ${array[@]: -7:0}
-
-@end verbatim
-
-Substring expansion applied to an associative array produces undefined
-results.
-
-Substring indexing is zero-based unless the positional parameters
-are used, in which case the indexing starts at 1 by default.
-If @var{offset} is 0, and the positional parameters are used, @code{$@@} is
-prefixed to the list.
-
-@item $@{!@var{prefix}*@}
-@itemx $@{!@var{prefix}@@@}
-Expands to the names of variables whose names begin with @var{prefix},
-separated by the first character of the @env{IFS} special variable.
-When @samp{@@} is used and the expansion appears within double quotes, each
-variable name expands to a separate word.
-
-@item $@{!@var{name}[@@]@}
-@itemx $@{!@var{name}[*]@}
-If @var{name} is an array variable, expands to the list of array indices
-(keys) assigned in @var{name}.
-If @var{name} is not an array, expands to 0 if @var{name} is set and null
-otherwise.
-When @samp{@@} is used and the expansion appears within double quotes, each
-key expands to a separate word.
-
-@item $@{#@var{parameter}@}
-The length in characters of the expanded value of @var{parameter} is
-substituted.
-If @var{parameter} is @samp{*} or @samp{@@}, the value substituted
-is the number of positional parameters.
-If @var{parameter} is an array name subscripted by @samp{*} or @samp{@@}, 
-the value substituted is the number of elements in the array.
-If @var{parameter}
-is an indexed array name subscripted by a negative number, that number is
-interpreted as relative to one greater than the maximum index of
-@var{parameter}, so negative indices count back from the end of the
-array, and an index of -1 references the last element.
-
-@item $@{@var{parameter}#@var{word}@}
-@itemx $@{@var{parameter}##@var{word}@}
-The @var{word}
-is expanded to produce a pattern just as in filename
-expansion (@pxref{Filename Expansion}).  If the pattern matches
-the beginning of the expanded value of @var{parameter},
-then the result of the expansion is the expanded value of @var{parameter}
-with the shortest matching pattern (the @samp{#} case) or the
-longest matching pattern (the @samp{##} case) deleted.
-If @var{parameter} is @samp{@@} or @samp{*},
-the pattern removal operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If @var{parameter} is an array variable subscripted with
-@samp{@@} or @samp{*},
-the pattern removal operation is applied to each member of the
-array in turn, and the expansion is the resultant list.
-
-@item $@{@var{parameter}%@var{word}@}
-@itemx $@{@var{parameter}%%@var{word}@}
-The @var{word} is expanded to produce a pattern just as in
-filename expansion.
-If the pattern matches a trailing portion of the expanded value of
-@var{parameter}, then the result of the expansion is the value of
-@var{parameter} with the shortest matching pattern (the @samp{%} case)
-or the longest matching pattern (the @samp{%%} case) deleted.
-If @var{parameter} is @samp{@@} or @samp{*},
-the pattern removal operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If @var{parameter}
-is an array variable subscripted with @samp{@@} or @samp{*},
-the pattern removal operation is applied to each member of the
-array in turn, and the expansion is the resultant list.
-
-@item $@{@var{parameter}/@var{pattern}/@var{string}@} 
-
-The @var{pattern} is expanded to produce a pattern just as in
-filename expansion.
-@var{Parameter} is expanded and the longest match of @var{pattern}
-against its value is replaced with @var{string}.
-If @var{pattern} begins with @samp{/}, all matches of @var{pattern} are
-replaced with @var{string}.  Normally only the first match is replaced.
-If @var{pattern} begins with @samp{#}, it must match at the beginning
-of the expanded value of @var{parameter}.
-If @var{pattern} begins with @samp{%}, it must match at the end
-of the expanded value of @var{parameter}.
-If @var{string} is null, matches of @var{pattern} are deleted
-and the @code{/} following @var{pattern} may be omitted.
-If @var{parameter} is @samp{@@} or @samp{*},
-the substitution operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If @var{parameter}
-is an array variable subscripted with @samp{@@} or @samp{*},
-the substitution operation is applied to each member of the
-array in turn, and the expansion is the resultant list.
-
-@item $@{@var{parameter}^@var{pattern}@}
-@itemx $@{@var{parameter}^^@var{pattern}@}
-@itemx $@{@var{parameter},@var{pattern}@}
-@itemx $@{@var{parameter},,@var{pattern}@}
-This expansion modifies the case of alphabetic characters in @var{parameter}.
-The @var{pattern} is expanded to produce a pattern just as in
-filename expansion.
-Each character in the expanded value of @var{parameter} is tested against
-@var{pattern}, and, if it matches the pattern, its case is converted.
-The pattern should not attempt to match more than one character.
-The @samp{^} operator converts lowercase letters matching @var{pattern}
-to uppercase; the @samp{,} operator converts matching uppercase letters
-to lowercase.
-The @samp{^^} and @samp{,,} expansions convert each matched character in the
-expanded value; the @samp{^} and @samp{,} expansions match and convert only
-the first character in the expanded value.
-If @var{pattern} is omitted, it is treated like a @samp{?}, which matches
-every character.
-If @var{parameter} is @samp{@@} or @samp{*},
-the case modification operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If @var{parameter}
-is an array variable subscripted with @samp{@@} or @samp{*},
-the case modification operation is applied to each member of the
-array in turn, and the expansion is the resultant list.
-@end table
-
-@node Command Substitution
-@subsection Command Substitution
-@cindex command substitution
-
-Command substitution allows the output of a command to replace
-the command itself.
-Command substitution occurs when a command is enclosed as follows:
-@example
-$(@var{command})
-@end example
-@noindent
-or
-@example
-`@var{command}`
-@end example
-
-@noindent
-Bash performs the expansion by executing @var{command} and
-replacing the command substitution with the standard output of the
-command, with any trailing newlines deleted.
-Embedded newlines are not deleted, but they may be removed during
-word splitting.
-The command substitution @code{$(cat @var{file})} can be
-replaced by the equivalent but faster @code{$(< @var{file})}.
-
-When the old-style backquote form of substitution is used,
-backslash retains its literal meaning except when followed by
-@samp{$}, @samp{`}, or @samp{\}. 
-The first backquote not preceded by a backslash terminates the
-command substitution.
-When using the @code{$(@var{command})} form, all characters between
-the parentheses make up the command; none are treated specially.
-
-Command substitutions may be nested.  To nest when using the backquoted
-form, escape the inner backquotes with backslashes.
-
-If the substitution appears within double quotes, word splitting and
-filename expansion are not performed on the results.
-
-@node Arithmetic Expansion
-@subsection Arithmetic Expansion
-@cindex expansion, arithmetic
-@cindex arithmetic expansion
-
-Arithmetic expansion allows the evaluation of an arithmetic expression
-and the substitution of the result.  The format for arithmetic expansion is:
-
-@example
-$(( @var{expression} ))
-@end example
-
-The expression is treated as if it were within double quotes, but
-a double quote inside the parentheses is not treated specially.
-All tokens in the expression undergo parameter expansion, command
-substitution, and quote removal.
-Arithmetic expansions may be nested. 
-
-The evaluation is performed according to the rules listed below
-(@pxref{Shell Arithmetic}).
-If the expression is invalid, Bash prints a message indicating
-failure to the standard error and no substitution occurs.
-
-@node Process Substitution
-@subsection Process Substitution
-@cindex process substitution
-
-Process substitution is supported on systems that support named
-pipes (@sc{fifo}s) or the @file{/dev/fd} method of naming open files.
-It takes the form of 
-@example
-<(@var{list})
-@end example
-@noindent
-or
-@example
->(@var{list})
-@end example
-@noindent
-The process @var{list} is run with its input or output connected to a
-@sc{fifo} or some file in @file{/dev/fd}.  The name of this file is
-passed as an argument to the current command as the result of the
-expansion.  If the @code{>(@var{list})} form is used, writing to
-the file will provide input for @var{list}.  If the
-@code{<(@var{list})} form is used, the file passed as an
-argument should be read to obtain the output of @var{list}.
-Note that no space may appear between the @code{<} or @code{>}
-and the left parenthesis, otherwise the construct would be interpreted
-as a redirection.
-
-When available, process substitution is performed simultaneously with
-parameter and variable expansion, command substitution, and arithmetic
-expansion.
-
-@node Word Splitting
-@subsection Word Splitting
-@cindex word splitting
-
-The shell scans the results of parameter expansion, command substitution,
-and arithmetic expansion that did not occur within double quotes for
-word splitting.
-
-The shell treats each character of @env{$IFS} as a delimiter, and splits
-the results of the other expansions into words on these characters.
-If @env{IFS} is unset, or its value is exactly @code{<space><tab><newline>},
-the default, then sequences of
-@code{ <space>}, @code{<tab>}, and @code{<newline>}
-at the beginning and end of the results of the previous
-expansions are ignored, and any sequence of @env{IFS}
-characters not at the beginning or end serves to delimit words.
-If @env{IFS} has a value other than the default, then sequences of
-the whitespace characters @code{space} and @code{tab}
-are ignored at the beginning and end of the
-word, as long as the whitespace character is in the
-value of @env{IFS} (an @env{IFS} whitespace character).
-Any character in @env{IFS} that is not @env{IFS}
-whitespace, along with any adjacent @env{IFS}
-whitespace characters, delimits a field.  A sequence of @env{IFS}
-whitespace characters is also treated as a delimiter.
-If the value of @env{IFS} is null, no word splitting occurs.
-
-Explicit null arguments (@code{""} or @code{''}) are retained.
-Unquoted implicit null arguments, resulting from the expansion of
-parameters that have no values, are removed.
-If a parameter with no value is expanded within double quotes, a
-null argument results and is retained.
-
-Note that if no expansion occurs, no splitting
-is performed.
-
-@node Filename Expansion
-@subsection Filename Expansion
-@menu
-* Pattern Matching::   How the shell matches patterns.
-@end menu
-@cindex expansion, filename
-@cindex expansion, pathname
-@cindex filename expansion
-@cindex pathname expansion
-
-After word splitting, unless the @option{-f} option has been set
-(@pxref{The Set Builtin}), Bash scans each word for the characters
-@samp{*}, @samp{?}, and @samp{[}.
-If one of these characters appears, then the word is
-regarded as a @var{pattern},
-and replaced with an alphabetically sorted list of
-filenames matching the pattern (@pxref{Pattern Matching}).
-If no matching filenames are found,
-and the shell option @code{nullglob} is disabled, the word is left
-unchanged.
-If the @code{nullglob} option is set, and no matches are found, the word
-is removed.
-If the @code{failglob} shell option is set, and no matches are found,
-an error message is printed and the command is not executed.
-If the shell option @code{nocaseglob} is enabled, the match is performed
-without regard to the case of alphabetic characters.
-
-When a pattern is used for filename expansion, the character @samp{.}
-at the start of a filename or immediately following a slash
-must be matched explicitly, unless the shell option @code{dotglob} is set.
-When matching a filename, the slash character must always be
-matched explicitly.
-In other cases, the @samp{.} character is not treated specially.
-
-See the description of @code{shopt} in @ref{The Shopt Builtin},
-for a description of the @code{nocaseglob}, @code{nullglob},
-@code{failglob}, and @code{dotglob} options.
-
-The @env{GLOBIGNORE}
-shell variable may be used to restrict the set of filenames matching a
-pattern.  If @env{GLOBIGNORE}
-is set, each matching filename that also matches one of the patterns in
-@env{GLOBIGNORE} is removed from the list of matches.  The filenames
-@file{.} and @file{..}
-are always ignored when @env{GLOBIGNORE}
-is set and not null.
-However, setting @env{GLOBIGNORE} to a non-null value has the effect of
-enabling the @code{dotglob}
-shell option, so all other filenames beginning with a
-@samp{.} will match.
-To get the old behavior of ignoring filenames beginning with a
-@samp{.}, make @samp{.*} one of the patterns in @env{GLOBIGNORE}.
-The @code{dotglob} option is disabled when @env{GLOBIGNORE}
-is unset.
-
-@node Pattern Matching
-@subsubsection Pattern Matching
-@cindex pattern matching
-@cindex matching, pattern
-
-Any character that appears in a pattern, other than the special pattern
-characters described below, matches itself.
-The @sc{nul} character may not occur in a pattern.
-A backslash escapes the following character; the
-escaping backslash is discarded when matching.
-The special pattern characters must be quoted if they are to be matched
-literally.
-
-The special pattern characters have the following meanings:
-@table @code
-@item *
-Matches any string, including the null string.
-When the @code{globstar} shell option is enabled, and @samp{*} is used in
-a filename expansion context, two adjacent @samp{*}s used as a single
-pattern will match all files and zero or more directories and
-subdirectories.
-If followed by a @samp{/}, two adjacent @samp{*}s will match only
-directories and subdirectories.
-@item ?
-Matches any single character.
-@item [@dots{}]
-Matches any one of the enclosed characters.  A pair of characters
-separated by a hyphen denotes a @var{range expression};
-any character that falls between those two characters, inclusive,
-using the current locale's collating sequence and character set,
-is matched.  If the first character following the
-@samp{[} is a @samp{!}  or a @samp{^}
-then any character not enclosed is matched.  A @samp{@minus{}}
-may be matched by including it as the first or last character
-in the set.  A @samp{]} may be matched by including it as the first
-character in the set.
-The sorting order of characters in range expressions is determined by
-the current locale and the values of the
-@env{LC_COLLATE} and @env{LC_ALL} shell variables, if set.
-
-For example, in the default C locale, @samp{[a-dx-z]} is equivalent to
-@samp{[abcdxyz]}.  Many locales sort characters in dictionary order, and in
-these locales @samp{[a-dx-z]} is typically not equivalent to @samp{[abcdxyz]};
-it might be equivalent to @samp{[aBbCcDdxXyYz]}, for example.  To obtain
-the traditional interpretation of ranges in bracket expressions, you can
-force the use of the C locale by setting the @env{LC_COLLATE} or
-@env{LC_ALL} environment variable to the value @samp{C}, or enable the
-@code{globasciiranges} shell option.
-
-Within @samp{[} and @samp{]}, @var{character classes} can be specified
-using the syntax
-@code{[:}@var{class}@code{:]}, where @var{class} is one of the
-following classes defined in the @sc{posix} standard:
-@example
-alnum   alpha   ascii   blank   cntrl   digit   graph   lower
-print   punct   space   upper   word    xdigit
-@end example
-@noindent
-A character class matches any character belonging to that class.
-The @code{word} character class matches letters, digits, and the character
-@samp{_}.
-
-Within @samp{[} and @samp{]}, an @var{equivalence class} can be
-specified using the syntax @code{[=}@var{c}@code{=]}, which
-matches all characters with the same collation weight (as defined
-by the current locale) as the character @var{c}.
-
-Within @samp{[} and @samp{]}, the syntax @code{[.}@var{symbol}@code{.]}
-matches the collating symbol @var{symbol}.
-@end table
-
-If the @code{extglob} shell option is enabled using the @code{shopt}
-builtin, several extended pattern matching operators are recognized.
-In the following description, a @var{pattern-list} is a list of one
-or more patterns separated by a @samp{|}.
-Composite patterns may be formed using one or more of the following
-sub-patterns:
-
-@table @code
-@item ?(@var{pattern-list})
-Matches zero or one occurrence of the given patterns.
-
-@item *(@var{pattern-list})
-Matches zero or more occurrences of the given patterns.
-
-@item +(@var{pattern-list})
-Matches one or more occurrences of the given patterns.
-
-@item @@(@var{pattern-list})
-Matches one of the given patterns.
-
-@item !(@var{pattern-list})
-Matches anything except one of the given patterns.
-@end table
-
-@node Quote Removal
-@subsection Quote Removal
-
-After the preceding expansions, all unquoted occurrences of the
-characters @samp{\}, @samp{'}, and @samp{"} that did not
-result from one of the above expansions are removed.
-
-@node Redirections
-@section Redirections
-@cindex redirection
-
-Before a command is executed, its input and output
-may be @var{redirected}
-using a special notation interpreted by the shell.
-Redirection allows commands' file handles to be
-duplicated, opened, closed,
-made to refer to different files,
-and can change the files the command reads from and writes to.
-Redirection may also be used to modify file handles in the
-current shell execution environment.  The following redirection
-operators may precede or appear anywhere within a
-simple command or may follow a command.
-Redirections are processed in the order they appear, from
-left to right.
-
-Each redirection that may be preceded by a file descriptor number
-may instead be preceded by a word of the form @{@var{varname}@}.
-In this case, for each redirection operator except
->&- and <&-, the shell will allocate a file descriptor greater
-than 10 and assign it to @{@var{varname}@}.  If >&- or <&- is preceded
-by @{@var{varname}@}, the value of @var{varname} defines the file
-descriptor to close.
-
-In the following descriptions, if the file descriptor number is
-omitted, and the first character of the redirection operator is
-@samp{<}, the redirection refers to the standard input (file
-descriptor 0).  If the first character of the redirection operator
-is @samp{>}, the redirection refers to the standard output (file
-descriptor 1).
-
-The word following the redirection operator in the following
-descriptions, unless otherwise noted, is subjected to brace expansion,
-tilde expansion, parameter expansion, command substitution, arithmetic
-expansion, quote removal, filename expansion, and word splitting.
-If it expands to more than one word, Bash reports an error.
-
-Note that the order of redirections is significant.  For example,
-the command
-@example
-ls > @var{dirlist} 2>&1
-@end example
-@noindent
-directs both standard output (file descriptor 1) and standard error
-(file descriptor 2) to the file @var{dirlist}, while the command
-@example
-ls 2>&1 > @var{dirlist}
-@end example
-@noindent
-directs only the standard output to file @var{dirlist},
-because the standard error was made a copy of the standard output
-before the standard output was redirected to @var{dirlist}.
-
-Bash handles several filenames specially when they are used in
-redirections, as described in the following table:
-
-@table @code
-@item /dev/fd/@var{fd}
-If @var{fd} is a valid integer, file descriptor @var{fd} is duplicated.
-
-@item /dev/stdin
-File descriptor 0 is duplicated.
-
-@item /dev/stdout
-File descriptor 1 is duplicated.
-
-@item /dev/stderr
-File descriptor 2 is duplicated.
-
-@item /dev/tcp/@var{host}/@var{port}
-If @var{host} is a valid hostname or Internet address, and @var{port}
-is an integer port number or service name, Bash attempts to open
-the corresponding TCP socket.
-
-@item /dev/udp/@var{host}/@var{port}
-If @var{host} is a valid hostname or Internet address, and @var{port}
-is an integer port number or service name, Bash attempts to open 
-the corresponding UDP socket.
-@end table
-
-A failure to open or create a file causes the redirection to fail.
-
-Redirections using file descriptors greater than 9 should be used with
-care, as they may conflict with file descriptors the shell uses
-internally.
-
-@subsection Redirecting Input
-Redirection of input causes the file whose name results from
-the expansion of @var{word}
-to be opened for reading on file descriptor @code{n},
-or the standard input (file descriptor 0) if @code{n}
-is not specified.
-
-The general format for redirecting input is:
-@example
-[@var{n}]<@var{word}
-@end example
-
-@subsection Redirecting Output
-Redirection of output causes the file whose name results from
-the expansion of @var{word}
-to be opened for writing on file descriptor @var{n},
-or the standard output (file descriptor 1) if @var{n}
-is not specified.  If the file does not exist it is created;
-if it does exist it is truncated to zero size.
-
-The general format for redirecting output is:
-@example
-[@var{n}]>[|]@var{word}
-@end example
-
-If the redirection operator is @samp{>}, and the @code{noclobber}
-option to the @code{set} builtin has been enabled, the redirection
-will fail if the file whose name results from the expansion of
-@var{word} exists and is a regular file.
-If the redirection operator is @samp{>|}, or the redirection operator is
-@samp{>} and the @code{noclobber} option is not enabled, the redirection
-is attempted even if the file named by @var{word} exists.
-
-@subsection Appending Redirected Output
-Redirection of output in this fashion
-causes the file whose name results from
-the expansion of @var{word}
-to be opened for appending on file descriptor @var{n},
-or the standard output (file descriptor 1) if @var{n}
-is not specified.  If the file does not exist it is created.
-
-The general format for appending output is:
-@example
-[@var{n}]>>@var{word}
-@end example
-
-@subsection Redirecting Standard Output and Standard Error
-This construct allows both the
-standard output (file descriptor 1) and
-the standard error output (file descriptor 2)
-to be redirected to the file whose name is the
-expansion of @var{word}.
-
-There are two formats for redirecting standard output and
-standard error:
-@example
-&>@var{word}
-@end example
-@noindent
-and
-@example
->&@var{word}
-@end example
-@noindent
-Of the two forms, the first is preferred.
-This is semantically equivalent to
-@example
->@var{word} 2>&1
-@end example
-When using the second form, @var{word} may not expand to a number or
-@samp{-}.  If it does, other redirection operators apply
-(see Duplicating File Descriptors below) for compatibility reasons.
-
-@subsection Appending Standard Output and Standard Error
-This construct allows both the
-standard output (file descriptor 1) and
-the standard error output (file descriptor 2)
-to be appended to the file whose name is the
-expansion of @var{word}.
-
-The format for appending standard output and standard error is:
-@example
-&>>@var{word}
-@end example
-@noindent
-This is semantically equivalent to
-@example
->>@var{word} 2>&1
-@end example
-(see Duplicating File Descriptors below).
-
-@subsection Here Documents
-This type of redirection instructs the shell to read input from the
-current source until a line containing only @var{word}
-(with no trailing blanks) is seen.  All of
-the lines read up to that point are then used as the standard
-input for a command.
-
-The format of here-documents is:
-@example
-<<[@minus{}]@var{word}
-        @var{here-document}
-@var{delimiter}
-@end example
-
-No parameter and variable expansion, command substitution,
-arithmetic expansion, or filename expansion is performed on
-@var{word}.  If any characters in @var{word} are quoted, the
-@var{delimiter} is the result of quote removal on @var{word},
-and the lines in the here-document are not expanded.
-If @var{word} is unquoted,
-all lines of the here-document are subjected to
-parameter expansion, command substitution, and arithmetic expansion,
-the character sequence @code{\newline} is ignored, and @samp{\}
-must be used to quote the characters
-@samp{\}, @samp{$}, and @samp{`}.
-
-If the redirection operator is @samp{<<-},
-then all leading tab characters are stripped from input lines and the
-line containing @var{delimiter}.
-This allows here-documents within shell scripts to be indented in a
-natural fashion.
-
-@subsection Here Strings
-A variant of here documents, the format is:
-@example
-<<< @var{word}
-@end example
-
-The @var{word} undergoes
-brace expansion, tilde expansion, parameter and variable expansion,
-command substitution, arithmetic expansion, and quote removal.
-Pathname expansion and word splitting are not performed.
-The result is supplied as a single string to the command on its
-standard input.
-
-@subsection Duplicating File Descriptors
-The redirection operator
-@example
-[@var{n}]<&@var{word}
-@end example
-@noindent
-is used to duplicate input file descriptors.
-If @var{word}
-expands to one or more digits, the file descriptor denoted by @var{n}
-is made to be a copy of that file descriptor.
-If the digits in @var{word} do not specify a file descriptor open for
-input, a redirection error occurs.
-If @var{word}
-evaluates to @samp{-}, file descriptor @var{n} is closed.
-If @var{n} is not specified, the standard input (file descriptor 0) is used.
-
-The operator
-@example
-[@var{n}]>&@var{word}
-@end example
-@noindent
-is used similarly to duplicate output file descriptors.  If
-@var{n} is not specified, the standard output (file descriptor 1) is used.
-If the digits in @var{word} do not specify a file descriptor open for
-output, a redirection error occurs.
-If @var{word}
-evaluates to @samp{-}, file descriptor @var{n} is closed.
-As a special case, if @var{n} is omitted, and @var{word} does not
-expand to one or more digits or @samp{-}, the standard output and standard
-error are redirected as described previously.
-
-@subsection Moving File Descriptors
-The redirection operator
-@example
-[@var{n}]<&@var{digit}-
-@end example
-@noindent
-moves the file descriptor @var{digit} to file descriptor @var{n},
-or the standard input (file descriptor 0) if @var{n} is not specified.
-@var{digit} is closed after being duplicated to @var{n}.
-
-Similarly, the redirection operator
-@example
-[@var{n}]>&@var{digit}-
-@end example
-@noindent
-moves the file descriptor @var{digit} to file descriptor @var{n},
-or the standard output (file descriptor 1) if @var{n} is not specified.
-
-@subsection Opening File Descriptors for Reading and Writing
-The redirection operator
-@example
-[@var{n}]<>@var{word}
-@end example
-@noindent
-causes the file whose name is the expansion of @var{word}
-to be opened for both reading and writing on file descriptor
-@var{n}, or on file descriptor 0 if @var{n}
-is not specified.  If the file does not exist, it is created.
-
-@node Executing Commands
-@section Executing Commands
-
-@menu
-* Simple Command Expansion::   How Bash expands simple commands before
-                               executing them.
-* Command Search and Execution::       How Bash finds commands and runs them.
-* Command Execution Environment::      The environment in which Bash
-                                       executes commands that are not
-                                       shell builtins.
-* Environment::                The environment given to a command.
-* Exit Status::                The status returned by commands and how Bash
-                       interprets it.
-* Signals::            What happens when Bash or a command it runs
-                       receives a signal.
-@end menu
-
-@node Simple Command Expansion
-@subsection Simple Command Expansion
-@cindex command expansion
-
-When a simple command is executed, the shell performs the following
-expansions, assignments, and redirections, from left to right.
-
-@enumerate
-@item
-The words that the parser has marked as variable assignments (those
-preceding the command name) and redirections are saved for later
-processing.
-
-@item
-The words that are not variable assignments or redirections are
-expanded (@pxref{Shell Expansions}).
-If any words remain after expansion, the first word
-is taken to be the name of the command and the remaining words are
-the arguments.
-
-@item
-Redirections are performed as described above (@pxref{Redirections}).
-
-@item
-The text after the @samp{=} in each variable assignment undergoes tilde
-expansion, parameter expansion, command substitution, arithmetic expansion,
-and quote removal before being assigned to the variable.
-@end enumerate
-
-If no command name results, the variable assignments affect the current
-shell environment.  Otherwise, the variables are added to the environment
-of the executed command and do not affect the current shell environment.
-If any of the assignments attempts to assign a value to a readonly variable,
-an error occurs, and the command exits with a non-zero status.
-
-If no command name results, redirections are performed, but do not
-affect the current shell environment.  A redirection error causes the
-command to exit with a non-zero status.
-
-If there is a command name left after expansion, execution proceeds as
-described below.  Otherwise, the command exits.  If one of the expansions
-contained a command substitution, the exit status of the command is
-the exit status of the last command substitution performed.  If there
-were no command substitutions, the command exits with a status of zero.
-
-@node Command Search and Execution
-@subsection Command Search and Execution
-@cindex command execution
-@cindex command search
-
-After a command has been split into words, if it results in a
-simple command and an optional list of arguments, the following
-actions are taken.
-
-@enumerate
-@item
-If the command name contains no slashes, the shell attempts to
-locate it.  If there exists a shell function by that name, that
-function is invoked as described in @ref{Shell Functions}.
-
-@item
-If the name does not match a function, the shell searches for
-it in the list of shell builtins.  If a match is found, that
-builtin is invoked.
-
-@item
-If the name is neither a shell function nor a builtin,
-and contains no slashes, Bash searches each element of
-@env{$PATH} for a directory containing an executable file
-by that name.  Bash uses a hash table to remember the full
-pathnames of executable files to avoid multiple @env{PATH} searches
-(see the description of @code{hash} in @ref{Bourne Shell Builtins}).
-A full search of the directories in @env{$PATH}
-is performed only if the command is not found in the hash table.
-If the search is unsuccessful, the shell searches for a defined shell
-function named @code{command_not_found_handle}.
-If that function exists, it is invoked with the original command and
-the original command's arguments as its arguments, and the function's
-exit status becomes the exit status of the shell.
-If that function is not defined, the shell prints an error
-message and returns an exit status of 127.
-
-@item
-If the search is successful, or if the command name contains
-one or more slashes, the shell executes the named program in
-a separate execution environment.
-Argument 0 is set to the name given, and the remaining arguments
-to the command are set to the arguments supplied, if any.
-
-@item
-If this execution fails because the file is not in executable
-format, and the file is not a directory, it is assumed to be a
-@var{shell script} and the shell executes it as described in
-@ref{Shell Scripts}.
-
-@item
-If the command was not begun asynchronously, the shell waits for
-the command to complete and collects its exit status.
-
-@end enumerate
-
-@node Command Execution Environment
-@subsection Command Execution Environment
-@cindex execution environment
-
-The shell has an @var{execution environment}, which consists of the
-following:
-
-@itemize @bullet
-@item
-open files inherited by the shell at invocation, as modified by
-redirections supplied to the @code{exec} builtin
-
-@item
-the current working directory as set by @code{cd}, @code{pushd}, or
-@code{popd}, or inherited by the shell at invocation
-
-@item
-the file creation mode mask as set by @code{umask} or inherited from
-the shell's parent
-
-@item
-current traps set by @code{trap}
-
-@item
-shell parameters that are set by variable assignment or with @code{set}
-or inherited from the shell's parent in the environment
-
-@item
-shell functions defined during execution or inherited from the shell's
-parent in the environment
-
-@item
-options enabled at invocation (either by default or with command-line
-arguments) or by @code{set}
-
-@item
-options enabled by @code{shopt} (@pxref{The Shopt Builtin})
-
-@item
-shell aliases defined with @code{alias} (@pxref{Aliases})
-
-@item
-various process @sc{id}s, including those of background jobs
-(@pxref{Lists}), the value of @code{$$}, and the value of
-@env{$PPID}
-
-@end itemize
-
-When a simple command other than a builtin or shell function
-is to be executed, it
-is invoked in a separate execution environment that consists of
-the following.  Unless otherwise noted, the values are inherited
-from the shell.
-
-@itemize @bullet
-@item
-the shell's open files, plus any modifications and additions specified
-by redirections to the command
-
-@item
-the current working directory
-
-@item
-the file creation mode mask
-
-@item
-shell variables and functions marked for export, along with variables
-exported for the command, passed in the environment (@pxref{Environment})
-
-@item
-traps caught by the shell are reset to the values inherited from the
-shell's parent, and traps ignored by the shell are ignored
-
-@end itemize
-
-A command invoked in this separate environment cannot affect the
-shell's execution environment. 
-
-Command substitution, commands grouped with parentheses,
-and asynchronous commands are invoked in a
-subshell environment that is a duplicate of the shell environment,
-except that traps caught by the shell are reset to the values
-that the shell inherited from its parent at invocation.  Builtin
-commands that are invoked as part of a pipeline are also executed
-in a subshell environment.  Changes made to the subshell environment
-cannot affect the shell's execution environment.
-
-Subshells spawned to execute command substitutions inherit the value of
-the @option{-e} option from the parent shell.  When not in @sc{posix} mode,
-Bash clears the @option{-e} option in such subshells.
-
-If a command is followed by a @samp{&} and job control is not active, the
-default standard input for the command is the empty file @file{/dev/null}.
-Otherwise, the invoked command inherits the file descriptors of the calling
-shell as modified by redirections.
-
-@node Environment
-@subsection Environment
-@cindex environment
-
-When a program is invoked it is given an array of strings
-called the @var{environment}.
-This is a list of name-value pairs, of the form @code{name=value}.
-
-Bash provides several ways to manipulate the environment.
-On invocation, the shell scans its own environment and
-creates a parameter for each name found, automatically marking
-it for @var{export}
-to child processes.  Executed commands inherit the environment.
-The @code{export} and @samp{declare -x}
-commands allow parameters and functions to be added to and
-deleted from the environment.  If the value of a parameter
-in the environment is modified, the new value becomes part
-of the environment, replacing the old.  The environment
-inherited by any executed command consists of the shell's
-initial environment, whose values may be modified in the shell,
-less any pairs removed by the @code{unset} and @samp{export -n}
-commands, plus any additions via the @code{export} and
-@samp{declare -x} commands.
-
-The environment for any simple command
-or function may be augmented temporarily by prefixing it with
-parameter assignments, as described in @ref{Shell Parameters}.
-These assignment statements affect only the environment seen
-by that command.
-
-If the @option{-k} option is set (@pxref{The Set Builtin}), then all
-parameter assignments are placed in the environment for a command,
-not just those that precede the command name.
-
-When Bash invokes an external command, the variable @samp{$_}
-is set to the full pathname of the command and passed to that
-command in its environment.
-
-@node Exit Status
-@subsection Exit Status
-@cindex exit status
-
-The exit status of an executed command is the value returned by the
-@var{waitpid} system call or equivalent function.  Exit statuses    
-fall between 0 and 255, though, as explained below, the shell may
-use values above 125 specially.  Exit statuses from shell builtins and
-compound commands are also limited to this range.  Under certain
-circumstances, the shell will use special values to indicate specific
-failure modes.
-
-For the shell's purposes, a command which exits with a
-zero exit status has succeeded.
-A non-zero exit status indicates failure.
-This seemingly counter-intuitive scheme is used so there
-is one well-defined way to indicate success and a variety of
-ways to indicate various failure modes.
-When a command terminates on a fatal signal whose number is @var{N},
-Bash uses the value 128+@var{N} as the exit status.
-
-If a command is not found, the child process created to
-execute it returns a status of 127.  If a command is found  
-but is not executable, the return status is 126.
-
-If a command fails because of an error during expansion or redirection,
-the exit status is greater than zero.
-
-The exit status is used by the Bash conditional commands
-(@pxref{Conditional Constructs}) and some of the list
-constructs (@pxref{Lists}).
-
-All of the Bash builtins return an exit status of zero if they succeed
-and a non-zero status on failure, so they may be used by the
-conditional and list constructs.
-All builtins return an exit status of 2 to indicate incorrect usage.
-
-@node Signals
-@subsection Signals
-@cindex signal handling
-
-When Bash is interactive, in the absence of any traps, it ignores
-@code{SIGTERM} (so that @samp{kill 0} does not kill an interactive shell),
-and @code{SIGINT}
-is caught and handled (so that the @code{wait} builtin is interruptible).
-When Bash receives a @code{SIGINT}, it breaks out of any executing loops.
-In all cases, Bash ignores @code{SIGQUIT}.
-If job control is in effect (@pxref{Job Control}), Bash
-ignores @code{SIGTTIN}, @code{SIGTTOU}, and @code{SIGTSTP}.
-
-Non-builtin commands started by Bash have signal handlers set to the
-values inherited by the shell from its parent.
-When job control is not in effect, asynchronous commands
-ignore @code{SIGINT} and @code{SIGQUIT} in addition to these inherited
-handlers.
-Commands run as a result of
-command substitution ignore the keyboard-generated job control signals
-@code{SIGTTIN}, @code{SIGTTOU}, and @code{SIGTSTP}.
-
-The shell exits by default upon receipt of a @code{SIGHUP}.
-Before exiting, an interactive shell resends the @code{SIGHUP} to
-all jobs, running or stopped.
-Stopped jobs are sent @code{SIGCONT} to ensure that they receive
-the @code{SIGHUP}.
-To prevent the shell from sending the @code{SIGHUP} signal to a
-particular job, it should be removed
-from the jobs table with the @code{disown}
-builtin (@pxref{Job Control Builtins}) or marked
-to not receive @code{SIGHUP} using @code{disown -h}.
-
-If the  @code{huponexit} shell option has been set with @code{shopt}
-(@pxref{The Shopt Builtin}), Bash sends a @code{SIGHUP} to all jobs when
-an interactive login shell exits.
-
-If Bash is waiting for a command to complete and receives a signal
-for which a trap has been set, the trap will not be executed until
-the command completes. 
-When Bash is waiting for an asynchronous
-command via the @code{wait} builtin, the reception of a signal for
-which a trap has been set will cause the @code{wait} builtin to return
-immediately with an exit status greater than 128, immediately after
-which the trap is executed.
-
-@node Shell Scripts
-@section Shell Scripts
-@cindex shell script
-
-A shell script is a text file containing shell commands.  When such
-a file is used as the first non-option argument when invoking Bash,
-and neither the @option{-c} nor @option{-s} option is supplied
-(@pxref{Invoking Bash}), 
-Bash reads and executes commands from the file, then exits.  This
-mode of operation creates a non-interactive shell.  The shell first
-searches for the file in the current directory, and looks in the
-directories in @env{$PATH} if not found there.
-
-When Bash runs
-a shell script, it sets the special parameter @code{0} to the name
-of the file, rather than the name of the shell, and the positional
-parameters are set to the remaining arguments, if any are given.
-If no additional arguments are supplied, the positional parameters
-are unset.
-
-A shell script may be made executable by using the @code{chmod} command
-to turn on the execute bit.  When Bash finds such a file while
-searching the @env{$PATH} for a command, it spawns a subshell to
-execute it.  In other words, executing
-@example
-filename @var{arguments}
-@end example
-@noindent
-is equivalent to executing
-@example
-bash filename @var{arguments}
-@end example
-
-@noindent
-if @code{filename} is an executable shell script.
-This subshell reinitializes itself, so that the effect is as if a
-new shell had been invoked to interpret the script, with the
-exception that the locations of commands remembered by the parent
-(see the description of @code{hash} in @ref{Bourne Shell Builtins})
-are retained by the child.
-
-Most versions of Unix make this a part of the operating system's command
-execution mechanism.  If the first line of a script begins with
-the two characters @samp{#!}, the remainder of the line specifies
-an interpreter for the program.
-Thus, you can specify Bash, @code{awk}, Perl, or some other
-interpreter and write the rest of the script file in that language.
-
-The arguments to the interpreter
-consist of a single optional argument following the interpreter
-name on the first line of the script file, followed by the name of
-the script file, followed by the rest of the arguments.  Bash
-will perform this action on operating systems that do not handle it
-themselves.  Note that some older versions of Unix limit the interpreter
-name and argument to a maximum of 32 characters.
-
-Bash scripts often begin with @code{#! /bin/bash} (assuming that
-Bash has been installed in @file{/bin}), since this ensures that
-Bash will be used to interpret the script, even if it is executed
-under another shell.
-
-@node Shell Builtin Commands
-@chapter Shell Builtin Commands
-
-@menu
-* Bourne Shell Builtins::      Builtin commands inherited from the Bourne
-                               Shell.
-* Bash Builtins::              Table of builtins specific to Bash.
-* Modifying Shell Behavior::   Builtins to modify shell attributes and
-                               optional behavior.
-* Special Builtins::           Builtin commands classified specially by
-                               POSIX.
-@end menu
-
-Builtin commands are contained within the shell itself.
-When the name of a builtin command is used as the first word of
-a simple command (@pxref{Simple Commands}), the shell executes
-the command directly, without invoking another program.
-Builtin commands are necessary to implement functionality impossible
-or inconvenient to obtain with separate utilities.
-
-This section briefly describes the builtins which Bash inherits from
-the Bourne Shell, as well as the builtin commands which are unique
-to or have been extended in Bash.
-
-Several builtin commands are described in other chapters:  builtin
-commands which provide the Bash interface to the job control
-facilities (@pxref{Job Control Builtins}), the directory stack
-(@pxref{Directory Stack Builtins}), the command history
-(@pxref{Bash History Builtins}), and the programmable completion
-facilities (@pxref{Programmable Completion Builtins}).
-
-Many of the builtins have been extended by @sc{posix} or Bash.
-
-Unless otherwise noted, each builtin command documented as accepting
-options preceded by @samp{-} accepts @samp{--}
-to signify the end of the options.
-The @code{:}, @code{true}, @code{false}, and @code{test}
-builtins do not accept options and do not treat @samp{--} specially.
-The @code{exit}, @code{logout}, @code{break}, @code{continue}, @code{let},
-and @code{shift} builtins accept and process arguments beginning
-with @samp{-} without requiring @samp{--}.
-Other builtins that accept arguments but are not specified as accepting
-options interpret arguments beginning with @samp{-} as invalid options and
-require @samp{--} to prevent this interpretation.
-
-@node Bourne Shell Builtins
-@section Bourne Shell Builtins
-
-The following shell builtin commands are inherited from the Bourne Shell.
-These commands are implemented as specified by the @sc{posix} standard.
-
-@table @code
-@item :    @r{(a colon)}
-@btindex :
-@example
-: [@var{arguments}]
-@end example
-
-Do nothing beyond expanding @var{arguments} and performing redirections.
-The return status is zero.
-
-@item .    @r{(a period)}
-@btindex .
-@example
-. @var{filename} [@var{arguments}]
-@end example
-
-Read and execute commands from the @var{filename} argument in the
-current shell context.  If @var{filename} does not contain a slash,
-the @env{PATH} variable is used to find @var{filename}.
-When Bash is not in @sc{posix} mode, the current directory is searched
-if @var{filename} is not found in @env{$PATH}.
-If any @var{arguments} are supplied, they become the positional
-parameters when @var{filename} is executed.  Otherwise the positional
-parameters are unchanged.
-The return status is the exit status of the last command executed, or
-zero if no commands are executed.  If @var{filename} is not found, or
-cannot be read, the return status is non-zero.
-This builtin is equivalent to @code{source}.
-
-@item break
-@btindex break
-@example
-break [@var{n}]
-@end example
-
-Exit from a @code{for}, @code{while}, @code{until}, or @code{select} loop.
-If @var{n} is supplied, the @var{n}th enclosing loop is exited.
-@var{n} must be greater than or equal to 1.
-The return status is zero unless @var{n} is not greater than or equal to 1.
-
-@item cd
-@btindex cd
-@example
-cd [-L|[-P [-e]]] [@var{directory}]
-@end example
-
-Change the current working directory to @var{directory}.
-If @var{directory} is not supplied, the value of the @env{HOME}
-shell variable is used.
-Any additional arguments following @var{directory} are ignored.
-If the shell variable
-@env{CDPATH} exists, it is used as a search path:
-each directory name in @env{CDPATH} is searched for
-@var{directory}, with alternative directory names in @env{CDPATH}
-separated by a colon (@samp{:}).
-If @var{directory} begins with a slash, @env{CDPATH} is not used.
-
-The @option{-P} option means to not follow symbolic links: symbolic links
-are resolved while @code{cd} is traversing @var{directory} and before
-processing an instance of @samp{..} in @var{directory}.
-
-By default, or when the @option{-L} option is supplied, symbolic links
-in @var{directory} are resolved after @code{cd} processes an instance
-of @samp{..} in @var{directory}.
-
-If @samp{..} appears in @var{directory}, it is processed by removing the
-immediately preceding pathname component, back to a slash or the beginning
-of @var{directory}.
-
-If the @option{-e} option is supplied with @option{-P}
-and the current working directory cannot be successfully determined
-after a successful directory change, @code{cd} will return an unsuccessful
-status.
-If @var{directory} is @samp{-}, it is converted to @env{$OLDPWD}
-before the directory change is attempted.
-
-If a non-empty directory name from @env{CDPATH} is used, or if
-@samp{-} is the first argument, and the directory change is
-successful, the absolute pathname of the new working directory is
-written to the standard output.
-
-The return status is zero if the directory is successfully changed,
-non-zero otherwise.
-
-@item continue
-@btindex continue
-@example
-continue [@var{n}]
-@end example
-
-Resume the next iteration of an enclosing @code{for}, @code{while},
-@code{until}, or @code{select} loop.
-If @var{n} is supplied, the execution of the @var{n}th enclosing loop
-is resumed.
-@var{n} must be greater than or equal to 1.
-The return status is zero unless @var{n} is not greater than or equal to 1.
-
-@item eval
-@btindex eval
-@example
-eval [@var{arguments}]
-@end example
-
-The arguments are concatenated together into a single command, which is
-then read and executed, and its exit status returned as the exit status
-of @code{eval}.
-If there are no arguments or only empty arguments, the return status is
-zero.
-
-@item exec
-@btindex exec
-@example
-exec [-cl] [-a @var{name}] [@var{command} [@var{arguments}]]
-@end example
-
-If @var{command}
-is supplied, it replaces the shell without creating a new process.
-If the @option{-l} option is supplied, the shell places a dash at the
-beginning of the zeroth argument passed to @var{command}.
-This is what the @code{login} program does.
-The @option{-c} option causes @var{command} to be executed with an empty
-environment.
-If @option{-a} is supplied, the shell passes @var{name} as the zeroth
-argument to @var{command}.
-If @var{command}
-cannot be executed for some reason, a non-interactive shell exits,
-unless the @code{execfail} shell option
-is enabled.  In that case, it returns failure.
-An interactive shell returns failure if the file cannot be executed.
-If no @var{command} is specified, redirections may be used to affect
-the current shell environment.  If there are no redirection errors, the
-return status is zero; otherwise the return status is non-zero.
-
-@item exit
-@btindex exit
-@example
-exit [@var{n}]
-@end example
-
-Exit the shell, returning a status of @var{n} to the shell's parent.
-If @var{n} is omitted, the exit status is that of the last command executed.
-Any trap on @code{EXIT} is executed before the shell terminates.
-
-@item export
-@btindex export
-@example
-export [-fn] [-p] [@var{name}[=@var{value}]]
-@end example
-
-Mark each @var{name} to be passed to child processes
-in the environment.  If the @option{-f} option is supplied, the @var{name}s
-refer to shell functions; otherwise the names refer to shell variables.
-The @option{-n} option means to no longer mark each @var{name} for export.
-If no @var{names} are supplied, or if the @option{-p} option is given, a
-list of names of all exported variables is displayed.
-The @option{-p} option displays output in a form that may be reused as input.
-If a variable name is followed by =@var{value}, the value of
-the variable is set to @var{value}.
-
-The return status is zero unless an invalid option is supplied, one of
-the names is not a valid shell variable name, or @option{-f} is supplied
-with a name that is not a shell function.
-
-@item getopts
-@btindex getopts
-@example
-getopts @var{optstring} @var{name} [@var{args}]
-@end example
-
-@code{getopts} is used by shell scripts to parse positional parameters.
-@var{optstring} contains the option characters to be recognized; if a
-character is followed by a colon, the option is expected to have an
-argument, which should be separated from it by whitespace.
-The colon (@samp{:}) and question mark (@samp{?}) may not be
-used as option characters.
-Each time it is invoked, @code{getopts}
-places the next option in the shell variable @var{name}, initializing
-@var{name} if it does not exist,
-and the index of the next argument to be processed into the
-variable @env{OPTIND}.
-@env{OPTIND} is initialized to 1 each time the shell or a shell script
-is invoked.
-When an option requires an argument,
-@code{getopts} places that argument into the variable @env{OPTARG}.
-The shell does not reset @env{OPTIND} automatically; it must be manually
-reset between multiple calls to @code{getopts} within the same shell
-invocation if a new set of parameters is to be used.
-
-When the end of options is encountered, @code{getopts} exits with a
-return value greater than zero.
-@env{OPTIND} is set to the index of the first non-option argument,
-and @var{name} is set to @samp{?}.
-
-@code{getopts}
-normally parses the positional parameters, but if more arguments are
-given in @var{args}, @code{getopts} parses those instead.
-
-@code{getopts} can report errors in two ways.  If the first character of
-@var{optstring} is a colon, @var{silent}
-error reporting is used.  In normal operation, diagnostic messages
-are printed when invalid options or missing option arguments are
-encountered.
-If the variable @env{OPTERR}
-is set to 0, no error messages will be displayed, even if the first
-character of @code{optstring} is not a colon.
-
-If an invalid option is seen,
-@code{getopts} places @samp{?} into @var{name} and, if not silent,
-prints an error message and unsets @env{OPTARG}.
-If @code{getopts} is silent, the option character found is placed in
-@env{OPTARG} and no diagnostic message is printed.
-
-If a required argument is not found, and @code{getopts}
-is not silent, a question mark (@samp{?}) is placed in @var{name},
-@code{OPTARG} is unset, and a diagnostic message is printed.
-If @code{getopts} is silent, then a colon (@samp{:}) is placed in
-@var{name} and @env{OPTARG} is set to the option character found.
-
-@item hash
-@btindex hash
-@example
-hash [-r] [-p @var{filename}] [-dt] [@var{name}]
-@end example
-
-Each time @code{hash} is invoked, it remembers the full pathnames of the
-commands specified as @var{name} arguments,
-so they need not be searched for on subsequent invocations.
-The commands are found by searching through the directories listed in
-@env{$PATH}.
-Any previously-remembered pathname is discarded.
-The @option{-p} option inhibits the path search, and @var{filename} is
-used as the location of @var{name}.
-The @option{-r} option causes the shell to forget all remembered locations.
-The @option{-d} option causes the shell to forget the remembered location
-of each @var{name}.
-If the @option{-t} option is supplied, the full pathname to which each
-@var{name} corresponds is printed.  If multiple @var{name} arguments are
-supplied with @option{-t} the @var{name} is printed before the hashed
-full pathname.
-The @option{-l} option causes output to be displayed in a format
-that may be reused as input.
-If no arguments are given, or if only @option{-l} is supplied,
-information about remembered commands is printed.
-The return status is zero unless a @var{name} is not found or an invalid
-option is supplied.
-
-@item pwd
-@btindex pwd
-@example
-pwd [-LP]
-@end example
-
-Print the absolute pathname of the current working directory.
-If the @option{-P} option is supplied, the pathname printed will not
-contain symbolic links.
-If the @option{-L} option is supplied, the pathname printed may contain
-symbolic links.
-The return status is zero unless an error is encountered while
-determining the name of the current directory or an invalid option
-is supplied.
-
-@item readonly
-@btindex readonly
-@example
-readonly [-aAf] [-p] [@var{name}[=@var{value}]] @dots{}
-@end example
-
-Mark each @var{name} as readonly.
-The values of these names may not be changed by subsequent assignment.
-If the @option{-f} option is supplied, each @var{name} refers to a shell
-function.
-The @option{-a} option means each @var{name} refers to an indexed
-array variable; the @option{-A} option means each @var{name} refers
-to an associative array variable.
-If both options are supplied, @option{-A} takes precedence.
-If no @var{name} arguments are given, or if the @option{-p}
-option is supplied, a list of all readonly names is printed.
-The other options may be used to restrict the output to a subset of
-the set of readonly names.
-The @option{-p} option causes output to be displayed in a format that
-may be reused as input.
-If a variable name is followed by =@var{value}, the value of
-the variable is set to @var{value}.
-The return status is zero unless an invalid option is supplied, one of
-the @var{name} arguments is not a valid shell variable or function name,
-or the @option{-f} option is supplied with a name that is not a shell function.
-
-@item return
-@btindex return
-@example
-return [@var{n}]
-@end example
-
-Cause a shell function to stop executing and return the value @var{n}
-to its caller.
-If @var{n} is not supplied, the return value is the exit status of the
-last command executed in the function.
-@code{return} may also be used to terminate execution of a script
-being executed with the @code{.} (@code{source}) builtin,
-returning either @var{n} or
-the exit status of the last command executed within the script as the exit
-status of the script.
-If @var{n} is supplied, the return value is its least significant
-8 bits.
-Any command associated with the @code{RETURN} trap is executed
-before execution resumes after the function or script.
-The return status is non-zero if @code{return} is supplied a non-numeric
-argument or is used outside a function
-and not during the execution of a script by @code{.} or @code{source}.
-
-@item shift
-@btindex shift
-@example
-shift [@var{n}]
-@end example
-
-Shift the positional parameters to the left by @var{n}.
-The positional parameters from @var{n}+1 @dots{} @code{$#} are
-renamed to @code{$1} @dots{} @code{$#}-@var{n}.
-Parameters represented by the numbers @code{$#} to @code{$#}-@var{n}+1
-are unset.
-@var{n} must be a non-negative number less than or equal to @code{$#}.
-If @var{n} is zero or greater than @code{$#}, the positional parameters
-are not changed.
-If @var{n} is not supplied, it is assumed to be 1.
-The return status is zero unless @var{n} is greater than @code{$#} or
-less than zero, non-zero otherwise.
-
-@item test
-@itemx [
-@btindex test
-@btindex [
-@example
-test @var{expr}
-@end example
-
-Evaluate a conditional express
-ion @var{expr} and return a status of 0
-(true) or 1 (false).
-Each operator and operand must be a separate argument.
-Expressions are composed of the primaries described below in
-@ref{Bash Conditional Expressions}.
-@code{test} does not accept any options, nor does it accept and ignore
-an argument of @option{--} as signifying the end of options.
-
-When the @code{[} form is used, the last argument to the command must
-be a @code{]}.
-
-Expressions may be combined using the following operators, listed in
-decreasing order of precedence.
-The evaluation depends on the number of arguments; see below.
-Operator precedence is used when there are five or more arguments.
-
-@table @code
-@item ! @var{expr}
-True if @var{expr} is false.
-
-@item ( @var{expr} )
-Returns the value of @var{expr}.
-This may be used to override the normal precedence of operators.
-
-@item @var{expr1} -a @var{expr2}
-True if both @var{expr1} and @var{expr2} are true.
-
-@item @var{expr1} -o @var{expr2}
-True if either @var{expr1} or @var{expr2} is true.
-@end table
-
-The @code{test} and @code{[} builtins evaluate conditional
-expressions using a set of rules based on the number of arguments.
-
-@table @asis
-@item 0 arguments
-The expression is false.
-
-@item 1 argument
-The expression is true if and only if the argument is not null.
-
-@item 2 arguments
-If the first argument is @samp{!}, the expression is true if and
-only if the second argument is null.
-If the first argument is one of the unary conditional operators
-(@pxref{Bash Conditional Expressions}), the expression
-is true if the unary test is true.
-If the first argument is not a valid unary operator, the expression is
-false.
-
-@item 3 arguments
-The following conditions are applied in the order listed.
-If the second argument is one of the binary conditional
-operators (@pxref{Bash Conditional Expressions}), the
-result of the expression is the result of the binary test using the
-first and third arguments as operands.
-The @samp{-a} and @samp{-o} operators are considered binary operators
-when there are three arguments.
-If the first argument is @samp{!}, the value is the negation of
-the two-argument test using the second and third arguments.
-If the first argument is exactly @samp{(} and the third argument is
-exactly @samp{)}, the result is the one-argument test of the second
-argument.
-Otherwise, the expression is false.
-
-@item 4 arguments
-If the first argument is @samp{!}, the result is the negation of
-the three-argument expression composed of the remaining arguments.
-Otherwise, the expression is parsed and evaluated according to 
-precedence using the rules listed above.
-
-@item 5 or more arguments
-The expression is parsed and evaluated according to precedence
-using the rules listed above.
-@end table
-
-When used with @code{test} or @samp{[}, the @samp{<} and @samp{>}
-operators sort lexicographically using ASCII ordering.
-
-@item times
-@btindex times
-@example
-times
-@end example
-
-Print out the user and system times used by the shell and its children.
-The return status is zero.
-
-@item trap
-@btindex trap
-@example
-trap [-lp] [@var{arg}] [@var{sigspec} @dots{}]
-@end example
-
-The commands in @var{arg} are to be read and executed when the
-shell receives signal @var{sigspec}.  If @var{arg} is absent (and
-there is a single @var{sigspec}) or
-equal to @samp{-}, each specified signal's disposition is reset
-to the value it had when the shell was started.
-If @var{arg} is the null string, then the signal specified by
-each @var{sigspec} is ignored by the shell and commands it invokes.
-If @var{arg} is not present and @option{-p} has been supplied,
-the shell displays the trap commands associated with each @var{sigspec}.
-If no arguments are supplied, or
-only @option{-p} is given, @code{trap} prints the list of commands
-associated with each signal number in a form that may be reused as
-shell input.
-The @option{-l} option causes the shell to print a list of signal names
-and their corresponding numbers.
-Each @var{sigspec} is either a signal name or a signal number.
-Signal names are case insensitive and the @code{SIG} prefix is optional.
-
-If a @var{sigspec}
-is @code{0} or @code{EXIT}, @var{arg} is executed when the shell exits.
-If a @var{sigspec} is @code{DEBUG}, the command @var{arg} is executed
-before every simple command, @code{for} command, @code{case} command,
-@code{select} command, every arithmetic @code{for} command, and before
-the first command executes in a shell function.
-Refer to the description of the @code{extdebug} option to the
-@code{shopt} builtin (@pxref{The Shopt Builtin}) for details of its
-effect on the @code{DEBUG} trap.
-If a @var{sigspec} is @code{RETURN}, the command @var{arg} is executed
-each time a shell function or a script executed with the @code{.} or
-@code{source} builtins finishes executing.
-
-If a @var{sigspec} is @code{ERR}, the command @var{arg} 
-is executed whenever a simple command has a non-zero exit status,
-subject to the following conditions.
-The @code{ERR} trap is not executed if the failed command is part of the
-command list immediately following an @code{until} or @code{while} keyword,
-part of the test following the @code{if} or @code{elif} reserved words,
-part of a command executed in a @code{&&} or @code{||} list,
-or if the command's return
-status is being inverted using @code{!}.
-These are the same conditions obeyed by the @code{errexit} option.
-
-Signals ignored upon entry to the shell cannot be trapped or reset.
-Trapped signals that are not being ignored are reset to their original
-values in a subshell or subshell environment when one is created.
-
-The return status is zero unless a @var{sigspec} does not specify a
-valid signal.
-
-@item umask
-@btindex umask
-@example
-umask [-p] [-S] [@var{mode}]
-@end example
-
-Set the shell process's file creation mask to @var{mode}.  If
-@var{mode} begins with a digit, it is interpreted as an octal number;
-if not, it is interpreted as a symbolic mode mask similar
-to that accepted by the @code{chmod} command.  If @var{mode} is
-omitted, the current value of the mask is printed.  If the @option{-S}
-option is supplied without a @var{mode} argument, the mask is printed
-in a symbolic format.
-If the  @option{-p} option is supplied, and @var{mode}
-is omitted, the output is in a form that may be reused as input.
-The return status is zero if the mode is successfully changed or if
-no @var{mode} argument is supplied, and non-zero otherwise.
-
-Note that when the mode is interpreted as an octal number, each number
-of the umask is subtracted from @code{7}.  Thus, a umask of @code{022}
-results in permissions of @code{755}.
-
-@item unset
-@btindex unset
-@example
-unset [-fnv] [@var{name}]
-@end example
-
-Remove each variable or function @var{name}.
-If the @option{-v} option is given, each
-@var{name} refers to a shell variable and that variable is remvoved.
-If the @option{-f} option is given, the @var{name}s refer to shell
-functions, and the function definition is removed.
-If the @option{-n} option is supplied, and @var{name} is a variable with
-the @var{nameref} attribute, @var{name} will be unset rather than the
-variable it references.
-@option{-n} has no effect if the @option{-f} option is supplied.
-If no options are supplied, each @var{name} refers to a variable; if
-there is no variable by that name, any function with that name is
-unset.
-Readonly variables and functions may not be unset.
-The return status is zero unless a @var{name} is readonly.
-@end table
-
-@node Bash Builtins
-@section Bash Builtin Commands
-
-This section describes builtin commands which are unique to
-or have been extended in Bash.
-Some of these commands are specified in the @sc{posix} standard.
-
-@table @code
-
-@item alias
-@btindex alias
-@example
-alias [-p] [@var{name}[=@var{value}] @dots{}]
-@end example
-
-Without arguments or with the @option{-p} option, @code{alias} prints
-the list of aliases on the standard output in a form that allows
-them to be reused as input.
-If arguments are supplied, an alias is defined for each @var{name}
-whose @var{value} is given.  If no @var{value} is given, the name
-and value of the alias is printed.
-Aliases are described in @ref{Aliases}.
-
-@item bind
-@btindex bind
-@example
-bind [-m @var{keymap}] [-lpsvPSVX]
-bind [-m @var{keymap}] [-q @var{function}] [-u @var{function}] [-r @var{keyseq}]
-bind [-m @var{keymap}] -f @var{filename}
-bind [-m @var{keymap}] -x @var{keyseq:shell-command}
-bind [-m @var{keymap}] @var{keyseq:function-name}
-bind @var{readline-command}
-@end example
-
-Display current Readline (@pxref{Command Line Editing})
-key and function bindings,
-bind a key sequence to a Readline function or macro,
-or set a Readline variable.
-Each non-option argument is a command as it would appear in a
-Readline initialization file (@pxref{Readline Init File}),
-but each binding or command must be passed as a separate argument;  e.g.,
-@samp{"\C-x\C-r":re-read-init-file}.
-
-Options, if supplied, have the following meanings:
-
-@table @code
-@item -m @var{keymap}
-Use @var{keymap} as the keymap to be affected by
-the subsequent bindings.  Acceptable @var{keymap}
-names are
-@code{emacs},
-@code{emacs-standard},
-@code{emacs-meta},
-@code{emacs-ctlx},
-@code{vi},
-@code{vi-move},
-@code{vi-command}, and
-@code{vi-insert}.
-@code{vi} is equivalent to @code{vi-command};
-@code{emacs} is equivalent to @code{emacs-standard}.
-
-@item -l
-List the names of all Readline functions.
-
-@item -p
-Display Readline function names and bindings in such a way that they
-can be used as input or in a Readline initialization file.
-
-@item -P
-List current Readline function names and bindings.
-
-@item -v
-Display Readline variable names and values in such a way that they
-can be used as input or in a Readline initialization file.
-
-@item -V
-List current Readline variable names and values.
-
-@item -s
-Display Readline key sequences bound to macros and the strings they output
-in such a way that they can be used as input or in a Readline
-initialization file.
-
-@item -S
-Display Readline key sequences bound to macros and the strings they output.
-
-@item -f @var{filename}
-Read key bindings from @var{filename}.
-
-@item -q @var{function}
-Query about which keys invoke the named @var{function}.
-
-@item -u @var{function}
-Unbind all keys bound to the named @var{function}.
-
-@item -r @var{keyseq}
-Remove any current binding for @var{keyseq}.
-
-@item -x @var{keyseq:shell-command}
-Cause @var{shell-command} to be executed whenever @var{keyseq} is
-entered.
-When @var{shell-command} is executed, the shell sets the
-@code{READLINE_LINE} variable to the contents of the Readline line
-buffer and the @code{READLINE_POINT} variable to the current location
-of the insertion point.
-If the executed command changes the value of @code{READLINE_LINE} or
-@code{READLINE_POINT}, those new values will be reflected in the
-editing state.
-
-@item -X
-List all key sequences bound to shell commands and the associated commands
-in a format that can be reused as input.
-@end table
-
-@noindent
-The return status is zero unless an invalid option is supplied or an
-error occurs.
-
-@item builtin
-@btindex builtin
-@example
-builtin [@var{shell-builtin} [@var{args}]]
-@end example
-
-Run a shell builtin, passing it @var{args}, and return its exit status.
-This is useful when defining a shell function with the same
-name as a shell builtin, retaining the functionality of the builtin within
-the function.
-The return status is non-zero if @var{shell-builtin} is not a shell
-builtin command.
-
-@item caller
-@btindex caller
-@example
-caller [@var{expr}]
-@end example
-
-Returns the context of any active subroutine call (a shell function or
-a script executed with the @code{.} or @code{source} builtins).
-
-Without @var{expr}, @code{caller} displays the line number and source
-filename of the current subroutine call.
-If a non-negative integer is supplied as @var{expr}, @code{caller} 
-displays the line number, subroutine name, and source file corresponding
-to that position in the current execution call stack.  This extra
-information may be used, for example, to print a stack trace.  The
-current frame is frame 0.
-
-The return value is 0 unless the shell is not executing a subroutine
-call or @var{expr} does not correspond to a valid position in the
-call stack.
-
-@item command
-@btindex command
-@example
-command [-pVv] @var{command} [@var{arguments} @dots{}]
-@end example
-
-Runs @var{command} with @var{arguments} ignoring any shell function
-named @var{command}.
-Only shell builtin commands or commands found by searching the
-@env{PATH} are executed.
-If there is a shell function named @code{ls}, running @samp{command ls}
-within the function will execute the external command @code{ls}
-instead of calling the function recursively.
-The @option{-p} option means to use a default value for @env{PATH}
-that is guaranteed to find all of the standard utilities.
-The return status in this case is 127 if @var{command} cannot be
-found or an error occurred, and the exit status of @var{command}
-otherwise.
-
-If either the @option{-V} or @option{-v} option is supplied, a
-description of @var{command} is printed.  The @option{-v} option
-causes a single word indicating the command or file name used to
-invoke @var{command} to be displayed; the @option{-V} option produces
-a more verbose description.  In this case, the return status is
-zero if @var{command} is found, and non-zero if not.
-
-@item declare
-@btindex declare
-@example
-declare [-aAfFgilnrtux] [-p] [@var{name}[=@var{value}] @dots{}]
-@end example
-
-Declare variables and give them attributes.  If no @var{name}s
-are given, then display the values of variables instead. 
-
-The @option{-p} option will display the attributes and values of each
-@var{name}.
-When @option{-p} is used with @var{name} arguments, additional options
-are ignored.
-
-When @option{-p} is supplied without @var{name} arguments, @code{declare}
-will display the attributes and values of all variables having the
-attributes specified by the additional options.
-If no other options are supplied with @option{-p}, @code{declare} will
-display the attributes and values of all shell variables.  The @option{-f}
-option will restrict the display to shell functions.
-
-The @option{-F} option inhibits the display of function definitions;
-only the function name and attributes are printed.
-If the @code{extdebug} shell option is enabled using @code{shopt}
-(@pxref{The Shopt Builtin}), the source file name and line number where
-the function is defined are displayed as well.
-@option{-F} implies @option{-f}.
-
-The @option{-g} option forces variables to be created or modified at
-the global scope, even when @code{declare} is executed in a shell function.
-It is ignored in all other cases.
-
-The following options can be used to restrict output to variables with
-the specified attributes or to give variables attributes:
-
-@table @code
-@item -a
-Each @var{name} is an indexed array variable (@pxref{Arrays}).
-
-@item -A
-Each @var{name} is an associative array variable (@pxref{Arrays}).
-
-@item -f
-Use function names only.
-
-@item -i
-The variable is to be treated as
-an integer; arithmetic evaluation (@pxref{Shell Arithmetic}) is
-performed when the variable is assigned a value.
-
-@item -l
-When the variable is assigned a value, all upper-case characters are
-converted to lower-case.
-The upper-case attribute is disabled.
-
-@item -n
-Give each @var{name} the @var{nameref} attribute, making
-it a name reference to another variable.
-That other variable is defined by the value of @var{name}.
-All references and assignments to @var{name}, except for changing the
-@option{-n} attribute itself, are performed on the variable referenced by
-@var{name}'s value.
-The @option{-n} attribute cannot be applied to array variables.
-
-@item -r
-Make @var{name}s readonly.  These names cannot then be assigned values
-by subsequent assignment statements or unset.
-
-@item -t
-Give each @var{name} the @code{trace} attribute.
-Traced functions inherit the @code{DEBUG} and @code{RETURN} traps from
-the calling shell.
-The trace attribute has no special meaning for variables.
-
-@item -u
-When the variable is assigned a value, all lower-case characters are
-converted to upper-case.
-The lower-case attribute is disabled.
-
-@item -x
-Mark each @var{name} for export to subsequent commands via
-the environment.
-@end table
-
-Using @samp{+} instead of @samp{-} turns off the attribute instead,
-with the exceptions that @samp{+a}
-may not be used to destroy an array variable and @samp{+r} will not
-remove the readonly attribute.
-When used in a function, @code{declare} makes each @var{name} local,
-as with the @code{local} command, unless the @option{-g} option is used.
-If a variable name is followed by =@var{value}, the value of the variable
-is set to @var{value}.
-
-The return status is zero unless an invalid option is encountered,
-an attempt is made to define a function using @samp{-f foo=bar},
-an attempt is made to assign a value to a readonly variable,
-an attempt is made to assign a value to an array variable without
-using the compound assignment syntax (@pxref{Arrays}),
-one of the @var{names} is not a valid shell variable name,
-an attempt is made to turn off readonly status for a readonly variable,
-an attempt is made to turn off array status for an array variable,
-or an attempt is made to display a non-existent function with @option{-f}.
-
-@item echo
-@btindex echo
-@example
-echo [-neE] [@var{arg} @dots{}]
-@end example
-
-Output the @var{arg}s, separated by spaces, terminated with a
-newline.
-The return status is 0 unless a write error occurs.
-If @option{-n} is specified, the trailing newline is suppressed.
-If the @option{-e} option is given, interpretation of the following
-backslash-escaped characters is enabled.
-The @option{-E} option disables the interpretation of these escape characters,
-even on systems where they are interpreted by default.
-The @code{xpg_echo} shell option may be used to
-dynamically determine whether or not @code{echo} expands these
-escape characters by default.
-@code{echo} does not interpret @option{--} to mean the end of options.
-
-@code{echo} interprets the following escape sequences:
-@table @code
-@item \a
-alert (bell)
-@item \b
-backspace
-@item \c
-suppress further output
-@item \e
-@itemx \E
-escape
-@item \f
-form feed
-@item \n
-new line
-@item \r
-carriage return
-@item \t 
-horizontal tab
-@item \v
-vertical tab
-@item \\
-backslash
-@item \0@var{nnn}
-the eight-bit character whose value is the octal value @var{nnn}
-(zero to three octal digits)
-@item \x@var{HH}
-the eight-bit character whose value is the hexadecimal value @var{HH}
-(one or two hex digits)
-@item \u@var{HHHH}
-the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
-@var{HHHH} (one to four hex digits)
-@item \U@var{HHHHHHHH}
-the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
-@var{HHHHHHHH} (one to eight hex digits)
-@end table
-
-@item enable
-@btindex enable
-@example
-enable [-a] [-dnps] [-f @var{filename}] [@var{name} @dots{}]
-@end example
-
-Enable and disable builtin shell commands.
-Disabling a builtin allows a disk command which has the same name
-as a shell builtin to be executed without specifying a full pathname,
-even though the shell normally searches for builtins before disk commands.
-If @option{-n} is used, the @var{name}s become disabled.  Otherwise
-@var{name}s are enabled.  For example, to use the @code{test} binary
-found via @env{$PATH} instead of the shell builtin version, type
-@samp{enable -n test}.
-
-If the @option{-p} option is supplied, or no @var{name} arguments appear,
-a list of shell builtins is printed.  With no other arguments, the list
-consists of all enabled shell builtins.
-The @option{-a} option means to list
-each builtin with an indication of whether or not it is enabled. 
-
-The @option{-f} option means to load the new builtin command @var{name}
-from shared object @var{filename}, on systems that support dynamic loading.
-The @option{-d} option will delete a builtin loaded with @option{-f}.
-
-If there are no options, a list of the shell builtins is displayed.
-The @option{-s} option restricts @code{enable} to the @sc{posix} special
-builtins.  If @option{-s} is used with @option{-f}, the new builtin becomes
-a special builtin (@pxref{Special Builtins}).
-
-The return status is zero unless a @var{name} is not a shell builtin
-or there is an error loading a new builtin from a shared object.
-
-@item help
-@btindex help
-@example
-help [-dms] [@var{pattern}]
-@end example
-
-Display helpful information about builtin commands.
-If @var{pattern} is specified, @code{help} gives detailed help
-on all commands matching @var{pattern}, otherwise a list of
-the builtins is printed.
-
-Options, if supplied, have the following meanings:
-
-@table @code
-@item -d
-Display a short description of each @var{pattern}
-@item -m
-Display the description of each @var{pattern} in a manpage-like format
-@item -s
-Display only a short usage synopsis for each @var{pattern}
-@end table
-
-The return status is zero unless no command matches @var{pattern}.
-
-@item let
-@btindex let
-@example
-let @var{expression} [@var{expression} @dots{}]
-@end example
-
-The @code{let} builtin allows arithmetic to be performed on shell
-variables.  Each @var{expression} is evaluated according to the
-rules given below in @ref{Shell Arithmetic}.  If the
-last @var{expression} evaluates to 0, @code{let} returns 1;
-otherwise 0 is returned.
-
-@item local
-@btindex local
-@example
-local [@var{option}] @var{name}[=@var{value}] @dots{}
-@end example
-
-For each argument, a local variable named @var{name} is created,
-and assigned @var{value}.
-The @var{option} can be any of the options accepted by @code{declare}.
-@code{local} can only be used within a function; it makes the variable
-@var{name} have a visible scope restricted to that function and its
-children.  The return status is zero unless @code{local} is used outside
-a function, an invalid @var{name} is supplied, or @var{name} is a
-readonly variable.
-
-@item logout
-@btindex logout
-@example
-logout [@var{n}]
-@end example
-
-Exit a login shell, returning a status of @var{n} to the shell's
-parent.
-
-@item mapfile
-@btindex mapfile
-@example
-mapfile [-n @var{count}] [-O @var{origin}] [-s @var{count}] [-t] [-u @var{fd}]
-    [-C @var{callback}] [-c @var{quantum}] [@var{array}]
-@end example
-
-Read lines from the standard input into the indexed array variable @var{array},
-or from file descriptor @var{fd}
-if the @option{-u} option is supplied.
-The variable @code{MAPFILE} is the default @var{array}.
-Options, if supplied, have the following meanings:
-
-@table @code
-
-@item -n
-Copy at most @var{count} lines.  If @var{count} is 0, all lines are copied.
-@item -O
-Begin assigning to @var{array} at index @var{origin}.
-The default index is 0.
-@item -s
-Discard the first @var{count} lines read.
-@item -t
-Remove a trailing newline from each line read.
-@item -u
-Read lines from file descriptor @var{fd} instead of the standard input.
-@item -C
-Evaluate @var{callback} each time @var{quantum}P lines are read.
-The @option{-c} option specifies @var{quantum}.
-@item -c
-Specify the number of lines read between each call to @var{callback}.
-@end table
-
-If @option{-C} is specified without @option{-c}, 
-the default quantum is 5000.
-When @var{callback}  is evaluated, it is supplied the index of the next
-array element to be assigned and the line to be assigned to that element
-as additional arguments.
-@var{callback} is evaluated after the line is read but before the 
-array element is assigned.
-
-If not supplied with an explicit origin, @code{mapfile} will clear @var{array}
-before assigning to it.
-
-@code{mapfile} returns successfully unless an invalid option or option
-argument is supplied, @var{array} is invalid or unassignable, or @var{array}
-is not an indexed array.
-
-@item printf
-@btindex printf
-@example
-printf [-v @var{var}] @var{format} [@var{arguments}]
-@end example
-
-Write the formatted @var{arguments} to the standard output under the
-control of the @var{format}.
-The @option{-v} option causes the output to be assigned to the variable
-@var{var} rather than being printed to the standard output.
-
-The @var{format} is a character string which contains three types of objects:
-plain characters, which are simply copied to standard output, character
-escape sequences, which are converted and copied to the standard output, and
-format specifications, each of which causes printing of the next successive
-@var{argument}.
-In addition to the standard @code{printf(1)} formats, @code{printf}
-interprets the following extensions:
-
-@table @code
-@item %b
-Causes @code{printf} to expand backslash escape sequences in the
-corresponding @var{argument},
-except that @samp{\c} terminates output, backslashes in
-@samp{\'}, @samp{\"}, and @samp{\?} are not removed, and octal escapes
-beginning with @samp{\0} may contain up to four digits.
-@item %q
-Causes @code{printf} to output the
-corresponding @var{argument} in a format that can be reused as shell input.
-@item %(@var{datefmt})T
-Causes @code{printf} to output the date-time string resulting from using
-@var{datefmt} as a format string for @code{strftime}(3).
-The corresponding @var{argument} is an integer representing the number of
-seconds since the epoch.
-Two special argument values may be used: -1 represents the current
-time, and -2 represents the time the shell was invoked.
-If no argument is specified, conversion behaves as if -1 had been given.
-This is an exception to the usual @code{printf} behavior.
-@end table
-
-@noindent
-Arguments to non-string format specifiers are treated as C language constants,
-except that a leading plus or minus sign is allowed, and if the leading
-character is a single or double quote, the value is the ASCII value of
-the following character.
-
-The @var{format} is reused as necessary to consume all of the @var{arguments}.
-If the @var{format} requires more @var{arguments} than are supplied, the
-extra format specifications behave as if a zero value or null string, as
-appropriate, had been supplied.  The return value is zero on success,
-non-zero on failure.
-
-@item read
-@btindex read
-@example
-read [-ers] [-a @var{aname}] [-d @var{delim}] [-i @var{text}] [-n @var{nchars}]
-    [-N @var{nchars}] [-p @var{prompt}] [-t @var{timeout}] [-u @var{fd}] [@var{name} @dots{}]
-@end example
-
-One line is read from the standard input, or from the file descriptor
-@var{fd} supplied as an argument to the @option{-u} option, and the first word
-is assigned to the first @var{name}, the second word to the second @var{name},
-and so on, with leftover words and their intervening separators assigned
-to the last @var{name}.
-If there are fewer words read from the input stream than names,
-the remaining names are assigned empty values.
-The characters in the value of the @env{IFS} variable
-are used to split the line into words.
-The backslash character @samp{\} may be used to remove any special
-meaning for the next character read and for line continuation.
-If no names are supplied, the line read is assigned to the
-variable @env{REPLY}.
-The return code is zero, unless end-of-file is encountered, @code{read}
-times out (in which case the return code is greater than 128),
-a variable assignment error (such as assigning to a readonly variable) occurs,
-or an invalid file descriptor is supplied as the argument to @option{-u}.
-
-Options, if supplied, have the following meanings:
-
-@table @code
-@item -a @var{aname}
-The words are assigned to sequential indices of the array variable
-@var{aname}, starting at 0.
-All elements are removed from @var{aname} before the assignment.
-Other @var{name} arguments are ignored.
-
-@item -d @var{delim}
-The first character of @var{delim} is used to terminate the input line,
-rather than newline.
-
-@item -e
-Readline (@pxref{Command Line Editing}) is used to obtain the line.
-Readline uses the current (or default, if line editing was not previously
-active) editing settings.
-
-@item -i @var{text}
-If Readline is being used to read the line, @var{text} is placed into
-the editing buffer before editing begins.
-
-@item -n @var{nchars}
-@code{read} returns after reading @var{nchars} characters rather than
-waiting for a complete line of input, but honor a delimiter if fewer
-than @var{nchars} characters are read before the delimiter.
-
-@item -N @var{nchars}
-@code{read} returns after reading exactly @var{nchars} characters rather
-than waiting for a complete line of input, unless EOF is encountered or
-@code{read} times out.
-Delimiter characters encountered in the input are
-not treated specially and do not cause @code{read} to return until
-@var{nchars} characters are read.
-
-@item -p @var{prompt}
-Display @var{prompt}, without a trailing newline, before attempting
-to read any input.
-The prompt is displayed only if input is coming from a terminal.
-
-@item -r
-If this option is given, backslash does not act as an escape character.
-The backslash is considered to be part of the line.
-In particular, a backslash-newline pair may not be used as a line
-continuation.
-
-@item -s
-Silent mode.  If input is coming from a terminal, characters are
-not echoed.
-
-@item -t @var{timeout}
-Cause @code{read} to time out and return failure if a complete line of
-input (or a specified number of characters)
-is not read within @var{timeout} seconds.
-@var{timeout}  may be a decimal number with a fractional portion following
-the decimal point.
-This option is only effective if @code{read} is reading input from a
-terminal, pipe, or other special file; it has no effect when reading
-from regular files.
-If @code{read} times out, @code{read} saves any partial input read into
-the specified variable @var{name}.
-If @var{timeout} is 0, @code{read} returns immediately, without trying to
-read and data.  The exit status is 0 if input is available on
-the specified file descriptor, non-zero otherwise.
-The exit status is greater than 128 if the timeout is exceeded.
-
-@item -u @var{fd}
-Read input from file descriptor @var{fd}.
-@end table
-
-@item readarray
-@btindex readarray
-@example
-readarray [-n @var{count}] [-O @var{origin}] [-s @var{count}] [-t] [-u @var{fd}]
-    [-C @var{callback}] [-c @var{quantum}] [@var{array}]
-@end example
-
-Read lines from the standard input into the indexed array variable @var{array},
-or from file descriptor @var{fd}
-if the @option{-u} option is supplied.
-
-A synonym for @code{mapfile}.
-
-@item source
-@btindex source
-@example
-source @var{filename}
-@end example
-
-A synonym for @code{.} (@pxref{Bourne Shell Builtins}).
-
-@item type
-@btindex type
-@example
-type [-afptP] [@var{name} @dots{}]
-@end example
-
-For each @var{name}, indicate how it would be interpreted if used as a
-command name.
-
-If the @option{-t} option is used, @code{type} prints a single word
-which is one of @samp{alias}, @samp{function}, @samp{builtin},
-@samp{file} or @samp{keyword},
-if @var{name} is an alias, shell function, shell builtin,
-disk file, or shell reserved word, respectively.
-If the @var{name} is not found, then nothing is printed, and
-@code{type} returns a failure status.
-
-If the @option{-p} option is used, @code{type} either returns the name
-of the disk file that would be executed, or nothing if @option{-t}
-would not return @samp{file}.
-
-The @option{-P} option forces a path search for each @var{name}, even if
-@option{-t} would not return @samp{file}.
-
-If a command is hashed, @option{-p} and @option{-P} print the hashed value,
-which is not necessarily the file that appears first in @code{$PATH}.
-
-If the @option{-a} option is used, @code{type} returns all of the places
-that contain an executable named @var{file}.
-This includes aliases and functions, if and only if the @option{-p} option
-is not also used.
-
-If the @option{-f} option is used, @code{type} does not attempt to find
-shell functions, as with the @code{command} builtin.
-
-The return status is zero if all of the @var{names} are found, non-zero
-if any are not found.
-
-@item typeset
-@btindex typeset
-@example
-typeset [-afFgrxilnrtux] [-p] [@var{name}[=@var{value}] @dots{}]
-@end example
-
-The @code{typeset} command is supplied for compatibility with the Korn
-shell.
-It is a synonym for the @code{declare} builtin command.
-
-@item ulimit
-@btindex ulimit
-@example
-ulimit [-abcdefilmnpqrstuvxHST] [@var{limit}]
-@end example
-
-@code{ulimit} provides control over the resources available to processes
-started by the shell, on systems that allow such control.  If an
-option is given, it is interpreted as follows:
-
-@table @code
-@item -S
-Change and report the soft limit associated with a resource.
-
-@item -H
-Change and report the hard limit associated with a resource.
-
-@item -a
-All current limits are reported.
-
-@item -b
-The maximum socket buffer size.
-
-@item -c
-The maximum size of core files created.
-
-@item -d
-The maximum size of a process's data segment.
-
-@item -e
-The maximum scheduling priority ("nice").
-
-@item -f
-The maximum size of files written by the shell and its children.
-
-@item -i
-The maximum number of pending signals.
-
-@item -l
-The maximum size that may be locked into memory.
-
-@item -m
-The maximum resident set size (many systems do not honor this limit).
-
-@item -n
-The maximum number of open file descriptors (most systems do not
-allow this value to be set).
-
-@item -p
-The pipe buffer size.
-
-@item -q
-The maximum number of bytes in POSIX message queues.
-
-@item -r
-The maximum real-time scheduling priority.
-
-@item -s
-The maximum stack size.
-
-@item -t
-The maximum amount of cpu time in seconds.
-
-@item -u
-The maximum number of processes available to a single user.
-
-@item -v
-The maximum amount of virtual memory available to the shell, and, on
-some systems, to its children.
-
-@item -x
-The maximum number of file locks.
-
-@item -T
-The maximum number of threads.
-@end table
-
-If @var{limit} is given, and the @option{-a} option is not used,
-@var{limit} is the new value of the specified resource.
-The special @var{limit} values @code{hard}, @code{soft}, and
-@code{unlimited} stand for the current hard limit, the current soft limit,
-and no limit, respectively.
-A hard limit cannot be increased by a non-root user once it is set;
-a soft limit may be increased up to the value of the hard limit.
-Otherwise, the current value of the soft limit for the specified resource
-is printed, unless the @option{-H} option is supplied.
-When setting new limits, if neither @option{-H} nor @option{-S} is supplied,
-both the hard and soft limits are set.
-If no option is given, then @option{-f} is assumed.  Values are in 1024-byte
-increments, except for @option{-t}, which is in seconds; @option{-p},
-which is in units of 512-byte blocks; and @option{-T}, @option{-b},
-@option{-n} and @option{-u}, which are unscaled values.
-
-The return status is zero unless an invalid option or argument is supplied,
-or an error occurs while setting a new limit.
-
-@item unalias
-@btindex unalias
-@example
-unalias [-a] [@var{name} @dots{} ]
-@end example
-
-Remove each @var{name} from the list of aliases.  If @option{-a} is
-supplied, all aliases are removed.
-Aliases are described in @ref{Aliases}.
-@end table
-
-@node Modifying Shell Behavior
-@section Modifying Shell Behavior
-@menu
-* The Set Builtin::            Change the values of shell attributes and
-                               positional parameters.
-* The Shopt Builtin::          Modify shell optional behavior.
-@end menu
-
-@node The Set Builtin
-@subsection The Set Builtin
-
-This builtin is so complicated that it deserves its own section.  @code{set}
-allows you to change the values of shell options and set the positional
-parameters, or to display the names and values of shell variables.
-
-@table @code
-@item set
-@btindex set
-@example
-set [--abefhkmnptuvxBCEHPT] [-o @var{option-name}] [@var{argument} @dots{}]
-set [+abefhkmnptuvxBCEHPT] [+o @var{option-name}] [@var{argument} @dots{}]
-@end example
-
-If no options or arguments are supplied, @code{set} displays the names
-and values of all shell variables and functions, sorted according to the
-current locale, in a format that may be reused as input
-for setting or resetting the currently-set variables.
-Read-only variables cannot be reset.
-In @sc{posix} mode, only shell variables are listed.
-
-When options are supplied, they set or unset shell attributes.
-Options, if specified, have the following meanings:
-
-@table @code
-@item -a
-Mark variables and function which are modified or created for export
-to the environment of subsequent commands.
-
-@item -b
-Cause the status of terminated background jobs to be reported
-immediately, rather than before printing the next primary prompt.
-
-@item -e
-Exit immediately if
-a pipeline (@pxref{Pipelines}), which may consist of a single simple command
-(@pxref{Simple Commands}),
-a list (@pxref{Lists}),
-or a compound command (@pxref{Compound Commands})
-returns a non-zero status.
-The shell does not exit if the command that fails is part of the
-command list immediately following a @code{while} or @code{until} keyword,
-part of the test in an @code{if} statement,
-part of any command executed in a @code{&&} or @code{||} list except
-the command following the final @code{&&} or @code{||},
-any command in a pipeline but the last,
-or if the command's return status is being inverted with @code{!}.
-If a compound command other than a subshell
-returns a non-zero status because a command failed
-while @option{-e} was being ignored, the shell does not exit.
-A trap on @code{ERR}, if set, is executed before the shell exits.
-
-This option applies to the shell environment and each subshell environment
-separately (@pxref{Command Execution Environment}), and may cause
-subshells to exit before executing all the commands in the subshell.
-
-If a compound command or shell function executes in a context where
-@option{-e} is being ignored,
-none of the commands executed within the compound command or function body
-will be affected by the @option{-e} setting, even if @option{-e} is set
-and a command returns a failure status.
-If a compound command or shell function sets @option{-e} while executing in
-a context where @option{-e} is ignored, that setting will not have any
-effect until the compound command or the command containing the function
-call completes.
-
-@item -f
-Disable filename expansion (globbing).
-
-@item -h
-Locate and remember (hash) commands as they are looked up for execution.
-This option is enabled by default.
-
-@item -k
-All arguments in the form of assignment statements are placed
-in the environment for a command, not just those that precede
-the command name.
-
-@item -m
-Job control is enabled (@pxref{Job Control}).
-All processes run in a separate process group.
-When a background job completes, the shell prints a line
-containing its exit status.
-
-@item -n
-Read commands but do not execute them; this may be used to check a
-script for syntax errors.
-This option is ignored by interactive shells.
-
-@item -o @var{option-name}
-
-Set the option corresponding to @var{option-name}:
-
-@table @code
-@item allexport
-Same as @code{-a}.
-
-@item braceexpand
-Same as @code{-B}.
-
-@item emacs
-Use an @code{emacs}-style line editing interface (@pxref{Command Line Editing}).
-This also affects the editing interface used for @code{read -e}.
-
-@item errexit
-Same as @code{-e}.
-
-@item errtrace
-Same as @code{-E}.
-
-@item functrace
-Same as @code{-T}.
-
-@item hashall
-Same as @code{-h}.
-
-@item histexpand
-Same as @code{-H}.
-
-@item history
-Enable command history, as described in @ref{Bash History Facilities}.
-This option is on by default in interactive shells.
-
-@item ignoreeof
-An interactive shell will not exit upon reading EOF.
-
-@item keyword
-Same as @code{-k}.
-
-@item monitor
-Same as @code{-m}.
-
-@item noclobber
-Same as @code{-C}.
-
-@item noexec
-Same as @code{-n}.
-
-@item noglob
-Same as @code{-f}.
-
-@item nolog
-Currently ignored.
-
-@item notify
-Same as @code{-b}.
-
-@item nounset
-Same as @code{-u}.
-
-@item onecmd
-Same as @code{-t}.
-
-@item physical
-Same as @code{-P}.
-
-@item pipefail
-If set, the return value of a pipeline is the value of the last
-(rightmost) command to exit with a non-zero status, or zero if all
-commands in the pipeline exit successfully.
-This option is disabled by default.
-
-@item posix
-Change the behavior of Bash where the default operation differs
-from the @sc{posix} standard to match the standard
-(@pxref{Bash POSIX Mode}).
-This is intended to make Bash behave as a strict superset of that
-standard.
-
-@item privileged
-Same as @code{-p}.
-
-@item verbose
-Same as @code{-v}.
-
-@item vi
-Use a @code{vi}-style line editing interface.
-This also affects the editing interface used for @code{read -e}.
-
-@item xtrace
-Same as @code{-x}.
-@end table
-
-@item -p
-Turn on privileged mode.
-In this mode, the @env{$BASH_ENV} and @env{$ENV} files are not
-processed, shell functions are not inherited from the environment,
-and the @env{SHELLOPTS}, @env{BASHOPTS}, @env{CDPATH} and @env{GLOBIGNORE}
-variables, if they appear in the environment, are ignored.
-If the shell is started with the effective user (group) id not equal to the
-real user (group) id, and the @option{-p} option is not supplied, these actions
-are taken and the effective user id is set to the real user id.
-If the @option{-p} option is supplied at startup, the effective user id is
-not reset.
-Turning this option off causes the effective user
-and group ids to be set to the real user and group ids.
-
-@item -t
-Exit after reading and executing one command.
-
-@item -u
-Treat unset variables and parameters other than the special parameters
-@samp{@@} or @samp{*} as an error when performing parameter expansion.
-An error message will be written to the standard error, and a non-interactive
-shell will exit.
-
-@item -v
-Print shell input lines as they are read.
-
-@item -x
-Print a trace of simple commands, @code{for} commands, @code{case}
-commands, @code{select} commands, and arithmetic @code{for} commands
-and their arguments or associated word lists after they are
-expanded and before they are executed.  The value of the @env{PS4}
-variable is expanded and the resultant value is printed before
-the command and its expanded arguments.
-
-@item -B
-The shell will perform brace expansion (@pxref{Brace Expansion}).
-This option is on by default.
-
-@item -C
-Prevent output redirection using @samp{>}, @samp{>&}, and @samp{<>}
-from overwriting existing files.
-
-@item -E
-If set, any trap on @code{ERR} is inherited by shell functions, command
-substitutions, and commands executed in a subshell environment.
-The @code{ERR} trap is normally not inherited in such cases.
-
-@item -H
-Enable @samp{!} style history substitution (@pxref{History Interaction}).
-This option is on by default for interactive shells.
-
-@item -P
-If set, do not resolve symbolic links when performing commands such as
-@code{cd} which change the current directory.  The physical directory
-is used instead.  By default, Bash follows
-the logical chain of directories when performing commands
-which change the current directory.
-
-For example, if @file{/usr/sys} is a symbolic link to @file{/usr/local/sys}
-then:
-@example
-$ cd /usr/sys; echo $PWD
-/usr/sys
-$ cd ..; pwd
-/usr
-@end example
-
-@noindent
-If @code{set -P} is on, then:
-@example
-$ cd /usr/sys; echo $PWD
-/usr/local/sys
-$ cd ..; pwd
-/usr/local
-@end example
-
-@item -T
-If set, any trap on @code{DEBUG} and @code{RETURN} are inherited by
-shell functions, command substitutions, and commands executed
-in a subshell environment.
-The @code{DEBUG} and @code{RETURN} traps are normally not inherited
-in such cases.
-
-@item --
-If no arguments follow this option, then the positional parameters are
-unset.  Otherwise, the positional parameters are set to the
-@var{arguments}, even if some of them begin with a @samp{-}.
-
-@item -
-Signal the end of options, cause all remaining @var{arguments}
-to be assigned to the positional parameters.  The @option{-x}
-and @option{-v}  options are turned off.
-If there are no arguments, the positional parameters remain unchanged.
-@end table
-
-Using @samp{+} rather than @samp{-} causes these options to be
-turned off.  The options can also be used upon invocation of the
-shell.  The current set of options may be found in @code{$-}.
-
-The remaining N @var{arguments} are positional parameters and are
-assigned, in order, to @code{$1}, @code{$2}, @dots{}  @code{$N}.
-The special parameter @code{#} is set to N.
-
-The return status is always zero unless an invalid option is supplied.
-@end table
-
-@node The Shopt Builtin
-@subsection The Shopt Builtin
-
-This builtin allows you to change additional shell optional behavior.
-
-@table @code
-
-@item shopt
-@btindex shopt
-@example
-shopt [-pqsu] [-o] [@var{optname} @dots{}]
-@end example
-
-Toggle the values of variables controlling optional shell behavior.
-With no options, or with the @option{-p} option, a list of all settable
-options is displayed, with an indication of whether or not each is set.
-The @option{-p} option causes output to be displayed in a form that
-may be reused as input.
-Other options have the following meanings:
-
-@table @code
-@item -s
-Enable (set) each @var{optname}.
-
-@item -u
-Disable (unset) each @var{optname}.
-
-@item -q
-Suppresses normal output; the return status
-indicates whether the @var{optname} is set or unset.
-If multiple @var{optname} arguments are given with @option{-q},
-the return status is zero if all @var{optnames} are enabled;
-non-zero otherwise.
-
-@item -o
-Restricts the values of
-@var{optname} to be those defined for the @option{-o} option to the
-@code{set} builtin (@pxref{The Set Builtin}).
-@end table
-
-If either @option{-s} or @option{-u}
-is used with no @var{optname} arguments, @code{shopt} shows only
-those options which are set or unset, respectively.
-
-Unless otherwise noted, the @code{shopt} options are disabled (off)
-by default.
-
-The return status when listing options is zero if all @var{optnames}
-are enabled, non-zero otherwise.  When setting or unsetting options,
-the return status is zero unless an @var{optname} is not a valid shell
-option.
-
-The list of @code{shopt} options is:
-@table @code
-
-@item autocd
-If set, a command name that is the name of a directory is executed as if
-it were the argument to the @code{cd} command.
-This option is only used by interactive shells.
-
-@item cdable_vars
-If this is set, an argument to the @code{cd} builtin command that
-is not a directory is assumed to be the name of a variable whose
-value is the directory to change to.
-
-@item cdspell
-If set, minor errors in the spelling of a directory component in a
-@code{cd} command will be corrected.
-The errors checked for are transposed characters,
-a missing character, and a character too many.
-If a correction is found, the corrected path is printed,
-and the command proceeds.
-This option is only used by interactive shells.
-
-@item checkhash
-If this is set, Bash checks that a command found in the hash
-table exists before trying to execute it.  If a hashed command no
-longer exists, a normal path search is performed.
-
-@item checkjobs
-If set, Bash lists the status of any stopped and running jobs before
-exiting an interactive shell.  If any jobs are running, this causes
-the exit to be deferred until a second exit is attempted without an
-intervening command (@pxref{Job Control}).
-The shell always postpones exiting if any jobs are stopped.
-
-@item checkwinsize
-If set, Bash checks the window size after each command
- and, if necessary, updates the values of    
-@env{LINES} and @env{COLUMNS}.
-
-@item cmdhist
-If set, Bash
-attempts to save all lines of a multiple-line
-command in the same history entry.  This allows
-easy re-editing of multi-line commands.
-
-@item compat31
-If set, Bash
-changes its behavior to that of version 3.1 with respect to quoted
-arguments to the conditional command's @samp{=~} operator
-and with respect to locale-specific
-string comparison when using the @code{[[}
-conditional command's @samp{<} and @samp{>} operators.
-Bash versions prior to bash-4.1 use ASCII collation and strcmp(3);
-bash-4.1 and later use the current locale's collation sequence and strcoll(3).
-
-@item compat32
-If set, Bash
-changes its behavior to that of version 3.2 with respect to locale-specific
-string comparison when using the @code{[[}
-conditional command's @samp{<} and @samp{>} operators (see previous item).
-
-@item compat40
-If set, Bash
-changes its behavior to that of version 4.0 with respect to locale-specific
-string comparison when using the @code{[[}
-conditional command's @samp{<} and @samp{>} operators (see description
-of @code{compat31})
-and the effect of interrupting a command list.
-Bash versions 4.0 and later interrupt the list as if the shell received the
-interrupt; previous versions continue with the next command in the list.
-
-@item compat41
-If set, Bash, when in posix mode, treats a single quote in a double-quoted
-parameter expansion as a special character.  The single quotes must match
-(an even number) and the characters between the single quotes are considered
-quoted.  This is the behavior of @sc{posix} mode through version 4.1.
-The default Bash behavior remains as in previous versions.
-
-@item compat42
-If set, Bash
-does not process the replacement string in the pattern substitution word
-expansion using quote removal.
-
-@item complete_fullquote
-If set, Bash
-quotes all shell metacharacters in filenames and directory names when
-performing completion.
-If not set, Bash
-removes metacharacters such as the dollar sign from the set of
-characters that will be quoted in completed filenames
-when these metacharacters appear in shell variable references in words to be
-completed.
-This means that dollar signs in variable names that expand to directories
-will not be quoted;
-however, any dollar signs appearing in filenames will not be quoted, either.
-This is active only when bash is using backslashes to quote completed
-filenames.
-This variable is set by default, which is the default Bash behavior in
-versions through 4.2.
-
-@item direxpand
-If set, Bash
-replaces directory names with the results of word expansion when performing
-filename completion.  This changes the contents of the readline editing
-buffer.
-If not set, Bash attempts to preserve what the user typed.
-
-@item dirspell
-If set, Bash
-attempts spelling correction on directory names during word completion 
-if the directory name initially supplied does not exist.
-
-@item dotglob
-If set, Bash includes filenames beginning with a `.' in
-the results of filename expansion.
-
-@item execfail
-If this is set, a non-interactive shell will not exit if
-it cannot execute the file specified as an argument to the @code{exec}
-builtin command.  An interactive shell does not exit if @code{exec}
-fails.
-
-@item expand_aliases
-If set, aliases are expanded as described below under Aliases,
-@ref{Aliases}.
-This option is enabled by default for interactive shells.
-
-@item extdebug
-If set, behavior intended for use by debuggers is enabled:
-
-@enumerate
-@item
-The @option{-F} option to the @code{declare} builtin (@pxref{Bash Builtins})
-displays the source file name and line number corresponding to each function
-name supplied as an argument.
-
-@item
-If the command run by the @code{DEBUG} trap returns a non-zero value, the
-next command is skipped and not executed.
-
-@item
-If the command run by the @code{DEBUG} trap returns a value of 2, and the
-shell is executing in a subroutine (a shell function or a shell script
-executed by the @code{.} or @code{source} builtins), a call to
-@code{return} is simulated.
-
-@item
-@code{BASH_ARGC} and @code{BASH_ARGV} are updated as described in their
-descriptions (@pxref{Bash Variables}).
-
-@item
-Function tracing is enabled:  command substitution, shell functions, and
-subshells invoked with @code{( @var{command} )} inherit the
-@code{DEBUG} and @code{RETURN} traps.
-
-@item
-Error tracing is enabled:  command substitution, shell functions, and
-subshells invoked with @code{( @var{command} )} inherit the
-@code{ERR} trap.
-@end enumerate
-
-@item extglob
-If set, the extended pattern matching features described above
-(@pxref{Pattern Matching}) are enabled.
-
-@item extquote
-If set, @code{$'@var{string}'} and @code{$"@var{string}"} quoting is  
-performed within @code{$@{@var{parameter}@}} expansions                     
-enclosed in double quotes.  This option is enabled by default. 
-
-@item failglob
-If set, patterns which fail to match filenames during filename expansion
-result in an expansion error.
-
-@item force_fignore
-If set, the suffixes specified by the @env{FIGNORE} shell variable
-cause words to be ignored when performing word completion even if
-the ignored words are the only possible completions.
-@xref{Bash Variables}, for a description of @env{FIGNORE}.
-This option is enabled by default.
-
-@item globasciiranges
-If set, range expressions used in pattern matching (@pxref{Pattern Matching})
-behave as if in the traditional C locale when performing
-comparisons.  That is, the current locale's collating sequence
-is not taken into account, so
-@samp{b} will not collate between @samp{A} and @samp{B},
-and upper-case and lower-case ASCII characters will collate together.   
-
-@item globstar
-If set, the pattern @samp{**} used in a filename expansion context will
-match all files and zero or more directories and subdirectories.
-If the pattern is followed by a @samp{/}, only directories and
-subdirectories match.
-
-@item gnu_errfmt
-If set, shell error messages are written in the standard @sc{gnu} error
-message format.
-
-@item histappend
-If set, the history list is appended to the file named by the value
-of the @env{HISTFILE}
-variable when the shell exits, rather than overwriting the file.
-
-@item histreedit
-If set, and Readline
-is being used, a user is given the opportunity to re-edit a
-failed history substitution.
-
-@item histverify
-If set, and Readline
-is being used, the results of history substitution are not immediately
-passed to the shell parser.  Instead, the resulting line is loaded into
-the Readline editing buffer, allowing further modification.
-
-@item hostcomplete
-If set, and Readline is being used, Bash will attempt to perform
-hostname completion when a word containing a @samp{@@} is being
-completed (@pxref{Commands For Completion}).  This option is enabled
-by default.
-
-@item huponexit
-If set, Bash will send @code{SIGHUP} to all jobs when an interactive
-login shell exits (@pxref{Signals}).
-
-@item interactive_comments
-Allow a word beginning with @samp{#}
-to cause that word and all remaining characters on that
-line to be ignored in an interactive shell.
-This option is enabled by default.
-
-@item lastpipe
-If set, and job control is not active, the shell runs the last command of
-a pipeline not executed in the background in the current shell environment.
-
-@item lithist
-If enabled, and the @code{cmdhist}
-option is enabled, multi-line commands are saved to the history with
-embedded newlines rather than using semicolon separators where possible.
-
-@item login_shell
-The shell sets this option if it is started as a login shell
-(@pxref{Invoking Bash}).
-The value may not be changed.
-
-@item mailwarn
-If set, and a file that Bash is checking for mail has been  
-accessed since the last time it was checked, the message
-@code{"The mail in @var{mailfile} has been read"} is displayed.
-
-@item no_empty_cmd_completion
-If set, and Readline is being used, Bash will not attempt to search
-the @env{PATH} for possible completions when completion is attempted
-on an empty line.
-
-@item nocaseglob
-If set, Bash matches filenames in a case-insensitive fashion when
-performing filename expansion.
-
-@item nocasematch
-If set, Bash matches patterns in a case-insensitive fashion when
-performing matching while executing @code{case} or @code{[[}
-conditional commands.
-
-@item nullglob
-If set, Bash allows filename patterns which match no
-files to expand to a null string, rather than themselves.
-
-@item progcomp
-If set, the programmable completion facilities
-(@pxref{Programmable Completion}) are enabled.
-This option is enabled by default.
-
-@item promptvars
-If set, prompt strings undergo
-parameter expansion, command substitution, arithmetic
-expansion, and quote removal after being expanded
-as described below (@pxref{Controlling the Prompt}).
-This option is enabled by default.
-
-@item restricted_shell
-The shell sets this option if it is started in restricted mode
-(@pxref{The Restricted Shell}).
-The value may not be changed.
-This is not reset when the startup files are executed, allowing
-the startup files to discover whether or not a shell is restricted.
-
-@item shift_verbose
-If this is set, the @code{shift}
-builtin prints an error message when the shift count exceeds the
-number of positional parameters.
-
-@item sourcepath
-If set, the @code{source} builtin uses the value of @env{PATH}
-to find the directory containing the file supplied as an argument.
-This option is enabled by default.
-
-@item xpg_echo
-If set, the @code{echo} builtin expands backslash-escape sequences
-by default.
-
-@end table
-
-@noindent
-The return status when listing options is zero if all @var{optnames}
-are enabled, non-zero otherwise.
-When setting or unsetting options, the return status is zero unless an
-@var{optname} is not a valid shell option.
-@end table
-
-@node Special Builtins
-@section Special Builtins
-@cindex special builtin
-
-For historical reasons, the @sc{posix} standard has classified
-several builtin commands as @emph{special}.
-When Bash is executing in @sc{posix} mode, the special builtins
-differ from other builtin commands in three respects:
-
-@enumerate
-@item
-Special builtins are found before shell functions during command lookup.
-
-@item
-If a special builtin returns an error status, a non-interactive shell exits.
-
-@item
-Assignment statements preceding the command stay in effect in the shell
-environment after the command completes.
-@end enumerate
-
-When Bash is not executing in @sc{posix} mode, these builtins behave no
-differently than the rest of the Bash builtin commands.
-The Bash @sc{posix} mode is described in @ref{Bash POSIX Mode}. 
-
-These are the @sc{posix} special builtins:
-@example
-@w{break : . continue eval exec exit export readonly return set}
-@w{shift trap unset}
-@end example
-
-@node Shell Variables
-@chapter Shell Variables
-
-@menu
-* Bourne Shell Variables::     Variables which Bash uses in the same way
-                               as the Bourne Shell.
-* Bash Variables::             List of variables that exist in Bash.
-@end menu
-
-This chapter describes the shell variables that Bash uses.
-Bash automatically assigns default values to a number of variables.
-
-@node Bourne Shell Variables
-@section Bourne Shell Variables
-
-Bash uses certain shell variables in the same way as the Bourne shell.
-In some cases, Bash assigns a default value to the variable.
-
-@vtable @code
-
-@item CDPATH
-A colon-separated list of directories used as a search path for
-the @code{cd} builtin command.
-
-@item HOME
-The current user's home directory; the default for the @code{cd} builtin
-command.
-The value of this variable is also used by tilde expansion
-(@pxref{Tilde Expansion}).
-
-@item IFS
-A list of characters that separate fields; used when the shell splits
-words as part of expansion.
-
-@item MAIL
-If this parameter is set to a filename or directory name
-and the @env{MAILPATH} variable
-is not set, Bash informs the user of the arrival of mail in
-the specified file or Maildir-format directory.
-
-@item MAILPATH
-A colon-separated list of filenames which the shell periodically checks
-for new mail.
-Each list entry can specify the message that is printed when new mail
-arrives in the mail file by separating the filename from the message with
-a @samp{?}.
-When used in the text of the message, @code{$_} expands to the name of
-the current mail file.
-
-@item OPTARG
-The value of the last option argument processed by the @code{getopts} builtin.
-
-@item OPTIND
-The index of the last option argument processed by the @code{getopts} builtin.
-
-@item PATH
-A colon-separated list of directories in which the shell looks for
-commands.
-A zero-length (null) directory name in the value of @code{PATH} indicates the
-current directory.
-A null directory name may appear as two adjacent colons, or as an initial
-or trailing colon.
-
-
-@item PS1
-The primary prompt string.  The default value is @samp{\s-\v\$ }.
-@xref{Controlling the Prompt}, for the complete list of escape
-sequences that are expanded before @env{PS1} is displayed.
-
-@item PS2
-The secondary prompt string.  The default value is @samp{> }.
-
-@end vtable
-
-@node Bash Variables
-@section Bash Variables
-
-These variables are set or used by Bash, but other shells
-do not normally treat them specially.
-
-A few variables used by Bash are described in different chapters:
-variables for controlling the job control facilities
-(@pxref{Job Control Variables}).
-
-@vtable @code
-
-@item BASH
-The full pathname used to execute the current instance of Bash.
-
-@item BASHOPTS
-A colon-separated list of enabled shell options.  Each word in
-the list is a valid argument for the @option{-s} option to the
-@code{shopt} builtin command (@pxref{The Shopt Builtin}).
-The options appearing in @env{BASHOPTS} are those reported
-as @samp{on} by @samp{shopt}.
-If this variable is in the environment when Bash
-starts up, each shell option in the list will be enabled before
-reading any startup files.  This variable is readonly.
-
-@item BASHPID
-Expands to the process ID of the current Bash process.
-This differs from @code{$$} under certain circumstances, such as subshells
-that do not require Bash to be re-initialized.
-
-@item BASH_ALIASES
-An associative array variable whose members correspond to the internal
-list of aliases as maintained by the @code{alias} builtin.
-(@pxref{Bourne Shell Builtins}).
-Elements added to this array appear in the alias list; unsetting array
-elements cause aliases to be removed from the alias list.
-
-@item BASH_ARGC
-An array variable whose values are the number of parameters in each
-frame of the current bash execution call stack.  The number of
-parameters to the current subroutine (shell function or script executed
-with @code{.} or @code{source}) is at the top of the stack.  When a
-subroutine is executed, the number of parameters passed is pushed onto
-@code{BASH_ARGC}.
-The shell sets @code{BASH_ARGC} only when in extended debugging mode
-(see @ref{The Shopt Builtin}
-for a description of the @code{extdebug} option to the @code{shopt}
-builtin).
-
-@item BASH_ARGV
-An array variable containing all of the parameters in the current bash
-execution call stack.  The final parameter of the last subroutine call
-is at the top of the stack; the first parameter of the initial call is
-at the bottom.  When a subroutine is executed, the parameters supplied
-are pushed onto @code{BASH_ARGV}.
-The shell sets @code{BASH_ARGV} only when in extended debugging mode
-(see @ref{The Shopt Builtin}
-for a description of the @code{extdebug} option to the @code{shopt}
-builtin).
-
-@item BASH_CMDS
-An associative array variable whose members correspond to the internal
-hash table of commands as maintained by the @code{hash} builtin
-(@pxref{Bourne Shell Builtins}).
-Elements added to this array appear in the hash table; unsetting array
-elements cause commands to be removed from the hash table.
-
-@item BASH_COMMAND
-The command currently being executed or about to be executed, unless the
-shell is executing a command as the result of a trap,
-in which case it is the command executing at the time of the trap.
-
-@item BASH_COMPAT
-The value is used to set the shell's compatibility level.
-@xref{The Shopt Builtin} for a description of the various compatibility
-levels and their effects.
-The value may be a decimal number (e.g., 4.2) or an integer (e.g., 42)
-corresponding to the desired compatibility level.
-If @code{BASH_COMPAT} is unset or set to the empty string, the compatibility
-level is set to the default for the current version.
-If @code{BASH_COMPAT} is set to a value that is not one of the valid
-compatibility levels, the shell prints an error message and sets the
-compatibility level to the default for the current version.
-The valid compatibility levels correspond to the compatibility options
-accepted by the @code{shopt} builtin described above (for example,
-@var{compat42} means that 4.2 and 42 are valid values).
-The current version is also a valid value.
-
-@item BASH_ENV
-If this variable is set when Bash is invoked to execute a shell
-script, its value is expanded and used as the name of a startup file
-to read before executing the script.  @xref{Bash Startup Files}.
-
-@item BASH_EXECUTION_STRING
-The command argument to the @option{-c} invocation option.
-
-@item BASH_LINENO
-An array variable whose members are the line numbers in source files
-where each corresponding member of @var{FUNCNAME} was invoked.
-@code{$@{BASH_LINENO[$i]@}} is the line number in the source file
-(@code{$@{BASH_SOURCE[$i+1]@}}) where
-@code{$@{FUNCNAME[$i]@}} was called (or @code{$@{BASH_LINENO[$i-1]@}} if
-referenced within another shell function). 
-Use @code{LINENO} to obtain the current line number.
-
-@item BASH_REMATCH
-An array variable whose members are assigned by the @samp{=~} binary
-operator to the @code{[[} conditional command
-(@pxref{Conditional Constructs}).
-The element with index 0 is the portion of the string
-matching the entire regular expression.
-The element with index @var{n} is the portion of the
-string matching the @var{n}th parenthesized subexpression.
-This variable is read-only.
-
-@item BASH_SOURCE
-An array variable whose members are the source filenames where the
-corresponding shell function names in the @code{FUNCNAME} array
-variable are defined.
-The shell function @code{$@{FUNCNAME[$i]@}} is defined in the file
-@code{$@{BASH_SOURCE[$i]@}} and called from @code{$@{BASH_SOURCE[$i+1]@}}
-
-@item BASH_SUBSHELL
-Incremented by one within each subshell or subshell environment when
-the shell begins executing in that environment.
-The initial value is 0.
-
-@item BASH_VERSINFO
-A readonly array variable (@pxref{Arrays})
-whose members hold version information for this instance of Bash.
-The values assigned to the array members are as follows:
-
-@table @code
-
-@item BASH_VERSINFO[0]
-The major version number (the @var{release}).
-
-@item BASH_VERSINFO[1]
-The minor version number (the @var{version}).
-
-@item BASH_VERSINFO[2]
-The patch level.
-
-@item BASH_VERSINFO[3]
-The build version.
-
-@item BASH_VERSINFO[4]
-The release status (e.g., @var{beta1}).
-
-@item BASH_VERSINFO[5]
-The value of @env{MACHTYPE}.
-@end table
-
-@item BASH_VERSION
-The version number of the current instance of Bash.
-
-@item BASH_XTRACEFD
-If set to an integer corresponding to a valid file descriptor, Bash
-will write the trace output generated when @samp{set -x}
-is enabled to that file descriptor.
-This allows tracing output to be separated from diagnostic and error
-messages.
-The file descriptor is closed when @code{BASH_XTRACEFD} is unset or assigned
-a new value.
-Unsetting @code{BASH_XTRACEFD} or assigning it the empty string causes the
-trace output to be sent to the standard error.
-Note that setting @code{BASH_XTRACEFD} to 2 (the standard error file
-descriptor) and then unsetting it will result in the standard error
-being closed.
-
-@item CHILD_MAX
-Set the number of exited child status values for the shell to remember.
-Bash will not allow this value to be decreased below a @sc{posix}-mandated
-minimum, and there is a maximum value (currently 8192) that this may
-not exceed.
-The minimum value is system-dependent.
-
-@item COLUMNS
-Used by the @code{select} command to determine the terminal width
-when printing selection lists.  Automatically set by an interactive shell
-upon receipt of a
-@code{SIGWINCH}.
-
-@item COMP_CWORD
-An index into @env{$@{COMP_WORDS@}} of the word containing the current
-cursor position.
-This variable is available only in shell functions invoked by the
-programmable completion facilities (@pxref{Programmable Completion}).
-
-@item COMP_LINE
-The current command line.
-This variable is available only in shell functions and external
-commands invoked by the
-programmable completion facilities (@pxref{Programmable Completion}).
-
-@item COMP_POINT
-The index of the current cursor position relative to the beginning of
-the current command.
-If the current cursor position is at the end of the current command,
-the value of this variable is equal to @code{$@{#COMP_LINE@}}.
-This variable is available only in shell functions and external
-commands invoked by the
-programmable completion facilities (@pxref{Programmable Completion}).
-
-@item COMP_TYPE
-Set to an integer value corresponding to the type of completion attempted
-that caused a completion function to be called:
-@var{TAB}, for normal completion,
-@samp{?}, for listing completions after successive tabs,
-@samp{!}, for listing alternatives on partial word completion,
-@samp{@@}, to list completions if the word is not unmodified,
-or
-@samp{%}, for menu completion.
-This variable is available only in shell functions and external
-commands invoked by the
-programmable completion facilities (@pxref{Programmable Completion}).
-
-@item COMP_KEY
-The key (or final key of a key sequence) used to invoke the current
-completion function.
-
-@item COMP_WORDBREAKS
-The set of characters that the Readline library treats as word
-separators when performing word completion.
-If @code{COMP_WORDBREAKS} is unset, it loses its special properties,
-even if it is subsequently reset.
-
-@item COMP_WORDS
-An array variable consisting of the individual
-words in the current command line.
-The line is split into words as Readline would split it, using
-@code{COMP_WORDBREAKS} as described above.
-This variable is available only in shell functions invoked by the
-programmable completion facilities (@pxref{Programmable Completion}).
-
-@item COMPREPLY
-An array variable from which Bash reads the possible completions
-generated by a shell function invoked by the programmable completion
-facility (@pxref{Programmable Completion}).
-Each array element contains one possible completion.
-
-@item COPROC
-An array variable created to hold the file descriptors
-for output from and input to an unnamed coprocess (@pxref{Coprocesses}).
-
-@item DIRSTACK
-An array variable containing the current contents of the directory stack.
-Directories appear in the stack in the order they are displayed by the
-@code{dirs} builtin.
-Assigning to members of this array variable may be used to modify
-directories already in the stack, but the @code{pushd} and @code{popd}
-builtins must be used to add and remove directories.
-Assignment to this variable will not change the current directory.
-If @env{DIRSTACK} is unset, it loses its special properties, even if
-it is subsequently reset.
-
-@item EMACS
-If Bash finds this variable in the environment when the shell
-starts with value @samp{t}, it assumes that the shell is running in an
-Emacs shell buffer and disables line editing.
-
-@item ENV
-Similar to @code{BASH_ENV}; used when the shell is invoked in
-@sc{posix} Mode (@pxref{Bash POSIX Mode}).
-
-@item EUID
-The numeric effective user id of the current user.  This variable
-is readonly.
-
-@item FCEDIT
-The editor used as a default by the @option{-e} option to the @code{fc}
-builtin command.
-
-@item FIGNORE
-A colon-separated list of suffixes to ignore when performing
-filename completion.
-A filename whose suffix matches one of the entries in 
-@env{FIGNORE}
-is excluded from the list of matched filenames.  A sample
-value is @samp{.o:~}
-
-@item FUNCNAME
-An array variable containing the names of all shell functions
-currently in the execution call stack.
-The element with index 0 is the name of any currently-executing
-shell function.
-The bottom-most element (the one with the highest index)
-is @code{"main"}.
-This variable exists only when a shell function is executing.
-Assignments to @env{FUNCNAME} have no effect and return an error status.
-If @env{FUNCNAME} is unset, it loses its special properties, even if
-it is subsequently reset.
-
-This variable can be used with @code{BASH_LINENO} and @code{BASH_SOURCE}.
-Each element of @code{FUNCNAME} has corresponding elements in
-@code{BASH_LINENO} and @code{BASH_SOURCE} to describe the call stack.
-For instance, @code{$@{FUNCNAME[$i]@}} was called from the file
-@code{$@{BASH_SOURCE[$i+1]@}} at line number @code{$@{BASH_LINENO[$i]@}}.
-The @code{caller} builtin displays the current call stack using this
-information.
-
-@item FUNCNEST
-If set to a numeric value greater than 0, defines a maximum function
-nesting level.  Function invocations that exceed this nesting level
-will cause the current command to abort.
-
-@item GLOBIGNORE
-A colon-separated list of patterns defining the set of filenames to
-be ignored by filename expansion.
-If a filename matched by a filename expansion pattern also matches one
-of the patterns in @env{GLOBIGNORE}, it is removed from the list
-of matches.
-
-@item GROUPS
-An array variable containing the list of groups of which the current    
-user is a member.
-Assignments to @env{GROUPS} have no effect and return an error status.
-If @env{GROUPS} is unset, it loses its special properties, even if it is
-subsequently reset.
-
-@item histchars
-Up to three characters which control history expansion, quick
-substitution, and tokenization (@pxref{History Interaction}).
-The first character is the
-@var{history expansion} character, that is, the character which signifies the
-start of a history expansion, normally @samp{!}.  The second character is the
-character which signifies `quick substitution' when seen as the first
-character on a line, normally @samp{^}.  The optional third character is the
-character which indicates that the remainder of the line is a comment when
-found as the first character of a word, usually @samp{#}.  The history
-comment character causes history substitution to be skipped for the
-remaining words on the line.  It does not necessarily cause the shell
-parser to treat the rest of the line as a comment.
-
-@item HISTCMD
-The history number, or index in the history list, of the current
-command.  If @env{HISTCMD} is unset, it loses its special properties,
-even if it is subsequently reset.
-
-@item HISTCONTROL
-A colon-separated list of values controlling how commands are saved on
-the history list.
-If the list of values includes @samp{ignorespace}, lines which begin
-with a space character are not saved in the history list.
-A value of @samp{ignoredups} causes lines which match the previous
-history entry to not be saved.
-A value of @samp{ignoreboth} is shorthand for
-@samp{ignorespace} and @samp{ignoredups}.
-A value of @samp{erasedups} causes all previous lines matching the
-current line to be removed from the history list before that line
-is saved.
-Any value not in the above list is ignored.
-If @env{HISTCONTROL} is unset, or does not include a valid value, 
-all lines read by the shell parser are saved on the history list, 
-subject to the value of @env{HISTIGNORE}.
-The second and subsequent lines of a multi-line compound command are
-not tested, and are added to the history regardless of the value of
-@env{HISTCONTROL}.
-
-@item HISTFILE
-The name of the file to which the command history is saved.  The
-default value is @file{~/.bash_history}.
-
-@item HISTFILESIZE
-The maximum number of lines contained in the history file.
-When this variable is assigned a value, the history file is truncated,
-if necessary, to contain no more than that number of lines
-by removing the oldest entries.
-The history file is also truncated to this size after
-writing it when a shell exits.
-If the value is 0, the history file is truncated to zero size.
-Non-numeric values and numeric values less than zero inhibit truncation.
-The shell sets the default value to the value of @env{HISTSIZE}
-after reading any startup files.
-
-@item HISTIGNORE
-A colon-separated list of patterns used to decide which command
-lines should be saved on the history list.  Each pattern is
-anchored at the beginning of the line and must match the complete
-line (no implicit @samp{*} is appended).  Each pattern is tested
-against the line after the checks specified by @env{HISTCONTROL}
-are applied.  In addition to the normal shell pattern matching
-characters, @samp{&} matches the previous history line.  @samp{&}
-may be escaped using a backslash; the backslash is removed
-before attempting a match. 
-The second and subsequent lines of a multi-line compound command are
-not tested, and are added to the history regardless of the value of
-@env{HISTIGNORE}.
-
-@env{HISTIGNORE} subsumes the function of @env{HISTCONTROL}.  A
-pattern of @samp{&} is identical to @code{ignoredups}, and a
-pattern of @samp{[ ]*} is identical to @code{ignorespace}. 
-Combining these two patterns, separating them with a colon,
-provides the functionality of @code{ignoreboth}. 
-
-@item HISTSIZE
-The maximum number of commands to remember on the history list.
-If the value is 0, commands are not saved in the history list.
-Numeric values less than zero result in every command being saved
-on the history list (there is no limit).
-The shell sets the default value to 500 after reading any startup files.
-
-@item HISTTIMEFORMAT
-If this variable is set and not null, its value is used as a format string
-for @var{strftime} to print the time stamp associated with each history
-entry displayed by the @code{history} builtin.
-If this variable is set, time stamps are written to the history file so
-they may be preserved across shell sessions.
-This uses the history comment character to distinguish timestamps from
-other history lines.
-
-@item HOSTFILE
-Contains the name of a file in the same format as @file{/etc/hosts} that
-should be read when the shell needs to complete a hostname.
-The list of possible hostname completions may be changed while the shell
-is running;
-the next time hostname completion is attempted after the
-value is changed, Bash adds the contents of the new file to the
-existing list.
-If @env{HOSTFILE} is set, but has no value, or does not name a readable file,
-Bash attempts to read 
-@file{/etc/hosts} to obtain the list of possible hostname completions.
-When @env{HOSTFILE} is unset, the hostname list is cleared.
-
-@item HOSTNAME
-The name of the current host.
-
-@item HOSTTYPE
-A string describing the machine Bash is running on.
-
-@item IGNOREEOF
-Controls the action of the shell on receipt of an @code{EOF} character
-as the sole input.  If set, the value denotes the number
-of consecutive @code{EOF} characters that can be read as the
-first character on an input line
-before the shell will exit.  If the variable exists but does not
-have a numeric value (or has no value) then the default is 10.
-If the variable does not exist, then @code{EOF} signifies the end of 
-input to the shell.  This is only in effect for interactive shells.
-
-@item INPUTRC
-The name of the Readline initialization file, overriding the default
-of @file{~/.inputrc}.
-
-@item LANG  
-Used to determine the locale category for any category not specifically
-selected with a variable starting with @code{LC_}.
-
-@item LC_ALL
-This variable overrides the value of @env{LANG} and any other
-@code{LC_} variable specifying a locale category.
-
-@item LC_COLLATE
-This variable determines the collation order used when sorting the
-results of filename expansion, and
-determines the behavior of range expressions, equivalence classes,
-and collating sequences within filename expansion and pattern matching
-(@pxref{Filename Expansion}).
-
-@item LC_CTYPE
-This variable determines the interpretation of characters and the
-behavior of character classes within filename expansion and pattern
-matching (@pxref{Filename Expansion}).
-
-@item LC_MESSAGES
-This variable determines the locale used to translate double-quoted
-strings preceded by a @samp{$} (@pxref{Locale Translation}).
-
-@item LC_NUMERIC
-This variable determines the locale category used for number formatting.
-
-@item LINENO
-The line number in the script or shell function currently executing.
-
-@item LINES
-Used by the @code{select} command to determine the column length
-for printing selection lists.  Automatically set by an interactive shell
-upon receipt of a
-@code{SIGWINCH}.
-
-@item MACHTYPE
-A string that fully describes the system type on which Bash
-is executing, in the standard @sc{gnu} @var{cpu-company-system} format.
-
-@item MAILCHECK
-How often (in seconds) that the shell should check for mail in the
-files specified in the @env{MAILPATH} or @env{MAIL} variables.
-The default is 60 seconds.  When it is time to check
-for mail, the shell does so before displaying the primary prompt.
-If this variable is unset, or set to a value that is not a number
-greater than or equal to zero, the shell disables mail checking.
-
-@item MAPFILE
-An array variable created to hold the text read by the
-@code{mapfile} builtin when no variable name is supplied.
-
-@item OLDPWD
-The previous working directory as set by the @code{cd} builtin.
-
-@item OPTERR
-If set to the value 1, Bash displays error messages
-generated by the @code{getopts} builtin command.
-
-@item OSTYPE
-A string describing the operating system Bash is running on.
-
-@item PIPESTATUS
-An array variable (@pxref{Arrays})
-containing a list of exit status values from the processes
-in the most-recently-executed foreground pipeline (which may
-contain only a single command).
-
-@item POSIXLY_CORRECT
-If this variable is in the environment when Bash starts, the shell
-enters @sc{posix} mode (@pxref{Bash POSIX Mode}) before reading the
-startup files, as if the @option{--posix} invocation option had been supplied.
-If it is set while the shell is running, Bash enables @sc{posix} mode,
-as if the command
-@example
-@code{set -o posix}
-@end example
-@noindent
-had been executed.  
-
-@item PPID
-The process @sc{id} of the shell's parent process.  This variable
-is readonly.
-
-@item PROMPT_COMMAND
-If set, the value is interpreted as a command to execute
-before the printing of each primary prompt (@env{$PS1}).
-
-@item PROMPT_DIRTRIM
-If set to a number greater than zero, the value is used as the number of
-trailing directory components to retain when expanding the @code{\w} and
-@code{\W} prompt string escapes (@pxref{Controlling the Prompt}).
-Characters removed are replaced with an ellipsis.
-
-@item PS3
-The value of this variable is used as the prompt for the
-@code{select} command.  If this variable is not set, the
-@code{select} command prompts with @samp{#? }
-
-@item PS4
-The value is the prompt printed before the command line is echoed
-when the @option{-x} option is set (@pxref{The Set Builtin}).
-The first character of @env{PS4} is replicated multiple times, as
-necessary, to indicate multiple levels of indirection.
-The default is @samp{+ }.
-
-@item PWD
-The current working directory as set by the @code{cd} builtin.
-
-@item RANDOM
-Each time this parameter is referenced, a random integer
-between 0 and 32767 is generated.  Assigning a value to this
-variable seeds the random number generator.
-
-@item READLINE_LINE
-The contents of the Readline line buffer, for use
-with @samp{bind -x} (@pxref{Bash Builtins}).
-
-@item READLINE_POINT
-The position of the insertion point in the Readline line buffer, for use
-with @samp{bind -x} (@pxref{Bash Builtins}).
-
-@item REPLY
-The default variable for the @code{read} builtin.
-
-@item SECONDS
-This variable expands to the number of seconds since the
-shell was started.  Assignment to this variable resets
-the count to the value assigned, and the expanded value
-becomes the value assigned plus the number of seconds
-since the assignment.
-
-@item SHELL
-The full pathname to the shell is kept in this environment variable.
-If it is not set when the shell starts,
-Bash assigns to it the full pathname of the current user's login shell.
-
-@item SHELLOPTS
-A colon-separated list of enabled shell options.  Each word in
-the list is a valid argument for the @option{-o} option to the
-@code{set} builtin command (@pxref{The Set Builtin}).
-The options appearing in @env{SHELLOPTS} are those reported
-as @samp{on} by @samp{set -o}.
-If this variable is in the environment when Bash
-starts up, each shell option in the list will be enabled before
-reading any startup files.  This variable is readonly.
-
-@item SHLVL
-Incremented by one each time a new instance of Bash is started.  This is
-intended to be a count of how deeply your Bash shells are nested.
-
-@item TIMEFORMAT
-The value of this parameter is used as a format string specifying
-how the timing information for pipelines prefixed with the @code{time}
-reserved word should be displayed.
-The @samp{%} character introduces an
-escape sequence that is expanded to a time value or other
-information.
-The escape sequences and their meanings are as
-follows; the braces denote optional portions. 
-
-@table @code
-
-@item %%
-A literal @samp{%}.
-
-@item %[@var{p}][l]R
-The elapsed time in seconds. 
-
-@item %[@var{p}][l]U
-The number of CPU seconds spent in user mode. 
-
-@item %[@var{p}][l]S
-The number of CPU seconds spent in system mode. 
-
-@item %P
-The CPU percentage, computed as (%U + %S) / %R. 
-@end table
-
-The optional @var{p} is a digit specifying the precision, the number of
-fractional digits after a decimal point.
-A value of 0 causes no decimal point or fraction to be output.
-At most three places after the decimal point may be specified; values
-of @var{p} greater than 3 are changed to 3.
-If @var{p} is not specified, the value 3 is used. 
-
-The optional @code{l} specifies a longer format, including minutes, of
-the form @var{MM}m@var{SS}.@var{FF}s.
-The value of @var{p} determines whether or not the fraction is included. 
-
-If this variable is not set, Bash acts as if it had the value
-@example
-@code{$'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS'}
-@end example
-If the value is null, no timing information is displayed.
-A trailing newline is added when the format string is displayed.
-
-@item TMOUT
-If set to a value greater than zero, @code{TMOUT} is treated as the
-default timeout for the @code{read} builtin (@pxref{Bash Builtins}).
-The @code{select} command (@pxref{Conditional Constructs}) terminates
-if input does not arrive after @code{TMOUT} seconds when input is coming
-from a terminal.
-
-In an interactive shell, the value is interpreted as
-the number of seconds to wait for a line of input after issuing
-the primary prompt.
-Bash
-terminates after waiting for that number of seconds if a complete
-line of input does not arrive.
-
-@item TMPDIR
-If set, Bash uses its value as the name of a directory in which
-Bash creates temporary files for the shell's use.
-
-@item UID
-The numeric real user id of the current user.  This variable is readonly.
-
-@end vtable
-
-@node Bash Features
-@chapter Bash Features
-
-This chapter describes features unique to Bash.
-
-@menu
-* Invoking Bash::              Command line options that you can give
-                               to Bash.
-* Bash Startup Files::         When and how Bash executes scripts.
-* Interactive Shells::         What an interactive shell is.
-* Bash Conditional Expressions::       Primitives used in composing expressions for
-                               the @code{test} builtin.
-* Shell Arithmetic::           Arithmetic on shell variables.
-* Aliases::                    Substituting one command for another.
-* Arrays::                     Array Variables.
-* The Directory Stack::                History of visited directories.
-* Controlling the Prompt::     Customizing the various prompt strings.
-* The Restricted Shell::       A more controlled mode of shell execution.
-* Bash POSIX Mode::            Making Bash behave more closely to what
-                               the POSIX standard specifies.
-@end menu
-
-@node Invoking Bash
-@section Invoking Bash
-
-@example
-bash [long-opt] [-ir] [-abefhkmnptuvxdBCDHP] [-o @var{option}] [-O @var{shopt_option}] [@var{argument} @dots{}]
-bash [long-opt] [-abefhkmnptuvxdBCDHP] [-o @var{option}] [-O @var{shopt_option}] -c @var{string} [@var{argument} @dots{}]
-bash [long-opt] -s [-abefhkmnptuvxdBCDHP] [-o @var{option}] [-O @var{shopt_option}] [@var{argument} @dots{}]
-@end example
-
-All of the single-character options used with the @code{set} builtin
-(@pxref{The Set Builtin}) can be used as options when the shell is invoked.
-In addition, there are several multi-character
-options that you can use.  These options must appear on the command
-line before the single-character options to be recognized. 
-
-@table @code
-@item --debugger
-Arrange for the debugger profile to be executed before the shell
-starts.  Turns on extended debugging mode (see @ref{The Shopt Builtin}
-for a description of the @code{extdebug} option to the @code{shopt}
-builtin).
-
-@item --dump-po-strings
-A list of all double-quoted strings preceded by @samp{$}
-is printed on the standard output
-in the @sc{gnu} @code{gettext} PO (portable object) file format.
-Equivalent to @option{-D} except for the output format.
-
-@item --dump-strings
-Equivalent to @option{-D}.
-
-@item --help
-Display a usage message on standard output and exit successfully.
-
-@item --init-file @var{filename}
-@itemx --rcfile @var{filename}
-Execute commands from @var{filename} (instead of @file{~/.bashrc})
-in an interactive shell.
-
-@item --login
-Equivalent to @option{-l}.
-
-@item --noediting
-Do not use the @sc{gnu} Readline library (@pxref{Command Line Editing})
-to read  command lines when the shell is interactive.
-
-@item --noprofile
-Don't load the system-wide startup file @file{/etc/profile}
-or any of the personal initialization files
-@file{~/.bash_profile}, @file{~/.bash_login}, or @file{~/.profile}
-when Bash is invoked as a login shell.
-
-@item --norc
-Don't read the @file{~/.bashrc} initialization file in an
-interactive shell.  This is on by default if the shell is
-invoked as @code{sh}.
-
-@item --posix
-Change the behavior of Bash where the default operation differs
-from the @sc{posix} standard to match the standard.  This
-is intended to make Bash behave as a strict superset of that
-standard.  @xref{Bash POSIX Mode}, for a description of the Bash
-@sc{posix} mode.
-
-@item --restricted
-Make the shell a restricted shell (@pxref{The Restricted Shell}).
-
-@item --verbose
-Equivalent to @option{-v}.  Print shell input lines as they're read.
-
-@item --version
-Show version information for this instance of
-Bash on the standard output and exit successfully.
-@end table
-
-There are several single-character options that may be supplied at
-invocation which are not available with the @code{set} builtin.
-
-@table @code
-@item -c
-Read and execute commands from the first non-option @var{argument}
-after processing the options, then exit. 
-Any remaining arguments are assigned to the
-positional parameters, starting with @code{$0}.
-
-@item -i
-Force the shell to run interactively.  Interactive shells are
-described in @ref{Interactive Shells}.
-
-@item -l
-Make this shell act as if it had been directly invoked by login.
-When the shell is interactive, this is equivalent to starting a
-login shell with @samp{exec -l bash}.
-When the shell is not interactive, the login shell startup files will
-be executed.
-@samp{exec bash -l} or @samp{exec bash --login}
-will replace the current shell with a Bash login shell.
-@xref{Bash Startup Files}, for a description of the special behavior
-of a login shell.
-
-@item -r
-Make the shell a restricted shell (@pxref{The Restricted Shell}).
-
-@item -s
-If this option is present, or if no arguments remain after option
-processing, then commands are read from the standard input.
-This option allows the positional parameters to be set
-when invoking an interactive shell.
-
-@item -D
-A list of all double-quoted strings preceded by @samp{$}
-is printed on the standard output.
-These are the strings that
-are subject to language translation when the current locale
-is not @code{C} or @code{POSIX} (@pxref{Locale Translation}).
-This implies the @option{-n} option; no commands will be executed.
-
-@item [-+]O [@var{shopt_option}]
-@var{shopt_option} is one of the shell options accepted by the
-@code{shopt} builtin (@pxref{The Shopt Builtin}).
-If @var{shopt_option} is present, @option{-O} sets the value of that option;
-@option{+O} unsets it.  
-If @var{shopt_option} is not supplied, the names and values of the shell
-options accepted by @code{shopt} are printed on the standard output.
-If the invocation option is @option{+O}, the output is displayed in a format
-that may be reused as input.
-
-@item --
-A @code{--} signals the end of options and disables further option
-processing.
-Any arguments after the @code{--} are treated as filenames and arguments.
-@end table
-
-@cindex login shell
-A @emph{login} shell is one whose first character of argument zero is
-@samp{-}, or one invoked with the @option{--login} option.
-
-@cindex interactive shell
-An @emph{interactive} shell is one started without non-option arguments,
-unless @option{-s} is specified,
-without specifying the @option{-c} option, and whose input and output are both
-connected to terminals (as determined by @code{isatty(3)}), or one
-started with the @option{-i} option.  @xref{Interactive Shells}, for more
-information.
-
-If arguments remain after option processing, and neither the
-@option{-c} nor the @option{-s}
-option has been supplied, the first argument is assumed to
-be the name of a file containing shell commands (@pxref{Shell Scripts}).
-When Bash is invoked in this fashion, @code{$0}
-is set to the name of the file, and the positional parameters
-are set to the remaining arguments.
-Bash reads and executes commands from this file, then exits.   
-Bash's exit status is the exit status of the last command executed
-in the script.  If no commands are executed, the exit status is 0.
-
-@node Bash Startup Files
-@section Bash Startup Files
-@cindex startup files
-
-This section describes how Bash executes its startup files.
-If any of the files exist but cannot be read, Bash reports an error.
-Tildes are expanded in filenames as described above under
-Tilde Expansion (@pxref{Tilde Expansion}).
-
-Interactive shells are described in @ref{Interactive Shells}.
-
-@subsubheading Invoked as an interactive login shell, or with @option{--login}
-
-When Bash is invoked as an interactive login shell, or as a
-non-interactive shell with the @option{--login} option, it first reads and
-executes commands from the file @file{/etc/profile}, if that file exists.
-After reading that file, it looks for @file{~/.bash_profile},
-@file{~/.bash_login}, and @file{~/.profile}, in that order, and reads
-and executes commands from the first one that exists and is readable.
-The @option{--noprofile} option may be used when the shell is started to
-inhibit this behavior.
-
-When a login shell exits, Bash reads and executes commands from
-the file @file{~/.bash_logout}, if it exists.
-
-@subsubheading Invoked as an interactive non-login shell
-
-When an interactive shell that is not a login shell is started, Bash
-reads and executes commands from @file{~/.bashrc}, if that file exists.
-This may be inhibited by using the @option{--norc} option.
-The @option{--rcfile @var{file}} option will force Bash to read and
-execute commands from @var{file} instead of @file{~/.bashrc}.
-
-So, typically, your @file{~/.bash_profile} contains the line
-@example
-@code{if [ -f ~/.bashrc ]; then . ~/.bashrc; fi}
-@end example
-@noindent
-after (or before) any login-specific initializations.
-
-@subsubheading Invoked non-interactively
-
-When Bash is started non-interactively, to run a shell script,
-for example, it looks for the variable @env{BASH_ENV} in the environment,
-expands its value if it appears there, and uses the expanded value as
-the name of a file to read and execute.  Bash behaves as if the
-following command were executed:
-@example
-@code{if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi}
-@end example
-@noindent
-but the value of the @env{PATH} variable is not used to search for the
-filename.
-
-As noted above, if a non-interactive shell is invoked with the
-@option{--login} option, Bash attempts to read and execute commands from the
-login shell startup files. 
-
-@subsubheading Invoked with name @code{sh}
-
-If Bash is invoked with the name @code{sh}, it tries to mimic the
-startup behavior of historical versions of @code{sh} as closely as
-possible, while conforming to the @sc{posix} standard as well.
-
-When invoked as an interactive login shell, or as a non-interactive
-shell with the @option{--login} option, it first attempts to read
-and execute commands from @file{/etc/profile} and @file{~/.profile}, in
-that order.
-The @option{--noprofile} option may be used to inhibit this behavior.
-When invoked as an interactive shell with the name @code{sh}, Bash
-looks for the variable @env{ENV}, expands its value if it is defined,
-and uses the expanded value as the name of a file to read and execute.
-Since a shell invoked as @code{sh} does not attempt to read and execute
-commands from any other startup files, the @option{--rcfile} option has
-no effect.
-A non-interactive shell invoked with the name @code{sh} does not attempt
-to read any other startup files.
-
-When invoked as @code{sh}, Bash enters @sc{posix} mode after
-the startup files are read.
-
-@subsubheading Invoked in @sc{posix} mode
-
-When Bash is started in @sc{posix} mode, as with the
-@option{--posix} command line option, it follows the @sc{posix} standard
-for startup files.
-In this mode, interactive shells expand the @env{ENV} variable
-and commands are read and executed from the file whose name is the
-expanded value.
-No other startup files are read.
-
-@subsubheading Invoked by remote shell daemon
-
-Bash attempts to determine when it is being run with its standard input
-connected to a network connection, as when executed by the remote shell
-daemon, usually @code{rshd}, or the secure shell daemon @code{sshd}.
-If Bash determines it is being run in
-this fashion, it reads and executes commands from @file{~/.bashrc}, if that
-file exists and is readable.
-It will not do this if invoked as @code{sh}.
-The @option{--norc} option may be used to inhibit this behavior, and the
-@option{--rcfile} option may be used to force another file to be read, but
-@code{rshd} does not generally invoke the shell with those options or
-allow them to be specified.
-
-@subsubheading Invoked with unequal effective and real @sc{uid/gid}s
-
-If Bash is started with the effective user (group) id not equal to the
-real user (group) id, and the @option{-p} option is not supplied, no startup
-files are read, shell functions are not inherited from the environment,
-the @env{SHELLOPTS}, @env{BASHOPTS}, @env{CDPATH}, and @env{GLOBIGNORE}
-variables, if they appear in the environment, are ignored, and the effective
-user id is set to the real user id.
-If the @option{-p} option is supplied at invocation, the startup behavior is
-the same, but the effective user id is not reset.
-
-@node Interactive Shells
-@section Interactive Shells
-@cindex interactive shell
-@cindex shell, interactive
-
-@menu
-* What is an Interactive Shell?::      What determines whether a shell is Interactive.
-* Is this Shell Interactive?:: How to tell if a shell is interactive.
-* Interactive Shell Behavior:: What changes in a interactive shell?
-@end menu
-
-@node What is an Interactive Shell?
-@subsection What is an Interactive Shell?
-
-An interactive shell
-is one started without non-option arguments, unless @option{-s} is
-specified, without specifying the @option{-c} option, and
-whose input and error output are both
-connected to terminals (as determined by @code{isatty(3)}),
-or one started with the @option{-i} option.
-
-An interactive shell generally reads from and writes to a user's
-terminal.
-
-The @option{-s} invocation option may be used to set the positional parameters
-when an interactive shell is started.
-
-@node Is this Shell Interactive?
-@subsection Is this Shell Interactive?
-
-To determine within a startup script whether or not Bash is
-running interactively,
-test the value of the @samp{-} special parameter.
-It contains @code{i} when the shell is interactive.  For example:
-
-@example
-case "$-" in
-*i*)   echo This shell is interactive ;;
-*)     echo This shell is not interactive ;;
-esac
-@end example
-
-Alternatively, startup scripts may examine the variable
-@env{PS1}; it is unset in non-interactive shells, and set in
-interactive shells.  Thus:
-
-@example
-if [ -z "$PS1" ]; then
-        echo This shell is not interactive
-else
-        echo This shell is interactive
-fi
-@end example
-
-@node Interactive Shell Behavior
-@subsection Interactive Shell Behavior
-
-When the shell is running interactively, it changes its behavior in
-several ways.
-
-@enumerate
-@item
-Startup files are read and executed as described in @ref{Bash Startup Files}.
-
-@item
-Job Control (@pxref{Job Control}) is enabled by default.  When job
-control is in effect, Bash ignores the keyboard-generated job control
-signals @code{SIGTTIN}, @code{SIGTTOU}, and @code{SIGTSTP}.
-
-@item
-Bash expands and displays @env{PS1} before reading the first line
-of a command, and expands and displays @env{PS2} before reading the
-second and subsequent lines of a multi-line command.
-
-@item
-Bash executes the value of the @env{PROMPT_COMMAND} variable as a command
-before printing the primary prompt, @env{$PS1}
-(@pxref{Bash Variables}).
-
-@item
-Readline (@pxref{Command Line Editing}) is used to read commands from
-the user's terminal.
-
-@item
-Bash inspects the value of the @code{ignoreeof} option to @code{set -o}
-instead of exiting immediately when it receives an @code{EOF} on its
-standard input when reading a command (@pxref{The Set Builtin}).
-
-@item
-Command history (@pxref{Bash History Facilities})
-and history expansion (@pxref{History Interaction})
-are enabled by default.
-Bash will save the command history to the file named by @env{$HISTFILE}
-when a shell with history enabled exits.
-
-@item
-Alias expansion (@pxref{Aliases}) is performed by default.
-
-@item
-In the absence of any traps, Bash ignores @code{SIGTERM}
-(@pxref{Signals}).
-
-@item
-In the absence of any traps, @code{SIGINT} is caught and handled
-((@pxref{Signals}).
-@code{SIGINT} will interrupt some shell builtins.
-
-@item
-An interactive login shell sends a @code{SIGHUP} to all jobs on exit
-if the @code{huponexit} shell option has been enabled (@pxref{Signals}).
-
-@item
-The @option{-n} invocation option is ignored, and @samp{set -n} has
-no effect (@pxref{The Set Builtin}).
-
-@item
-Bash will check for mail periodically, depending on the values of the
-@env{MAIL}, @env{MAILPATH}, and @env{MAILCHECK} shell variables
-(@pxref{Bash Variables}).
-
-@item
-Expansion errors due to references to unbound shell variables after
-@samp{set -u} has been enabled will not cause the shell to exit
-(@pxref{The Set Builtin}).
-
-@item
-The shell will not exit on expansion errors caused by @var{var} being unset
-or null in @code{$@{@var{var}:?@var{word}@}} expansions
-(@pxref{Shell Parameter Expansion}).
-
-@item
-Redirection errors encountered by shell builtins will not cause the
-shell to exit.
-
-@item
-When running in @sc{posix} mode, a special builtin returning an error
-status will not cause the shell to exit (@pxref{Bash POSIX Mode}).
-
-@item
-A failed @code{exec} will not cause the shell to exit
-(@pxref{Bourne Shell Builtins}).
-
-@item
-Parser syntax errors will not cause the shell to exit.
-
-@item
-Simple spelling correction for directory arguments to the @code{cd}
-builtin is enabled by default (see the description of the @code{cdspell}
-option to the @code{shopt} builtin in @ref{The Shopt Builtin}).
-
-@item
-The shell will check the value of the @env{TMOUT} variable and exit
-if a command is not read within the specified number of seconds after
-printing @env{$PS1} (@pxref{Bash Variables}).
-
-@end enumerate
-
-@node Bash Conditional Expressions
-@section Bash Conditional Expressions
-@cindex expressions, conditional
-
-Conditional expressions are used by the @code{[[} compound command
-and the @code{test} and @code{[} builtin commands.
-
-Expressions may be unary or binary.
-Unary expressions are often used to examine the status of a file.
-There are string operators and numeric comparison operators as well.
-If the @var{file} argument to one of the primaries is of the form
-@file{/dev/fd/@var{N}}, then file descriptor @var{N} is checked.
-If the @var{file} argument to one of the primaries is one of
-@file{/dev/stdin}, @file{/dev/stdout}, or @file{/dev/stderr}, file
-descriptor 0, 1, or 2, respectively, is checked.
-
-When used with @code{[[}, the @samp{<} and @samp{>} operators sort
-lexicographically using the current locale.
-The @code{test} command uses ASCII ordering.
-
-Unless otherwise specified, primaries that operate on files follow symbolic
-links and operate on the target of the link, rather than the link itself.
-
-@table @code
-@item -a @var{file}
-True if @var{file} exists.
-
-@item -b @var{file}
-True if @var{file} exists and is a block special file.
-
-@item -c @var{file}
-True if @var{file} exists and is a character special file.
-
-@item -d @var{file}
-True if @var{file} exists and is a directory.
-
-@item -e @var{file}
-True if @var{file} exists.
-
-@item -f @var{file}
-True if @var{file} exists and is a regular file.
-
-@item -g @var{file}
-True if @var{file} exists and its set-group-id bit is set.
-
-@item -h @var{file}
-True if @var{file} exists and is a symbolic link.
-
-@item -k @var{file}
-True if @var{file} exists and its "sticky" bit is set.
-
-@item -p @var{file}
-True if @var{file} exists and is a named pipe (FIFO).
-
-@item -r @var{file}
-True if @var{file} exists and is readable.
-
-@item -s @var{file}
-True if @var{file} exists and has a size greater than zero.
-
-@item -t @var{fd}
-True if file descriptor @var{fd} is open and refers to a terminal.
-
-@item -u @var{file}
-True if @var{file} exists and its set-user-id bit is set.
-
-@item -w @var{file}
-True if @var{file} exists and is writable.
-
-@item -x @var{file}
-True if @var{file} exists and is executable.
-
-@item -G @var{file}
-True if @var{file} exists and is owned by the effective group id.
-
-@item -L @var{file}
-True if @var{file} exists and is a symbolic link.
-
-@item -N @var{file}
-True if @var{file} exists and has been modified since it was last read.
-
-@item -O @var{file}
-True if @var{file} exists and is owned by the effective user id.
-
-@item -S @var{file}
-True if @var{file} exists and is a socket.
-
-@item @var{file1} -ef @var{file2}
-True if @var{file1} and @var{file2} refer to the same device and
-inode numbers.
-
-@item @var{file1} -nt @var{file2}
-True if @var{file1} is newer (according to modification date)
-than @var{file2}, or if @var{file1} exists and @var{file2} does not.
-
-@item @var{file1} -ot @var{file2}
-True if @var{file1} is older than @var{file2},
-or if @var{file2} exists and @var{file1} does not.
-
-@item -o @var{optname}
-True if the shell option @var{optname} is enabled.
-The list of options appears in the description of the @option{-o}
-option to the @code{set} builtin (@pxref{The Set Builtin}).
-
-@item -v @var{varname}
-True if the shell variable @var{varname} is set (has been assigned a value).
-
-@item -R @var{varname}
-True if the shell variable @var{varname} is set and is a name reference.
-
-@item -z @var{string}
-True if the length of @var{string} is zero.
-
-@item -n @var{string}
-@itemx @var{string}
-True if the length of @var{string} is non-zero.
-
-@item @var{string1} == @var{string2}
-@itemx @var{string1} = @var{string2}
-True if the strings are equal.
-When used with the @code{[[} command, this performs pattern matching as
-described above (@pxref{Conditional Constructs}).
-
-@samp{=} should be used with the @code{test} command for @sc{posix} conformance.
-
-@item @var{string1} != @var{string2}
-True if the strings are not equal.
-
-@item @var{string1} < @var{string2}
-True if @var{string1} sorts before @var{string2} lexicographically.
-
-@item @var{string1} > @var{string2}
-True if @var{string1} sorts after @var{string2} lexicographically.
-
-@item @var{arg1} OP @var{arg2}
-@code{OP} is one of 
-@samp{-eq}, @samp{-ne}, @samp{-lt}, @samp{-le}, @samp{-gt}, or @samp{-ge}.
-These arithmetic binary operators return true if @var{arg1}
-is equal to, not equal to, less than, less than or equal to,
-greater than, or greater than or equal to @var{arg2},
-respectively.  @var{Arg1} and @var{arg2}
-may be positive or negative integers.
-@end table
-
-@node Shell Arithmetic
-@section Shell Arithmetic
-@cindex arithmetic, shell
-@cindex shell arithmetic
-@cindex expressions, arithmetic
-@cindex evaluation, arithmetic
-@cindex arithmetic evaluation
-
-The shell allows arithmetic expressions to be evaluated, as one of
-the shell expansions or by the @code{let} and the @option{-i} option
-to the @code{declare} builtins.
-
-Evaluation is done in fixed-width integers with no check for overflow,
-though division by 0 is trapped and flagged as an error.
-The operators and their precedence, associativity, and values
-are the same as in the C language.
-The following list of operators is grouped into levels of
-equal-precedence operators.
-The levels are listed in order of decreasing precedence. 
-
-@table @code
-
-@item @var{id}++ @var{id}--
-variable post-increment and post-decrement 
-
-@item ++@var{id} --@var{id}
-variable pre-increment and pre-decrement
-
-@item - +
-unary minus and plus
-
-@item ! ~
-logical and bitwise negation
-
-@item **
-exponentiation
-
-@item * / %
-multiplication, division, remainder
-
-@item + -
-addition, subtraction
-
-@item << >>
-left and right bitwise shifts
-
-@item <= >= < >
-comparison
-
-@item == !=
-equality and inequality
-
-@item &
-bitwise AND
-
-@item ^
-bitwise exclusive OR
-
-@item |
-bitwise OR
-
-@item &&
-logical AND
-
-@item ||
-logical OR
-
-@item expr ? expr : expr
-conditional operator
-
-@item = *= /= %= += -= <<= >>= &= ^= |=
-assignment
-
-@item expr1 , expr2
-comma
-@end table
-
-Shell variables are allowed as operands; parameter expansion is
-performed before the expression is evaluated. 
-Within an expression, shell variables may also be referenced by name
-without using the parameter expansion syntax.
-A shell variable that is null or unset evaluates to 0 when referenced
-by name without using the parameter expansion syntax.
-The value of a variable is evaluated as an arithmetic expression
-when it is referenced, or when a variable which has been given the  
-@var{integer} attribute using @samp{declare -i} is assigned a value.
-A null value evaluates to 0.
-A shell variable need not have its @var{integer} attribute turned on
-to be used in an expression.
-
-Constants with a leading 0 are interpreted as octal numbers.
-A leading @samp{0x} or @samp{0X} denotes hexadecimal.  Otherwise,
-numbers take the form [@var{base}@code{#}]@var{n}, where the optional @var{base}
-is a decimal number between 2 and 64 representing the arithmetic
-base, and @var{n} is a number in that base.
-If @var{base}@code{#} is omitted, then base 10 is used.
-When specifying @var{n},
-he digits greater than 9 are represented by the lowercase letters,
-the uppercase letters, @samp{@@}, and @samp{_}, in that order.
-If @var{base} is less than or equal to 36, lowercase and uppercase
-letters may be used interchangeably to represent numbers between 10
-and 35.
-
-Operators are evaluated in order of precedence.  Sub-expressions in
-parentheses are evaluated first and may override the precedence
-rules above.
-
-@node Aliases
-@section Aliases
-@cindex alias expansion
-
-@var{Aliases} allow a string to be substituted for a word when it is used
-as the first word of a simple command.
-The shell maintains a list of aliases that may be set and unset with
-the @code{alias} and @code{unalias} builtin commands.
-
-The first word of each simple command, if unquoted, is checked to see
-if it has an alias.
-If so, that word is replaced by the text of the alias.
-The characters @samp{/}, @samp{$}, @samp{`}, @samp{=} and any of the
-shell metacharacters or quoting characters listed above may not appear
-in an alias name.
-The replacement text may contain any valid
-shell input, including shell metacharacters.
-The first word of the replacement text is tested for
-aliases, but a word that is identical to an alias being expanded
-is not expanded a second time.
-This means that one may alias @code{ls} to @code{"ls -F"},
-for instance, and Bash does not try to recursively expand the
-replacement text.
-If the last character of the alias value is a
-@var{blank}, then the next command word following the
-alias is also checked for alias expansion.
-
-Aliases are created and listed with the @code{alias}
-command, and removed with the @code{unalias} command.
-
-There is no mechanism for using arguments in the replacement text,
-as in @code{csh}.
-If arguments are needed, a shell function should be used
-(@pxref{Shell Functions}).
-
-Aliases are not expanded when the shell is not interactive,
-unless the @code{expand_aliases} shell option is set using
-@code{shopt} (@pxref{The Shopt Builtin}).
-
-The rules concerning the definition and use of aliases are
-somewhat confusing.  Bash
-always reads at least one complete line
-of input before executing any
-of the commands on that line.  Aliases are expanded when a
-command is read, not when it is executed.  Therefore, an
-alias definition appearing on the same line as another
-command does not take effect until the next line of input is read.
-The commands following the alias definition
-on that line are not affected by the new alias.
-This behavior is also an issue when functions are executed.
-Aliases are expanded when a function definition is read,
-not when the function is executed, because a function definition
-is itself a compound command.  As a consequence, aliases
-defined in a function are not available until after that
-function is executed.  To be safe, always put
-alias definitions on a separate line, and do not use @code{alias}
-in compound commands.
-
-For almost every purpose, shell functions are preferred over aliases.
-
-@node Arrays
-@section Arrays
-@cindex arrays
-
-Bash provides one-dimensional indexed and associative array variables.
-Any variable may be used as an indexed array;
-the @code{declare} builtin will explicitly declare an array.
-There is no maximum
-limit on the size of an array, nor any requirement that members
-be indexed or assigned contiguously.
-Indexed arrays are referenced using integers (including arithmetic
-expressions (@pxref{Shell Arithmetic})) and are zero-based;
-associative arrays use arbitrary strings.
-Unless otherwise noted, indexed array indices must be non-negative integers.
-
-An indexed array is created automatically if any variable is assigned to
-using the syntax
-@example
-@var{name}[@var{subscript}]=@var{value}
-@end example
-
-@noindent
-The @var{subscript}
-is treated as an arithmetic expression that must evaluate to a number.
-To explicitly declare an array, use
-@example
-declare -a @var{name}
-@end example
-@noindent
-The syntax
-@example
-declare -a @var{name}[@var{subscript}]
-@end example
-@noindent
-is also accepted; the @var{subscript} is ignored.
-
-@noindent
-Associative arrays are created using
-@example
-declare -A @var{name}.
-@end example
-
-Attributes may be
-specified for an array variable using the @code{declare} and
-@code{readonly} builtins.  Each attribute applies to all members of
-an array.
-
-Arrays are assigned to using compound assignments of the form
-@example
-@var{name}=(@var{value1} @var{value2} @dots{} )
-@end example
-@noindent
-where each
-@var{value} is of the form @code{[@var{subscript}]=}@var{string}.
-Indexed array assignments do not require anything but @var{string}.
-When assigning to indexed arrays, if
-the optional subscript is supplied, that index is assigned to;
-otherwise the index of the element assigned is the last index assigned
-to by the statement plus one.  Indexing starts at zero.
-
-When assigning to an associative array, the subscript is required.
-
-This syntax is also accepted by the @code{declare}
-builtin.  Individual array elements may be assigned to using the
-@code{@var{name}[@var{subscript}]=@var{value}} syntax introduced above.
-
-When assigning to an indexed array, if @var{name}
-is subscripted by a negative number, that number is
-interpreted as relative to one greater than the maximum index of
-@var{name}, so negative indices count back from the end of the
-array, and an index of -1 references the last element.
-
-Any element of an array may be referenced using
-@code{$@{@var{name}[@var{subscript}]@}}.
-The braces are required to avoid
-conflicts with the shell's filename expansion operators.  If the
-@var{subscript} is @samp{@@} or @samp{*}, the word expands to all members
-of the array @var{name}.  These subscripts differ only when the word
-appears within double quotes.
-If the word is double-quoted,
-@code{$@{@var{name}[*]@}} expands to a single word with
-the value of each array member separated by the first character of the
-@env{IFS} variable, and @code{$@{@var{name}[@@]@}} expands each element of
-@var{name} to a separate word.  When there are no array members,
-@code{$@{@var{name}[@@]@}} expands to nothing.
-If the double-quoted expansion occurs within a word, the expansion of
-the first parameter is joined with the beginning part of the original
-word, and the expansion of the last parameter is joined with the last
-part of the original word.
-This is analogous to the
-expansion of the special parameters @samp{@@} and @samp{*}. 
-@code{$@{#@var{name}[@var{subscript}]@}} expands to the length of
-@code{$@{@var{name}[@var{subscript}]@}}.
-If @var{subscript} is @samp{@@} or
-@samp{*}, the expansion is the number of elements in the array. 
-Referencing an array variable without a subscript is equivalent to
-referencing with a subscript of 0. 
-If the @var{subscript}
-used to reference an element of an indexed array
-evaluates to a number less than zero, it is 
-interpreted as relative to one greater than the maximum index of the array,
-so negative indices count back from the end of the array,
-and an index of -1 refers to the last element.
-
-An array variable is considered set if a subscript has been assigned a
-value.  The null string is a valid value.
-
-The @code{unset} builtin is used to destroy arrays.
-@code{unset @var{name}[@var{subscript}]}
-destroys the array element at index @var{subscript}.
-Negative subscripts to indexed arrays are interpreted as described above.
-Care must be taken to avoid unwanted side effects caused by filename
-expansion.
-@code{unset @var{name}}, where @var{name} is an array, removes the
-entire array.  A subscript of @samp{*} or @samp{@@} also removes the
-entire array.
-
-The @code{declare}, @code{local}, and @code{readonly}
-builtins each accept a @option{-a} option to specify an indexed
-array and a @option{-A} option to specify an associative array.
-If both options are supplied, @option{-A} takes precedence.
-The @code{read} builtin accepts a @option{-a}
-option to assign a list of words read from the standard input
-to an array, and can read values from the standard input into
-individual array elements.  The @code{set} and @code{declare}
-builtins display array values in a way that allows them to be
-reused as input.
-
-@node The Directory Stack
-@section The Directory Stack
-@cindex directory stack
-
-@menu
-* Directory Stack Builtins::           Bash builtin commands to manipulate
-                                       the directory stack.
-@end menu
-
-The directory stack is a list of recently-visited directories.  The
-@code{pushd} builtin adds directories to the stack as it changes
-the current directory, and the @code{popd} builtin removes specified
-directories from the stack and changes the current directory to
-the directory removed.  The @code{dirs} builtin displays the contents
-of the directory stack.
-
-The contents of the directory stack are also visible
-as the value of the @env{DIRSTACK} shell variable.
-
-@node Directory Stack Builtins
-@subsection Directory Stack Builtins
-
-@table @code
-
-@item dirs
-@btindex dirs
-@example
-dirs [-clpv] [+@var{N} | -@var{N}]
-@end example
-
-Display the list of currently remembered directories.  Directories
-are added to the list with the @code{pushd} command; the
-@code{popd} command removes directories from the list.
-
-@table @code
-@item -c
-Clears the directory stack by deleting all of the elements.
-@item -l
-Produces a listing using full pathnames;
-the default listing format uses a tilde to denote the home directory.
-@item -p
-Causes @code{dirs} to print the directory stack with one entry per
-line.
-@item -v
-Causes @code{dirs} to print the directory stack with one entry per
-line, prefixing each entry with its index in the stack.
-@item +@var{N}
-Displays the @var{N}th directory (counting from the left of the
-list printed by @code{dirs} when invoked without options), starting
-with zero.
-@item -@var{N}
-Displays the @var{N}th directory (counting from the right of the
-list printed by @code{dirs} when invoked without options), starting
-with zero.
-@end table
-
-@item popd
-@btindex popd
-@example
-popd [-n] [+@var{N} | -@var{N}]
-@end example
-
-Remove the top entry from the directory stack, and @code{cd}
-to the new top directory.
-When no arguments are given, @code{popd}
-removes the top directory from the stack and
-performs a @code{cd} to the new top directory.  The
-elements are numbered from 0 starting at the first directory listed with
-@code{dirs}; that is, @code{popd} is equivalent to @code{popd +0}.
-
-@table @code
-@item -n
-Suppresses the normal change of directory when removing directories
-from the stack, so that only the stack is manipulated.
-@item +@var{N}
-Removes the @var{N}th directory (counting from the left of the
-list printed by @code{dirs}), starting with zero.
-@item -@var{N}
-Removes the @var{N}th directory (counting from the right of the
-list printed by @code{dirs}), starting with zero.
-@end table
-
-@btindex pushd
-@item pushd
-@example
-pushd [-n] [@var{+N} | @var{-N} | @var{dir}]
-@end example
-
-Save the current directory on the top of the directory stack
-and then @code{cd} to @var{dir}.
-With no arguments, @code{pushd} exchanges the top two directories.
-
-@table @code
-@item -n
-Suppresses the normal change of directory when adding directories
-to the stack, so that only the stack is manipulated.
-@item +@var{N}
-Brings the @var{N}th directory (counting from the left of the
-list printed by @code{dirs}, starting with zero) to the top of
-the list by rotating the stack.
-@item -@var{N}
-Brings the @var{N}th directory (counting from the right of the
-list printed by @code{dirs}, starting with zero) to the top of
-the list by rotating the stack.
-@item @var{dir}
-Makes the current working directory be the top of the stack, making
-it the new current directory as if it had been supplied as an argument
-to the @code{cd} builtin.
-@end table
-@end table
-
-@node Controlling the Prompt
-@section Controlling the Prompt
-@cindex prompting
-
-The value of the variable @env{PROMPT_COMMAND} is examined just before
-Bash prints each primary prompt.  If @env{PROMPT_COMMAND} is set and
-has a non-null value, then the
-value is executed just as if it had been typed on the command line.
-
-In addition, the following table describes the special characters which
-can appear in the prompt variables @env{PS1} to @env{PS4}:
-
-@table @code
-@item \a
-A bell character.
-@item \d
-The date, in "Weekday Month Date" format (e.g., "Tue May 26").
-@item \D@{@var{format}@}
-The @var{format} is passed to @code{strftime}(3) and the result is inserted
-into the prompt string; an empty @var{format} results in a locale-specific
-time representation.  The braces are required.
-@item \e
-An escape character.
-@item \h
-The hostname, up to the first `.'.
-@item \H
-The hostname.
-@item \j
-The number of jobs currently managed by the shell.
-@item \l
-The basename of the shell's terminal device name.
-@item \n
-A newline.
-@item \r
-A carriage return.
-@item \s
-The name of the shell, the basename of @code{$0} (the portion
-following the final slash).
-@item \t
-The time, in 24-hour HH:MM:SS format.
-@item \T
-The time, in 12-hour HH:MM:SS format.
-@item \@@
-The time, in 12-hour am/pm format.
-@item \A
-The time, in 24-hour HH:MM format.
-@item \u
-The username of the current user.
-@item \v
-The version of Bash (e.g., 2.00)          
-@item \V
-The release of Bash, version + patchlevel (e.g., 2.00.0)
-@item \w
-The current working directory, with @env{$HOME} abbreviated with a tilde
-(uses the @env{$PROMPT_DIRTRIM} variable).
-@item \W
-The basename of @env{$PWD}, with @env{$HOME} abbreviated with a tilde.
-@item \!
-The history number of this command.
-@item \#
-The command number of this command.
-@item \$
-If the effective uid is 0, @code{#}, otherwise @code{$}.
-@item \@var{nnn}
-The character whose ASCII code is the octal value @var{nnn}.
-@item \\
-A backslash.
-@item \[
-Begin a sequence of non-printing characters.  This could be used to
-embed a terminal control sequence into the prompt.
-@item \]
-End a sequence of non-printing characters.
-@end table
-
-The command number and the history number are usually different:
-the history number of a command is its position in the history
-list, which may include commands restored from the history file
-(@pxref{Bash History Facilities}), while the command number is
-the position in the sequence of commands executed during the current
-shell session.
-
-After the string is decoded, it is expanded via
-parameter expansion, command substitution, arithmetic
-expansion, and quote removal, subject to the value of the
-@code{promptvars} shell option (@pxref{Bash Builtins}).
-
-@node The Restricted Shell
-@section The Restricted Shell
-@cindex restricted shell
-
-If Bash is started with the name @code{rbash}, or the
-@option{--restricted}
-or
-@option{-r}
-option is supplied at invocation, the shell becomes restricted.
-A restricted shell is used to
-set up an environment more controlled than the standard shell.
-A restricted shell behaves identically to @code{bash}
-with the exception that the following are disallowed or not performed:
-
-@itemize @bullet
-@item
-Changing directories with the @code{cd} builtin.
-@item
-Setting or unsetting the values of the @env{SHELL}, @env{PATH},
-@env{ENV}, or @env{BASH_ENV} variables.
-@item
-Specifying command names containing slashes.
-@item
-Specifying a filename containing a slash as an argument to the @code{.}
-builtin command.
-@item
-Specifying a filename containing a slash as an argument to the @option{-p}
-option to the @code{hash} builtin command.
-@item
-Importing function definitions from the shell environment at startup.
-@item
-Parsing the value of @env{SHELLOPTS} from the shell environment at startup.
-@item
-Redirecting output using the @samp{>}, @samp{>|}, @samp{<>}, @samp{>&},
-@samp{&>}, and @samp{>>} redirection operators.
-@item
-Using the @code{exec} builtin to replace the shell with another command.
-@item
-Adding or deleting builtin commands with the
-@option{-f} and @option{-d} options to the @code{enable} builtin.
-@item
-Using the @code{enable} builtin command to enable disabled shell builtins.
-@item
-Specifying the @option{-p} option to the @code{command} builtin.
-@item
-Turning off restricted mode with @samp{set +r} or @samp{set +o restricted}.
-@end itemize
-
-These restrictions are enforced after any startup files are read.
-
-When a command that is found to be a shell script is executed
-(@pxref{Shell Scripts}), @code{rbash} turns off any restrictions in
-the shell spawned to execute the script.
-
-@node Bash POSIX Mode
-@section Bash POSIX Mode
-@cindex POSIX Mode
-
-Starting Bash with the @option{--posix} command-line option or executing
-@samp{set -o posix} while Bash is running will cause Bash to conform more
-closely to the @sc{posix} standard by changing the behavior to
-match that specified by @sc{posix} in areas where the Bash default differs.
-
-When invoked as @code{sh}, Bash enters @sc{posix} mode after reading the
-startup files.
-
-The following list is what's changed when `@sc{posix} mode' is in effect:
-
-@enumerate
-@item
-When a command in the hash table no longer exists, Bash will re-search
-@env{$PATH} to find the new location.  This is also available with
-@samp{shopt -s checkhash}.
-
-@item
-The message printed by the job control code and builtins when a job
-exits with a non-zero status is `Done(status)'.
-
-@item
-The message printed by the job control code and builtins when a job
-is stopped is `Stopped(@var{signame})', where @var{signame} is, for
-example, @code{SIGTSTP}.
-
-@item
-The @code{bg} builtin uses the required format to describe each job placed
-in the background, which does not include an indication of whether the job
-is the current or previous job.
-
-@item
-Reserved words appearing in a context where reserved words are recognized
-do not undergo alias expansion.
-
-@item
-The @sc{posix} @env{PS1} and @env{PS2} expansions of @samp{!} to
-the history number and @samp{!!} to @samp{!} are enabled,
-and parameter expansion is performed on the values of @env{PS1} and
-@env{PS2} regardless of the setting of the @code{promptvars} option.
-
-@item
-The @sc{posix} startup files are executed (@env{$ENV}) rather than
-the normal Bash files.
-
-@item
-Tilde expansion is only performed on assignments preceding a command
-name, rather than on all assignment statements on the line.
-
-@item
-The @code{command} builtin does not prevent builtins that take assignment
-statements as arguments from expanding them as assignment statements;
-when not in @sc{posix} mode, assignment builtins lose their assignment
-statement expansion properties when preceded by @code{command}.
-
-@item
-The default history file is @file{~/.sh_history} (this is the
-default value of @env{$HISTFILE}).
-
-@item
-The output of @samp{kill -l} prints all the signal names on a single line,
-separated by spaces, without the @samp{SIG} prefix.
-
-@item
-The @code{kill} builtin does not accept signal names with a @samp{SIG}
-prefix.
-
-@item
-Non-interactive shells exit if @var{filename} in @code{.} @var{filename}
-is not found.
-
-@item
-Non-interactive shells exit if a syntax error in an arithmetic expansion
-results in an invalid expression.
-
-@item
-Non-interactive shells exit if there is a syntax error in a script read
-with the @code{.} or @code{source} builtins, or in a string processed by
-the @code{eval} builtin.
-
-@item
-Redirection operators do not perform filename expansion on the word
-in the redirection unless the shell is interactive.
-
-@item
-Redirection operators do not perform word splitting on the word in the
-redirection.
-
-@item
-Function names must be valid shell @code{name}s.  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 invalid name
-causes a fatal syntax error in non-interactive shells.
-
-@item
-Function names may not be the same as one of the @sc{posix} special
-builtins.
-
-@item
-@sc{posix} special builtins are found before shell functions
-during command lookup.
-
-@item
-The @code{time} reserved word may be used by itself as a command.  When
-used in this way, it displays timing statistics for the shell and its
-completed children.  The @env{TIMEFORMAT} variable controls the format
-of the timing information.
-
-@item
-When parsing and expanding a $@{@dots{}@} expansion that appears within
-double quotes, single quotes are no longer special and cannot be used to
-quote a closing brace or other special character, unless the operator is
-one of those defined to perform pattern removal.  In this case, they do
-not have to appear as matched pairs.
-
-@item
-The parser does not recognize @code{time} as a reserved word if the next
-token begins with a @samp{-}.
-
-@item
-If a @sc{posix} special builtin returns an error status, a
-non-interactive shell exits.  The fatal errors are those listed in
-the @sc{posix} standard, and include things like passing incorrect options,
-redirection errors, variable assignment errors for assignments preceding
-the command name, and so on.
-
-@item
-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 readonly variable.
-
-@item
-A non-interactive shell exists with an error status if a variable
-assignment error occurs in an assignment statement preceding a special
-builtin, but not with any other simple command.
-
-@item
-A non-interactive shell exits with an error status if the iteration
-variable in a @code{for} statement or the selection variable in a
-@code{select} statement is a readonly variable.
-
-@item
-Process substitution is not available.
-
-@item
-While variable indirection is available, it may not be applied to the
-@samp{#} and @samp{?} special parameters.
-
-@item
-Assignment statements preceding @sc{posix} special builtins
-persist in the shell environment after the builtin completes.
-
-@item
-Assignment statements preceding shell function calls persist in the
-shell environment after the function returns, as if a @sc{posix}
-special builtin command had been executed.
-
-@item
-The @code{export} and @code{readonly} builtin commands display their
-output in the format required by @sc{posix}.
-
-@item
-The @code{trap} builtin displays signal names without the leading
-@code{SIG}.
-
-@item
-The @code{trap} builtin doesn't check the first argument for a possible
-signal specification and revert the signal handling to the original
-disposition if it is, unless that argument consists solely of digits and
-is a valid signal number.  If users want to reset the handler for a given
-signal to the original disposition, they should use @samp{-} as the
-first argument.
-
-@item
-The @code{.} and @code{source} builtins do not search the current directory
-for the filename argument if it is not found by searching @env{PATH}.
-
-@item
-Subshells spawned to execute command substitutions inherit the value of
-the @option{-e} option from the parent shell.  When not in @sc{posix} mode,
-Bash clears the @option{-e} option in such subshells.
-
-@item
-Alias expansion is always enabled, even in non-interactive shells.
-
-@item
-When the @code{alias} builtin displays alias definitions, it does not
-display them with a leading @samp{alias } unless the @option{-p} option
-is supplied.
-
-@item
-When the @code{set} builtin is invoked without options, it does not display
-shell function names and definitions.
-
-@item
-When the @code{set} builtin is invoked without options, it displays
-variable values without quotes, unless they contain shell metacharacters,
-even if the result contains nonprinting characters.
-
-@item
-When the @code{cd} builtin is invoked in @var{logical} mode, and the pathname
-constructed from @code{$PWD} and the directory name supplied as an argument
-does not refer to an existing directory, @code{cd} will fail instead of
-falling back to @var{physical} mode.
-
-@item
-The @code{pwd} builtin verifies that the value it prints is the same as the
-current directory, even if it is not asked to check the file system with the
-@option{-P} option.
-
-@item
-When listing the history, the @code{fc} builtin does not include an
-indication of whether or not a history entry has been modified.
-
-@item
-The default editor used by @code{fc} is @code{ed}.
-
-@item
-The @code{type} and @code{command} builtins will not report a non-executable
-file as having been found, though the shell will attempt to execute such a
-file if it is the only so-named file found in @code{$PATH}.
-
-@item
-The @code{vi} editing mode will invoke the @code{vi} editor directly when
-the @samp{v} command is run, instead of checking @code{$VISUAL} and
-@code{$EDITOR}.
-
-@item
-When the @code{xpg_echo} option is enabled, Bash does not attempt to interpret
-any arguments to @code{echo} as options.  Each argument is displayed, after
-escape characters are converted.
-
-@item
-The @code{ulimit} builtin uses a block size of 512 bytes for the @option{-c}
-and @option{-f} options.
-
-@item
-The arrival of @code{SIGCHLD}  when a trap is set on @code{SIGCHLD} does
-not interrupt the @code{wait} builtin and cause it to return immediately.
-The trap command is run once for each child that exits.
-
-@item
-The @code{read} builtin may be interrupted by a signal for which a trap
-has been set.
-If Bash receives a trapped signal while executing @code{read}, the trap
-handler executes and @code{read} returns an exit status greater than 128.
-
-@end enumerate
-
-There is other @sc{posix} behavior that Bash does not implement by
-default even when in @sc{posix} mode.
-Specifically:
-
-@enumerate
-
-@item
-The @code{fc} builtin checks @code{$EDITOR} as a program to edit history
-entries if @code{FCEDIT} is unset, rather than defaulting directly to
-@code{ed}.  @code{fc} uses @code{ed} if @code{EDITOR} is unset.
-
-@item
-As noted above, Bash requires the @code{xpg_echo} option to be enabled for
-the @code{echo} builtin to be fully conformant.
-
-@end enumerate
-
-Bash can be configured to be @sc{posix}-conformant by default, by specifying
-the @option{--enable-strict-posix-default} to @code{configure} when building
-(@pxref{Optional Features}).
-
-@node Job Control
-@chapter Job Control
-
-This chapter discusses what job control is, how it works, and how
-Bash allows you to access its facilities.
-
-@menu
-* Job Control Basics::         How job control works.
-* Job Control Builtins::       Bash builtin commands used to interact
-                               with job control.
-* Job Control Variables::      Variables Bash uses to customize job
-                               control.
-@end menu
-
-@node Job Control Basics
-@section Job Control Basics
-@cindex job control
-@cindex foreground
-@cindex background
-@cindex suspending jobs
-
-Job control
-refers to the ability to selectively stop (suspend)
-the execution of processes and continue (resume)
-their execution at a later point.  A user typically employs
-this facility via an interactive interface supplied jointly
-by the operating system kernel's terminal driver and Bash.
-
-The shell associates a @var{job} with each pipeline.  It keeps a
-table of currently executing jobs, which may be listed with the
-@code{jobs} command.  When Bash starts a job
-asynchronously, it prints a line that looks
-like:
-@example
-[1] 25647
-@end example
-@noindent
-indicating that this job is job number 1 and that the process @sc{id}
-of the last process in the pipeline associated with this job is
-25647.  All of the processes in a single pipeline are members of
-the same job.  Bash uses the @var{job} abstraction as the
-basis for job control. 
-
-To facilitate the implementation of the user interface to job
-control, the operating system maintains the notion of a current terminal
-process group @sc{id}.  Members of this process group (processes whose
-process group @sc{id} is equal to the current terminal process group
-@sc{id}) receive keyboard-generated signals such as @code{SIGINT}. 
-These processes are said to be in the foreground.  Background
-processes are those whose process group @sc{id} differs from the
-terminal's; such processes are immune to keyboard-generated
-signals.  Only foreground processes are allowed to read from or, if
-the user so specifies with @code{stty tostop}, write to the terminal.
-Background processes which attempt to
-read from (write to when @code{stty tostop} is in effect) the
-terminal are sent a @code{SIGTTIN} (@code{SIGTTOU})
-signal by the kernel's terminal driver,
-which, unless caught, suspends the process. 
-
-If the operating system on which Bash is running supports
-job control, Bash contains facilities to use it.  Typing the
-@var{suspend} character (typically @samp{^Z}, Control-Z) while a
-process is running causes that process to be stopped and returns
-control to Bash.  Typing the @var{delayed suspend} character
-(typically @samp{^Y}, Control-Y) causes the process to be stopped
-when it attempts to read input from the terminal, and control to
-be returned to Bash.  The user then manipulates the state of
-this job, using the @code{bg} command to continue it in the
-background, the @code{fg} command to continue it in the
-foreground, or the @code{kill} command to kill it.  A @samp{^Z}
-takes effect immediately, and has the additional side effect of
-causing pending output and typeahead to be discarded. 
-
-There are a number of ways to refer to a job in the shell.  The
-character @samp{%} introduces a job specification (@var{jobspec}).
-
-Job number @code{n} may be referred to as @samp{%n}.
-The symbols @samp{%%} and  @samp{%+} refer to the shell's notion of the
-current job, which is the last job stopped while it was in the foreground
-or started in the background.
-A single @samp{%} (with no accompanying job specification) also refers
-to the current job.
-The previous job may be referenced using @samp{%-}.
-If there is only a single job, @samp{%+} and @samp{%-} can both be used
-to refer to that job.
-In output pertaining to jobs (e.g., the output of the @code{jobs}
-command), the current job is always flagged with a @samp{+}, and the
-previous job with a @samp{-}. 
-
-A job may also be referred to
-using a prefix of the name used to start it, or using a substring
-that appears in its command line.  For example, @samp{%ce} refers
-to a stopped @code{ce} job.  Using @samp{%?ce}, on the
-other hand, refers to any job containing the string @samp{ce} in
-its command line.  If the prefix or substring matches more than one job,
-Bash reports an error.
-
-Simply naming a job can be used to bring it into the foreground:
-@samp{%1} is a synonym for @samp{fg %1}, bringing job 1 from the
-background into the foreground.  Similarly, @samp{%1 &} resumes
-job 1 in the background, equivalent to @samp{bg %1}
-
-The shell learns immediately whenever a job changes state. 
-Normally, Bash waits until it is about to print a prompt
-before reporting changes in a job's status so as to not interrupt
-any other output.
-If the @option{-b} option to the @code{set} builtin is enabled,
-Bash reports such changes immediately (@pxref{The Set Builtin}).
-Any trap on @code{SIGCHLD} is executed for each child process
-that exits.
-
-If an attempt to exit Bash is made while jobs are stopped, (or running, if
-the @code{checkjobs} option is enabled -- see @ref{The Shopt Builtin}), the
-shell prints a warning message, and if the @code{checkjobs} option is
-enabled, lists the jobs and their statuses.
-The @code{jobs} command may then be used to inspect their status.
-If a second attempt to exit is made without an intervening command,
-Bash does not print another warning, and any stopped jobs are terminated.
-
-@node Job Control Builtins
-@section Job Control Builtins
-
-@table @code
-
-@item bg
-@btindex bg
-@example
-bg [@var{jobspec} @dots{}]
-@end example
-
-Resume each suspended job @var{jobspec} in the background, as if it
-had been started with @samp{&}.
-If @var{jobspec} is not supplied, the current job is used.
-The return status is zero unless it is run when job control is not
-enabled, or, when run with job control enabled, any
-@var{jobspec} was not found or specifies a job
-that was started without job control.
-
-@item fg
-@btindex fg
-@example
-fg [@var{jobspec}]
-@end example
-
-Resume the job @var{jobspec} in the foreground and make it the current job.
-If @var{jobspec} is not supplied, the current job is used.
-The return status is that of the command placed into the foreground,
-or non-zero if run when job control is disabled or, when run with
-job control enabled, @var{jobspec} does not specify a valid job or
-@var{jobspec} specifies a job that was started without job control.
-
-@item jobs
-@btindex jobs
-@example
-jobs [-lnprs] [@var{jobspec}]
-jobs -x @var{command} [@var{arguments}]
-@end example
-
-The first form lists the active jobs.  The options have the
-following meanings:
-
-@table @code
-@item -l
-List process @sc{id}s in addition to the normal information.
-
-@item -n
-Display information only about jobs that have changed status since
-the user was last notified of their status.
-
-@item -p
-List only the process @sc{id} of the job's process group leader.
-
-@item -r
-Display only running jobs.
-
-@item -s
-Display only stopped jobs.
-@end table
-
-If @var{jobspec} is given,
-output is restricted to information about that job. 
-If @var{jobspec} is not supplied, the status of all jobs is
-listed.
-
-If the @option{-x} option is supplied, @code{jobs} replaces any
-@var{jobspec} found in @var{command} or @var{arguments} with the
-corresponding process group @sc{id}, and executes @var{command},
-passing it @var{argument}s, returning its exit status. 
-
-@item kill
-@btindex kill
-@example
-kill [-s @var{sigspec}] [-n @var{signum}] [-@var{sigspec}] @var{jobspec} or @var{pid}
-kill -l [@var{exit_status}]
-@end example
-
-Send a signal specified by @var{sigspec} or @var{signum} to the process
-named by job specification @var{jobspec} or process @sc{id} @var{pid}.
-@var{sigspec} is either a case-insensitive signal name such as
-@code{SIGINT} (with or without the @code{SIG} prefix)
-or a signal number; @var{signum} is a signal number.
-If @var{sigspec} and @var{signum} are not present, @code{SIGTERM} is used.
-The @option{-l} option lists the signal names.
-If any arguments are supplied when @option{-l} is given, the names of the
-signals corresponding to the arguments are listed, and the return status
-is zero.
-@var{exit_status} is a number specifying a signal number or the exit
-status of a process terminated by a signal.
-The return status is zero if at least one signal was successfully sent,
-or non-zero if an error occurs or an invalid option is encountered.
-
-@item wait
-@btindex wait
-@example
-wait [@var{jobspec} or @var{pid} @dots{}]
-@end example
-
-Wait until the child process specified by each process @sc{id} @var{pid}
-or job specification @var{jobspec} exits and return the exit status of the
-last command waited for.
-If a job spec is given, all processes in the job are waited for.
-If no arguments are given, all currently active child processes are
-waited for, and the return status is zero.
-If the @option{-n} option is supplied, @code{wait} waits for any job to
-terminate and returns its exit status.
-If neither @var{jobspec} nor @var{pid} specifies an active child process
-of the shell, the return status is 127.
-
-@item disown
-@btindex disown
-@example
-disown [-ar] [-h] [@var{jobspec} @dots{}]
-@end example
-
-Without options, remove each @var{jobspec} from the table of
-active jobs.
-If the @option{-h} option is given, the job is not removed from the table,
-but is marked so that @code{SIGHUP} is not sent to the job if the shell
-receives a @code{SIGHUP}.
-If @var{jobspec} is not present, and neither the @option{-a} nor @option{-r}
-option is supplied, the current job is used.
-If no @var{jobspec} is supplied, the @option{-a} option means to remove or
-mark all jobs; the @option{-r} option without a @var{jobspec}
-argument restricts operation to running jobs.
-
-@item suspend
-@btindex suspend
-@example
-suspend [-f]
-@end example
-
-Suspend the execution of this shell until it receives a
-@code{SIGCONT} signal.
-A login shell cannot be suspended; the @option{-f}
-option can be used to override this and force the suspension.
-@end table
-
-When job control is not active, the @code{kill} and @code{wait}
-builtins do not accept @var{jobspec} arguments.  They must be
-supplied process @sc{id}s.
-
-@node Job Control Variables
-@section Job Control Variables
-
-@vtable @code
-
-@item auto_resume
-This variable controls how the shell interacts with the user and
-job control.  If this variable exists then single word simple
-commands without redirections are treated as candidates for resumption
-of an existing job.  There is no ambiguity allowed; if there is
-more than one job beginning with the string typed, then
-the most recently accessed job will be selected.
-The name of a stopped job, in this context, is the command line
-used to start it.  If this variable is set to the value @samp{exact},
-the string supplied must match the name of a stopped job exactly;
-if set to @samp{substring},
-the string supplied needs to match a substring of the name of a
-stopped job.  The @samp{substring} value provides functionality
-analogous to the @samp{%?} job @sc{id} (@pxref{Job Control Basics}).
-If set to any other value, the supplied string must
-be a prefix of a stopped job's name; this provides functionality
-analogous to the @samp{%} job @sc{id}.
-
-@end vtable
-
-@set readline-appendix
-@set history-appendix
-@cindex Readline, how to use
-@include rluser.texi
-@cindex History, how to use
-@include hsuser.texi
-@clear readline-appendix
-@clear history-appendix
-
-@node Installing Bash
-@chapter Installing Bash
-
-This chapter provides basic instructions for installing Bash on
-the various supported platforms.  The distribution supports the
-@sc{gnu} operating systems, nearly every version of Unix, and several
-non-Unix systems such as BeOS and Interix.
-Other independent ports exist for
-@sc{ms-dos}, @sc{os/2}, and Windows platforms.
-
-@menu
-* Basic Installation:: Installation instructions.
-* Compilers and Options::      How to set special options for various
-                               systems.
-* Compiling For Multiple Architectures::       How to compile Bash for more
-                                               than one kind of system from
-                                               the same source tree.
-* Installation Names:: How to set the various paths used by the installation.
-* Specifying the System Type:: How to configure Bash for a particular system.
-* Sharing Defaults::   How to share default configuration values among GNU
-                       programs.
-* Operation Controls:: Options recognized by the configuration program.
-* Optional Features::  How to enable and disable optional features when
-                       building Bash.
-@end menu
-
-@node Basic Installation
-@section Basic Installation
-@cindex installation
-@cindex configuration
-@cindex Bash installation
-@cindex Bash configuration
-
-These are installation instructions for Bash.
-
-The simplest way to compile Bash is:
-
-@enumerate
-@item
-@code{cd} to the directory containing the source code and type
-@samp{./configure} to configure Bash for your system.  If you're
-using @code{csh} on an old version of System V, you might need to
-type @samp{sh ./configure} instead to prevent @code{csh} from trying
-to execute @code{configure} itself.
-
-Running @code{configure} takes some time.
-While running, it prints messages telling which features it is
-checking for.
-
-@item
-Type @samp{make} to compile Bash and build the @code{bashbug} bug
-reporting script.
-
-@item
-Optionally, type @samp{make tests} to run the Bash test suite.
-
-@item
-Type @samp{make install} to install @code{bash} and @code{bashbug}.
-This will also install the manual pages and Info file.
-
-@end enumerate
-
-The @code{configure} shell script attempts to guess correct
-values for various system-dependent variables used during
-compilation.  It uses those values to create a @file{Makefile} in
-each directory of the package (the top directory, the
-@file{builtins}, @file{doc}, and @file{support} directories,
-each directory under @file{lib}, and several others).  It also creates a
-@file{config.h} file containing system-dependent definitions. 
-Finally, it creates a shell script named @code{config.status} that you
-can run in the future to recreate the current configuration, a
-file @file{config.cache} that saves the results of its tests to
-speed up reconfiguring, and a file @file{config.log} containing
-compiler output (useful mainly for debugging @code{configure}). 
-If at some point
-@file{config.cache} contains results you don't want to keep, you
-may remove or edit it. 
-
-To find out more about the options and arguments that the
-@code{configure} script understands, type 
-
-@example
-bash-2.04$ ./configure --help
-@end example
-
-@noindent
-at the Bash prompt in your Bash source directory.
-
-If you need to do unusual things to compile Bash, please
-try to figure out how @code{configure} could check whether or not
-to do them, and mail diffs or instructions to
-@email{bash-maintainers@@gnu.org} so they can be
-considered for the next release.
-
-The file @file{configure.ac} is used to create @code{configure}
-by a program called Autoconf.  You only need
-@file{configure.ac} if you want to change it or regenerate
-@code{configure} using a newer version of Autoconf.  If
-you do this, make sure you are using Autoconf version 2.50 or
-newer.
-
-You can remove the program binaries and object files from the
-source code directory by typing @samp{make clean}.  To also remove the
-files that @code{configure} created (so you can compile Bash for
-a different kind of computer), type @samp{make distclean}.
-
-@node Compilers and Options
-@section Compilers and Options
-
-Some systems require unusual options for compilation or linking
-that the @code{configure} script does not know about.  You can
-give @code{configure} initial values for variables by setting
-them in the environment.  Using a Bourne-compatible shell, you
-can do that on the command line like this:
-
-@example
-CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
-@end example
-
-On systems that have the @code{env} program, you can do it like this:
-
-@example
-env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
-@end example
-
-The configuration process uses GCC to build Bash if it
-is available.
-
-@node Compiling For Multiple Architectures
-@section Compiling For Multiple Architectures
-
-You can compile Bash for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory.  To do this, you must use a version of @code{make} that
-supports the @code{VPATH} variable, such as GNU @code{make}.
-@code{cd} to the
-directory where you want the object files and executables to go and run
-the @code{configure} script from the source directory.  You may need to
-supply the @option{--srcdir=PATH} argument to tell @code{configure} where the
-source files are.  @code{configure} automatically checks for the
-source code in the directory that @code{configure} is in and in `..'.
-
-If you have to use a @code{make} that does not supports the @code{VPATH}
-variable, you can compile Bash for one architecture at a
-time in the source code directory.  After you have installed
-Bash for one architecture, use @samp{make distclean} before
-reconfiguring for another architecture.
-
-Alternatively, if your system supports symbolic links, you can use the
-@file{support/mkclone} script to create a build tree which has
-symbolic links back to each file in the source directory.  Here's an
-example that creates a build directory in the current directory from a
-source directory @file{/usr/gnu/src/bash-2.0}:
-
-@example
-bash /usr/gnu/src/bash-2.0/support/mkclone -s /usr/gnu/src/bash-2.0 .
-@end example
-
-@noindent
-The @code{mkclone} script requires Bash, so you must have already built
-Bash for at least one architecture before you can create build
-directories for other architectures.
-
-@node Installation Names
-@section Installation Names
-
-By default, @samp{make install} will install into
-@file{/usr/local/bin}, @file{/usr/local/man}, etc.  You can
-specify an installation prefix other than @file{/usr/local} by
-giving @code{configure} the option @option{--prefix=@var{PATH}},
-or by specifying a value for the @code{DESTDIR} @samp{make}
-variable when running @samp{make install}.
-
-You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files. 
-If you give @code{configure} the option
-@option{--exec-prefix=@var{PATH}}, @samp{make install} will use
-@var{PATH} as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix. 
-
-@node Specifying the System Type
-@section Specifying the System Type
-
-There may be some features @code{configure} can not figure out
-automatically, but need to determine by the type of host Bash
-will run on.  Usually @code{configure} can figure that
-out, but if it prints a message saying it can not guess the host
-type, give it the @option{--host=TYPE} option.  @samp{TYPE} can
-either be a short name for the system type, such as @samp{sun4},
-or a canonical name with three fields: @samp{CPU-COMPANY-SYSTEM}
-(e.g., @samp{i386-unknown-freebsd4.2}).
-
-See the file @file{support/config.sub} for the possible
-values of each field. 
-
-@node Sharing Defaults
-@section Sharing Defaults
-
-If you want to set default values for @code{configure} scripts to
-share, you can create a site shell script called
-@code{config.site} that gives default values for variables like
-@code{CC}, @code{cache_file}, and @code{prefix}.  @code{configure}
-looks for @file{PREFIX/share/config.site} if it exists, then
-@file{PREFIX/etc/config.site} if it exists.  Or, you can set the
-@code{CONFIG_SITE} environment variable to the location of the site
-script.  A warning: the Bash @code{configure} looks for a site script,
-but not all @code{configure} scripts do.
-
-@node Operation Controls
-@section Operation Controls
-
-@code{configure} recognizes the following options to control how it
-operates.
-
-@table @code
-
-@item --cache-file=@var{file}
-Use and save the results of the tests in
-@var{file} instead of @file{./config.cache}.  Set @var{file} to
-@file{/dev/null} to disable caching, for debugging
-@code{configure}. 
-
-@item --help
-Print a summary of the options to @code{configure}, and exit.
-
-@item --quiet
-@itemx --silent
-@itemx -q
-Do not print messages saying which checks are being made.
-
-@item --srcdir=@var{dir}
-Look for the Bash source code in directory @var{dir}.  Usually
-@code{configure} can determine that directory automatically.
-
-@item --version
-Print the version of Autoconf used to generate the @code{configure}
-script, and exit.
-@end table
-
-@code{configure} also accepts some other, not widely used, boilerplate
-options.  @samp{configure --help} prints the complete list.
-
-@node Optional Features
-@section Optional Features
-
-The Bash @code{configure} has a number of @option{--enable-@var{feature}}
-options, where @var{feature} indicates an optional part of Bash.
-There are also several @option{--with-@var{package}} options,
-where @var{package} is something like @samp{bash-malloc} or @samp{purify}.
-To turn off the default use of a package, use
-@option{--without-@var{package}}.  To configure Bash without a feature
-that is enabled by default, use @option{--disable-@var{feature}}.
-
-Here is a complete list of the @option{--enable-} and
-@option{--with-} options that the Bash @code{configure} recognizes. 
-
-@table @code
-@item --with-afs
-Define if you are using the Andrew File System from Transarc.
-
-@item --with-bash-malloc
-Use the Bash version of
-@code{malloc} in the directory @file{lib/malloc}.  This is not the same
-@code{malloc} that appears in @sc{gnu} libc, but an older version
-originally derived from the 4.2 @sc{bsd} @code{malloc}.  This @code{malloc}
-is very fast, but wastes some space on each allocation.
-This option is enabled by default.
-The @file{NOTES} file contains a list of systems for
-which this should be turned off, and @code{configure} disables this
-option automatically for a number of systems.
-
-@item --with-curses
-Use the curses library instead of the termcap library.  This should
-be supplied if your system has an inadequate or incomplete termcap
-database.
-
-@item --with-gnu-malloc
-A synonym for @code{--with-bash-malloc}.
-
-@item --with-installed-readline[=@var{PREFIX}]
-Define this to make Bash link with a locally-installed version of Readline
-rather than the version in @file{lib/readline}.  This works only with
-Readline 5.0 and later versions.  If @var{PREFIX} is @code{yes} or not
-supplied, @code{configure} uses the values of the make variables
-@code{includedir} and @code{libdir}, which are subdirectories of @code{prefix}
-by default, to find the installed version of Readline if it is not in
-the standard system include and library directories.
-If @var{PREFIX} is @code{no}, Bash links with the version in
-@file{lib/readline}.
-If @var{PREFIX} is set to any other value, @code{configure} treats it as
-a directory pathname and looks for
-the installed version of Readline in subdirectories of that directory
-(include files in @var{PREFIX}/@code{include} and the library in
-@var{PREFIX}/@code{lib}).
-
-@item --with-purify
-Define this to use the Purify memory allocation checker from Rational
-Software.
-
-@item --enable-minimal-config
-This produces a shell with minimal features, close to the historical
-Bourne shell.
-@end table
-
-There are several @option{--enable-} options that alter how Bash is
-compiled and linked, rather than changing run-time features.
-
-@table @code
-@item --enable-largefile
-Enable support for @uref{http://www.sas.com/standards/large_file/x_open.20Mar96.html,
-large files} if the operating system requires special compiler options
-to build programs which can access large files.  This is enabled by
-default, if the operating system provides large file support.
-
-@item --enable-profiling
-This builds a Bash binary that produces profiling information to be
-processed by @code{gprof} each time it is executed.
-
-@item --enable-static-link
-This causes Bash to be linked statically, if @code{gcc} is being used.
-This could be used to build a version to use as root's shell.
-@end table
-
-The @samp{minimal-config} option can be used to disable all of
-the following options, but it is processed first, so individual
-options may be enabled using @samp{enable-@var{feature}}. 
-
-All of the following options except for @samp{disabled-builtins},
-@samp{directpand-default}, and
-@samp{xpg-echo-default} are
-enabled by default, unless the operating system does not provide the
-necessary support.
-
-@table @code
-@item --enable-alias
-Allow alias expansion and include the @code{alias} and @code{unalias}
-builtins (@pxref{Aliases}).
-
-@item --enable-arith-for-command
-Include support for the alternate form of the @code{for} command
-that behaves like the C language @code{for} statement
-(@pxref{Looping Constructs}).
-
-@item --enable-array-variables
-Include support for one-dimensional array shell variables
-(@pxref{Arrays}).
-
-@item --enable-bang-history
-Include support for @code{csh}-like history substitution
-(@pxref{History Interaction}).
-
-@item --enable-brace-expansion
-Include @code{csh}-like brace expansion
-( @code{b@{a,b@}c} @expansion{} @code{bac bbc} ).
-See @ref{Brace Expansion}, for a complete description.
-
-@item --enable-casemod-attributes
-Include support for case-modifying attributes in the @code{declare} builtin
-and assignment statements.  Variables with the @var{uppercase} attribute,
-for example, will have their values converted to uppercase upon assignment.
-
-@item --enable-casemod-expansion
-Include support for case-modifying word expansions.
-
-@item --enable-command-timing
-Include support for recognizing @code{time} as a reserved word and for
-displaying timing statistics for the pipeline following @code{time}
-(@pxref{Pipelines}).
-This allows pipelines as well as shell builtins and functions to be timed.
-
-@item --enable-cond-command
-Include support for the @code{[[} conditional command.
-(@pxref{Conditional Constructs}).
-
-@item --enable-cond-regexp
-Include support for matching @sc{posix} regular expressions using the
-@samp{=~} binary operator in the @code{[[} conditional command.
-(@pxref{Conditional Constructs}).
-
-@item --enable-coprocesses
-Include support for coprocesses and the @code{coproc} reserved word
-(@pxref{Pipelines}).
-
-@item --enable-debugger
-Include support for the bash debugger (distributed separately).
-
-@item --enable-direxpand-default
-Cause the @code{direxpand} shell option (@pxref{The Shopt Builtin})
-to be enabled by default when the shell starts.
-It is normally disabled by default.
-
-@item --enable-directory-stack
-Include support for a @code{csh}-like directory stack and the
-@code{pushd}, @code{popd}, and @code{dirs} builtins
-(@pxref{The Directory Stack}).
-
-@item --enable-disabled-builtins
-Allow builtin commands to be invoked via @samp{builtin xxx}
-even after @code{xxx} has been disabled using @samp{enable -n xxx}.
-See @ref{Bash Builtins}, for details of the @code{builtin} and
-@code{enable} builtin commands.
-
-@item --enable-dparen-arithmetic
-Include support for the @code{((@dots{}))} command
-(@pxref{Conditional Constructs}).
-
-@item --enable-extended-glob
-Include support for the extended pattern matching features described
-above under @ref{Pattern Matching}.
-
-@item --enable-extended-glob-default
-Set the default value of the @var{extglob} shell option described
-above under @ref{The Shopt Builtin} to be enabled.
-
-@item --enable-help-builtin
-Include the @code{help} builtin, which displays help on shell builtins and
-variables (@pxref{Bash Builtins}).
-
-@item --enable-history
-Include command history and the @code{fc} and @code{history}
-builtin commands (@pxref{Bash History Facilities}).
-
-@item --enable-job-control
-This enables the job control features (@pxref{Job Control}),
-if the operating system supports them.
-
-@item --enable-multibyte
-This enables support for multibyte characters if the operating
-system provides the necessary support.
-
-@item --enable-net-redirections
-This enables the special handling of filenames of the form
-@code{/dev/tcp/@var{host}/@var{port}} and
-@code{/dev/udp/@var{host}/@var{port}}
-when used in redirections (@pxref{Redirections}).
-
-@item --enable-process-substitution
-This enables process substitution (@pxref{Process Substitution}) if
-the operating system provides the necessary support.
-
-@item --enable-progcomp
-Enable the programmable completion facilities
-(@pxref{Programmable Completion}).
-If Readline is not enabled, this option has no effect.
-
-@item --enable-prompt-string-decoding
-Turn on the interpretation of a number of backslash-escaped characters
-in the @env{$PS1}, @env{$PS2}, @env{$PS3}, and @env{$PS4} prompt
-strings.  See @ref{Controlling the Prompt}, for a complete list of prompt
-string escape sequences.
-
-@item --enable-readline
-Include support for command-line editing and history with the Bash
-version of the Readline library (@pxref{Command Line Editing}).
-
-@item --enable-restricted
-Include support for a @dfn{restricted shell}.  If this is enabled, Bash,
-when called as @code{rbash}, enters a restricted mode.  See
-@ref{The Restricted Shell}, for a description of restricted mode.
-
-@item --enable-select
-Include the @code{select} compound command, which allows the generation of
-simple menus (@pxref{Conditional Constructs}).
-
-@item --enable-separate-helpfiles
-Use external files for the documentation displayed by the @code{help} builtin
-instead of storing the text internally.
-
-@item --enable-single-help-strings
-Store the text displayed by the @code{help} builtin as a single string for
-each help topic.  This aids in translating the text to different languages.
-You may need to disable this if your compiler cannot handle very long string
-literals.
-
-@item --enable-strict-posix-default
-Make Bash @sc{posix}-conformant by default (@pxref{Bash POSIX Mode}).
-
-@item --enable-usg-echo-default
-A synonym for @code{--enable-xpg-echo-default}.
-
-@item --enable-xpg-echo-default
-Make the @code{echo} builtin expand backslash-escaped characters by default,
-without requiring the @option{-e} option.
-This sets the default value of the @code{xpg_echo} shell option to @code{on},
-which makes the Bash @code{echo} behave more like the version specified in
-the Single Unix Specification, version 3.
-@xref{Bash Builtins}, for a description of the escape sequences that
-@code{echo} recognizes.
-@end table
-
-The file @file{config-top.h} contains C Preprocessor
-@samp{#define} statements for options which are not settable from
-@code{configure}.
-Some of these are not meant to be changed; beware of the consequences if
-you do.
-Read the comments associated with each definition for more
-information about its effect.
-
-@node Reporting Bugs
-@appendix Reporting Bugs
-
-Please report all bugs you find in Bash.
-But first, you should
-make sure that it really is a bug, and that it appears in the latest
-version of Bash.
-The latest version of Bash is always available for FTP from
-@uref{ftp://ftp.gnu.org/pub/gnu/bash/}.
-
-Once you have determined that a bug actually exists, use the
-@code{bashbug} command to submit a bug report.
-If you have a fix, you are encouraged to mail that as well!
-Suggestions and `philosophical' bug reports may be mailed
-to @email{bug-bash@@gnu.org} or posted to the Usenet
-newsgroup @code{gnu.bash.bug}.
-
-All bug reports should include:
-@itemize @bullet
-@item
-The version number of Bash.
-@item
-The hardware and operating system.
-@item
-The compiler used to compile Bash.
-@item
-A description of the bug behaviour.
-@item
-A short script or `recipe' which exercises the bug and may be used
-to reproduce it.
-@end itemize
-
-@noindent
-@code{bashbug} inserts the first three items automatically into
-the template it provides for filing a bug report.
-
-Please send all reports concerning this manual to
-@email{bug-bash@@gnu.org}.
-
-@node Major Differences From The Bourne Shell
-@appendix Major Differences From The Bourne Shell
-
-Bash implements essentially the same grammar, parameter and
-variable expansion, redirection, and quoting as the Bourne Shell. 
-Bash uses the @sc{posix} standard as the specification of
-how these features are to be implemented.  There are some
-differences between the traditional Bourne shell and Bash; this
-section quickly details the differences of significance.  A
-number of these differences are explained in greater depth in
-previous sections.
-This section uses the version of @code{sh} included in SVR4.2 (the
-last version of the historical Bourne shell) as the baseline reference.
-
-@itemize @bullet
-
-@item
-Bash is @sc{posix}-conformant, even where the @sc{posix} specification
-differs from traditional @code{sh} behavior (@pxref{Bash POSIX Mode}).
-
-@item
-Bash has multi-character invocation options (@pxref{Invoking Bash}).
-
-@item
-Bash has command-line editing (@pxref{Command Line Editing}) and
-the @code{bind} builtin.
-
-@item
-Bash provides a programmable word completion mechanism
-(@pxref{Programmable Completion}), and builtin commands
-@code{complete}, @code{compgen}, and @code{compopt}, to
-manipulate it.
-
-@item
-Bash has command history (@pxref{Bash History Facilities}) and the
-@code{history} and @code{fc} builtins to manipulate it.
-The Bash history list maintains timestamp information and uses the
-value of the @code{HISTTIMEFORMAT} variable to display it.
-
-@item
-Bash implements @code{csh}-like history expansion
-(@pxref{History Interaction}).
-
-@item
-Bash has one-dimensional array variables (@pxref{Arrays}), and the
-appropriate variable expansions and assignment syntax to use them.
-Several of the Bash builtins take options to act on arrays.
-Bash provides a number of built-in array variables.
-
-@item
-The @code{$'@dots{}'} quoting syntax, which expands ANSI-C
-backslash-escaped characters in the text between the single quotes,
-is supported (@pxref{ANSI-C Quoting}).
-
-@item
-Bash supports the @code{$"@dots{}"} quoting syntax to do
-locale-specific translation of the characters between the double
-quotes.  The @option{-D}, @option{--dump-strings}, and @option{--dump-po-strings}
-invocation options list the translatable strings found in a script
-(@pxref{Locale Translation}).
-
-@item
-Bash implements the @code{!} keyword to negate the return value of
-a pipeline (@pxref{Pipelines}).
-Very useful when an @code{if} statement needs to act only if a test fails.
-The Bash @samp{-o pipefail} option to @code{set} will cause a pipeline to
-return a failure status if any command fails.
-
-@item
-Bash has the @code{time} reserved word and command timing (@pxref{Pipelines}).
-The display of the timing statistics may be controlled with the
-@env{TIMEFORMAT} variable.
-
-@item
-Bash implements the @code{for (( @var{expr1} ; @var{expr2} ; @var{expr3} ))}
-arithmetic for command, similar to the C language (@pxref{Looping Constructs}).
-
-@item
-Bash includes the @code{select} compound command, which allows the
-generation of simple menus (@pxref{Conditional Constructs}).
-
-@item
-Bash includes the @code{[[} compound command, which makes conditional
-testing part of the shell grammar (@pxref{Conditional Constructs}), including
-optional regular expression matching.
-
-@item
-Bash provides optional case-insensitive matching for the @code{case} and
-@code{[[} constructs.
-
-@item
-Bash includes brace expansion (@pxref{Brace Expansion}) and tilde
-expansion (@pxref{Tilde Expansion}).
-
-@item
-Bash implements command aliases and the @code{alias} and @code{unalias}
-builtins (@pxref{Aliases}).
-
-@item
-Bash provides shell arithmetic, the @code{((} compound command
-(@pxref{Conditional Constructs}),
-and arithmetic expansion (@pxref{Shell Arithmetic}).
-
-@item
-Variables present in the shell's initial environment are automatically
-exported to child processes.  The Bourne shell does not normally do
-this unless the variables are explicitly marked using the @code{export}
-command.
-
-@item
-Bash supports the @samp{+=} assignment operator, which appends to the value
-of the variable named on the left hand side.
-
-@item
-Bash includes the @sc{posix} pattern removal @samp{%}, @samp{#}, @samp{%%}
-and @samp{##} expansions to remove leading or trailing substrings from
-variable values (@pxref{Shell Parameter Expansion}).
-
-@item
-The expansion @code{$@{#xx@}}, which returns the length of @code{$@{xx@}},
-is supported (@pxref{Shell Parameter Expansion}).
-
-@item
-The expansion @code{$@{var:}@var{offset}@code{[:}@var{length}@code{]@}},
-which expands to the substring of @code{var}'s value of length
-@var{length}, beginning at @var{offset}, is present
-(@pxref{Shell Parameter Expansion}).
-
-@item
-The expansion
-@code{$@{var/[/]}@var{pattern}@code{[/}@var{replacement}@code{]@}},
-which matches @var{pattern} and replaces it with @var{replacement} in
-the value of @code{var}, is available (@pxref{Shell Parameter Expansion}).
-
-@item
-The expansion @code{$@{!@var{prefix}*@}} expansion, which expands to
-the names of all shell variables whose names begin with @var{prefix},
-is available (@pxref{Shell Parameter Expansion}).
-
-@item
-Bash has @var{indirect} variable expansion using @code{$@{!word@}}
-(@pxref{Shell Parameter Expansion}).
-
-@item
-Bash can expand positional parameters beyond @code{$9} using
-@code{$@{@var{num}@}}.
-
-@item
-The @sc{posix} @code{$()} form of command substitution
-is implemented (@pxref{Command Substitution}),
-and preferred to the Bourne shell's @code{``} (which
-is also implemented for backwards compatibility).
-
-@item
-Bash has process substitution (@pxref{Process Substitution}).
-
-@item
-Bash automatically assigns variables that provide information about the
-current user (@env{UID}, @env{EUID}, and @env{GROUPS}), the current host
-(@env{HOSTTYPE}, @env{OSTYPE}, @env{MACHTYPE}, and @env{HOSTNAME}),
-and the instance of Bash that is running (@env{BASH},
-@env{BASH_VERSION}, and @env{BASH_VERSINFO}).  @xref{Bash Variables},
-for details.
-
-@item
-The @env{IFS} variable is used to split only the results of expansion,
-not all words (@pxref{Word Splitting}).
-This closes a longstanding shell security hole.
-
-@item
-The filename expansion bracket expression code uses @samp{!} and @samp{^}
-to negate the set of characters between the brackets.
-The Bourne shell uses only @samp{!}.
-
-@item
-Bash implements the full set of @sc{posix} filename expansion operators,
-including @var{character classes}, @var{equivalence classes}, and
-@var{collating symbols} (@pxref{Filename Expansion}).
-
-@item
-Bash implements extended pattern matching features when the @code{extglob}
-shell option is enabled (@pxref{Pattern Matching}).
-
-@item
-It is possible to have a variable and a function with the same name;
-@code{sh} does not separate the two name spaces.
-
-@item
-Bash functions are permitted to have local variables using the
-@code{local} builtin, and thus useful recursive functions may be written
-(@pxref{Bash Builtins}).
-
-@item
-Variable assignments preceding commands affect only that command, even
-builtins and functions (@pxref{Environment}).
-In @code{sh}, all variable assignments 
-preceding commands are global unless the command is executed from the
-file system.
-
-@item
-Bash performs filename expansion on filenames specified as operands
-to input and output redirection operators (@pxref{Redirections}).
-
-@item
-Bash contains the @samp{<>} redirection operator, allowing a file to be
-opened for both reading and writing, and the @samp{&>} redirection
-operator, for directing standard output and standard error to the same
-file (@pxref{Redirections}).
-
-@item
-Bash includes the @samp{<<<} redirection operator, allowing a string to
-be used as the standard input to a command.
-
-@item
-Bash implements the @samp{[n]<&@var{word}} and @samp{[n]>&@var{word}}
-redirection operators, which move one file descriptor to another.
-
-@item
-Bash treats a number of filenames specially when they are
-used in redirection operators (@pxref{Redirections}).
-
-@item
-Bash can open network connections to arbitrary machines and services
-with the redirection operators (@pxref{Redirections}).
-
-@item
-The @code{noclobber} option is available to avoid overwriting existing
-files with output redirection (@pxref{The Set Builtin}).
-The @samp{>|} redirection operator may be used to override @code{noclobber}.
-
-@item
-The Bash @code{cd} and @code{pwd} builtins (@pxref{Bourne Shell Builtins})
-each take @option{-L} and @option{-P} options to switch between logical and
-physical modes.
-
-@item
-Bash allows a function to override a builtin with the same name, and provides
-access to that builtin's functionality within the function via the
-@code{builtin} and @code{command} builtins (@pxref{Bash Builtins}).
-
-@item
-The @code{command} builtin allows selective disabling of functions
-when command lookup is performed (@pxref{Bash Builtins}).
-
-@item
-Individual builtins may be enabled or disabled using the @code{enable}
-builtin (@pxref{Bash Builtins}).
-
-@item
-The Bash @code{exec} builtin takes additional options that allow users
-to control the contents of the environment passed to the executed
-command, and what the zeroth argument to the command is to be
-(@pxref{Bourne Shell Builtins}).
-
-@item
-Shell functions may be exported to children via the environment
-using @code{export -f} (@pxref{Shell Functions}).
-
-@item
-The Bash @code{export}, @code{readonly}, and @code{declare} builtins can
-take a @option{-f} option to act on shell functions, a @option{-p} option to
-display variables with various attributes set in a format that can be
-used as shell input, a @option{-n} option to remove various variable
-attributes, and @samp{name=value} arguments to set variable attributes
-and values simultaneously.
-
-@item
-The Bash @code{hash} builtin allows a name to be associated with
-an arbitrary filename, even when that filename cannot be found by
-searching the @env{$PATH}, using @samp{hash -p}
-(@pxref{Bourne Shell Builtins}).
-
-@item
-Bash includes a @code{help} builtin for quick reference to shell
-facilities (@pxref{Bash Builtins}).
-
-@item
-The @code{printf} builtin is available to display formatted output
-(@pxref{Bash Builtins}).
-
-@item
-The Bash @code{read} builtin (@pxref{Bash Builtins})
-will read a line ending in @samp{\} with
-the @option{-r} option, and will use the @env{REPLY} variable as a
-default if no non-option arguments are supplied.
-The Bash @code{read} builtin
-also accepts a prompt string with the @option{-p} option and will use
-Readline to obtain the line when given the @option{-e} option.
-The @code{read} builtin also has additional options to control input:
-the @option{-s} option will turn off echoing of input characters as
-they are read, the @option{-t} option will allow @code{read} to time out
-if input does not arrive within a specified number of seconds, the
-@option{-n} option will allow reading only a specified number of
-characters rather than a full line, and the @option{-d} option will read
-until a particular character rather than newline.
-
-@item
-The @code{return} builtin may be used to abort execution of scripts
-executed with the @code{.} or @code{source} builtins
-(@pxref{Bourne Shell Builtins}).
-
-@item
-Bash includes the @code{shopt} builtin, for finer control of shell
-optional capabilities (@pxref{The Shopt Builtin}), and allows these options
-to be set and unset at shell invocation (@pxref{Invoking Bash}).
-
-@item
-Bash has much more optional behavior controllable with the @code{set}
-builtin (@pxref{The Set Builtin}).
-
-@item
-The @samp{-x} (@option{xtrace}) option displays commands other than
-simple commands when performing an execution trace
-(@pxref{The Set Builtin}).
-
-@item
-The @code{test} builtin (@pxref{Bourne Shell Builtins})
-is slightly different, as it implements the @sc{posix} algorithm,
-which specifies the behavior based on the number of arguments.
-
-@item
-Bash includes the @code{caller} builtin, which displays the context of
-any active subroutine call (a shell function or a script executed with
-the @code{.} or @code{source} builtins).  This supports the bash
-debugger.
-
-@item
-The @code{trap} builtin (@pxref{Bourne Shell Builtins}) allows a
-@code{DEBUG} pseudo-signal specification, similar to @code{EXIT}.
-Commands specified with a @code{DEBUG} trap are executed before every
-simple command, @code{for} command, @code{case} command,
-@code{select} command, every arithmetic @code{for} command, and before
-the first command executes in a shell function.
-The @code{DEBUG} trap is not inherited by shell functions unless the
-function has been given the @code{trace} attribute or the
-@code{functrace} option has been enabled using the @code{shopt} builtin.
-The @code{extdebug} shell option has additional effects on the
-@code{DEBUG} trap.
-
-The @code{trap} builtin (@pxref{Bourne Shell Builtins}) allows an
-@code{ERR} pseudo-signal specification, similar to @code{EXIT} and @code{DEBUG}.
-Commands specified with an @code{ERR} trap are executed after a simple
-command fails, with a few exceptions.
-The @code{ERR} trap is not inherited by shell functions unless the
-@code{-o errtrace} option to the @code{set} builtin is enabled.
-
-The @code{trap} builtin (@pxref{Bourne Shell Builtins}) allows a
-@code{RETURN} pseudo-signal specification, similar to
-@code{EXIT} and @code{DEBUG}.
-Commands specified with an @code{RETURN} trap are executed before
-execution resumes after a shell function or a shell script executed with
-@code{.} or @code{source} returns.
-The @code{RETURN} trap is not inherited by shell functions unless the
-function has been given the @code{trace} attribute or the
-@code{functrace} option has been enabled using the @code{shopt} builtin.
-
-@item
-The Bash @code{type} builtin is more extensive and gives more information
-about the names it finds (@pxref{Bash Builtins}).
-
-@item
-The Bash @code{umask} builtin permits a @option{-p} option to cause
-the output to be displayed in the form of a @code{umask} command
-that may be reused as input (@pxref{Bourne Shell Builtins}).
-
-@item
-Bash implements a @code{csh}-like directory stack, and provides the
-@code{pushd}, @code{popd}, and @code{dirs} builtins to manipulate it
-(@pxref{The Directory Stack}).
-Bash also makes the directory stack visible as the value of the
-@env{DIRSTACK} shell variable.
-
-@item
-Bash interprets special backslash-escaped characters in the prompt
-strings when interactive (@pxref{Controlling the Prompt}).
-
-@item
-The Bash restricted mode is more useful (@pxref{The Restricted Shell});
-the SVR4.2 shell restricted mode is too limited.
-
-@item
-The @code{disown} builtin can remove a job from the internal shell
-job table (@pxref{Job Control Builtins}) or suppress the sending
-of @code{SIGHUP} to a job when the shell exits as the result of a
-@code{SIGHUP}.
-
-@item
-Bash includes a number of features to support a separate debugger for
-shell scripts.
-
-@item
-The SVR4.2 shell has two privilege-related builtins
-(@code{mldmode} and @code{priv}) not present in Bash.
-
-@item
-Bash does not have the @code{stop} or @code{newgrp} builtins.
-
-@item
-Bash does not use the @env{SHACCT} variable or perform shell accounting.
-
-@item
-The SVR4.2 @code{sh} uses a @env{TIMEOUT} variable like Bash uses
-@env{TMOUT}.
-
-@end itemize
-
-@noindent
-More features unique to Bash may be found in @ref{Bash Features}.
-
-
-@appendixsec Implementation Differences From The SVR4.2 Shell
-
-Since Bash is a completely new implementation, it does not suffer from
-many of the limitations of the SVR4.2 shell.  For instance:
-
-@itemize @bullet
-
-@item
-Bash does not fork a subshell when redirecting into or out of
-a shell control structure such as  an @code{if} or @code{while}
-statement.
-
-@item
-Bash does not allow unbalanced quotes.  The SVR4.2 shell will silently
-insert a needed closing quote at @code{EOF} under certain circumstances.
-This can be the cause of some hard-to-find errors.
-
-@item
-The SVR4.2 shell uses a baroque memory management scheme based on
-trapping @code{SIGSEGV}.  If the shell is started from a process with
-@code{SIGSEGV} blocked (e.g., by using the @code{system()} C library
-function call), it misbehaves badly.
-
-@item
-In a questionable attempt at security, the SVR4.2 shell,
-when invoked without the @option{-p} option, will alter its real
-and effective @sc{uid} and @sc{gid} if they are less than some
-magic threshold value, commonly 100.
-This can lead to unexpected results.
-
-@item
-The SVR4.2 shell does not allow users to trap @code{SIGSEGV},
-@code{SIGALRM}, or @code{SIGCHLD}.
-
-@item
-The SVR4.2 shell does not allow the @env{IFS}, @env{MAILCHECK},
-@env{PATH}, @env{PS1}, or @env{PS2} variables to be unset.
-
-@item
-The SVR4.2 shell treats @samp{^} as the undocumented equivalent of
-@samp{|}.
-
-@item
-Bash allows multiple option arguments when it is invoked (@code{-x -v});
-the SVR4.2 shell allows only one option argument (@code{-xv}).  In
-fact, some versions of the shell dump core if the second argument begins
-with a @samp{-}.
-
-@item
-The SVR4.2 shell exits a script if any builtin fails; Bash exits
-a script only if one of the @sc{posix} special builtins fails, and
-only for certain failures, as enumerated in the @sc{posix} standard.
-
-@item 
-The SVR4.2 shell behaves differently when invoked as @code{jsh}
-(it turns on job control).
-@end itemize
-
-@node GNU Free Documentation License
-@appendix GNU Free Documentation License
-
-@include fdl.texi
-
-@node Indexes
-@appendix Indexes
-
-@menu
-* Builtin Index::              Index of Bash builtin commands.
-* Reserved Word Index::                Index of Bash reserved words.
-* Variable Index::             Quick reference helps you find the
-                               variable you want.
-* Function Index::             Index of bindable Readline functions.
-* Concept Index::              General index for concepts described in
-                               this manual.
-@end menu
-
-@node Builtin Index
-@appendixsec Index of Shell Builtin Commands
-@printindex bt
-
-@node Reserved Word Index
-@appendixsec Index of Shell Reserved Words
-@printindex rw
-
-@node Variable Index
-@appendixsec Parameter and Variable Index
-@printindex vr
-
-@node Function Index
-@appendixsec Function Index
-@printindex fn
-
-@node Concept Index
-@appendixsec Concept Index
-@printindex cp
-
-@bye
diff --git a/doc/version.texi~ b/doc/version.texi~
deleted file mode 100644 (file)
index a08aaa5..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-@ignore
-Copyright (C) 1988-2012 Free Software Foundation, Inc.
-@end ignore
-
-@set LASTCHANGE Sat Dec 29 11:19:39 EST 2012
-
-@set EDITION 4.2
-@set VERSION 4.2
-@set UPDATED 29 December 2012
-@set UPDATED-MONTH December 2012
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/execute_cmd.c~ b/execute_cmd.c~
deleted file mode 100644 (file)
index b8dbe03..0000000
+++ /dev/null
@@ -1,5399 +0,0 @@
-/* execute_cmd.c -- Execute a COMMAND structure. */
-
-/* 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/>.
-*/
-
-#include "config.h"
-
-#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
-  #pragma alloca
-#endif /* _AIX && RISC6000 && !__GNUC__ */
-
-#include <stdio.h>
-#include "chartypes.h"
-#include "bashtypes.h"
-#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
-#  include <sys/file.h>
-#endif
-#include "filecntl.h"
-#include "posixstat.h"
-#include <signal.h>
-#if defined (HAVE_SYS_PARAM_H)
-#  include <sys/param.h>
-#endif
-
-#if defined (HAVE_UNISTD_H)
-#  include <unistd.h>
-#endif
-
-#include "posixtime.h"
-
-#if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE)
-#  include <sys/resource.h>
-#endif
-
-#if defined (HAVE_SYS_TIMES_H) && defined (HAVE_TIMES)
-#  include <sys/times.h>
-#endif
-
-#include <errno.h>
-
-#if !defined (errno)
-extern int errno;
-#endif
-
-#define NEED_FPURGE_DECL
-
-#include "bashansi.h"
-#include "bashintl.h"
-
-#include "memalloc.h"
-#include "shell.h"
-#include <y.tab.h>     /* use <...> so we pick it up from the build directory */
-#include "flags.h"
-#include "builtins.h"
-#include "hashlib.h"
-#include "jobs.h"
-#include "execute_cmd.h"
-#include "findcmd.h"
-#include "redir.h"
-#include "trap.h"
-#include "pathexp.h"
-#include "hashcmd.h"
-
-#if defined (COND_COMMAND)
-#  include "test.h"
-#endif
-
-#include "builtins/common.h"
-#include "builtins/builtext.h" /* list of builtins */
-
-#include <glob/strmatch.h>
-#include <tilde/tilde.h>
-
-#if defined (BUFFERED_INPUT)
-#  include "input.h"
-#endif
-
-#if defined (ALIAS)
-#  include "alias.h"
-#endif
-
-#if defined (HISTORY)
-#  include "bashhist.h"
-#endif
-
-extern int dollar_dollar_pid;
-extern int posixly_correct;
-extern int expand_aliases;
-extern int autocd;
-extern int breaking, continuing, loop_level;
-extern int parse_and_execute_level, running_trap, sourcelevel;
-extern int command_string_index, line_number;
-extern int dot_found_in_search;
-extern int already_making_children;
-extern int tempenv_assign_error;
-extern char *the_printed_command, *shell_name;
-extern pid_t last_command_subst_pid;
-extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
-extern char **subshell_argv, **subshell_envp;
-extern int subshell_argc;
-extern time_t shell_start_time;
-#if 0
-extern char *glob_argv_flags;
-#endif
-
-extern int job_control;        /* XXX */
-
-extern int close __P((int));
-
-/* Static functions defined and used in this file. */
-static void close_pipes __P((int, int));
-static void do_piping __P((int, int));
-static void bind_lastarg __P((char *));
-static int shell_control_structure __P((enum command_type));
-static void cleanup_redirects __P((REDIRECT *));
-
-#if defined (JOB_CONTROL)
-static int restore_signal_mask __P((sigset_t *));
-#endif
-
-static void async_redirect_stdin __P((void));
-
-static int builtin_status __P((int));
-
-static int execute_for_command __P((FOR_COM *));
-#if defined (SELECT_COMMAND)
-static int displen __P((const char *));
-static int print_index_and_element __P((int, int, WORD_LIST *));
-static void indent __P((int, int));
-static void print_select_list __P((WORD_LIST *, int, int, int));
-static char *select_query __P((WORD_LIST *, int, char *, int));
-static int execute_select_command __P((SELECT_COM *));
-#endif
-#if defined (DPAREN_ARITHMETIC)
-static int execute_arith_command __P((ARITH_COM *));
-#endif
-#if defined (COND_COMMAND)
-static int execute_cond_node __P((COND_COM *));
-static int execute_cond_command __P((COND_COM *));
-#endif
-#if defined (COMMAND_TIMING)
-static int mkfmt __P((char *, int, int, time_t, int));
-static void print_formatted_time __P((FILE *, char *,
-                                     time_t, int, time_t, int,
-                                     time_t, int, int));
-static int time_command __P((COMMAND *, int, int, int, struct fd_bitmap *));
-#endif
-#if defined (ARITH_FOR_COMMAND)
-static intmax_t eval_arith_for_expr __P((WORD_LIST *, int *));
-static int execute_arith_for_command __P((ARITH_FOR_COM *));
-#endif
-static int execute_case_command __P((CASE_COM *));
-static int execute_while_command __P((WHILE_COM *));
-static int execute_until_command __P((WHILE_COM *));
-static int execute_while_or_until __P((WHILE_COM *, int));
-static int execute_if_command __P((IF_COM *));
-static int execute_null_command __P((REDIRECT *, int, int, int));
-static void fix_assignment_words __P((WORD_LIST *));
-static int execute_simple_command __P((SIMPLE_COM *, int, int, int, struct fd_bitmap *));
-static int execute_builtin __P((sh_builtin_func_t *, WORD_LIST *, int, int));
-static int execute_function __P((SHELL_VAR *, WORD_LIST *, int, struct fd_bitmap *, int, int));
-static int execute_builtin_or_function __P((WORD_LIST *, sh_builtin_func_t *,
-                                           SHELL_VAR *,
-                                           REDIRECT *, struct fd_bitmap *, int));
-static void execute_subshell_builtin_or_function __P((WORD_LIST *, REDIRECT *,
-                                                     sh_builtin_func_t *,
-                                                     SHELL_VAR *,
-                                                     int, int, int,
-                                                     struct fd_bitmap *,
-                                                     int));
-static int execute_disk_command __P((WORD_LIST *, REDIRECT *, char *,
-                                     int, int, int, struct fd_bitmap *, int));
-
-static char *getinterp __P((char *, int, int *));
-static void initialize_subshell __P((void));
-static int execute_in_subshell __P((COMMAND *, int, int, int, struct fd_bitmap *));
-#if defined (COPROCESS_SUPPORT)
-static int execute_coproc __P((COMMAND *, int, int, struct fd_bitmap *));
-#endif
-
-static int execute_pipeline __P((COMMAND *, int, int, int, struct fd_bitmap *));
-
-static int execute_connection __P((COMMAND *, int, int, int, struct fd_bitmap *));
-
-static int execute_intern_function __P((WORD_DESC *, FUNCTION_DEF *));
-
-/* Set to 1 if fd 0 was the subject of redirection to a subshell.  Global
-   so that reader_loop can set it to zero before executing a command. */
-int stdin_redir;
-
-/* The name of the command that is currently being executed.
-   `test' needs this, for example. */
-char *this_command_name;
-
-/* The printed representation of the currently-executing command (same as
-   the_printed_command), except when a trap is being executed.  Useful for
-   a debugger to know where exactly the program is currently executing. */
-char *the_printed_command_except_trap;
-
-/* For catching RETURN in a function. */
-int return_catch_flag;
-int return_catch_value;
-procenv_t return_catch;
-
-/* The value returned by the last synchronous command. */
-int last_command_exit_value;
-
-/* Whether or not the last command (corresponding to last_command_exit_value)
-   was terminated by a signal, and, if so, which one. */
-int last_command_exit_signal;
-
-/* Are we currently ignoring the -e option for the duration of a builtin's
-   execution? */
-int builtin_ignoring_errexit = 0;
-
-/* The list of redirections to perform which will undo the redirections
-   that I made in the shell. */
-REDIRECT *redirection_undo_list = (REDIRECT *)NULL;
-
-/* The list of redirections to perform which will undo the internal
-   redirections performed by the `exec' builtin.  These are redirections
-   that must be undone even when exec discards redirection_undo_list. */
-REDIRECT *exec_redirection_undo_list = (REDIRECT *)NULL;
-
-/* When greater than zero, value is the `level' of builtins we are
-   currently executing (e.g. `eval echo a' would have it set to 2). */
-int executing_builtin = 0;
-
-/* Non-zero if we are executing a command list (a;b;c, etc.) */
-int executing_list = 0;
-
-/* Non-zero if failing commands in a command substitution should not exit the
-   shell even if -e is set.  Used to pass the CMD_IGNORE_RETURN flag down to
-   commands run in command substitutions by parse_and_execute. */
-int comsub_ignore_return = 0;
-
-/* Non-zero if we have just forked and are currently running in a subshell
-   environment. */
-int subshell_environment;
-
-/* Count of nested subshells, like SHLVL.  Available via $BASH_SUBSHELL */
-int subshell_level = 0;
-
-/* Currently-executing shell function. */
-SHELL_VAR *this_shell_function;
-
-/* If non-zero, matches in case and [[ ... ]] are case-insensitive */
-int match_ignore_case = 0;
-
-int executing_command_builtin = 0;
-
-struct stat SB;                /* used for debugging */
-
-static int special_builtin_failed;
-
-static COMMAND *currently_executing_command;
-
-/* The line number that the currently executing function starts on. */
-static int function_line_number;
-
-/* XXX - set to 1 if we're running the DEBUG trap and we want to show the line
-   number containing the function name.  Used by executing_line_number to
-   report the correct line number.  Kind of a hack. */
-static int showing_function_line;
-
-/* $LINENO ($BASH_LINENO) for use by an ERR trap.  Global so parse_and_execute
-   can save and restore it. */
-int line_number_for_err_trap;
-
-/* A sort of function nesting level counter */
-int funcnest = 0;
-int funcnest_max = 0;          /* XXX - bash-4.2 */
-
-int lastpipe_opt = 0;
-
-struct fd_bitmap *current_fds_to_close = (struct fd_bitmap *)NULL;
-
-#define FD_BITMAP_DEFAULT_SIZE 32
-
-/* Functions to allocate and deallocate the structures used to pass
-   information from the shell to its children about file descriptors
-   to close. */
-struct fd_bitmap *
-new_fd_bitmap (size)
-     int size;
-{
-  struct fd_bitmap *ret;
-
-  ret = (struct fd_bitmap *)xmalloc (sizeof (struct fd_bitmap));
-
-  ret->size = size;
-
-  if (size)
-    {
-      ret->bitmap = (char *)xmalloc (size);
-      memset (ret->bitmap, '\0', size);
-    }
-  else
-    ret->bitmap = (char *)NULL;
-  return (ret);
-}
-
-void
-dispose_fd_bitmap (fdbp)
-     struct fd_bitmap *fdbp;
-{
-  FREE (fdbp->bitmap);
-  free (fdbp);
-}
-
-void
-close_fd_bitmap (fdbp)
-     struct fd_bitmap *fdbp;
-{
-  register int i;
-
-  if (fdbp)
-    {
-      for (i = 0; i < fdbp->size; i++)
-       if (fdbp->bitmap[i])
-         {
-           close (i);
-           fdbp->bitmap[i] = 0;
-         }
-    }
-}
-
-/* Return the line number of the currently executing command. */
-int
-executing_line_number ()
-{
-  if (executing && showing_function_line == 0 &&
-      (variable_context == 0 || interactive_shell == 0) &&
-      currently_executing_command)
-    {
-#if defined (COND_COMMAND)
-      if (currently_executing_command->type == cm_cond)
-       return currently_executing_command->value.Cond->line;
-#endif
-#if defined (DPAREN_ARITHMETIC)
-      else if (currently_executing_command->type == cm_arith)
-       return currently_executing_command->value.Arith->line;
-#endif
-#if defined (ARITH_FOR_COMMAND)
-      else if (currently_executing_command->type == cm_arith_for)
-       return currently_executing_command->value.ArithFor->line;
-#endif
-
-       return line_number;
-    }
-  else
-    return line_number;
-}
-
-/* Execute the command passed in COMMAND.  COMMAND is exactly what
-   read_command () places into GLOBAL_COMMAND.  See "command.h" for the
-   details of the command structure.
-
-   EXECUTION_SUCCESS or EXECUTION_FAILURE are the only possible
-   return values.  Executing a command with nothing in it returns
-   EXECUTION_SUCCESS. */
-int
-execute_command (command)
-     COMMAND *command;
-{
-  struct fd_bitmap *bitmap;
-  int result;
-
-  current_fds_to_close = (struct fd_bitmap *)NULL;
-  bitmap = new_fd_bitmap (FD_BITMAP_DEFAULT_SIZE);
-  begin_unwind_frame ("execute-command");
-  add_unwind_protect (dispose_fd_bitmap, (char *)bitmap);
-
-  /* Just do the command, but not asynchronously. */
-  result = execute_command_internal (command, 0, NO_PIPE, NO_PIPE, bitmap);
-
-  dispose_fd_bitmap (bitmap);
-  discard_unwind_frame ("execute-command");
-
-#if defined (PROCESS_SUBSTITUTION)
-  /* don't unlink fifos if we're in a shell function; wait until the function
-     returns. */
-  if (variable_context == 0)
-    unlink_fifo_list ();
-#endif /* PROCESS_SUBSTITUTION */
-
-  QUIT;
-  return (result);
-}
-
-/* Return 1 if TYPE is a shell control structure type. */
-static int
-shell_control_structure (type)
-     enum command_type type;
-{
-  switch (type)
-    {
-#if defined (ARITH_FOR_COMMAND)
-    case cm_arith_for:
-#endif
-#if defined (SELECT_COMMAND)
-    case cm_select:
-#endif
-#if defined (DPAREN_ARITHMETIC)
-    case cm_arith:
-#endif
-#if defined (COND_COMMAND)
-    case cm_cond:
-#endif
-    case cm_case:
-    case cm_while:
-    case cm_until:
-    case cm_if:
-    case cm_for:
-    case cm_group:
-    case cm_function_def:
-      return (1);
-
-    default:
-      return (0);
-    }
-}
-
-/* A function to use to unwind_protect the redirection undo list
-   for loops. */
-static void
-cleanup_redirects (list)
-     REDIRECT *list;
-{
-  do_redirections (list, RX_ACTIVE);
-  dispose_redirects (list);
-}
-
-#if 0
-/* Function to unwind_protect the redirections for functions and builtins. */
-static void
-cleanup_func_redirects (list)
-     REDIRECT *list;
-{
-  do_redirections (list, RX_ACTIVE);
-}
-#endif
-
-void
-dispose_exec_redirects ()
-{
-  if (exec_redirection_undo_list)
-    {
-      dispose_redirects (exec_redirection_undo_list);
-      exec_redirection_undo_list = (REDIRECT *)NULL;
-    }
-}
-
-#if defined (JOB_CONTROL)
-/* A function to restore the signal mask to its proper value when the shell
-   is interrupted or errors occur while creating a pipeline. */
-static int
-restore_signal_mask (set)
-     sigset_t *set;
-{
-  return (sigprocmask (SIG_SETMASK, set, (sigset_t *)NULL));
-}
-#endif /* JOB_CONTROL */
-
-#ifdef DEBUG
-/* A debugging function that can be called from gdb, for instance. */
-void
-open_files ()
-{
-  register int i;
-  int f, fd_table_size;
-
-  fd_table_size = getdtablesize ();
-
-  fprintf (stderr, "pid %ld open files:", (long)getpid ());
-  for (i = 3; i < fd_table_size; i++)
-    {
-      if ((f = fcntl (i, F_GETFD, 0)) != -1)
-       fprintf (stderr, " %d (%s)", i, f ? "close" : "open");
-    }
-  fprintf (stderr, "\n");
-}
-#endif
-
-static void
-async_redirect_stdin ()
-{
-  int fd;
-
-  fd = open ("/dev/null", O_RDONLY);
-  if (fd > 0)
-    {
-      dup2 (fd, 0);
-      close (fd);
-    }
-  else if (fd < 0)
-    internal_error (_("cannot redirect standard input from /dev/null: %s"), strerror (errno));
-}
-
-#define DESCRIBE_PID(pid) do { if (interactive) describe_pid (pid); } while (0)
-
-/* Execute the command passed in COMMAND, perhaps doing it asynchrounously.
-   COMMAND is exactly what read_command () places into GLOBAL_COMMAND.
-   ASYNCHROUNOUS, if non-zero, says to do this command in the background.
-   PIPE_IN and PIPE_OUT are file descriptors saying where input comes
-   from and where it goes.  They can have the value of NO_PIPE, which means
-   I/O is stdin/stdout.
-   FDS_TO_CLOSE is a list of file descriptors to close once the child has
-   been forked.  This list often contains the unusable sides of pipes, etc.
-
-   EXECUTION_SUCCESS or EXECUTION_FAILURE are the only possible
-   return values.  Executing a command with nothing in it returns
-   EXECUTION_SUCCESS. */
-int
-execute_command_internal (command, asynchronous, pipe_in, pipe_out,
-                         fds_to_close)
-     COMMAND *command;
-     int asynchronous;
-     int pipe_in, pipe_out;
-     struct fd_bitmap *fds_to_close;
-{
-  int exec_result, user_subshell, invert, ignore_return, was_error_trap;
-  REDIRECT *my_undo_list, *exec_undo_list;
-  char *tcmd;
-  volatile int last_pid;
-  volatile int save_line_number;
-#if defined (PROCESS_SUBSTITUTION)
-  volatile int ofifo, nfifo, osize, saved_fifo;
-  volatile char *ofifo_list;
-#endif
-
-  if (breaking || continuing)
-    return (last_command_exit_value);
-  if (command == 0 || read_but_dont_execute)
-    return (EXECUTION_SUCCESS);
-
-  QUIT;
-  run_pending_traps ();
-
-#if 0
-  if (running_trap == 0)
-#endif
-    currently_executing_command = command;
-
-  invert = (command->flags & CMD_INVERT_RETURN) != 0;
-
-  /* If we're inverting the return value and `set -e' has been executed,
-     we don't want a failing command to inadvertently cause the shell
-     to exit. */
-  if (exit_immediately_on_error && invert)     /* XXX */
-    command->flags |= CMD_IGNORE_RETURN;       /* XXX */
-
-  exec_result = EXECUTION_SUCCESS;
-
-  /* If a command was being explicitly run in a subshell, or if it is
-     a shell control-structure, and it has a pipe, then we do the command
-     in a subshell. */
-  if (command->type == cm_subshell && (command->flags & CMD_NO_FORK))
-    return (execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close));
-
-#if defined (COPROCESS_SUPPORT)
-  if (command->type == cm_coproc)
-    return (execute_coproc (command, pipe_in, pipe_out, fds_to_close));
-#endif
-
-  user_subshell = command->type == cm_subshell || ((command->flags & CMD_WANT_SUBSHELL) != 0);
-
-  if (command->type == cm_subshell ||
-      (command->flags & (CMD_WANT_SUBSHELL|CMD_FORCE_SUBSHELL)) ||
-      (shell_control_structure (command->type) &&
-       (pipe_out != NO_PIPE || pipe_in != NO_PIPE || asynchronous)))
-    {
-      pid_t paren_pid;
-      int s;
-
-      /* Fork a subshell, turn off the subshell bit, turn off job
-        control and call execute_command () on the command again. */
-      line_number_for_err_trap = line_number;
-      tcmd = make_command_string (command);
-      paren_pid = make_child (savestring (tcmd), asynchronous);
-
-      if (user_subshell && signal_is_trapped (ERROR_TRAP) && 
-         signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
-       {
-         FREE (the_printed_command_except_trap);
-         the_printed_command_except_trap = savestring (the_printed_command);
-       }
-
-      if (paren_pid == 0)
-        {
-         /* We want to run the exit trap for forced {} subshells, and we
-            want to note this before execute_in_subshell modifies the
-            COMMAND struct.  Need to keep in mind that execute_in_subshell
-            runs the exit trap for () subshells itself. */
-         s = user_subshell == 0 && command->type == cm_group && pipe_in == NO_PIPE && pipe_out == NO_PIPE && asynchronous;
-
-         last_command_exit_value = execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close);
-         if (s)
-           subshell_exit (last_command_exit_value);
-         else
-           exit (last_command_exit_value);
-         /* NOTREACHED */
-        }
-      else
-       {
-         close_pipes (pipe_in, pipe_out);
-
-#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
-         if (variable_context == 0)    /* wait until shell function completes */
-           unlink_fifo_list ();
-#endif
-         /* If we are part of a pipeline, and not the end of the pipeline,
-            then we should simply return and let the last command in the
-            pipe be waited for.  If we are not in a pipeline, or are the
-            last command in the pipeline, then we wait for the subshell
-            and return its exit status as usual. */
-         if (pipe_out != NO_PIPE)
-           return (EXECUTION_SUCCESS);
-
-         stop_pipeline (asynchronous, (COMMAND *)NULL);
-
-         if (asynchronous == 0)
-           {
-             was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
-             invert = (command->flags & CMD_INVERT_RETURN) != 0;
-             ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
-
-             exec_result = wait_for (paren_pid);
-
-             /* If we have to, invert the return value. */
-             if (invert)
-               exec_result = ((exec_result == EXECUTION_SUCCESS)
-                               ? EXECUTION_FAILURE
-                               : EXECUTION_SUCCESS);
-
-             last_command_exit_value = exec_result;
-             if (user_subshell && was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
-               {
-                 save_line_number = line_number;
-                 line_number = line_number_for_err_trap;
-                 run_error_trap ();
-                 line_number = save_line_number;
-               }
-
-             if (user_subshell && ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
-               {
-                 run_pending_traps ();
-                 jump_to_top_level (ERREXIT);
-               }
-
-             return (last_command_exit_value);
-           }
-         else
-           {
-             DESCRIBE_PID (paren_pid);
-
-             run_pending_traps ();
-
-             return (EXECUTION_SUCCESS);
-           }
-       }
-    }
-
-#if defined (COMMAND_TIMING)
-  if (command->flags & CMD_TIME_PIPELINE)
-    {
-      if (asynchronous)
-       {
-         command->flags |= CMD_FORCE_SUBSHELL;
-         exec_result = execute_command_internal (command, 1, pipe_in, pipe_out, fds_to_close);
-       }
-      else
-       {
-         exec_result = time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close);
-#if 0
-         if (running_trap == 0)
-#endif
-           currently_executing_command = (COMMAND *)NULL;
-       }
-      return (exec_result);
-    }
-#endif /* COMMAND_TIMING */
-
-  if (shell_control_structure (command->type) && command->redirects)
-    stdin_redir = stdin_redirects (command->redirects);
-
-#if defined (PROCESS_SUBSTITUTION)
-  if (variable_context != 0)
-    {
-      ofifo = num_fifos ();
-      ofifo_list = copy_fifo_list ((int *)&osize);
-      saved_fifo = 1;
-    }
-  else
-    saved_fifo = 0;
-#endif
-
-  /* Handle WHILE FOR CASE etc. with redirections.  (Also '&' input
-     redirection.)  */
-  if (do_redirections (command->redirects, RX_ACTIVE|RX_UNDOABLE) != 0)
-    {
-      cleanup_redirects (redirection_undo_list);
-      redirection_undo_list = (REDIRECT *)NULL;
-      dispose_exec_redirects ();
-#if defined (PROCESS_SUBSTITUTION)
-      if (saved_fifo)
-       free ((void *)ofifo_list);
-#endif
-      return (last_command_exit_value = EXECUTION_FAILURE);
-    }
-
-  if (redirection_undo_list)
-    {
-      /* XXX - why copy here? */
-      my_undo_list = (REDIRECT *)copy_redirects (redirection_undo_list);
-      dispose_redirects (redirection_undo_list);
-      redirection_undo_list = (REDIRECT *)NULL;
-    }
-  else
-    my_undo_list = (REDIRECT *)NULL;
-
-  if (exec_redirection_undo_list)
-    {
-      /* XXX - why copy here? */
-      exec_undo_list = (REDIRECT *)copy_redirects (exec_redirection_undo_list);
-      dispose_redirects (exec_redirection_undo_list);
-      exec_redirection_undo_list = (REDIRECT *)NULL;
-    }
-  else
-    exec_undo_list = (REDIRECT *)NULL;
-
-  if (my_undo_list || exec_undo_list)
-    begin_unwind_frame ("loop_redirections");
-
-  if (my_undo_list)
-    add_unwind_protect ((Function *)cleanup_redirects, my_undo_list);
-
-  if (exec_undo_list)
-    add_unwind_protect ((Function *)dispose_redirects, exec_undo_list);
-
-  ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
-
-  QUIT;
-
-  switch (command->type)
-    {
-    case cm_simple:
-      {
-       save_line_number = line_number;
-       /* We can't rely on variables retaining their values across a
-          call to execute_simple_command if a longjmp occurs as the
-          result of a `return' builtin.  This is true for sure with gcc. */
-#if defined (RECYCLES_PIDS)
-       last_made_pid = NO_PID;
-#endif
-       last_pid = last_made_pid;
-       was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
-
-       if (ignore_return && command->value.Simple)
-         command->value.Simple->flags |= CMD_IGNORE_RETURN;
-       if (command->flags & CMD_STDIN_REDIR)
-         command->value.Simple->flags |= CMD_STDIN_REDIR;
-
-       line_number_for_err_trap = line_number = command->value.Simple->line;
-       exec_result =
-         execute_simple_command (command->value.Simple, pipe_in, pipe_out,
-                                 asynchronous, fds_to_close);
-       line_number = save_line_number;
-
-       /* The temporary environment should be used for only the simple
-          command immediately following its definition. */
-       dispose_used_env_vars ();
-
-#if (defined (ultrix) && defined (mips)) || defined (C_ALLOCA)
-       /* Reclaim memory allocated with alloca () on machines which
-          may be using the alloca emulation code. */
-       (void) alloca (0);
-#endif /* (ultrix && mips) || C_ALLOCA */
-
-       /* If we forked to do the command, then we must wait_for ()
-          the child. */
-
-       /* XXX - this is something to watch out for if there are problems
-          when the shell is compiled without job control.  Don't worry about
-          whether or not last_made_pid == last_pid; already_making_children
-          tells us whether or not there are unwaited-for children to wait
-          for and reap. */
-       if (already_making_children && pipe_out == NO_PIPE)
-         {
-           stop_pipeline (asynchronous, (COMMAND *)NULL);
-
-           if (asynchronous)
-             {
-               DESCRIBE_PID (last_made_pid);
-             }
-           else
-#if !defined (JOB_CONTROL)
-             /* Do not wait for asynchronous processes started from
-                startup files. */
-           if (last_made_pid != last_asynchronous_pid)
-#endif
-           /* When executing a shell function that executes other
-              commands, this causes the last simple command in
-              the function to be waited for twice.  This also causes
-              subshells forked to execute builtin commands (e.g., in
-              pipelines) to be waited for twice. */
-             exec_result = wait_for (last_made_pid);
-         }
-      }
-
-      /* 2009/02/13 -- pipeline failure is processed elsewhere.  This handles
-        only the failure of a simple command. */
-      if (was_error_trap && ignore_return == 0 && invert == 0 && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS)
-       {
-         last_command_exit_value = exec_result;
-         line_number = line_number_for_err_trap;
-         run_error_trap ();
-         line_number = save_line_number;
-       }
-
-      if (ignore_return == 0 && invert == 0 &&
-         ((posixly_correct && interactive == 0 && special_builtin_failed) ||
-          (exit_immediately_on_error && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS)))
-       {
-         last_command_exit_value = exec_result;
-         run_pending_traps ();
-         jump_to_top_level (ERREXIT);
-       }
-
-      break;
-
-    case cm_for:
-      if (ignore_return)
-       command->value.For->flags |= CMD_IGNORE_RETURN;
-      exec_result = execute_for_command (command->value.For);
-      break;
-
-#if defined (ARITH_FOR_COMMAND)
-    case cm_arith_for:
-      if (ignore_return)
-       command->value.ArithFor->flags |= CMD_IGNORE_RETURN;
-      exec_result = execute_arith_for_command (command->value.ArithFor);
-      break;
-#endif
-
-#if defined (SELECT_COMMAND)
-    case cm_select:
-      if (ignore_return)
-       command->value.Select->flags |= CMD_IGNORE_RETURN;
-      exec_result = execute_select_command (command->value.Select);
-      break;
-#endif
-
-    case cm_case:
-      if (ignore_return)
-       command->value.Case->flags |= CMD_IGNORE_RETURN;
-      exec_result = execute_case_command (command->value.Case);
-      break;
-
-    case cm_while:
-      if (ignore_return)
-       command->value.While->flags |= CMD_IGNORE_RETURN;
-      exec_result = execute_while_command (command->value.While);
-      break;
-
-    case cm_until:
-      if (ignore_return)
-       command->value.While->flags |= CMD_IGNORE_RETURN;
-      exec_result = execute_until_command (command->value.While);
-      break;
-
-    case cm_if:
-      if (ignore_return)
-       command->value.If->flags |= CMD_IGNORE_RETURN;
-      exec_result = execute_if_command (command->value.If);
-      break;
-
-    case cm_group:
-
-      /* This code can be executed from either of two paths: an explicit
-        '{}' command, or via a function call.  If we are executed via a
-        function call, we have already taken care of the function being
-        executed in the background (down there in execute_simple_command ()),
-        and this command should *not* be marked as asynchronous.  If we
-        are executing a regular '{}' group command, and asynchronous == 1,
-        we must want to execute the whole command in the background, so we
-        need a subshell, and we want the stuff executed in that subshell
-        (this group command) to be executed in the foreground of that
-        subshell (i.e. there will not be *another* subshell forked).
-
-        What we do is to force a subshell if asynchronous, and then call
-        execute_command_internal again with asynchronous still set to 1,
-        but with the original group command, so the printed command will
-        look right.
-
-        The code above that handles forking off subshells will note that
-        both subshell and async are on, and turn off async in the child
-        after forking the subshell (but leave async set in the parent, so
-        the normal call to describe_pid is made).  This turning off
-        async is *crucial*; if it is not done, this will fall into an
-        infinite loop of executions through this spot in subshell after
-        subshell until the process limit is exhausted. */
-
-      if (asynchronous)
-       {
-         command->flags |= CMD_FORCE_SUBSHELL;
-         exec_result =
-           execute_command_internal (command, 1, pipe_in, pipe_out,
-                                     fds_to_close);
-       }
-      else
-       {
-         if (ignore_return && command->value.Group->command)
-           command->value.Group->command->flags |= CMD_IGNORE_RETURN;
-         exec_result =
-           execute_command_internal (command->value.Group->command,
-                                     asynchronous, pipe_in, pipe_out,
-                                     fds_to_close);
-       }
-      break;
-
-    case cm_connection:
-      exec_result = execute_connection (command, asynchronous,
-                                       pipe_in, pipe_out, fds_to_close);
-      break;
-
-#if defined (DPAREN_ARITHMETIC)
-    case cm_arith:
-      was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
-      if (ignore_return)
-       command->value.Arith->flags |= CMD_IGNORE_RETURN;
-      line_number_for_err_trap = save_line_number = line_number;
-      exec_result = execute_arith_command (command->value.Arith);
-      line_number = save_line_number;
-
-      if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
-       {
-         last_command_exit_value = exec_result;
-         save_line_number = line_number;
-         line_number = line_number_for_err_trap;
-         run_error_trap ();
-         line_number = save_line_number;
-       }
-
-      if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
-       {
-         last_command_exit_value = exec_result;
-         run_pending_traps ();
-         jump_to_top_level (ERREXIT);
-       }
-
-      break;
-#endif
-
-#if defined (COND_COMMAND)
-    case cm_cond:
-      was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
-      if (ignore_return)
-       command->value.Cond->flags |= CMD_IGNORE_RETURN;
-
-      line_number_for_err_trap = save_line_number = line_number;
-      exec_result = execute_cond_command (command->value.Cond);
-      line_number = save_line_number;
-
-      if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
-       {
-         last_command_exit_value = exec_result;
-         save_line_number = line_number;
-         line_number = line_number_for_err_trap;
-         run_error_trap ();
-         line_number = save_line_number;
-       }
-
-      if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
-       {
-         last_command_exit_value = exec_result;
-         run_pending_traps ();
-         jump_to_top_level (ERREXIT);
-       }
-
-      break;
-#endif
-    
-    case cm_function_def:
-      exec_result = execute_intern_function (command->value.Function_def->name,
-                                            command->value.Function_def);
-      break;
-
-    default:
-      command_error ("execute_command", CMDERR_BADTYPE, command->type, 0);
-    }
-
-  if (my_undo_list)
-    {
-      do_redirections (my_undo_list, RX_ACTIVE);
-      dispose_redirects (my_undo_list);
-    }
-
-  if (exec_undo_list)
-    dispose_redirects (exec_undo_list);
-
-  if (my_undo_list || exec_undo_list)
-    discard_unwind_frame ("loop_redirections");
-
-#if defined (PROCESS_SUBSTITUTION)
-  if (saved_fifo)
-    {
-      nfifo = num_fifos ();
-      if (nfifo > ofifo)
-       close_new_fifos ((char *)ofifo_list, osize);
-      free ((void *)ofifo_list);
-    }
-#endif
-
-  /* Invert the return value if we have to */
-  if (invert)
-    exec_result = (exec_result == EXECUTION_SUCCESS)
-                   ? EXECUTION_FAILURE
-                   : EXECUTION_SUCCESS;
-
-#if defined (DPAREN_ARITHMETIC) || defined (COND_COMMAND)
-  /* This is where we set PIPESTATUS from the exit status of the appropriate
-     compound commands (the ones that look enough like simple commands to
-     cause confusion).  We might be able to optimize by not doing this if
-     subshell_environment != 0. */
-  switch (command->type)
-    {
-#  if defined (DPAREN_ARITHMETIC)
-    case cm_arith:
-#  endif
-#  if defined (COND_COMMAND)
-    case cm_cond:
-#  endif
-      set_pipestatus_from_exit (exec_result);
-      break;
-    }
-#endif
-
-  last_command_exit_value = exec_result;
-  run_pending_traps ();
-#if 0
-  if (running_trap == 0)
-#endif
-    currently_executing_command = (COMMAND *)NULL;
-
-  return (last_command_exit_value);
-}
-
-#if defined (COMMAND_TIMING)
-
-#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
-extern struct timeval *difftimeval __P((struct timeval *, struct timeval *, struct timeval *));
-extern struct timeval *addtimeval __P((struct timeval *, struct timeval *, struct timeval *));
-extern int timeval_to_cpu __P((struct timeval *, struct timeval *, struct timeval *));
-#endif
-
-#define POSIX_TIMEFORMAT "real %2R\nuser %2U\nsys %2S"
-#define BASH_TIMEFORMAT  "\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS"
-
-static const int precs[] = { 0, 100, 10, 1 };
-
-/* Expand one `%'-prefixed escape sequence from a time format string. */
-static int
-mkfmt (buf, prec, lng, sec, sec_fraction)
-     char *buf;
-     int prec, lng;
-     time_t sec;
-     int sec_fraction;
-{
-  time_t min;
-  char abuf[INT_STRLEN_BOUND(time_t) + 1];
-  int ind, aind;
-
-  ind = 0;
-  abuf[sizeof(abuf) - 1] = '\0';
-
-  /* If LNG is non-zero, we want to decompose SEC into minutes and seconds. */
-  if (lng)
-    {
-      min = sec / 60;
-      sec %= 60;
-      aind = sizeof(abuf) - 2;
-      do
-       abuf[aind--] = (min % 10) + '0';
-      while (min /= 10);
-      aind++;
-      while (abuf[aind])
-       buf[ind++] = abuf[aind++];
-      buf[ind++] = 'm';
-    }
-
-  /* Now add the seconds. */
-  aind = sizeof (abuf) - 2;
-  do
-    abuf[aind--] = (sec % 10) + '0';
-  while (sec /= 10);
-  aind++;
-  while (abuf[aind])
-    buf[ind++] = abuf[aind++];
-
-  /* We want to add a decimal point and PREC places after it if PREC is
-     nonzero.  PREC is not greater than 3.  SEC_FRACTION is between 0
-     and 999. */
-  if (prec != 0)
-    {
-      buf[ind++] = '.';
-      for (aind = 1; aind <= prec; aind++)
-       {
-         buf[ind++] = (sec_fraction / precs[aind]) + '0';
-         sec_fraction %= precs[aind];
-       }
-    }
-
-  if (lng)
-    buf[ind++] = 's';
-  buf[ind] = '\0';
-
-  return (ind);
-}
-
-/* Interpret the format string FORMAT, interpolating the following escape
-   sequences:
-               %[prec][l][RUS]
-
-   where the optional `prec' is a precision, meaning the number of
-   characters after the decimal point, the optional `l' means to format
-   using minutes and seconds (MMmNN[.FF]s), like the `times' builtin',
-   and the last character is one of
-   
-               R       number of seconds of `real' time
-               U       number of seconds of `user' time
-               S       number of seconds of `system' time
-
-   An occurrence of `%%' in the format string is translated to a `%'.  The
-   result is printed to FP, a pointer to a FILE.  The other variables are
-   the seconds and thousandths of a second of real, user, and system time,
-   resectively. */
-static void
-print_formatted_time (fp, format, rs, rsf, us, usf, ss, ssf, cpu)
-     FILE *fp;
-     char *format;
-     time_t rs;
-     int rsf;
-     time_t us;
-     int usf;
-     time_t ss;
-     int ssf, cpu;
-{
-  int prec, lng, len;
-  char *str, *s, ts[INT_STRLEN_BOUND (time_t) + sizeof ("mSS.FFFF")];
-  time_t sum;
-  int sum_frac;
-  int sindex, ssize;
-
-  len = strlen (format);
-  ssize = (len + 64) - (len % 64);
-  str = (char *)xmalloc (ssize);
-  sindex = 0;
-
-  for (s = format; *s; s++)
-    {
-      if (*s != '%' || s[1] == '\0')
-       {
-         RESIZE_MALLOCED_BUFFER (str, sindex, 1, ssize, 64);
-         str[sindex++] = *s;
-       }
-      else if (s[1] == '%')
-       {
-         s++;
-         RESIZE_MALLOCED_BUFFER (str, sindex, 1, ssize, 64);
-         str[sindex++] = *s;
-       }
-      else if (s[1] == 'P')
-       {
-         s++;
-#if 0
-         /* clamp CPU usage at 100% */
-         if (cpu > 10000)
-           cpu = 10000;
-#endif
-         sum = cpu / 100;
-         sum_frac = (cpu % 100) * 10;
-         len = mkfmt (ts, 2, 0, sum, sum_frac);
-         RESIZE_MALLOCED_BUFFER (str, sindex, len, ssize, 64);
-         strcpy (str + sindex, ts);
-         sindex += len;
-       }
-      else
-       {
-         prec = 3;     /* default is three places past the decimal point. */
-         lng = 0;      /* default is to not use minutes or append `s' */
-         s++;
-         if (DIGIT (*s))               /* `precision' */
-           {
-             prec = *s++ - '0';
-             if (prec > 3) prec = 3;
-           }
-         if (*s == 'l')                /* `length extender' */
-           {
-             lng = 1;
-             s++;
-           }
-         if (*s == 'R' || *s == 'E')
-           len = mkfmt (ts, prec, lng, rs, rsf);
-         else if (*s == 'U')
-           len = mkfmt (ts, prec, lng, us, usf);
-         else if (*s == 'S')
-           len = mkfmt (ts, prec, lng, ss, ssf);
-         else
-           {
-             internal_error (_("TIMEFORMAT: `%c': invalid format character"), *s);
-             free (str);
-             return;
-           }
-         RESIZE_MALLOCED_BUFFER (str, sindex, len, ssize, 64);
-         strcpy (str + sindex, ts);
-         sindex += len;
-       }
-    }
-
-  str[sindex] = '\0';
-  fprintf (fp, "%s\n", str);
-  fflush (fp);
-
-  free (str);
-}
-
-static int
-time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
-     COMMAND *command;
-     int asynchronous, pipe_in, pipe_out;
-     struct fd_bitmap *fds_to_close;
-{
-  int rv, posix_time, old_flags, nullcmd;
-  time_t rs, us, ss;
-  int rsf, usf, ssf;
-  int cpu;
-  char *time_format;
-
-#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
-  struct timeval real, user, sys;
-  struct timeval before, after;
-#  if defined (HAVE_STRUCT_TIMEZONE)
-  struct timezone dtz;                         /* posix doesn't define this */
-#  endif
-  struct rusage selfb, selfa, kidsb, kidsa;    /* a = after, b = before */
-#else
-#  if defined (HAVE_TIMES)
-  clock_t tbefore, tafter, real, user, sys;
-  struct tms before, after;
-#  endif
-#endif
-
-#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
-#  if defined (HAVE_STRUCT_TIMEZONE)
-  gettimeofday (&before, &dtz);
-#  else
-  gettimeofday (&before, (void *)NULL);
-#  endif /* !HAVE_STRUCT_TIMEZONE */
-  getrusage (RUSAGE_SELF, &selfb);
-  getrusage (RUSAGE_CHILDREN, &kidsb);
-#else
-#  if defined (HAVE_TIMES)
-  tbefore = times (&before);
-#  endif
-#endif
-
-  posix_time = command && (command->flags & CMD_TIME_POSIX);
-
-  nullcmd = (command == 0) || (command->type == cm_simple && command->value.Simple->words == 0 && command->value.Simple->redirects == 0);
-  if (posixly_correct && nullcmd)
-    {
-#if defined (HAVE_GETRUSAGE)
-      selfb.ru_utime.tv_sec = kidsb.ru_utime.tv_sec = selfb.ru_stime.tv_sec = kidsb.ru_stime.tv_sec = 0;
-      selfb.ru_utime.tv_usec = kidsb.ru_utime.tv_usec = selfb.ru_stime.tv_usec = kidsb.ru_stime.tv_usec = 0;
-      before.tv_sec = shell_start_time;
-      before.tv_usec = 0;
-#else
-      before.tms_utime = before.tms_stime = before.tms_cutime = before.tms_cstime = 0;
-      tbefore = shell_start_time;
-#endif
-    }
-
-  old_flags = command->flags;
-  command->flags &= ~(CMD_TIME_PIPELINE|CMD_TIME_POSIX);
-  rv = execute_command_internal (command, asynchronous, pipe_in, pipe_out, fds_to_close);
-  command->flags = old_flags;
-
-  rs = us = ss = 0;
-  rsf = usf = ssf = cpu = 0;
-
-#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
-#  if defined (HAVE_STRUCT_TIMEZONE)
-  gettimeofday (&after, &dtz);
-#  else
-  gettimeofday (&after, (void *)NULL);
-#  endif /* !HAVE_STRUCT_TIMEZONE */
-  getrusage (RUSAGE_SELF, &selfa);
-  getrusage (RUSAGE_CHILDREN, &kidsa);
-
-  difftimeval (&real, &before, &after);
-  timeval_to_secs (&real, &rs, &rsf);
-
-  addtimeval (&user, difftimeval(&after, &selfb.ru_utime, &selfa.ru_utime),
-                    difftimeval(&before, &kidsb.ru_utime, &kidsa.ru_utime));
-  timeval_to_secs (&user, &us, &usf);
-
-  addtimeval (&sys, difftimeval(&after, &selfb.ru_stime, &selfa.ru_stime),
-                   difftimeval(&before, &kidsb.ru_stime, &kidsa.ru_stime));
-  timeval_to_secs (&sys, &ss, &ssf);
-
-  cpu = timeval_to_cpu (&real, &user, &sys);
-#else
-#  if defined (HAVE_TIMES)
-  tafter = times (&after);
-
-  real = tafter - tbefore;
-  clock_t_to_secs (real, &rs, &rsf);
-
-  user = (after.tms_utime - before.tms_utime) + (after.tms_cutime - before.tms_cutime);
-  clock_t_to_secs (user, &us, &usf);
-
-  sys = (after.tms_stime - before.tms_stime) + (after.tms_cstime - before.tms_cstime);
-  clock_t_to_secs (sys, &ss, &ssf);
-
-  cpu = (real == 0) ? 0 : ((user + sys) * 10000) / real;
-
-#  else
-  rs = us = ss = 0;
-  rsf = usf = ssf = cpu = 0;
-#  endif
-#endif
-
-  if (posix_time)
-    time_format = POSIX_TIMEFORMAT;
-  else if ((time_format = get_string_value ("TIMEFORMAT")) == 0)
-    {
-      if (posixly_correct && nullcmd)
-       time_format = "user\t%2lU\nsys\t%2lS";
-      else
-       time_format = BASH_TIMEFORMAT;
-    }
-  if (time_format && *time_format)
-    print_formatted_time (stderr, time_format, rs, rsf, us, usf, ss, ssf, cpu);
-
-  return rv;
-}
-#endif /* COMMAND_TIMING */
-
-/* Execute a command that's supposed to be in a subshell.  This must be
-   called after make_child and we must be running in the child process.
-   The caller will return or exit() immediately with the value this returns. */
-static int
-execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
-     COMMAND *command;
-     int asynchronous;
-     int pipe_in, pipe_out;
-     struct fd_bitmap *fds_to_close;
-{
-  int user_subshell, return_code, function_value, should_redir_stdin, invert;
-  int ois, user_coproc;
-  int result;
-  volatile COMMAND *tcom;
-
-  USE_VAR(user_subshell);
-  USE_VAR(user_coproc);
-  USE_VAR(invert);
-  USE_VAR(tcom);
-  USE_VAR(asynchronous);
-
-  subshell_level++;
-  should_redir_stdin = (asynchronous && (command->flags & CMD_STDIN_REDIR) &&
-                         pipe_in == NO_PIPE &&
-                         stdin_redirects (command->redirects) == 0);
-
-  invert = (command->flags & CMD_INVERT_RETURN) != 0;
-  user_subshell = command->type == cm_subshell || ((command->flags & CMD_WANT_SUBSHELL) != 0);
-  user_coproc = command->type == cm_coproc;
-
-  command->flags &= ~(CMD_FORCE_SUBSHELL | CMD_WANT_SUBSHELL | CMD_INVERT_RETURN);
-
-  /* If a command is asynchronous in a subshell (like ( foo ) & or
-     the special case of an asynchronous GROUP command where the
-     the subshell bit is turned on down in case cm_group: below),
-     turn off `asynchronous', so that two subshells aren't spawned.
-     XXX - asynchronous used to be set to 0 in this block, but that
-     means that setup_async_signals was never run.  Now it's set to
-     0 after subshell_environment is set appropriately and setup_async_signals
-     is run.
-
-     This seems semantically correct to me.  For example,
-     ( foo ) & seems to say ``do the command `foo' in a subshell
-     environment, but don't wait for that subshell to finish'',
-     and "{ foo ; bar ; } &" seems to me to be like functions or
-     builtins in the background, which executed in a subshell
-     environment.  I just don't see the need to fork two subshells. */
-
-  /* Don't fork again, we are already in a subshell.  A `doubly
-     async' shell is not interactive, however. */
-  if (asynchronous)
-    {
-#if defined (JOB_CONTROL)
-      /* If a construct like ( exec xxx yyy ) & is given while job
-        control is active, we want to prevent exec from putting the
-        subshell back into the original process group, carefully
-        undoing all the work we just did in make_child. */
-      original_pgrp = -1;
-#endif /* JOB_CONTROL */
-      ois = interactive_shell;
-      interactive_shell = 0;
-      /* This test is to prevent alias expansion by interactive shells that
-        run `(command) &' but to allow scripts that have enabled alias
-        expansion with `shopt -s expand_alias' to continue to expand
-        aliases. */
-      if (ois != interactive_shell)
-       expand_aliases = 0;
-    }
-
-  /* Subshells are neither login nor interactive. */
-  login_shell = interactive = 0;
-
-  if (user_subshell)
-    subshell_environment = SUBSHELL_PAREN;
-  else
-    {
-      subshell_environment = 0;                        /* XXX */
-      if (asynchronous)
-       subshell_environment |= SUBSHELL_ASYNC;
-      if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
-       subshell_environment |= SUBSHELL_PIPE;
-      if (user_coproc)
-       subshell_environment |= SUBSHELL_COPROC;
-    }
-
-  reset_terminating_signals ();                /* in sig.c */
-  /* Cancel traps, in trap.c. */
-  /* Reset the signal handlers in the child, but don't free the
-     trap strings.  Set a flag noting that we have to free the
-     trap strings if we run trap to change a signal disposition. */
-  reset_signal_handlers ();
-  subshell_environment |= SUBSHELL_RESETTRAP;
-
-  /* Make sure restore_original_signals doesn't undo the work done by
-     make_child to ensure that asynchronous children are immune to SIGINT
-     and SIGQUIT.  Turn off asynchronous to make sure more subshells are
-     not spawned. */
-  if (asynchronous)
-    {
-      setup_async_signals ();
-      asynchronous = 0;
-    }
-
-#if defined (JOB_CONTROL)
-  set_sigchld_handler ();
-#endif /* JOB_CONTROL */
-
-  set_sigint_handler ();
-
-#if defined (JOB_CONTROL)
-  /* Delete all traces that there were any jobs running.  This is
-     only for subshells. */
-  without_job_control ();
-#endif /* JOB_CONTROL */
-
-  if (fds_to_close)
-    close_fd_bitmap (fds_to_close);
-
-  do_piping (pipe_in, pipe_out);
-
-#if defined (COPROCESS_SUPPORT)
-  coproc_closeall ();
-#endif
-
-  /* If this is a user subshell, set a flag if stdin was redirected.
-     This is used later to decide whether to redirect fd 0 to
-     /dev/null for async commands in the subshell.  This adds more
-     sh compatibility, but I'm not sure it's the right thing to do. */
-  if (user_subshell)
-    {
-      stdin_redir = stdin_redirects (command->redirects);
-      restore_default_signal (EXIT_TRAP);
-    }
-
-  /* If this is an asynchronous command (command &), we want to
-     redirect the standard input from /dev/null in the absence of
-     any specific redirection involving stdin. */
-  if (should_redir_stdin && stdin_redir == 0)
-    async_redirect_stdin ();
-
-  /* Do redirections, then dispose of them before recursive call. */
-  if (command->redirects)
-    {
-      if (do_redirections (command->redirects, RX_ACTIVE) != 0)
-       exit (invert ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
-
-      dispose_redirects (command->redirects);
-      command->redirects = (REDIRECT *)NULL;
-    }
-
-  if (command->type == cm_subshell)
-    tcom = command->value.Subshell->command;
-  else if (user_coproc)
-    tcom = command->value.Coproc->command;
-  else
-    tcom = command;
-
-  if (command->flags & CMD_TIME_PIPELINE)
-    tcom->flags |= CMD_TIME_PIPELINE;
-  if (command->flags & CMD_TIME_POSIX)
-    tcom->flags |= CMD_TIME_POSIX;
-  
-  /* Make sure the subshell inherits any CMD_IGNORE_RETURN flag. */
-  if ((command->flags & CMD_IGNORE_RETURN) && tcom != command)
-    tcom->flags |= CMD_IGNORE_RETURN;
-
-  /* If this is a simple command, tell execute_disk_command that it
-     might be able to get away without forking and simply exec.
-     This means things like ( sleep 10 ) will only cause one fork.
-     If we're timing the command or inverting its return value, however,
-     we cannot do this optimization. */
-  if ((user_subshell || user_coproc) && (tcom->type == cm_simple || tcom->type == cm_subshell) &&
-      ((tcom->flags & CMD_TIME_PIPELINE) == 0) &&
-      ((tcom->flags & CMD_INVERT_RETURN) == 0))
-    {
-      tcom->flags |= CMD_NO_FORK;
-      if (tcom->type == cm_simple)
-       tcom->value.Simple->flags |= CMD_NO_FORK;
-    }
-
-  invert = (tcom->flags & CMD_INVERT_RETURN) != 0;
-  tcom->flags &= ~CMD_INVERT_RETURN;
-
-  result = setjmp_nosigs (top_level);
-
-  /* If we're inside a function while executing this subshell, we
-     need to handle a possible `return'. */
-  function_value = 0;
-  if (return_catch_flag)
-    function_value = setjmp_nosigs (return_catch);
-
-  /* If we're going to exit the shell, we don't want to invert the return
-     status. */
-  if (result == EXITPROG)
-    invert = 0, return_code = last_command_exit_value;
-  else if (result)
-    return_code = EXECUTION_FAILURE;
-  else if (function_value)
-    return_code = return_catch_value;
-  else
-    return_code = execute_command_internal ((COMMAND *)tcom, asynchronous, NO_PIPE, NO_PIPE, fds_to_close);
-
-  /* If we are asked to, invert the return value. */
-  if (invert)
-    return_code = (return_code == EXECUTION_SUCCESS) ? EXECUTION_FAILURE
-                                                    : EXECUTION_SUCCESS;
-
-  /* If we were explicitly placed in a subshell with (), we need
-     to do the `shell cleanup' things, such as running traps[0]. */
-  if (user_subshell && signal_is_trapped (0))
-    {
-      last_command_exit_value = return_code;
-      return_code = run_exit_trap ();
-    }
-
-  subshell_level--;
-  return (return_code);
-  /* NOTREACHED */
-}
-
-#if defined (COPROCESS_SUPPORT)
-#define COPROC_MAX     16
-
-typedef struct cpelement
-  {
-    struct cpelement *next;
-    struct coproc *coproc;
-  }
-cpelement_t;
-    
-typedef struct cplist
-  {
-    struct cpelement *head;
-    struct cpelement *tail;
-    int ncoproc;
-    int lock;
-  }
-cplist_t;
-
-static struct cpelement *cpe_alloc __P((struct coproc *));
-static void cpe_dispose __P((struct cpelement *));
-static struct cpelement *cpl_add __P((struct coproc *));
-static struct cpelement *cpl_delete __P((pid_t));
-static void cpl_reap __P((void));
-static void cpl_flush __P((void));
-static void cpl_closeall __P((void));
-static struct cpelement *cpl_search __P((pid_t));
-static struct cpelement *cpl_searchbyname __P((const char *));
-static void cpl_prune __P((void));
-
-static void coproc_free __P((struct coproc *));
-
-/* Will go away when there is fully-implemented support for multiple coprocs. */
-Coproc sh_coproc = { 0, NO_PID, -1, -1, 0, 0, 0, 0, 0 };
-
-cplist_t coproc_list = {0, 0, 0};
-
-/* Functions to manage the list of coprocs */
-
-static struct cpelement *
-cpe_alloc (cp)
-     Coproc *cp;
-{
-  struct cpelement *cpe;
-
-  cpe = (struct cpelement *)xmalloc (sizeof (struct cpelement));
-  cpe->coproc = cp;
-  cpe->next = (struct cpelement *)0;
-  return cpe;
-}
-
-static void
-cpe_dispose (cpe)
-      struct cpelement *cpe;
-{
-  free (cpe);
-}
-
-static struct cpelement *
-cpl_add (cp)
-     Coproc *cp;
-{
-  struct cpelement *cpe;
-
-  cpe = cpe_alloc (cp);
-
-  if (coproc_list.head == 0)
-    {
-      coproc_list.head = coproc_list.tail = cpe;
-      coproc_list.ncoproc = 0;                 /* just to make sure */
-    }
-  else
-    {
-      coproc_list.tail->next = cpe;
-      coproc_list.tail = cpe;
-    }
-  coproc_list.ncoproc++;
-
-  return cpe;
-}
-
-static struct cpelement *
-cpl_delete (pid)
-     pid_t pid;
-{
-  struct cpelement *prev, *p;
-
-  for (prev = p = coproc_list.head; p; prev = p, p = p->next)
-    if (p->coproc->c_pid == pid)
-      {
-        prev->next = p->next;  /* remove from list */
-        break;
-      }
-
-  if (p == 0)
-    return 0;          /* not found */
-
-#if defined (DEBUG)
-  itrace("cpl_delete: deleting %d", pid);
-#endif
-
-  /* Housekeeping in the border cases. */
-  if (p == coproc_list.head)
-    coproc_list.head = coproc_list.head->next;
-  else if (p == coproc_list.tail)
-    coproc_list.tail = prev;
-
-  coproc_list.ncoproc--;
-  if (coproc_list.ncoproc == 0)
-    coproc_list.head = coproc_list.tail = 0;
-  else if (coproc_list.ncoproc == 1)
-    coproc_list.tail = coproc_list.head;               /* just to make sure */
-
-  return (p);
-}
-
-static void
-cpl_reap ()
-{
-  struct cpelement *p, *next, *nh, *nt;
-
-  /* Build a new list by removing dead coprocs and fix up the coproc_list
-     pointers when done. */
-  nh = nt = next = (struct cpelement *)0;
-  for (p = coproc_list.head; p; p = next)
-    {
-      next = p->next;
-      if (p->coproc->c_flags & COPROC_DEAD)
-       {
-         coproc_list.ncoproc--;        /* keep running count, fix up pointers later */
-
-#if defined (DEBUG)
-         itrace("cpl_reap: deleting %d", p->coproc->c_pid);
-#endif
-
-         coproc_dispose (p->coproc);
-         cpe_dispose (p);
-       }
-      else if (nh == 0)
-       nh = nt = p;
-      else
-       {
-         nt->next = p;
-         nt = nt->next;
-       }
-    }
-
-  if (coproc_list.ncoproc == 0)
-    coproc_list.head = coproc_list.tail = 0;
-  else
-    {
-      if (nt)
-        nt->next = 0;
-      coproc_list.head = nh;
-      coproc_list.tail = nt;
-      if (coproc_list.ncoproc == 1)
-       coproc_list.tail = coproc_list.head;            /* just to make sure */  
-    }
-}
-
-/* Clear out the list of saved statuses */
-static void
-cpl_flush ()
-{
-  struct cpelement *cpe, *p;
-
-  for (cpe = coproc_list.head; cpe; )
-    {
-      p = cpe;
-      cpe = cpe->next;
-
-      coproc_dispose (p->coproc);
-      cpe_dispose (p);
-    }
-
-  coproc_list.head = coproc_list.tail = 0;
-  coproc_list.ncoproc = 0;
-}
-
-static void
-cpl_closeall ()
-{
-  struct cpelement *cpe;
-
-  for (cpe = coproc_list.head; cpe; cpe = cpe->next)
-    coproc_close (cpe->coproc);
-}
-
-static void
-cpl_fdchk (fd)
-     int fd;
-{
-  struct cpelement *cpe;
-
-  for (cpe = coproc_list.head; cpe; cpe = cpe->next)
-    coproc_checkfd (cpe->coproc, fd);
-}
-
-/* Search for PID in the list of coprocs; return the cpelement struct if
-   found.  If not found, return NULL. */
-static struct cpelement *
-cpl_search (pid)
-     pid_t pid;
-{
-  struct cpelement *cpe;
-
-  for (cpe = coproc_list.head ; cpe; cpe = cpe->next)
-    if (cpe->coproc->c_pid == pid)
-      return cpe;
-  return (struct cpelement *)NULL;
-}
-
-/* Search for the coproc named NAME in the list of coprocs; return the
-   cpelement struct if found.  If not found, return NULL. */
-static struct cpelement *
-cpl_searchbyname (name)
-     const char *name;
-{
-  struct cpelement *cp;
-
-  for (cp = coproc_list.head ; cp; cp = cp->next)
-    if (STREQ (cp->coproc->c_name, name))
-      return cp;
-  return (struct cpelement *)NULL;
-}
-
-#if 0
-static void
-cpl_prune ()
-{
-  struct cpelement *cp;
-
-  while (coproc_list.head && coproc_list.ncoproc > COPROC_MAX)
-    {
-      cp = coproc_list.head;
-      coproc_list.head = coproc_list.head->next;
-      coproc_dispose (cp->coproc);
-      cpe_dispose (cp);
-      coproc_list.ncoproc--;
-    }
-}
-#endif
-
-/* These currently use a single global "shell coproc" but are written in a
-   way to not preclude additional coprocs later (using the list management
-   package above). */
-
-struct coproc *
-getcoprocbypid (pid)
-     pid_t pid;
-{
-#if MULTIPLE_COPROCS
-  struct cpelement *p;
-
-  p = cpl_search (pid);
-  return (p ? p->coproc : 0);
-#else
-  return (pid == sh_coproc.c_pid ? &sh_coproc : 0);
-#endif
-}
-
-struct coproc *
-getcoprocbyname (name)
-     const char *name;
-{
-#if MULTIPLE_COPROCS
-  struct cpelement *p;
-
-  p = cpl_searchbyname (name);
-  return (p ? p->coproc : 0);
-#else
-  return ((sh_coproc.c_name && STREQ (sh_coproc.c_name, name)) ? &sh_coproc : 0);
-#endif
-}
-
-void
-coproc_init (cp)
-     struct coproc *cp;
-{
-  cp->c_name = 0;
-  cp->c_pid = NO_PID;
-  cp->c_rfd = cp->c_wfd = -1;
-  cp->c_rsave = cp->c_wsave = -1;
-  cp->c_flags = cp->c_status = cp->c_lock = 0;
-}
-
-struct coproc *
-coproc_alloc (name, pid)
-     char *name;
-     pid_t pid;
-{
-  struct coproc *cp;
-
-#if MULTIPLE_COPROCS
-  cp = (struct coproc *)xmalloc (sizeof (struct coproc));
-#else
-  cp = &sh_coproc;
-#endif
-  coproc_init (cp);
-  cp->c_lock = 2;
-
-  cp->c_pid = pid;
-  cp->c_name = savestring (name);
-#if MULTIPLE_COPROCS
-  cpl_add (cp);
-#endif
-  cp->c_lock = 0;
-  return (cp);
-}
-
-static void
-coproc_free (cp)
-     struct coproc *cp;
-{
-  free (cp);
-}
-
-void
-coproc_dispose (cp)
-     struct coproc *cp;
-{
-  sigset_t set, oset;
-
-  if (cp == 0)
-    return;
-
-  BLOCK_SIGNAL (SIGCHLD, set, oset);
-  cp->c_lock = 3;
-  coproc_unsetvars (cp);
-  FREE (cp->c_name);
-  coproc_close (cp);
-#if MULTIPLE_COPROCS
-  coproc_free (cp);
-#else
-  coproc_init (cp);
-  cp->c_lock = 0;
-#endif
-  UNBLOCK_SIGNAL (oset);
-}
-
-/* Placeholder for now.  Will require changes for multiple coprocs */
-void
-coproc_flush ()
-{
-#if MULTIPLE_COPROCS
-  cpl_flush ();
-#else
-  coproc_dispose (&sh_coproc);
-#endif
-}
-
-void
-coproc_close (cp)
-     struct coproc *cp;
-{
-  if (cp->c_rfd >= 0)
-    {
-      close (cp->c_rfd);
-      cp->c_rfd = -1;
-    }
-  if (cp->c_wfd >= 0)
-    {
-      close (cp->c_wfd);
-      cp->c_wfd = -1;
-    }
-  cp->c_rsave = cp->c_wsave = -1;
-}
-
-void
-coproc_closeall ()
-{
-#if MULTIPLE_COPROCS
-  cpl_closeall ();
-#else
-  coproc_close (&sh_coproc);   /* XXX - will require changes for multiple coprocs */
-#endif
-}
-
-void
-coproc_reap ()
-{
-#if MULTIPLE_COPROCS
-  cpl_reap ();
-#else
-  struct coproc *cp;
-
-  cp = &sh_coproc;             /* XXX - will require changes for multiple coprocs */
-  if (cp && (cp->c_flags & COPROC_DEAD))
-    coproc_dispose (cp);
-#endif
-}
-
-void
-coproc_rclose (cp, fd)
-     struct coproc *cp;
-     int fd;
-{
-  if (cp->c_rfd >= 0 && cp->c_rfd == fd)
-    {
-      close (cp->c_rfd);
-      cp->c_rfd = -1;
-    }
-}
-
-void
-coproc_wclose (cp, fd)
-     struct coproc *cp;
-     int fd;
-{
-  if (cp->c_wfd >= 0 && cp->c_wfd == fd)
-    {
-      close (cp->c_wfd);
-      cp->c_wfd = -1;
-    }
-}
-
-void
-coproc_checkfd (cp, fd)
-     struct coproc *cp;
-     int fd;
-{
-  int update;
-
-  update = 0;
-  if (cp->c_rfd >= 0 && cp->c_rfd == fd)
-    update = cp->c_rfd = -1;
-  if (cp->c_wfd >= 0 && cp->c_wfd == fd)
-    update = cp->c_wfd = -1;
-  if (update)
-    coproc_setvars (cp);
-}
-
-void
-coproc_fdchk (fd)
-     int fd;
-{
-#if MULTIPLE_COPROCS
-  cpl_fdchk (fd);
-#else
-  coproc_checkfd (&sh_coproc, fd);
-#endif
-}
-
-void
-coproc_fdclose (cp, fd)
-     struct coproc *cp;
-     int fd;
-{
-  coproc_rclose (cp, fd);
-  coproc_wclose (cp, fd);
-  coproc_setvars (cp);
-}
-
-void
-coproc_fdsave (cp)
-     struct coproc *cp;
-{
-  cp->c_rsave = cp->c_rfd;
-  cp->c_wsave = cp->c_wfd;
-}
-
-void
-coproc_fdrestore (cp)
-     struct coproc *cp;
-{
-  cp->c_rfd = cp->c_rsave;
-  cp->c_wfd = cp->c_wsave;
-}
-
-void
-coproc_pidchk (pid, status)
-     pid_t pid;
-{
-  struct coproc *cp;
-
-#if MULTIPLE_COPROCS
-  struct cpelement *cpe;
-
-  cpe = cpl_delete (pid);
-  cp = cpe ? cpe->coproc : 0;
-#else
-  cp = getcoprocbypid (pid);
-#endif
-  if (cp)
-    {
-      cp->c_lock = 4;
-      cp->c_status = status;
-      cp->c_flags |= COPROC_DEAD;
-      cp->c_flags &= ~COPROC_RUNNING;
-      /* Don't dispose the coproc or unset the COPROC_XXX variables because
-        this is executed in a signal handler context.  Wait until coproc_reap
-        takes care of it. */
-      cp->c_lock = 0;
-    }
-}
-
-void
-coproc_setvars (cp)
-     struct coproc *cp;
-{
-  SHELL_VAR *v;
-  char *namevar, *t;
-  int l;
-#if defined (ARRAY_VARS)
-  arrayind_t ind;
-#endif
-
-  if (cp->c_name == 0)
-    return;
-
-  l = strlen (cp->c_name);
-  namevar = xmalloc (l + 16);
-
-#if defined (ARRAY_VARS)
-  v = find_variable (cp->c_name);
-  if (v == 0)
-    v = make_new_array_variable (cp->c_name);
-  if (array_p (v) == 0)
-    v = convert_var_to_array (v);
-
-  t = itos (cp->c_rfd);
-  ind = 0;
-  v = bind_array_variable (cp->c_name, ind, t, 0);
-  free (t);
-
-  t = itos (cp->c_wfd);
-  ind = 1;
-  bind_array_variable (cp->c_name, ind, t, 0);
-  free (t);
-#else
-  sprintf (namevar, "%s_READ", cp->c_name);
-  t = itos (cp->c_rfd);
-  bind_variable (namevar, t, 0);
-  free (t);
-  sprintf (namevar, "%s_WRITE", cp->c_name);
-  t = itos (cp->c_wfd);
-  bind_variable (namevar, t, 0);
-  free (t);
-#endif
-
-  sprintf (namevar, "%s_PID", cp->c_name);
-  t = itos (cp->c_pid);
-  bind_variable (namevar, t, 0);
-  free (t);
-
-  free (namevar);
-}
-
-void
-coproc_unsetvars (cp)
-     struct coproc *cp;
-{
-  int l;
-  char *namevar;
-
-  if (cp->c_name == 0)
-    return;
-
-  l = strlen (cp->c_name);
-  namevar = xmalloc (l + 16);
-
-  sprintf (namevar, "%s_PID", cp->c_name);
-  unbind_variable (namevar);  
-
-#if defined (ARRAY_VARS)
-  unbind_variable (cp->c_name);
-#else
-  sprintf (namevar, "%s_READ", cp->c_name);
-  unbind_variable (namevar);
-  sprintf (namevar, "%s_WRITE", cp->c_name);
-  unbind_variable (namevar);
-#endif  
-
-  free (namevar);
-}
-
-static int
-execute_coproc (command, pipe_in, pipe_out, fds_to_close)
-     COMMAND *command;
-     int pipe_in, pipe_out;
-     struct fd_bitmap *fds_to_close;
-{
-  int rpipe[2], wpipe[2], estat, invert;
-  pid_t coproc_pid;
-  Coproc *cp;
-  char *tcmd;
-  sigset_t set, oset;
-
-  /* XXX -- can be removed after changes to handle multiple coprocs */
-#if !MULTIPLE_COPROCS
-  if (sh_coproc.c_pid != NO_PID)
-    internal_warning ("execute_coproc: coproc [%d:%s] still exists", sh_coproc.c_pid, sh_coproc.c_name);
-  coproc_init (&sh_coproc);
-#endif
-
-  invert = (command->flags & CMD_INVERT_RETURN) != 0;
-  command_string_index = 0;
-  tcmd = make_command_string (command);
-
-  sh_openpipe ((int *)&rpipe); /* 0 = parent read, 1 = child write */
-  sh_openpipe ((int *)&wpipe); /* 0 = child read, 1 = parent write */
-
-  BLOCK_SIGNAL (SIGCHLD, set, oset);
-
-  coproc_pid = make_child (savestring (tcmd), 1);
-
-  if (coproc_pid == 0)
-    {
-      close (rpipe[0]);
-      close (wpipe[1]);
-
-      UNBLOCK_SIGNAL (oset);
-      estat = execute_in_subshell (command, 1, wpipe[0], rpipe[1], fds_to_close);
-
-      fflush (stdout);
-      fflush (stderr);
-
-      exit (estat);
-    }
-
-  close (rpipe[1]);
-  close (wpipe[0]);
-
-  /* XXX - possibly run Coproc->name through word expansion? */
-  cp = coproc_alloc (command->value.Coproc->name, coproc_pid);
-  cp->c_rfd = rpipe[0];
-  cp->c_wfd = wpipe[1];
-
-  SET_CLOSE_ON_EXEC (cp->c_rfd);
-  SET_CLOSE_ON_EXEC (cp->c_wfd);
-
-  coproc_setvars (cp);
-
-  UNBLOCK_SIGNAL (oset);
-
-#if 0
-  itrace ("execute_coproc: [%d] %s", coproc_pid, the_printed_command);
-#endif
-
-  close_pipes (pipe_in, pipe_out);
-#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
-  unlink_fifo_list ();
-#endif
-  stop_pipeline (1, (COMMAND *)NULL);
-  DESCRIBE_PID (coproc_pid);
-  run_pending_traps ();
-
-  return (invert ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
-}
-#endif
-
-static void
-restore_stdin (s)
-     int s;
-{
-  dup2 (s, 0);
-  close (s);
-}
-
-/* Catch-all cleanup function for lastpipe code for unwind-protects */
-static void
-lastpipe_cleanup (s)
-     int s;
-{
-  unfreeze_jobs_list ();
-}
-
-static int
-execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close)
-     COMMAND *command;
-     int asynchronous, pipe_in, pipe_out;
-     struct fd_bitmap *fds_to_close;
-{
-  int prev, fildes[2], new_bitmap_size, dummyfd, ignore_return, exec_result;
-  int lstdin, lastpipe_flag, lastpipe_jid;
-  COMMAND *cmd;
-  struct fd_bitmap *fd_bitmap;
-  pid_t lastpid;
-
-#if defined (JOB_CONTROL)
-  sigset_t set, oset;
-  BLOCK_CHILD (set, oset);
-#endif /* JOB_CONTROL */
-
-  ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
-
-  prev = pipe_in;
-  cmd = command;
-
-  while (cmd && cmd->type == cm_connection &&
-        cmd->value.Connection && cmd->value.Connection->connector == '|')
-    {
-      /* Make a pipeline between the two commands. */
-      if (pipe (fildes) < 0)
-       {
-         sys_error (_("pipe error"));
-#if defined (JOB_CONTROL)
-         terminate_current_pipeline ();
-         kill_current_pipeline ();
-         UNBLOCK_CHILD (oset);
-#endif /* JOB_CONTROL */
-         last_command_exit_value = EXECUTION_FAILURE;
-         /* The unwind-protects installed below will take care
-            of closing all of the open file descriptors. */
-         throw_to_top_level ();
-         return (EXECUTION_FAILURE);   /* XXX */
-       }
-
-      /* Here is a problem: with the new file close-on-exec
-        code, the read end of the pipe (fildes[0]) stays open
-        in the first process, so that process will never get a
-        SIGPIPE.  There is no way to signal the first process
-        that it should close fildes[0] after forking, so it
-        remains open.  No SIGPIPE is ever sent because there
-        is still a file descriptor open for reading connected
-        to the pipe.  We take care of that here.  This passes
-        around a bitmap of file descriptors that must be
-        closed after making a child process in execute_simple_command. */
-
-      /* We need fd_bitmap to be at least as big as fildes[0].
-        If fildes[0] is less than fds_to_close->size, then
-        use fds_to_close->size. */
-      new_bitmap_size = (fildes[0] < fds_to_close->size)
-                               ? fds_to_close->size
-                               : fildes[0] + 8;
-
-      fd_bitmap = new_fd_bitmap (new_bitmap_size);
-
-      /* Now copy the old information into the new bitmap. */
-      xbcopy ((char *)fds_to_close->bitmap, (char *)fd_bitmap->bitmap, fds_to_close->size);
-
-      /* And mark the pipe file descriptors to be closed. */
-      fd_bitmap->bitmap[fildes[0]] = 1;
-
-      /* In case there are pipe or out-of-processes errors, we
-        want all these file descriptors to be closed when
-        unwind-protects are run, and the storage used for the
-        bitmaps freed up. */
-      begin_unwind_frame ("pipe-file-descriptors");
-      add_unwind_protect (dispose_fd_bitmap, fd_bitmap);
-      add_unwind_protect (close_fd_bitmap, fd_bitmap);
-      if (prev >= 0)
-       add_unwind_protect (close, prev);
-      dummyfd = fildes[1];
-      add_unwind_protect (close, dummyfd);
-
-#if defined (JOB_CONTROL)
-      add_unwind_protect (restore_signal_mask, &oset);
-#endif /* JOB_CONTROL */
-
-      if (ignore_return && cmd->value.Connection->first)
-       cmd->value.Connection->first->flags |= CMD_IGNORE_RETURN;
-      execute_command_internal (cmd->value.Connection->first, asynchronous,
-                               prev, fildes[1], fd_bitmap);
-
-      if (prev >= 0)
-       close (prev);
-
-      prev = fildes[0];
-      close (fildes[1]);
-
-      dispose_fd_bitmap (fd_bitmap);
-      discard_unwind_frame ("pipe-file-descriptors");
-
-      cmd = cmd->value.Connection->second;
-    }
-
-  lastpid = last_made_pid;
-
-  /* Now execute the rightmost command in the pipeline.  */
-  if (ignore_return && cmd)
-    cmd->flags |= CMD_IGNORE_RETURN;
-
-  lastpipe_flag = 0;
-
-  begin_unwind_frame ("lastpipe-exec");
-  lstdin = -1;
-  /* If the `lastpipe' option is set with shopt, and job control is not
-     enabled, execute the last element of non-async pipelines in the
-     current shell environment. */
-  if (lastpipe_opt && job_control == 0 && asynchronous == 0 && pipe_out == NO_PIPE && prev > 0)
-    {
-      lstdin = move_to_high_fd (0, 1, -1);
-      if (lstdin > 0)
-       {
-         do_piping (prev, pipe_out);
-         prev = NO_PIPE;
-         add_unwind_protect (restore_stdin, lstdin);
-         lastpipe_flag = 1;
-         freeze_jobs_list ();
-         lastpipe_jid = stop_pipeline (0, (COMMAND *)NULL);    /* XXX */
-         add_unwind_protect (lastpipe_cleanup, lastpipe_jid);
-       }
-      if (cmd)
-       cmd->flags |= CMD_LASTPIPE;
-    }    
-  if (prev >= 0)
-    add_unwind_protect (close, prev);
-
-  exec_result = execute_command_internal (cmd, asynchronous, prev, pipe_out, fds_to_close);
-
-  if (lstdin > 0)
-    restore_stdin (lstdin);
-
-  if (prev >= 0)
-    close (prev);
-
-#if defined (JOB_CONTROL)
-  UNBLOCK_CHILD (oset);
-#endif
-
-  QUIT;
-
-  if (lastpipe_flag)
-    {
-#if defined (JOB_CONTROL)
-      append_process (savestring (the_printed_command), dollar_dollar_pid, exec_result, lastpipe_jid);
-#endif
-      lstdin = wait_for (lastpid);
-#if defined (JOB_CONTROL)
-      exec_result = job_exit_status (lastpipe_jid);
-#endif
-      unfreeze_jobs_list ();
-    }
-
-  discard_unwind_frame ("lastpipe-exec");
-
-  return (exec_result);
-}
-
-static int
-execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close)
-     COMMAND *command;
-     int asynchronous, pipe_in, pipe_out;
-     struct fd_bitmap *fds_to_close;
-{
-  COMMAND *tc, *second;
-  int ignore_return, exec_result, was_error_trap, invert;
-  volatile int save_line_number;
-
-  ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
-
-  switch (command->value.Connection->connector)
-    {
-    /* Do the first command asynchronously. */
-    case '&':
-      tc = command->value.Connection->first;
-      if (tc == 0)
-       return (EXECUTION_SUCCESS);
-
-      if (ignore_return)
-       tc->flags |= CMD_IGNORE_RETURN;
-      tc->flags |= CMD_AMPERSAND;
-
-      /* If this shell was compiled without job control support,
-        if we are currently in a subshell via `( xxx )', or if job
-        control is not active then the standard input for an
-        asynchronous command is forced to /dev/null. */
-#if defined (JOB_CONTROL)
-      if ((subshell_environment || !job_control) && !stdin_redir)
-#else
-      if (!stdin_redir)
-#endif /* JOB_CONTROL */
-       tc->flags |= CMD_STDIN_REDIR;
-
-      exec_result = execute_command_internal (tc, 1, pipe_in, pipe_out, fds_to_close);
-      QUIT;
-
-      if (tc->flags & CMD_STDIN_REDIR)
-       tc->flags &= ~CMD_STDIN_REDIR;
-
-      second = command->value.Connection->second;
-      if (second)
-       {
-         if (ignore_return)
-           second->flags |= CMD_IGNORE_RETURN;
-
-         exec_result = execute_command_internal (second, asynchronous, pipe_in, pipe_out, fds_to_close);
-       }
-
-      break;
-
-    /* Just call execute command on both sides. */
-    case ';':
-      if (ignore_return)
-       {
-         if (command->value.Connection->first)
-           command->value.Connection->first->flags |= CMD_IGNORE_RETURN;
-         if (command->value.Connection->second)
-           command->value.Connection->second->flags |= CMD_IGNORE_RETURN;
-       }
-      executing_list++;
-      QUIT;
-      execute_command (command->value.Connection->first);
-      QUIT;
-      exec_result = execute_command_internal (command->value.Connection->second,
-                                     asynchronous, pipe_in, pipe_out,
-                                     fds_to_close);
-      executing_list--;
-      break;
-
-    case '|':
-      was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
-      invert = (command->flags & CMD_INVERT_RETURN) != 0;
-      ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
-
-      line_number_for_err_trap = line_number;
-      exec_result = execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close);
-
-      if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
-       {
-         last_command_exit_value = exec_result;
-         save_line_number = line_number;
-         line_number = line_number_for_err_trap;
-         run_error_trap ();
-         line_number = save_line_number;
-       }
-
-      if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
-       {
-         last_command_exit_value = exec_result;
-         run_pending_traps ();
-         jump_to_top_level (ERREXIT);
-       }
-
-      break;
-
-    case AND_AND:
-    case OR_OR:
-      if (asynchronous)
-       {
-         /* If we have something like `a && b &' or `a || b &', run the
-            && or || stuff in a subshell.  Force a subshell and just call
-            execute_command_internal again.  Leave asynchronous on
-            so that we get a report from the parent shell about the
-            background job. */
-         command->flags |= CMD_FORCE_SUBSHELL;
-         exec_result = execute_command_internal (command, 1, pipe_in, pipe_out, fds_to_close);
-         break;
-       }
-
-      /* Execute the first command.  If the result of that is successful
-        and the connector is AND_AND, or the result is not successful
-        and the connector is OR_OR, then execute the second command,
-        otherwise return. */
-
-      executing_list++;
-      if (command->value.Connection->first)
-       command->value.Connection->first->flags |= CMD_IGNORE_RETURN;
-
-      exec_result = execute_command (command->value.Connection->first);
-      QUIT;
-      if (((command->value.Connection->connector == AND_AND) &&
-          (exec_result == EXECUTION_SUCCESS)) ||
-         ((command->value.Connection->connector == OR_OR) &&
-          (exec_result != EXECUTION_SUCCESS)))
-       {
-         if (ignore_return && command->value.Connection->second)
-           command->value.Connection->second->flags |= CMD_IGNORE_RETURN;
-
-         exec_result = execute_command (command->value.Connection->second);
-       }
-      executing_list--;
-      break;
-
-    default:
-      command_error ("execute_connection", CMDERR_BADCONN, command->value.Connection->connector, 0);
-      jump_to_top_level (DISCARD);
-      exec_result = EXECUTION_FAILURE;
-    }
-
-  return exec_result;
-}
-
-#define REAP() \
-  do \
-    { \
-      if (!interactive_shell) \
-       reap_dead_jobs (); \
-    } \
-  while (0)
-
-/* Execute a FOR command.  The syntax is: FOR word_desc IN word_list;
-   DO command; DONE */
-static int
-execute_for_command (for_command)
-     FOR_COM *for_command;
-{
-  register WORD_LIST *releaser, *list;
-  SHELL_VAR *v;
-  char *identifier;
-  int retval, save_line_number;
-#if 0
-  SHELL_VAR *old_value = (SHELL_VAR *)NULL; /* Remember the old value of x. */
-#endif
-
-  save_line_number = line_number;
-  if (check_identifier (for_command->name, 1) == 0)
-    {
-      if (posixly_correct && interactive_shell == 0)
-       {
-         last_command_exit_value = EX_BADUSAGE;
-         jump_to_top_level (ERREXIT);
-       }
-      return (EXECUTION_FAILURE);
-    }
-
-  loop_level++;
-  identifier = for_command->name->word;
-
-  list = releaser = expand_words_no_vars (for_command->map_list);
-
-  begin_unwind_frame ("for");
-  add_unwind_protect (dispose_words, releaser);
-
-#if 0
-  if (lexical_scoping)
-    {
-      old_value = copy_variable (find_variable (identifier));
-      if (old_value)
-       add_unwind_protect (dispose_variable, old_value);
-    }
-#endif
-
-  if (for_command->flags & CMD_IGNORE_RETURN)
-    for_command->action->flags |= CMD_IGNORE_RETURN;
-
-  for (retval = EXECUTION_SUCCESS; list; list = list->next)
-    {
-      QUIT;
-
-      line_number = for_command->line;
-
-      /* Remember what this command looks like, for debugger. */
-      command_string_index = 0;
-      print_for_command_head (for_command);
-
-      if (echo_command_at_execute)
-       xtrace_print_for_command_head (for_command);
-
-      /* Save this command unless it's a trap command and we're not running
-        a debug trap. */
-      if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
-       {
-         FREE (the_printed_command_except_trap);
-         the_printed_command_except_trap = savestring (the_printed_command);
-       }
-
-      retval = run_debug_trap ();
-#if defined (DEBUGGER)
-      /* In debugging mode, if the DEBUG trap returns a non-zero status, we
-        skip the command. */
-      if (debugging_mode && retval != EXECUTION_SUCCESS)
-        continue;
-#endif
-
-      this_command_name = (char *)NULL;
-      /* XXX - special ksh93 for command index variable handling */
-      v = find_variable_last_nameref (identifier);
-      if (v && nameref_p (v))
-        {
-          v = bind_variable_value (v, list->word->word, 0);
-        }
-      else
-        v = bind_variable (identifier, list->word->word, 0);
-      if (readonly_p (v) || noassign_p (v))
-       {
-         line_number = save_line_number;
-         if (readonly_p (v) && interactive_shell == 0 && posixly_correct)
-           {
-             last_command_exit_value = EXECUTION_FAILURE;
-             jump_to_top_level (FORCE_EOF);
-           }
-         else
-           {
-             dispose_words (releaser);
-             discard_unwind_frame ("for");
-             loop_level--;
-             return (EXECUTION_FAILURE);
-           }
-       }
-      retval = execute_command (for_command->action);
-      REAP ();
-      QUIT;
-
-      if (breaking)
-       {
-         breaking--;
-         break;
-       }
-
-      if (continuing)
-       {
-         continuing--;
-         if (continuing)
-           break;
-       }
-    }
-
-  loop_level--;
-  line_number = save_line_number;
-
-#if 0
-  if (lexical_scoping)
-    {
-      if (!old_value)
-        unbind_variable (identifier);
-      else
-       {
-         SHELL_VAR *new_value;
-
-         new_value = bind_variable (identifier, value_cell(old_value), 0);
-         new_value->attributes = old_value->attributes;
-         dispose_variable (old_value);
-       }
-    }
-#endif
-
-  dispose_words (releaser);
-  discard_unwind_frame ("for");
-  return (retval);
-}
-
-#if defined (ARITH_FOR_COMMAND)
-/* Execute an arithmetic for command.  The syntax is
-
-       for (( init ; step ; test ))
-       do
-               body
-       done
-
-   The execution should be exactly equivalent to
-
-       eval \(\( init \)\)
-       while eval \(\( test \)\) ; do
-               body;
-               eval \(\( step \)\)
-       done
-*/
-static intmax_t
-eval_arith_for_expr (l, okp)
-     WORD_LIST *l;
-     int *okp;
-{
-  WORD_LIST *new;
-  intmax_t expresult;
-  int r;
-
-  new = expand_words_no_vars (l);
-  if (new)
-    {
-      if (echo_command_at_execute)
-       xtrace_print_arith_cmd (new);
-      this_command_name = "((";                /* )) for expression error messages */
-
-      command_string_index = 0;
-      print_arith_command (new);
-      if (signal_in_progress (DEBUG_TRAP) == 0)
-       {
-         FREE (the_printed_command_except_trap);
-         the_printed_command_except_trap = savestring (the_printed_command);
-       }
-
-      r = run_debug_trap ();
-      /* In debugging mode, if the DEBUG trap returns a non-zero status, we
-        skip the command. */
-#if defined (DEBUGGER)
-      if (debugging_mode == 0 || r == EXECUTION_SUCCESS)
-       expresult = evalexp (new->word->word, okp);
-      else
-       {
-         expresult = 0;
-         if (okp)
-           *okp = 1;
-       }
-#else
-      expresult = evalexp (new->word->word, okp);
-#endif
-      dispose_words (new);
-    }
-  else
-    {
-      expresult = 0;
-      if (okp)
-       *okp = 1;
-    }
-  return (expresult);
-}
-
-static int
-execute_arith_for_command (arith_for_command)
-     ARITH_FOR_COM *arith_for_command;
-{
-  intmax_t expresult;
-  int expok, body_status, arith_lineno, save_lineno;
-
-  body_status = EXECUTION_SUCCESS;
-  loop_level++;
-  save_lineno = line_number;
-
-  if (arith_for_command->flags & CMD_IGNORE_RETURN)
-    arith_for_command->action->flags |= CMD_IGNORE_RETURN;
-
-  this_command_name = "((";    /* )) for expression error messages */
-
-  /* save the starting line number of the command so we can reset
-     line_number before executing each expression -- for $LINENO
-     and the DEBUG trap. */
-  line_number = arith_lineno = arith_for_command->line;
-  if (variable_context && interactive_shell)
-    line_number -= function_line_number;
-
-  /* Evaluate the initialization expression. */
-  expresult = eval_arith_for_expr (arith_for_command->init, &expok);
-  if (expok == 0)
-    {
-      line_number = save_lineno;
-      return (EXECUTION_FAILURE);
-    }
-
-  while (1)
-    {
-      /* Evaluate the test expression. */
-      line_number = arith_lineno;
-      expresult = eval_arith_for_expr (arith_for_command->test, &expok);
-      line_number = save_lineno;
-
-      if (expok == 0)
-       {
-         body_status = EXECUTION_FAILURE;
-         break;
-       }
-      REAP ();
-      if (expresult == 0)
-       break;
-
-      /* Execute the body of the arithmetic for command. */
-      QUIT;
-      body_status = execute_command (arith_for_command->action);
-      QUIT;
-
-      /* Handle any `break' or `continue' commands executed by the body. */
-      if (breaking)
-       {
-         breaking--;
-         break;
-       }
-
-      if (continuing)
-       {
-         continuing--;
-         if (continuing)
-           break;
-       }
-
-      /* Evaluate the step expression. */
-      line_number = arith_lineno;
-      expresult = eval_arith_for_expr (arith_for_command->step, &expok);
-      line_number = save_lineno;
-
-      if (expok == 0)
-       {
-         body_status = EXECUTION_FAILURE;
-         break;
-       }
-    }
-
-  loop_level--;
-  line_number = save_lineno;
-
-  return (body_status);
-}
-#endif
-
-#if defined (SELECT_COMMAND)
-static int LINES, COLS, tabsize;
-
-#define RP_SPACE ") "
-#define RP_SPACE_LEN 2
-
-/* XXX - does not handle numbers > 1000000 at all. */
-#define NUMBER_LEN(s) \
-((s < 10) ? 1 \
-         : ((s < 100) ? 2 \
-                     : ((s < 1000) ? 3 \
-                                  : ((s < 10000) ? 4 \
-                                                : ((s < 100000) ? 5 \
-                                                               : 6)))))
-
-static int
-displen (s)
-     const char *s;
-{
-#if defined (HANDLE_MULTIBYTE)
-  wchar_t *wcstr;
-  size_t slen;
-  int wclen;
-
-  wcstr = 0;
-  slen = mbstowcs (wcstr, s, 0);
-  if (slen == -1)
-    slen = 0;
-  wcstr = (wchar_t *)xmalloc (sizeof (wchar_t) * (slen + 1));
-  mbstowcs (wcstr, s, slen + 1);
-  wclen = wcswidth (wcstr, slen);
-  free (wcstr);
-  return (wclen < 0 ? STRLEN(s) : wclen);
-#else
-  return (STRLEN (s));
-#endif
-}
-
-static int
-print_index_and_element (len, ind, list)
-      int len, ind;
-      WORD_LIST *list;
-{
-  register WORD_LIST *l;
-  register int i;
-
-  if (list == 0)
-    return (0);
-  for (i = ind, l = list; l && --i; l = l->next)
-    ;
-  if (l == 0)          /* don't think this can happen */
-    return (0);
-  fprintf (stderr, "%*d%s%s", len, ind, RP_SPACE, l->word->word);
-  return (displen (l->word->word));
-}
-
-static void
-indent (from, to)
-     int from, to;
-{
-  while (from < to)
-    {
-      if ((to / tabsize) > (from / tabsize))
-       {
-         putc ('\t', stderr);
-         from += tabsize - from % tabsize;
-       }
-      else
-       {
-         putc (' ', stderr);
-         from++;
-       }
-    }
-}
-
-static void
-print_select_list (list, list_len, max_elem_len, indices_len)
-     WORD_LIST *list;
-     int list_len, max_elem_len, indices_len;
-{
-  int ind, row, elem_len, pos, cols, rows;
-  int first_column_indices_len, other_indices_len;
-
-  if (list == 0)
-    {
-      putc ('\n', stderr);
-      return;
-    }
-
-  cols = max_elem_len ? COLS / max_elem_len : 1;
-  if (cols == 0)
-    cols = 1;
-  rows = list_len ? list_len / cols + (list_len % cols != 0) : 1;
-  cols = list_len ? list_len / rows + (list_len % rows != 0) : 1;
-
-  if (rows == 1)
-    {
-      rows = cols;
-      cols = 1;
-    }
-
-  first_column_indices_len = NUMBER_LEN (rows);
-  other_indices_len = indices_len;
-
-  for (row = 0; row < rows; row++)
-    {
-      ind = row;
-      pos = 0;
-      while (1)
-       {
-         indices_len = (pos == 0) ? first_column_indices_len : other_indices_len;
-         elem_len = print_index_and_element (indices_len, ind + 1, list);
-         elem_len += indices_len + RP_SPACE_LEN;
-         ind += rows;
-         if (ind >= list_len)
-           break;
-         indent (pos + elem_len, pos + max_elem_len);
-         pos += max_elem_len;
-       }
-      putc ('\n', stderr);
-    }
-}
-
-/* Print the elements of LIST, one per line, preceded by an index from 1 to
-   LIST_LEN.  Then display PROMPT and wait for the user to enter a number.
-   If the number is between 1 and LIST_LEN, return that selection.  If EOF
-   is read, return a null string.  If a blank line is entered, or an invalid
-   number is entered, the loop is executed again. */
-static char *
-select_query (list, list_len, prompt, print_menu)
-     WORD_LIST *list;
-     int list_len;
-     char *prompt;
-     int print_menu;
-{
-  int max_elem_len, indices_len, len;
-  intmax_t reply;
-  WORD_LIST *l;
-  char *repl_string, *t;
-
-#if 0
-  t = get_string_value ("LINES");
-  LINES = (t && *t) ? atoi (t) : 24;
-#endif
-  t = get_string_value ("COLUMNS");
-  COLS =  (t && *t) ? atoi (t) : 80;
-
-#if 0
-  t = get_string_value ("TABSIZE");
-  tabsize = (t && *t) ? atoi (t) : 8;
-  if (tabsize <= 0)
-    tabsize = 8;
-#else
-  tabsize = 8;
-#endif
-
-  max_elem_len = 0;
-  for (l = list; l; l = l->next)
-    {
-      len = displen (l->word->word);
-      if (len > max_elem_len)
-       max_elem_len = len;
-    }
-  indices_len = NUMBER_LEN (list_len);
-  max_elem_len += indices_len + RP_SPACE_LEN + 2;
-
-  while (1)
-    {
-      if (print_menu)
-       print_select_list (list, list_len, max_elem_len, indices_len);
-      fprintf (stderr, "%s", prompt);
-      fflush (stderr);
-      QUIT;
-
-      if (read_builtin ((WORD_LIST *)NULL) != EXECUTION_SUCCESS)
-       {
-         putchar ('\n');
-         return ((char *)NULL);
-       }
-      repl_string = get_string_value ("REPLY");
-      if (*repl_string == 0)
-       {
-         print_menu = 1;
-         continue;
-       }
-      if (legal_number (repl_string, &reply) == 0)
-       return "";
-      if (reply < 1 || reply > list_len)
-       return "";
-
-      for (l = list; l && --reply; l = l->next)
-       ;
-      return (l->word->word);          /* XXX - can't be null? */
-    }
-}
-
-/* Execute a SELECT command.  The syntax is:
-   SELECT word IN list DO command_list DONE
-   Only `break' or `return' in command_list will terminate
-   the command. */
-static int
-execute_select_command (select_command)
-     SELECT_COM *select_command;
-{
-  WORD_LIST *releaser, *list;
-  SHELL_VAR *v;
-  char *identifier, *ps3_prompt, *selection;
-  int retval, list_len, show_menu, save_line_number;
-
-  if (check_identifier (select_command->name, 1) == 0)
-    return (EXECUTION_FAILURE);
-
-  save_line_number = line_number;
-  line_number = select_command->line;
-
-  command_string_index = 0;
-  print_select_command_head (select_command);
-
-  if (echo_command_at_execute)
-    xtrace_print_select_command_head (select_command);
-
-#if 0
-  if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
-#else
-  if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
-#endif
-    {
-      FREE (the_printed_command_except_trap);
-      the_printed_command_except_trap = savestring (the_printed_command);
-    }
-
-  retval = run_debug_trap ();
-#if defined (DEBUGGER)
-  /* In debugging mode, if the DEBUG trap returns a non-zero status, we
-     skip the command. */
-  if (debugging_mode && retval != EXECUTION_SUCCESS)
-    return (EXECUTION_SUCCESS);
-#endif
-
-  loop_level++;
-  identifier = select_command->name->word;
-
-  /* command and arithmetic substitution, parameter and variable expansion,
-     word splitting, pathname expansion, and quote removal. */
-  list = releaser = expand_words_no_vars (select_command->map_list);
-  list_len = list_length (list);
-  if (list == 0 || list_len == 0)
-    {
-      if (list)
-       dispose_words (list);
-      line_number = save_line_number;
-      return (EXECUTION_SUCCESS);
-    }
-
-  begin_unwind_frame ("select");
-  add_unwind_protect (dispose_words, releaser);
-
-  if (select_command->flags & CMD_IGNORE_RETURN)
-    select_command->action->flags |= CMD_IGNORE_RETURN;
-
-  retval = EXECUTION_SUCCESS;
-  show_menu = 1;
-
-  while (1)
-    {
-      line_number = select_command->line;
-      ps3_prompt = get_string_value ("PS3");
-      if (ps3_prompt == 0)
-       ps3_prompt = "#? ";
-
-      QUIT;
-      selection = select_query (list, list_len, ps3_prompt, show_menu);
-      QUIT;
-      if (selection == 0)
-       {
-         /* select_query returns EXECUTION_FAILURE if the read builtin
-            fails, so we want to return failure in this case. */
-         retval = EXECUTION_FAILURE;
-         break;
-       }
-
-      v = bind_variable (identifier, selection, 0);
-      if (readonly_p (v) || noassign_p (v))
-       {
-         if (readonly_p (v) && interactive_shell == 0 && posixly_correct)
-           {
-             last_command_exit_value = EXECUTION_FAILURE;
-             jump_to_top_level (FORCE_EOF);
-           }
-         else
-           {
-             dispose_words (releaser);
-             discard_unwind_frame ("select");
-             loop_level--;
-             line_number = save_line_number;
-             return (EXECUTION_FAILURE);
-           }
-       }
-
-      retval = execute_command (select_command->action);
-
-      REAP ();
-      QUIT;
-
-      if (breaking)
-       {
-         breaking--;
-         break;
-       }
-
-      if (continuing)
-       {
-         continuing--;
-         if (continuing)
-           break;
-       }
-
-#if defined (KSH_COMPATIBLE_SELECT)
-      show_menu = 0;
-      selection = get_string_value ("REPLY");
-      if (selection && *selection == '\0')
-        show_menu = 1;
-#endif
-    }
-
-  loop_level--;
-  line_number = save_line_number;
-
-  dispose_words (releaser);
-  discard_unwind_frame ("select");
-  return (retval);
-}
-#endif /* SELECT_COMMAND */
-
-/* Execute a CASE command.  The syntax is: CASE word_desc IN pattern_list ESAC.
-   The pattern_list is a linked list of pattern clauses; each clause contains
-   some patterns to compare word_desc against, and an associated command to
-   execute. */
-static int
-execute_case_command (case_command)
-     CASE_COM *case_command;
-{
-  register WORD_LIST *list;
-  WORD_LIST *wlist, *es;
-  PATTERN_LIST *clauses;
-  char *word, *pattern;
-  int retval, match, ignore_return, save_line_number;
-
-  save_line_number = line_number;
-  line_number = case_command->line;
-
-  command_string_index = 0;
-  print_case_command_head (case_command);
-
-  if (echo_command_at_execute)
-    xtrace_print_case_command_head (case_command);
-
-#if 0
-  if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
-#else
-  if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
-#endif
-    {
-      FREE (the_printed_command_except_trap);
-      the_printed_command_except_trap = savestring (the_printed_command);
-    }
-
-  retval = run_debug_trap();
-#if defined (DEBUGGER)
-  /* In debugging mode, if the DEBUG trap returns a non-zero status, we
-     skip the command. */
-  if (debugging_mode && retval != EXECUTION_SUCCESS)
-    {
-      line_number = save_line_number;
-      return (EXECUTION_SUCCESS);
-    }
-#endif
-
-  wlist = expand_word_unsplit (case_command->word, 0);
-  word = wlist ? string_list (wlist) : savestring ("");
-  dispose_words (wlist);
-
-  retval = EXECUTION_SUCCESS;
-  ignore_return = case_command->flags & CMD_IGNORE_RETURN;
-
-  begin_unwind_frame ("case");
-  add_unwind_protect ((Function *)xfree, word);
-
-#define EXIT_CASE()  goto exit_case_command
-
-  for (clauses = case_command->clauses; clauses; clauses = clauses->next)
-    {
-      QUIT;
-      for (list = clauses->patterns; list; list = list->next)
-       {
-         es = expand_word_leave_quoted (list->word, 0);
-
-         if (es && es->word && es->word->word && *(es->word->word))
-           pattern = quote_string_for_globbing (es->word->word, QGLOB_CVTNULL);
-         else
-           {
-             pattern = (char *)xmalloc (1);
-             pattern[0] = '\0';
-           }
-
-         /* Since the pattern does not undergo quote removal (as per
-            Posix.2, section 3.9.4.3), the strmatch () call must be able
-            to recognize backslashes as escape characters. */
-         match = strmatch (pattern, word, FNMATCH_EXTFLAG|FNMATCH_IGNCASE) != FNM_NOMATCH;
-         free (pattern);
-
-         dispose_words (es);
-
-         if (match)
-           {
-             do
-               {
-                 if (clauses->action && ignore_return)
-                   clauses->action->flags |= CMD_IGNORE_RETURN;
-                 retval = execute_command (clauses->action);
-               }
-             while ((clauses->flags & CASEPAT_FALLTHROUGH) && (clauses = clauses->next));
-             if (clauses == 0 || (clauses->flags & CASEPAT_TESTNEXT) == 0)
-               EXIT_CASE ();
-             else
-               break;
-           }
-
-         QUIT;
-       }
-    }
-
-exit_case_command:
-  free (word);
-  discard_unwind_frame ("case");
-  line_number = save_line_number;
-  return (retval);
-}
-
-#define CMD_WHILE 0
-#define CMD_UNTIL 1
-
-/* The WHILE command.  Syntax: WHILE test DO action; DONE.
-   Repeatedly execute action while executing test produces
-   EXECUTION_SUCCESS. */
-static int
-execute_while_command (while_command)
-     WHILE_COM *while_command;
-{
-  return (execute_while_or_until (while_command, CMD_WHILE));
-}
-
-/* UNTIL is just like WHILE except that the test result is negated. */
-static int
-execute_until_command (while_command)
-     WHILE_COM *while_command;
-{
-  return (execute_while_or_until (while_command, CMD_UNTIL));
-}
-
-/* The body for both while and until.  The only difference between the
-   two is that the test value is treated differently.  TYPE is
-   CMD_WHILE or CMD_UNTIL.  The return value for both commands should
-   be EXECUTION_SUCCESS if no commands in the body are executed, and
-   the status of the last command executed in the body otherwise. */
-static int
-execute_while_or_until (while_command, type)
-     WHILE_COM *while_command;
-     int type;
-{
-  int return_value, body_status;
-
-  body_status = EXECUTION_SUCCESS;
-  loop_level++;
-
-  while_command->test->flags |= CMD_IGNORE_RETURN;
-  if (while_command->flags & CMD_IGNORE_RETURN)
-    while_command->action->flags |= CMD_IGNORE_RETURN;
-
-  while (1)
-    {
-      return_value = execute_command (while_command->test);
-      REAP ();
-
-      /* Need to handle `break' in the test when we would break out of the
-         loop.  The job control code will set `breaking' to loop_level
-         when a job in a loop is stopped with SIGTSTP.  If the stopped job
-         is in the loop test, `breaking' will not be reset unless we do
-         this, and the shell will cease to execute commands. */
-      if (type == CMD_WHILE && return_value != EXECUTION_SUCCESS)
-       {
-         if (breaking)
-           breaking--;
-         break;
-       }
-      if (type == CMD_UNTIL && return_value == EXECUTION_SUCCESS)
-       {
-         if (breaking)
-           breaking--;
-         break;
-       }
-
-      QUIT;
-      body_status = execute_command (while_command->action);
-      QUIT;
-
-      if (breaking)
-       {
-         breaking--;
-         break;
-       }
-
-      if (continuing)
-       {
-         continuing--;
-         if (continuing)
-           break;
-       }
-    }
-  loop_level--;
-
-  return (body_status);
-}
-
-/* IF test THEN command [ELSE command].
-   IF also allows ELIF in the place of ELSE IF, but
-   the parser makes *that* stupidity transparent. */
-static int
-execute_if_command (if_command)
-     IF_COM *if_command;
-{
-  int return_value, save_line_number;
-
-  save_line_number = line_number;
-  if_command->test->flags |= CMD_IGNORE_RETURN;
-  return_value = execute_command (if_command->test);
-  line_number = save_line_number;
-
-  if (return_value == EXECUTION_SUCCESS)
-    {
-      QUIT;
-
-      if (if_command->true_case && (if_command->flags & CMD_IGNORE_RETURN))
-       if_command->true_case->flags |= CMD_IGNORE_RETURN;
-
-      return (execute_command (if_command->true_case));
-    }
-  else
-    {
-      QUIT;
-
-      if (if_command->false_case && (if_command->flags & CMD_IGNORE_RETURN))
-       if_command->false_case->flags |= CMD_IGNORE_RETURN;
-
-      return (execute_command (if_command->false_case));
-    }
-}
-
-#if defined (DPAREN_ARITHMETIC)
-static int
-execute_arith_command (arith_command)
-     ARITH_COM *arith_command;
-{
-  int expok, save_line_number, retval;
-  intmax_t expresult;
-  WORD_LIST *new;
-  char *exp;
-
-  expresult = 0;
-
-  save_line_number = line_number;
-  this_command_name = "((";    /* )) */
-  line_number = arith_command->line;
-  /* If we're in a function, update the line number information. */
-  if (variable_context && interactive_shell)
-    line_number -= function_line_number;
-
-  command_string_index = 0;
-  print_arith_command (arith_command->exp);
-
-  if (signal_in_progress (DEBUG_TRAP) == 0)
-    {
-      FREE (the_printed_command_except_trap);
-      the_printed_command_except_trap = savestring (the_printed_command);
-    }
-
-  /* Run the debug trap before each arithmetic command, but do it after we
-     update the line number information and before we expand the various
-     words in the expression. */
-  retval = run_debug_trap ();
-#if defined (DEBUGGER)
-  /* In debugging mode, if the DEBUG trap returns a non-zero status, we
-     skip the command. */
-  if (debugging_mode && retval != EXECUTION_SUCCESS)
-    {
-      line_number = save_line_number;
-      return (EXECUTION_SUCCESS);
-    }
-#endif
-
-  new = expand_words_no_vars (arith_command->exp);
-
-  /* If we're tracing, make a new word list with `((' at the front and `))'
-     at the back and print it. */
-  if (echo_command_at_execute)
-    xtrace_print_arith_cmd (new);
-
-  if (new)
-    {
-      exp = new->next ? string_list (new) : new->word->word;
-      expresult = evalexp (exp, &expok);
-      line_number = save_line_number;
-      if (exp != new->word->word)
-       free (exp);
-      dispose_words (new);
-    }
-  else
-    {
-      expresult = 0;
-      expok = 1;
-    }
-
-  if (expok == 0)
-    return (EXECUTION_FAILURE);
-
-  return (expresult == 0 ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
-}
-#endif /* DPAREN_ARITHMETIC */
-
-#if defined (COND_COMMAND)
-
-static char * const nullstr = "";
-
-/* XXX - can COND ever be NULL when this is called? */
-static int
-execute_cond_node (cond)
-     COND_COM *cond;
-{
-  int result, invert, patmatch, rmatch, mflags, ignore;
-  char *arg1, *arg2;
-
-  invert = (cond->flags & CMD_INVERT_RETURN);
-  ignore = (cond->flags & CMD_IGNORE_RETURN);
-  if (ignore)
-    {
-      if (cond->left)
-       cond->left->flags |= CMD_IGNORE_RETURN;
-      if (cond->right)
-       cond->right->flags |= CMD_IGNORE_RETURN;
-    }
-      
-  if (cond->type == COND_EXPR)
-    result = execute_cond_node (cond->left);
-  else if (cond->type == COND_OR)
-    {
-      result = execute_cond_node (cond->left);
-      if (result != EXECUTION_SUCCESS)
-       result = execute_cond_node (cond->right);
-    }
-  else if (cond->type == COND_AND)
-    {
-      result = execute_cond_node (cond->left);
-      if (result == EXECUTION_SUCCESS)
-       result = execute_cond_node (cond->right);
-    }
-  else if (cond->type == COND_UNARY)
-    {
-      if (ignore)
-       comsub_ignore_return++;
-      arg1 = cond_expand_word (cond->left->op, 0);
-      if (ignore)
-       comsub_ignore_return--;
-      if (arg1 == 0)
-       arg1 = nullstr;
-      if (echo_command_at_execute)
-       xtrace_print_cond_term (cond->type, invert, cond->op, arg1, (char *)NULL);
-      result = unary_test (cond->op->word, arg1) ? EXECUTION_SUCCESS : EXECUTION_FAILURE;
-      if (arg1 != nullstr)
-       free (arg1);
-    }
-  else if (cond->type == COND_BINARY)
-    {
-      rmatch = 0;
-      patmatch = (((cond->op->word[1] == '=') && (cond->op->word[2] == '\0') &&
-                  (cond->op->word[0] == '!' || cond->op->word[0] == '=')) ||
-                 (cond->op->word[0] == '=' && cond->op->word[1] == '\0'));
-#if defined (COND_REGEXP)
-      rmatch = (cond->op->word[0] == '=' && cond->op->word[1] == '~' &&
-               cond->op->word[2] == '\0');
-#endif
-
-      if (ignore)
-       comsub_ignore_return++;
-      arg1 = cond_expand_word (cond->left->op, 0);
-      if (ignore)
-       comsub_ignore_return--;
-      if (arg1 == 0)
-       arg1 = nullstr;
-      if (ignore)
-       comsub_ignore_return++;
-      arg2 = cond_expand_word (cond->right->op,
-                              (rmatch && shell_compatibility_level > 31) ? 2 : (patmatch ? 1 : 0));
-      if (ignore)
-       comsub_ignore_return--;
-      if (arg2 == 0)
-       arg2 = nullstr;
-
-      if (echo_command_at_execute)
-       xtrace_print_cond_term (cond->type, invert, cond->op, arg1, arg2);
-
-#if defined (COND_REGEXP)
-      if (rmatch)
-       {
-         mflags = SHMAT_PWARN;
-#if defined (ARRAY_VARS)
-         mflags |= SHMAT_SUBEXP;
-#endif
-
-         result = sh_regmatch (arg1, arg2, mflags);
-       }
-      else
-#endif /* COND_REGEXP */
-       {
-         int oe;
-         oe = extended_glob;
-         extended_glob = 1;
-         result = binary_test (cond->op->word, arg1, arg2, TEST_PATMATCH|TEST_ARITHEXP|TEST_LOCALE)
-                                 ? EXECUTION_SUCCESS
-                                 : EXECUTION_FAILURE;
-         extended_glob = oe;
-       }
-      if (arg1 != nullstr)
-       free (arg1);
-      if (arg2 != nullstr)
-       free (arg2);
-    }
-  else
-    {
-      command_error ("execute_cond_node", CMDERR_BADTYPE, cond->type, 0);
-      jump_to_top_level (DISCARD);
-      result = EXECUTION_FAILURE;
-    }
-
-  if (invert)
-    result = (result == EXECUTION_SUCCESS) ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
-
-  return result;
-}
-
-static int
-execute_cond_command (cond_command)
-     COND_COM *cond_command;
-{
-  int retval, save_line_number;
-
-  retval = EXECUTION_SUCCESS;
-  save_line_number = line_number;
-
-  this_command_name = "[[";
-  line_number = cond_command->line;
-  /* If we're in a function, update the line number information. */
-  if (variable_context && interactive_shell)
-    line_number -= function_line_number;
-  command_string_index = 0;
-  print_cond_command (cond_command);
-
-  if (signal_in_progress (DEBUG_TRAP) == 0)
-    {
-      FREE (the_printed_command_except_trap);
-      the_printed_command_except_trap = savestring (the_printed_command);
-    }
-
-  /* Run the debug trap before each conditional command, but do it after we
-     update the line number information. */
-  retval = run_debug_trap ();
-#if defined (DEBUGGER)
-  /* In debugging mode, if the DEBUG trap returns a non-zero status, we
-     skip the command. */
-  if (debugging_mode && retval != EXECUTION_SUCCESS)
-    {
-      line_number = save_line_number;
-      return (EXECUTION_SUCCESS);
-    }
-#endif
-
-#if 0
-  debug_print_cond_command (cond_command);
-#endif
-
-  last_command_exit_value = retval = execute_cond_node (cond_command);
-  line_number = save_line_number;
-  return (retval);
-}
-#endif /* COND_COMMAND */
-
-static void
-bind_lastarg (arg)
-     char *arg;
-{
-  SHELL_VAR *var;
-
-  if (arg == 0)
-    arg = "";
-  var = bind_variable ("_", arg, 0);
-  VUNSETATTR (var, att_exported);
-}
-
-/* Execute a null command.  Fork a subshell if the command uses pipes or is
-   to be run asynchronously.  This handles all the side effects that are
-   supposed to take place. */
-static int
-execute_null_command (redirects, pipe_in, pipe_out, async)
-     REDIRECT *redirects;
-     int pipe_in, pipe_out, async;
-{
-  int r;
-  int forcefork;
-  REDIRECT *rd;
-
-  for (forcefork = 0, rd = redirects; rd; rd = rd->next)
-    forcefork += rd->rflags & REDIR_VARASSIGN;
-
-  if (forcefork || pipe_in != NO_PIPE || pipe_out != NO_PIPE || async)
-    {
-      /* We have a null command, but we really want a subshell to take
-        care of it.  Just fork, do piping and redirections, and exit. */
-      if (make_child ((char *)NULL, async) == 0)
-       {
-         /* Cancel traps, in trap.c. */
-         restore_original_signals ();          /* XXX */
-
-         do_piping (pipe_in, pipe_out);
-
-#if defined (COPROCESS_SUPPORT)
-         coproc_closeall ();
-#endif
-
-         subshell_environment = 0;
-         if (async)
-           subshell_environment |= SUBSHELL_ASYNC;
-         if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
-           subshell_environment |= SUBSHELL_PIPE;
-
-         if (do_redirections (redirects, RX_ACTIVE) == 0)
-           exit (EXECUTION_SUCCESS);
-         else
-           exit (EXECUTION_FAILURE);
-       }
-      else
-       {
-         close_pipes (pipe_in, pipe_out);
-#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
-         if (pipe_out == NO_PIPE)
-           unlink_fifo_list ();
-#endif
-         return (EXECUTION_SUCCESS);
-       }
-    }
-  else
-    {
-      /* Even if there aren't any command names, pretend to do the
-        redirections that are specified.  The user expects the side
-        effects to take place.  If the redirections fail, then return
-        failure.  Otherwise, if a command substitution took place while
-        expanding the command or a redirection, return the value of that
-        substitution.  Otherwise, return EXECUTION_SUCCESS. */
-
-      r = do_redirections (redirects, RX_ACTIVE|RX_UNDOABLE);
-      cleanup_redirects (redirection_undo_list);
-      redirection_undo_list = (REDIRECT *)NULL;
-
-      if (r != 0)
-       return (EXECUTION_FAILURE);
-      else if (last_command_subst_pid != NO_PID)
-       return (last_command_exit_value);
-      else
-       return (EXECUTION_SUCCESS);
-    }
-}
-
-/* This is a hack to suppress word splitting for assignment statements
-   given as arguments to builtins with the ASSIGNMENT_BUILTIN flag set. */
-static void
-fix_assignment_words (words)
-     WORD_LIST *words;
-{
-  WORD_LIST *w, *wcmd;
-  struct builtin *b;
-  int assoc, global, array;
-
-  if (words == 0)
-    return;
-
-  b = 0;
-  assoc = global = array = 0;
-
-  wcmd = words;
-  for (w = words; w; w = w->next)
-    if (w->word->flags & W_ASSIGNMENT)
-      {
-       if (b == 0)
-         {
-           /* Posix (post-2008) says that `command' doesn't change whether
-              or not the builtin it shadows is a `declaration command', even
-              though it removes other special builtin properties.  In Posix
-              mode, we skip over one or more instances of `command' and
-              deal with the next word as the assignment builtin. */
-           while (posixly_correct && wcmd && wcmd->word && wcmd->word->word && STREQ (wcmd->word->word, "command"))
-             wcmd = wcmd->next;
-           b = builtin_address_internal (wcmd->word->word, 0);
-           if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
-             return;
-           else if (b && (b->flags & ASSIGNMENT_BUILTIN))
-             wcmd->word->flags |= W_ASSNBLTIN;
-         }
-       w->word->flags |= (W_NOSPLIT|W_NOGLOB|W_TILDEEXP|W_ASSIGNARG);
-#if defined (ARRAY_VARS)
-       if (assoc)
-         w->word->flags |= W_ASSIGNASSOC;
-       if (array)
-         w->word->flags |= W_ASSIGNARRAY;
-#endif
-       if (global)
-         w->word->flags |= W_ASSNGLOBAL;
-      }
-#if defined (ARRAY_VARS)
-    /* Note that we saw an associative array option to a builtin that takes
-       assignment statements.  This is a bit of a kludge. */
-    else if (w->word->word[0] == '-' && (strchr (w->word->word+1, 'A') || strchr (w->word->word+1, 'a') || strchr (w->word->word+1, 'g')))
-#else
-    else if (w->word->word[0] == '-' && strchr (w->word->word+1, 'g'))
-#endif
-      {
-       if (b == 0)
-         {
-           while (posixly_correct && wcmd && wcmd->word && wcmd->word->word && STREQ (wcmd->word->word, "command"))
-             wcmd = wcmd->next;
-           b = builtin_address_internal (wcmd->word->word, 0);
-           if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
-             return;
-           else if (b && (b->flags & ASSIGNMENT_BUILTIN))
-             wcmd->word->flags |= W_ASSNBLTIN;
-         }
-       if ((wcmd->word->flags & W_ASSNBLTIN) && strchr (w->word->word+1, 'A'))
-         assoc = 1;
-       else if ((wcmd->word->flags & W_ASSNBLTIN) && strchr (w->word->word+1, 'a'))
-         array = 1;
-       if ((wcmd->word->flags & W_ASSNBLTIN) && strchr (w->word->word+1, 'g'))
-         global = 1;
-      }
-}
-
-/* Return 1 if the file found by searching $PATH for PATHNAME, defaulting
-   to PATHNAME, is a directory.  Used by the autocd code below. */
-static int
-is_dirname (pathname)
-     char *pathname;
-{
-  char *temp;
-  int ret;
-
-  temp = search_for_command (pathname, 0);
-  ret = (temp ? file_isdir (temp) : file_isdir (pathname));
-  free (temp);
-  return ret;
-}
-
-/* The meaty part of all the executions.  We have to start hacking the
-   real execution of commands here.  Fork a process, set things up,
-   execute the command. */
-static int
-execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
-     SIMPLE_COM *simple_command;
-     int pipe_in, pipe_out, async;
-     struct fd_bitmap *fds_to_close;
-{
-  WORD_LIST *words, *lastword;
-  char *command_line, *lastarg, *temp;
-  int first_word_quoted, result, builtin_is_special, already_forked, dofork;
-  pid_t old_last_async_pid;
-  sh_builtin_func_t *builtin;
-  SHELL_VAR *func;
-  volatile int old_builtin, old_command_builtin;
-
-  result = EXECUTION_SUCCESS;
-  special_builtin_failed = builtin_is_special = 0;
-  command_line = (char *)0;
-
-  QUIT;
-
-  /* If we're in a function, update the line number information. */
-  if (variable_context && interactive_shell && sourcelevel == 0)
-    line_number -= function_line_number;
-
-  /* Remember what this command line looks like at invocation. */
-  command_string_index = 0;
-  print_simple_command (simple_command);
-
-#if 0
-  if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
-#else
-  if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
-#endif
-    {
-      FREE (the_printed_command_except_trap);
-      the_printed_command_except_trap = the_printed_command ? savestring (the_printed_command) : (char *)0;
-    }
-
-  /* Run the debug trap before each simple command, but do it after we
-     update the line number information. */
-  result = run_debug_trap ();
-#if defined (DEBUGGER)
-  /* In debugging mode, if the DEBUG trap returns a non-zero status, we
-     skip the command. */
-  if (debugging_mode && result != EXECUTION_SUCCESS)
-    return (EXECUTION_SUCCESS);
-#endif
-
-  first_word_quoted =
-    simple_command->words ? (simple_command->words->word->flags & W_QUOTED) : 0;
-
-  last_command_subst_pid = NO_PID;
-  old_last_async_pid = last_asynchronous_pid;
-
-  already_forked = dofork = 0;
-
-  /* If we're in a pipeline or run in the background, set DOFORK so we
-     make the child early, before word expansion.  This keeps assignment
-     statements from affecting the parent shell's environment when they
-     should not. */
-  dofork = pipe_in != NO_PIPE || pipe_out != NO_PIPE || async;
-
-  /* Something like `%2 &' should restart job 2 in the background, not cause
-     the shell to fork here. */
-  if (dofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE &&
-       simple_command->words && simple_command->words->word &&
-       simple_command->words->word->word &&
-       (simple_command->words->word->word[0] == '%'))
-    dofork = 0;
-
-  if (dofork)
-    {
-      /* Do this now, because execute_disk_command will do it anyway in the
-        vast majority of cases. */
-      maybe_make_export_env ();
-
-      /* Don't let a DEBUG trap overwrite the command string to be saved with
-        the process/job associated with this child. */
-      if (make_child (savestring (the_printed_command_except_trap), async) == 0)
-       {
-         already_forked = 1;
-         simple_command->flags |= CMD_NO_FORK;
-
-         subshell_environment = SUBSHELL_FORK;
-         if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
-           subshell_environment |= SUBSHELL_PIPE;
-         if (async)
-           subshell_environment |= SUBSHELL_ASYNC;
-
-         /* We need to do this before piping to handle some really
-            pathological cases where one of the pipe file descriptors
-            is < 2. */
-         if (fds_to_close)
-           close_fd_bitmap (fds_to_close);
-
-         do_piping (pipe_in, pipe_out);
-         pipe_in = pipe_out = NO_PIPE;
-#if defined (COPROCESS_SUPPORT)
-         coproc_closeall ();
-#endif
-
-         last_asynchronous_pid = old_last_async_pid;
-       }
-      else
-       {
-         /* Don't let simple commands that aren't the last command in a
-            pipeline change $? for the rest of the pipeline (or at all). */
-         if (pipe_out != NO_PIPE)
-           result = last_command_exit_value;
-         close_pipes (pipe_in, pipe_out);
-#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
-         /* Close /dev/fd file descriptors in the parent after forking the
-            last child in a (possibly one-element) pipeline. */
-         if (pipe_out == NO_PIPE)              /* XXX */
-           unlink_fifo_list ();                /* XXX */
-#endif
-         command_line = (char *)NULL;      /* don't free this. */
-         bind_lastarg ((char *)NULL);
-         return (result);
-       }
-    }
-
-  /* If we are re-running this as the result of executing the `command'
-     builtin, do not expand the command words a second time. */
-  if ((simple_command->flags & CMD_INHIBIT_EXPANSION) == 0)
-    {
-      current_fds_to_close = fds_to_close;
-      fix_assignment_words (simple_command->words);
-      /* Pass the ignore return flag down to command substitutions */
-      if (simple_command->flags & CMD_IGNORE_RETURN)   /* XXX */
-       comsub_ignore_return++;
-      words = expand_words (simple_command->words);
-      if (simple_command->flags & CMD_IGNORE_RETURN)
-       comsub_ignore_return--;
-      current_fds_to_close = (struct fd_bitmap *)NULL;
-    }
-  else
-    words = copy_word_list (simple_command->words);
-
-  /* It is possible for WORDS not to have anything left in it.
-     Perhaps all the words consisted of `$foo', and there was
-     no variable `$foo'. */
-  if (words == 0)
-    {
-      this_command_name = 0;
-      result = execute_null_command (simple_command->redirects,
-                                    pipe_in, pipe_out,
-                                    already_forked ? 0 : async);
-      if (already_forked)
-       exit (result);
-      else
-       {
-         bind_lastarg ((char *)NULL);
-         set_pipestatus_from_exit (result);
-         return (result);
-       }
-    }
-
-  lastarg = (char *)NULL;
-
-  begin_unwind_frame ("simple-command");
-
-  if (echo_command_at_execute)
-    xtrace_print_word_list (words, 1);
-
-  builtin = (sh_builtin_func_t *)NULL;
-  func = (SHELL_VAR *)NULL;
-  if ((simple_command->flags & CMD_NO_FUNCTIONS) == 0)
-    {
-      /* Posix.2 says special builtins are found before functions.  We
-        don't set builtin_is_special anywhere other than here, because
-        this path is followed only when the `command' builtin is *not*
-        being used, and we don't want to exit the shell if a special
-        builtin executed with `command builtin' fails.  `command' is not
-        a special builtin. */
-      if (posixly_correct)
-       {
-         builtin = find_special_builtin (words->word->word);
-         if (builtin)
-           builtin_is_special = 1;
-       }
-      if (builtin == 0)
-       func = find_function (words->word->word);
-    }
-
-  /* In POSIX mode, assignment errors in the temporary environment cause a
-     non-interactive shell to exit. */
-  if (builtin_is_special && interactive_shell == 0 && tempenv_assign_error)
-    {
-      last_command_exit_value = EXECUTION_FAILURE;
-      jump_to_top_level (ERREXIT);
-    }
-  tempenv_assign_error = 0;    /* don't care about this any more */
-
-  add_unwind_protect (dispose_words, words);
-  QUIT;
-
-  /* Bind the last word in this command to "$_" after execution. */
-  for (lastword = words; lastword->next; lastword = lastword->next)
-    ;
-  lastarg = lastword->word->word;
-
-#if defined (JOB_CONTROL)
-  /* Is this command a job control related thing? */
-  if (words->word->word[0] == '%' && already_forked == 0)
-    {
-      this_command_name = async ? "bg" : "fg";
-      last_shell_builtin = this_shell_builtin;
-      this_shell_builtin = builtin_address (this_command_name);
-      result = (*this_shell_builtin) (words);
-      goto return_result;
-    }
-
-  /* One other possiblilty.  The user may want to resume an existing job.
-     If they do, find out whether this word is a candidate for a running
-     job. */
-  if (job_control && already_forked == 0 && async == 0 &&
-       !first_word_quoted &&
-       !words->next &&
-       words->word->word[0] &&
-       !simple_command->redirects &&
-       pipe_in == NO_PIPE &&
-       pipe_out == NO_PIPE &&
-       (temp = get_string_value ("auto_resume")))
-    {
-      int job, jflags, started_status;
-
-      jflags = JM_STOPPED|JM_FIRSTMATCH;
-      if (STREQ (temp, "exact"))
-       jflags |= JM_EXACT;
-      else if (STREQ (temp, "substring"))
-       jflags |= JM_SUBSTRING;
-      else
-       jflags |= JM_PREFIX;
-      job = get_job_by_name (words->word->word, jflags);
-      if (job != NO_JOB)
-       {
-         run_unwind_frame ("simple-command");
-         this_command_name = "fg";
-         last_shell_builtin = this_shell_builtin;
-         this_shell_builtin = builtin_address ("fg");
-
-         started_status = start_job (job, 1);
-         return ((started_status < 0) ? EXECUTION_FAILURE : started_status);
-       }
-    }
-#endif /* JOB_CONTROL */
-
-run_builtin:
-  /* Remember the name of this command globally. */
-  this_command_name = words->word->word;
-
-  QUIT;
-
-  /* This command could be a shell builtin or a user-defined function.
-     We have already found special builtins by this time, so we do not
-     set builtin_is_special.  If this is a function or builtin, and we
-     have pipes, then fork a subshell in here.  Otherwise, just execute
-     the command directly. */
-  if (func == 0 && builtin == 0)
-    builtin = find_shell_builtin (this_command_name);
-
-  last_shell_builtin = this_shell_builtin;
-  this_shell_builtin = builtin;
-
-  if (builtin || func)
-    {
-      if (builtin)
-        {
-         old_builtin = executing_builtin;
-         old_command_builtin = executing_command_builtin;
-         unwind_protect_int (executing_builtin);       /* modified in execute_builtin */
-         unwind_protect_int (executing_command_builtin);       /* ditto */
-        }
-      if (already_forked)
-       {
-         /* reset_terminating_signals (); */   /* XXX */
-         /* Reset the signal handlers in the child, but don't free the
-            trap strings.  Set a flag noting that we have to free the
-            trap strings if we run trap to change a signal disposition. */
-         reset_signal_handlers ();
-         subshell_environment |= SUBSHELL_RESETTRAP;
-
-         if (async)
-           {
-             if ((simple_command->flags & CMD_STDIN_REDIR) &&
-                   pipe_in == NO_PIPE &&
-                   (stdin_redirects (simple_command->redirects) == 0))
-               async_redirect_stdin ();
-             setup_async_signals ();
-           }
-
-         subshell_level++;
-         execute_subshell_builtin_or_function
-           (words, simple_command->redirects, builtin, func,
-            pipe_in, pipe_out, async, fds_to_close,
-            simple_command->flags);
-         subshell_level--;
-       }
-      else
-       {
-         result = execute_builtin_or_function
-           (words, builtin, func, simple_command->redirects, fds_to_close,
-            simple_command->flags);
-         if (builtin)
-           {
-             if (result > EX_SHERRBASE)
-               {
-                 result = builtin_status (result);
-                 if (builtin_is_special)
-                   special_builtin_failed = 1;
-               }
-             /* In POSIX mode, if there are assignment statements preceding
-                a special builtin, they persist after the builtin
-                completes. */
-             if (posixly_correct && builtin_is_special && temporary_env)
-               merge_temporary_env ();
-           }
-         else          /* function */
-           {
-             if (result == EX_USAGE)
-               result = EX_BADUSAGE;
-             else if (result > EX_SHERRBASE)
-               result = EXECUTION_FAILURE;
-           }
-
-         set_pipestatus_from_exit (result);
-
-         goto return_result;
-       }
-    }
-
-  if (autocd && interactive && words->word && is_dirname (words->word->word))
-    {
-      words = make_word_list (make_word ("cd"), words);
-      xtrace_print_word_list (words, 0);
-      goto run_builtin;
-    }
-
-  if (command_line == 0)
-    command_line = savestring (the_printed_command_except_trap ? the_printed_command_except_trap : "");
-
-#if defined (PROCESS_SUBSTITUTION)
-  if ((subshell_environment & SUBSHELL_COMSUB) && (simple_command->flags & CMD_NO_FORK) && fifos_pending() > 0)
-    simple_command->flags &= ~CMD_NO_FORK;
-#endif
-
-  result = execute_disk_command (words, simple_command->redirects, command_line,
-                       pipe_in, pipe_out, async, fds_to_close,
-                       simple_command->flags);
-
- return_result:
-  bind_lastarg (lastarg);
-  FREE (command_line);
-  dispose_words (words);
-  if (builtin)
-    {
-      executing_builtin = old_builtin;
-      executing_command_builtin = old_command_builtin;
-    }
-  discard_unwind_frame ("simple-command");
-  this_command_name = (char *)NULL;    /* points to freed memory now */
-  return (result);
-}
-
-/* Translate the special builtin exit statuses.  We don't really need a
-   function for this; it's a placeholder for future work. */
-static int
-builtin_status (result)
-     int result;
-{
-  int r;
-
-  switch (result)
-    {
-    case EX_USAGE:
-      r = EX_BADUSAGE;
-      break;
-    case EX_REDIRFAIL:
-    case EX_BADSYNTAX:
-    case EX_BADASSIGN:
-    case EX_EXPFAIL:
-      r = EXECUTION_FAILURE;
-      break;
-    default:
-      r = EXECUTION_SUCCESS;
-      break;
-    }
-  return (r);
-}
-
-static int
-execute_builtin (builtin, words, flags, subshell)
-     sh_builtin_func_t *builtin;
-     WORD_LIST *words;
-     int flags, subshell;
-{
-  int old_e_flag, result, eval_unwind;
-  int isbltinenv;
-  char *error_trap;
-
-  error_trap = 0;
-  old_e_flag = exit_immediately_on_error;
-  
-  /* The eval builtin calls parse_and_execute, which does not know about
-     the setting of flags, and always calls the execution functions with
-     flags that will exit the shell on an error if -e is set.  If the
-     eval builtin is being called, and we're supposed to ignore the exit
-     value of the command, we turn the -e flag off ourselves and disable
-     the ERR trap, then restore them when the command completes.  This is
-     also a problem (as below) for the command and source/. builtins. */
-  if (subshell == 0 && (flags & CMD_IGNORE_RETURN) &&
-       (builtin == eval_builtin || builtin == command_builtin || builtin == source_builtin))
-    {
-      begin_unwind_frame ("eval_builtin");
-      unwind_protect_int (exit_immediately_on_error);
-      unwind_protect_int (builtin_ignoring_errexit);
-      error_trap = TRAP_STRING (ERROR_TRAP);
-      if (error_trap)
-       {
-         error_trap = savestring (error_trap);
-         add_unwind_protect (xfree, error_trap);
-         add_unwind_protect (set_error_trap, error_trap);
-         restore_default_signal (ERROR_TRAP);
-       }
-      exit_immediately_on_error = 0;
-      builtin_ignoring_errexit = 1;
-      eval_unwind = 1;
-    }
-  else
-    eval_unwind = 0;
-
-  /* The temporary environment for a builtin is supposed to apply to
-     all commands executed by that builtin.  Currently, this is a
-     problem only with the `unset', `source' and `eval' builtins.
-     `mapfile' is a special case because it uses evalstring (same as
-     eval or source) to run its callbacks. */
-  isbltinenv = (builtin == source_builtin || builtin == eval_builtin || builtin == unset_builtin || builtin == mapfile_builtin);
-
-  if (isbltinenv)
-    {
-      if (subshell == 0)
-       begin_unwind_frame ("builtin_env");
-
-      if (temporary_env)
-       {
-         push_scope (VC_BLTNENV, temporary_env);
-         if (subshell == 0)
-           add_unwind_protect (pop_scope, (flags & CMD_COMMAND_BUILTIN) ? 0 : "1");
-          temporary_env = (HASH_TABLE *)NULL;    
-       }
-    }
-
-  /* `return' does a longjmp() back to a saved environment in execute_function.
-     If a variable assignment list preceded the command, and the shell is
-     running in POSIX mode, we need to merge that into the shell_variables
-     table, since `return' is a POSIX special builtin. */
-  if (posixly_correct && subshell == 0 && builtin == return_builtin && temporary_env)
-    {
-      begin_unwind_frame ("return_temp_env");
-      add_unwind_protect (merge_temporary_env, (char *)NULL);
-    }
-
-  executing_builtin++;
-  executing_command_builtin |= builtin == command_builtin;
-  result = ((*builtin) (words->next));
-
-  /* This shouldn't happen, but in case `return' comes back instead of
-     longjmp'ing, we need to unwind. */
-  if (posixly_correct && subshell == 0 && builtin == return_builtin && temporary_env)
-    discard_unwind_frame ("return_temp_env");
-
-  if (subshell == 0 && isbltinenv)
-    run_unwind_frame ("builtin_env");
-
-  if (eval_unwind)
-    {
-      exit_immediately_on_error = errexit_flag;
-      builtin_ignoring_errexit = 0;
-      if (error_trap)
-       {
-         set_error_trap (error_trap);
-         xfree (error_trap);
-       }
-      discard_unwind_frame ("eval_builtin");
-    }
-
-  return (result);
-}
-
-static int
-execute_function (var, words, flags, fds_to_close, async, subshell)
-     SHELL_VAR *var;
-     WORD_LIST *words;
-     int flags;
-     struct fd_bitmap *fds_to_close;
-     int async, subshell;
-{
-  int return_val, result;
-  COMMAND *tc, *fc, *save_current;
-  char *debug_trap, *error_trap, *return_trap;
-#if defined (ARRAY_VARS)
-  SHELL_VAR *funcname_v, *nfv, *bash_source_v, *bash_lineno_v;
-  ARRAY *funcname_a;
-  volatile ARRAY *bash_source_a;
-  volatile ARRAY *bash_lineno_a;
-#endif
-  FUNCTION_DEF *shell_fn;
-  char *sfile, *t;
-
-  USE_VAR(fc);
-
-  if (funcnest_max > 0 && funcnest >= funcnest_max)
-    {
-      internal_error (_("%s: maximum function nesting level exceeded (%d)"), var->name, funcnest);
-      funcnest = 0;    /* XXX - should we reset it somewhere else? */
-      jump_to_top_level (DISCARD);
-    }
-
-#if defined (ARRAY_VARS)
-  GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a);
-  GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a);
-  GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a);
-#endif
-
-  tc = (COMMAND *)copy_command (function_cell (var));
-  if (tc && (flags & CMD_IGNORE_RETURN))
-    tc->flags |= CMD_IGNORE_RETURN;
-
-  if (subshell == 0)
-    {
-      begin_unwind_frame ("function_calling");
-      push_context (var->name, subshell, temporary_env);
-      add_unwind_protect (pop_context, (char *)NULL);
-      unwind_protect_int (line_number);
-      unwind_protect_int (return_catch_flag);
-      unwind_protect_jmp_buf (return_catch);
-      add_unwind_protect (dispose_command, (char *)tc);
-      unwind_protect_pointer (this_shell_function);
-      unwind_protect_int (loop_level);
-      unwind_protect_int (funcnest);
-    }
-  else
-    push_context (var->name, subshell, temporary_env); /* don't unwind-protect for subshells */
-
-  temporary_env = (HASH_TABLE *)NULL;
-
-  this_shell_function = var;
-  make_funcname_visible (1);
-
-  debug_trap = TRAP_STRING(DEBUG_TRAP);
-  error_trap = TRAP_STRING(ERROR_TRAP);
-  return_trap = TRAP_STRING(RETURN_TRAP);
-  
-  /* The order of the unwind protects for debug_trap, error_trap and
-     return_trap is important here!  unwind-protect commands are run
-     in reverse order of registration.  If this causes problems, take
-     out the xfree unwind-protect calls and live with the small memory leak. */
-
-  /* function_trace_mode != 0 means that all functions inherit the DEBUG trap.
-     if the function has the trace attribute set, it inherits the DEBUG trap */
-  if (debug_trap && ((trace_p (var) == 0) && function_trace_mode == 0))
-    {
-      if (subshell == 0)
-       {
-         debug_trap = savestring (debug_trap);
-         add_unwind_protect (xfree, debug_trap);
-         add_unwind_protect (set_debug_trap, debug_trap);
-       }
-      restore_default_signal (DEBUG_TRAP);
-    }
-
-  /* error_trace_mode != 0 means that functions inherit the ERR trap. */
-  if (error_trap && error_trace_mode == 0)
-    {
-      if (subshell == 0)
-       {
-         error_trap = savestring (error_trap);
-         add_unwind_protect (xfree, error_trap);
-         add_unwind_protect (set_error_trap, error_trap);
-       }
-      restore_default_signal (ERROR_TRAP);
-    }
-
-  /* Shell functions inherit the RETURN trap if function tracing is on
-     globally or on individually for this function. */
-#if 0
-  if (return_trap && ((trace_p (var) == 0) && function_trace_mode == 0))
-#else
-  if (return_trap && (signal_in_progress (DEBUG_TRAP) || ((trace_p (var) == 0) && function_trace_mode == 0)))
-#endif
-    {
-      if (subshell == 0)
-       {
-         return_trap = savestring (return_trap);
-         add_unwind_protect (xfree, return_trap);
-         add_unwind_protect (set_return_trap, return_trap);
-       }
-      restore_default_signal (RETURN_TRAP);
-    }
-  
-  funcnest++;
-#if defined (ARRAY_VARS)
-  /* This is quite similar to the code in shell.c and elsewhere. */
-  shell_fn = find_function_def (this_shell_function->name);
-  sfile = shell_fn ? shell_fn->source_file : "";
-  array_push ((ARRAY *)funcname_a, this_shell_function->name);
-
-  array_push ((ARRAY *)bash_source_a, sfile);
-  t = itos (executing_line_number ());
-  array_push ((ARRAY *)bash_lineno_a, t);
-  free (t);
-#endif
-
-  /* The temporary environment for a function is supposed to apply to
-     all commands executed within the function body. */
-
-  remember_args (words->next, 1);
-
-  /* Update BASH_ARGV and BASH_ARGC */
-  if (debugging_mode)
-    push_args (words->next);
-
-  /* Number of the line on which the function body starts. */
-  line_number = function_line_number = tc->line;
-
-#if defined (JOB_CONTROL)
-  if (subshell)
-    stop_pipeline (async, (COMMAND *)NULL);
-#endif
-
-  fc = tc;
-
-  return_catch_flag++;
-  return_val = setjmp_nosigs (return_catch);
-
-  if (return_val)
-    {
-      result = return_catch_value;
-      /* Run the RETURN trap in the function's context. */
-      save_current = currently_executing_command;
-      run_return_trap ();
-      currently_executing_command = save_current;
-    }
-  else
-    {
-      /* Run the debug trap here so we can trap at the start of a function's
-        execution rather than the execution of the body's first command. */
-      showing_function_line = 1;
-      save_current = currently_executing_command;
-      result = run_debug_trap ();
-#if defined (DEBUGGER)
-      /* In debugging mode, if the DEBUG trap returns a non-zero status, we
-        skip the command. */
-      if (debugging_mode == 0 || result == EXECUTION_SUCCESS)
-       {
-         showing_function_line = 0;
-         currently_executing_command = save_current;
-         result = execute_command_internal (fc, 0, NO_PIPE, NO_PIPE, fds_to_close);
-
-         /* Run the RETURN trap in the function's context */
-         save_current = currently_executing_command;
-         run_return_trap ();
-         currently_executing_command = save_current;
-       }
-#else
-      result = execute_command_internal (fc, 0, NO_PIPE, NO_PIPE, fds_to_close);
-
-      save_current = currently_executing_command;
-      run_return_trap ();
-      currently_executing_command = save_current;
-#endif
-      showing_function_line = 0;
-    }
-
-  /* Restore BASH_ARGC and BASH_ARGV */
-  if (debugging_mode)
-    pop_args ();
-
-  if (subshell == 0)
-    run_unwind_frame ("function_calling");
-
-#if defined (ARRAY_VARS)
-  /* These two variables cannot be unset, and cannot be affected by the
-     function. */
-  array_pop ((ARRAY *)bash_source_a);
-  array_pop ((ARRAY *)bash_lineno_a);
-
-  /* FUNCNAME can be unset, and so can potentially be changed by the
-     function. */
-  GET_ARRAY_FROM_VAR ("FUNCNAME", nfv, funcname_a);
-  if (nfv == funcname_v)
-    array_pop (funcname_a);
-#endif
-  
-  if (variable_context == 0 || this_shell_function == 0)
-    {
-      make_funcname_visible (0);
-#if defined (PROCESS_SUBSTITUTION)
-      unlink_fifo_list ();
-#endif
-    }
-  
-  return (result);
-}
-
-/* A convenience routine for use by other parts of the shell to execute
-   a particular shell function. */
-int
-execute_shell_function (var, words)
-     SHELL_VAR *var;
-     WORD_LIST *words;
-{
-  int ret;
-  struct fd_bitmap *bitmap;
-
-  bitmap = new_fd_bitmap (FD_BITMAP_DEFAULT_SIZE);
-  begin_unwind_frame ("execute-shell-function");
-  add_unwind_protect (dispose_fd_bitmap, (char *)bitmap);
-      
-  ret = execute_function (var, words, 0, bitmap, 0, 0);
-
-  dispose_fd_bitmap (bitmap);
-  discard_unwind_frame ("execute-shell-function");
-
-  return ret;
-}
-
-/* Execute a shell builtin or function in a subshell environment.  This
-   routine does not return; it only calls exit().  If BUILTIN is non-null,
-   it points to a function to call to execute a shell builtin; otherwise
-   VAR points at the body of a function to execute.  WORDS is the arguments
-   to the command, REDIRECTS specifies redirections to perform before the
-   command is executed. */
-static void
-execute_subshell_builtin_or_function (words, redirects, builtin, var,
-                                     pipe_in, pipe_out, async, fds_to_close,
-                                     flags)
-     WORD_LIST *words;
-     REDIRECT *redirects;
-     sh_builtin_func_t *builtin;
-     SHELL_VAR *var;
-     int pipe_in, pipe_out, async;
-     struct fd_bitmap *fds_to_close;
-     int flags;
-{
-  int result, r, funcvalue;
-#if defined (JOB_CONTROL)
-  int jobs_hack;
-
-  jobs_hack = (builtin == jobs_builtin) &&
-               ((subshell_environment & SUBSHELL_ASYNC) == 0 || pipe_out != NO_PIPE);
-#endif
-
-  /* A subshell is neither a login shell nor interactive. */
-  login_shell = interactive = 0;
-
-  if (async)
-    subshell_environment |= SUBSHELL_ASYNC;
-  if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
-    subshell_environment |= SUBSHELL_PIPE;
-
-  maybe_make_export_env ();    /* XXX - is this needed? */
-
-#if defined (JOB_CONTROL)
-  /* Eradicate all traces of job control after we fork the subshell, so
-     all jobs begun by this subshell are in the same process group as
-     the shell itself. */
-
-  /* Allow the output of `jobs' to be piped. */
-  if (jobs_hack)
-    kill_current_pipeline ();
-  else
-    without_job_control ();
-
-  set_sigchld_handler ();
-#endif /* JOB_CONTROL */
-
-  set_sigint_handler ();
-
-  if (fds_to_close)
-    close_fd_bitmap (fds_to_close);
-
-  do_piping (pipe_in, pipe_out);
-
-  if (do_redirections (redirects, RX_ACTIVE) != 0)
-    exit (EXECUTION_FAILURE);
-
-  if (builtin)
-    {
-      /* Give builtins a place to jump back to on failure,
-        so we don't go back up to main(). */
-      result = setjmp_nosigs (top_level);
-
-      /* Give the return builtin a place to jump to when executed in a subshell
-         or pipeline */
-      funcvalue = 0;
-      if (return_catch_flag && builtin == return_builtin)
-        funcvalue = setjmp_nosigs (return_catch);
-
-      if (result == EXITPROG)
-       exit (last_command_exit_value);
-      else if (result)
-       exit (EXECUTION_FAILURE);
-      else if (funcvalue)
-       exit (return_catch_value);
-      else
-       {
-         r = execute_builtin (builtin, words, flags, 1);
-         fflush (stdout);
-         if (r == EX_USAGE)
-           r = EX_BADUSAGE;
-         exit (r);
-       }
-    }
-  else
-    {
-      r = execute_function (var, words, flags, fds_to_close, async, 1);
-      fflush (stdout);
-      exit (r);
-    }
-}
-
-/* Execute a builtin or function in the current shell context.  If BUILTIN
-   is non-null, it is the builtin command to execute, otherwise VAR points
-   to the body of a function.  WORDS are the command's arguments, REDIRECTS
-   are the redirections to perform.  FDS_TO_CLOSE is the usual bitmap of
-   file descriptors to close.
-
-   If BUILTIN is exec_builtin, the redirections specified in REDIRECTS are
-   not undone before this function returns. */
-static int
-execute_builtin_or_function (words, builtin, var, redirects,
-                            fds_to_close, flags)
-     WORD_LIST *words;
-     sh_builtin_func_t *builtin;
-     SHELL_VAR *var;
-     REDIRECT *redirects;
-     struct fd_bitmap *fds_to_close;
-     int flags;
-{
-  int result;
-  REDIRECT *saved_undo_list;
-#if defined (PROCESS_SUBSTITUTION)
-  int ofifo, nfifo, osize;
-  char *ofifo_list;
-#endif
-
-
-#if defined (PROCESS_SUBSTITUTION)  
-  ofifo = num_fifos ();
-  ofifo_list = copy_fifo_list (&osize);
-#endif
-
-  if (do_redirections (redirects, RX_ACTIVE|RX_UNDOABLE) != 0)
-    {
-      cleanup_redirects (redirection_undo_list);
-      redirection_undo_list = (REDIRECT *)NULL;
-      dispose_exec_redirects ();
-#if defined (PROCESS_SUBSTITUTION)
-      free (ofifo_list);
-#endif
-      return (EX_REDIRFAIL);   /* was EXECUTION_FAILURE */
-    }
-
-  saved_undo_list = redirection_undo_list;
-
-  /* Calling the "exec" builtin changes redirections forever. */
-  if (builtin == exec_builtin)
-    {
-      dispose_redirects (saved_undo_list);
-      saved_undo_list = exec_redirection_undo_list;
-      exec_redirection_undo_list = (REDIRECT *)NULL;
-    }
-  else
-    dispose_exec_redirects ();
-
-  if (saved_undo_list)
-    {
-      begin_unwind_frame ("saved redirects");
-      add_unwind_protect (cleanup_redirects, (char *)saved_undo_list);
-    }
-
-  redirection_undo_list = (REDIRECT *)NULL;
-
-  if (builtin)
-    result = execute_builtin (builtin, words, flags, 0);
-  else
-    result = execute_function (var, words, flags, fds_to_close, 0, 0);
-
-  /* We do this before undoing the effects of any redirections. */
-  fflush (stdout);
-  fpurge (stdout);
-  if (ferror (stdout))
-    clearerr (stdout);  
-
-  /* If we are executing the `command' builtin, but this_shell_builtin is
-     set to `exec_builtin', we know that we have something like
-     `command exec [redirection]', since otherwise `exec' would have
-     overwritten the shell and we wouldn't get here.  In this case, we
-     want to behave as if the `command' builtin had not been specified
-     and preserve the redirections. */
-  if (builtin == command_builtin && this_shell_builtin == exec_builtin)
-    {
-      int discard;
-
-      discard = 0;
-      if (saved_undo_list)
-       {
-         dispose_redirects (saved_undo_list);
-         discard = 1;
-       }
-      redirection_undo_list = exec_redirection_undo_list;
-      saved_undo_list = exec_redirection_undo_list = (REDIRECT *)NULL;      
-      if (discard)
-       discard_unwind_frame ("saved redirects");
-    }
-
-  if (saved_undo_list)
-    {
-      redirection_undo_list = saved_undo_list;
-      discard_unwind_frame ("saved redirects");
-    }
-
-  if (redirection_undo_list)
-    {
-      cleanup_redirects (redirection_undo_list);
-      redirection_undo_list = (REDIRECT *)NULL;
-    }
-
-#if defined (PROCESS_SUBSTITUTION)
-  /* Close any FIFOs created by this builtin or function. */
-  nfifo = num_fifos ();
-  if (nfifo > ofifo)
-    close_new_fifos (ofifo_list, osize);
-  free (ofifo_list);
-#endif
-
-  return (result);
-}
-
-void
-setup_async_signals ()
-{
-#if defined (__BEOS__)
-  set_signal_handler (SIGHUP, SIG_IGN);        /* they want csh-like behavior */
-#endif
-
-#if defined (JOB_CONTROL)
-  if (job_control == 0)
-#endif
-    {
-      set_signal_handler (SIGINT, SIG_IGN);
-      set_signal_ignored (SIGINT);
-      set_signal_handler (SIGQUIT, SIG_IGN);
-      set_signal_ignored (SIGQUIT);
-    }
-}
-
-/* Execute a simple command that is hopefully defined in a disk file
-   somewhere.
-
-   1) fork ()
-   2) connect pipes
-   3) look up the command
-   4) do redirections
-   5) execve ()
-   6) If the execve failed, see if the file has executable mode set.
-   If so, and it isn't a directory, then execute its contents as
-   a shell script.
-
-   Note that the filename hashing stuff has to take place up here,
-   in the parent.  This is probably why the Bourne style shells
-   don't handle it, since that would require them to go through
-   this gnarly hair, for no good reason.
-
-   NOTE: callers expect this to fork or exit(). */
-
-/* Name of a shell function to call when a command name is not found. */
-#ifndef NOTFOUND_HOOK
-#  define NOTFOUND_HOOK "command_not_found_handle"
-#endif
-
-static int
-execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
-                     async, fds_to_close, cmdflags)
-     WORD_LIST *words;
-     REDIRECT *redirects;
-     char *command_line;
-     int pipe_in, pipe_out, async;
-     struct fd_bitmap *fds_to_close;
-     int cmdflags;
-{
-  char *pathname, *command, **args;
-  int nofork, result;
-  pid_t pid;
-  SHELL_VAR *hookf;
-  WORD_LIST *wl;
-
-  nofork = (cmdflags & CMD_NO_FORK);  /* Don't fork, just exec, if no pipes */
-  pathname = words->word->word;
-
-  result = EXECUTION_SUCCESS;
-#if defined (RESTRICTED_SHELL)
-  command = (char *)NULL;
-  if (restricted && mbschr (pathname, '/'))
-    {
-      internal_error (_("%s: restricted: cannot specify `/' in command names"),
-                   pathname);
-      result = last_command_exit_value = EXECUTION_FAILURE;
-
-      /* If we're not going to fork below, we must already be in a child
-         process or a context in which it's safe to call exit(2).  */
-      if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE)
-       exit (last_command_exit_value);
-      else
-       goto parent_return;
-    }
-#endif /* RESTRICTED_SHELL */
-
-  command = search_for_command (pathname, 1);
-
-  if (command)
-    {
-      maybe_make_export_env ();
-      put_command_name_into_env (command);
-    }
-
-  /* We have to make the child before we check for the non-existence
-     of COMMAND, since we want the error messages to be redirected. */
-  /* If we can get away without forking and there are no pipes to deal with,
-     don't bother to fork, just directly exec the command. */
-  if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE)
-    pid = 0;
-  else
-    pid = make_child (savestring (command_line), async);
-
-  if (pid == 0)
-    {
-      int old_interactive;
-
-#if 0
-      /* This has been disabled for the time being. */
-#if !defined (ARG_MAX) || ARG_MAX >= 10240
-      if (posixly_correct == 0)
-       put_gnu_argv_flags_into_env ((long)getpid (), glob_argv_flags);
-#endif
-#endif
-
-      reset_terminating_signals ();    /* XXX */
-      /* Cancel traps, in trap.c. */
-      restore_original_signals ();
-
-      /* restore_original_signals may have undone the work done
-        by make_child to ensure that SIGINT and SIGQUIT are ignored
-        in asynchronous children. */
-      if (async)
-       {
-         if ((cmdflags & CMD_STDIN_REDIR) &&
-               pipe_in == NO_PIPE &&
-               (stdin_redirects (redirects) == 0))
-           async_redirect_stdin ();
-         setup_async_signals ();
-       }
-
-      /* This functionality is now provided by close-on-exec of the
-        file descriptors manipulated by redirection and piping.
-        Some file descriptors still need to be closed in all children
-        because of the way bash does pipes; fds_to_close is a
-        bitmap of all such file descriptors. */
-      if (fds_to_close)
-       close_fd_bitmap (fds_to_close);
-
-      do_piping (pipe_in, pipe_out);
-
-      old_interactive = interactive;
-      if (async)
-       interactive = 0;
-
-      subshell_environment = SUBSHELL_FORK;
-
-      if (redirects && (do_redirections (redirects, RX_ACTIVE) != 0))
-       {
-#if defined (PROCESS_SUBSTITUTION)
-         /* Try to remove named pipes that may have been created as the
-            result of redirections. */
-         unlink_fifo_list ();
-#endif /* PROCESS_SUBSTITUTION */
-         exit (EXECUTION_FAILURE);
-       }
-
-      if (async)
-       interactive = old_interactive;
-
-      if (command == 0)
-       {
-         hookf = find_function (NOTFOUND_HOOK);
-         if (hookf == 0)
-           {
-             /* Make sure filenames are displayed using printable characters */
-             if (ansic_shouldquote (pathname))
-               pathname = ansic_quote (pathname, 0, NULL);
-             internal_error (_("%s: command not found"), pathname);
-             exit (EX_NOTFOUND);       /* Posix.2 says the exit status is 127 */
-           }
-
-         /* May need to reinitialize more of the job control state here. */
-         kill_current_pipeline ();
-
-         wl = make_word_list (make_word (NOTFOUND_HOOK), words);
-         exit (execute_shell_function (hookf, wl));
-       }
-
-      /* Execve expects the command name to be in args[0].  So we
-        leave it there, in the same format that the user used to
-        type it in. */
-      args = strvec_from_word_list (words, 0, 0, (int *)NULL);
-      exit (shell_execve (command, args, export_env));
-    }
-  else
-    {
-parent_return:
-      QUIT;
-
-      /* Make sure that the pipes are closed in the parent. */
-      close_pipes (pipe_in, pipe_out);
-#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
-      if (variable_context == 0)
-        unlink_fifo_list ();
-#endif
-      FREE (command);
-      return (result);
-    }
-}
-
-/* CPP defines to decide whether a particular index into the #! line
-   corresponds to a valid interpreter name or argument character, or
-   whitespace.  The MSDOS define is to allow \r to be treated the same
-   as \n. */
-
-#if !defined (MSDOS)
-#  define STRINGCHAR(ind) \
-    (ind < sample_len && !whitespace (sample[ind]) && sample[ind] != '\n')
-#  define WHITECHAR(ind) \
-    (ind < sample_len && whitespace (sample[ind]))
-#else  /* MSDOS */
-#  define STRINGCHAR(ind) \
-    (ind < sample_len && !whitespace (sample[ind]) && sample[ind] != '\n' && sample[ind] != '\r')
-#  define WHITECHAR(ind) \
-    (ind < sample_len && whitespace (sample[ind]))
-#endif /* MSDOS */
-
-static char *
-getinterp (sample, sample_len, endp)
-     char *sample;
-     int sample_len, *endp;
-{
-  register int i;
-  char *execname;
-  int start;
-
-  /* Find the name of the interpreter to exec. */
-  for (i = 2; i < sample_len && whitespace (sample[i]); i++)
-    ;
-
-  for (start = i; STRINGCHAR(i); i++)
-    ;
-
-  execname = substring (sample, start, i);
-
-  if (endp)
-    *endp = i;
-  return execname;
-}
-
-#if !defined (HAVE_HASH_BANG_EXEC)
-/* If the operating system on which we're running does not handle
-   the #! executable format, then help out.  SAMPLE is the text read
-   from the file, SAMPLE_LEN characters.  COMMAND is the name of
-   the script; it and ARGS, the arguments given by the user, will
-   become arguments to the specified interpreter.  ENV is the environment
-   to pass to the interpreter.
-
-   The word immediately following the #! is the interpreter to execute.
-   A single argument to the interpreter is allowed. */
-
-static int
-execute_shell_script (sample, sample_len, command, args, env)
-     char *sample;
-     int sample_len;
-     char *command;
-     char **args, **env;
-{
-  char *execname, *firstarg;
-  int i, start, size_increment, larry;
-
-  /* Find the name of the interpreter to exec. */
-  execname = getinterp (sample, sample_len, &i);
-  size_increment = 1;
-
-  /* Now the argument, if any. */
-  for (firstarg = (char *)NULL, start = i; WHITECHAR(i); i++)
-    ;
-
-  /* If there is more text on the line, then it is an argument for the
-     interpreter. */
-
-  if (STRINGCHAR(i))  
-    {
-      for (start = i; STRINGCHAR(i); i++)
-       ;
-      firstarg = substring ((char *)sample, start, i);
-      size_increment = 2;
-    }
-
-  larry = strvec_len (args) + size_increment;
-  args = strvec_resize (args, larry + 1);
-
-  for (i = larry - 1; i; i--)
-    args[i] = args[i - size_increment];
-
-  args[0] = execname;
-  if (firstarg)
-    {
-      args[1] = firstarg;
-      args[2] = command;
-    }
-  else
-    args[1] = command;
-
-  args[larry] = (char *)NULL;
-
-  return (shell_execve (execname, args, env));
-}
-#undef STRINGCHAR
-#undef WHITECHAR
-
-#endif /* !HAVE_HASH_BANG_EXEC */
-
-static void
-initialize_subshell ()
-{
-#if defined (ALIAS)
-  /* Forget about any aliases that we knew of.  We are in a subshell. */
-  delete_all_aliases ();
-#endif /* ALIAS */
-
-#if defined (HISTORY)
-  /* Forget about the history lines we have read.  This is a non-interactive
-     subshell. */
-  history_lines_this_session = 0;
-#endif
-
-#if defined (JOB_CONTROL)
-  /* Forget about the way job control was working. We are in a subshell. */
-  without_job_control ();
-  set_sigchld_handler ();
-  init_job_stats ();
-#endif /* JOB_CONTROL */
-
-  /* Reset the values of the shell flags and options. */
-  reset_shell_flags ();
-  reset_shell_options ();
-  reset_shopt_options ();
-
-  /* Zero out builtin_env, since this could be a shell script run from a
-     sourced file with a temporary environment supplied to the `source/.'
-     builtin.  Such variables are not supposed to be exported (empirical
-     testing with sh and ksh).  Just throw it away; don't worry about a
-     memory leak. */
-  if (vc_isbltnenv (shell_variables))
-    shell_variables = shell_variables->down;
-
-  clear_unwind_protect_list (0);
-  /* XXX -- are there other things we should be resetting here? */
-  parse_and_execute_level = 0;         /* nothing left to restore it */
-
-  /* We're no longer inside a shell function. */
-  variable_context = return_catch_flag = funcnest = 0;
-
-  executing_list = 0;          /* XXX */
-
-  /* If we're not interactive, close the file descriptor from which we're
-     reading the current shell script. */
-  if (interactive_shell == 0)
-    unset_bash_input (0);
-}
-
-#if defined (HAVE_SETOSTYPE) && defined (_POSIX_SOURCE)
-#  define SETOSTYPE(x) __setostype(x)
-#else
-#  define SETOSTYPE(x)
-#endif
-
-#define READ_SAMPLE_BUF(file, buf, len) \
-  do \
-    { \
-      fd = open(file, O_RDONLY); \
-      if (fd >= 0) \
-       { \
-         len = read (fd, buf, 80); \
-         close (fd); \
-       } \
-      else \
-       len = -1; \
-    } \
-  while (0)
-      
-/* Call execve (), handling interpreting shell scripts, and handling
-   exec failures. */
-int
-shell_execve (command, args, env)
-     char *command;
-     char **args, **env;
-{
-  int larray, i, fd;
-  char sample[80];
-  int sample_len;
-
-  SETOSTYPE (0);               /* Some systems use for USG/POSIX semantics */
-  execve (command, args, env);
-  i = errno;                   /* error from execve() */
-  CHECK_TERMSIG;
-  SETOSTYPE (1);
-
-  /* If we get to this point, then start checking out the file.
-     Maybe it is something we can hack ourselves. */
-  if (i != ENOEXEC)
-    {
-      if (file_isdir (command))
-#if defined (EISDIR)
-       internal_error (_("%s: %s"), command, strerror (EISDIR));
-#else
-       internal_error (_("%s: is a directory"), command);
-#endif
-      else if (executable_file (command) == 0)
-       {
-         errno = i;
-         file_error (command);
-       }
-      /* errors not involving the path argument to execve. */
-      else if (i == E2BIG || i == ENOMEM)
-       {
-         errno = i;
-         file_error (command);
-       }
-      else
-       {
-         /* The file has the execute bits set, but the kernel refuses to
-            run it for some reason.  See why. */
-#if defined (HAVE_HASH_BANG_EXEC)
-         READ_SAMPLE_BUF (command, sample, sample_len);
-         sample[sample_len - 1] = '\0';
-         if (sample_len > 2 && sample[0] == '#' && sample[1] == '!')
-           {
-             char *interp;
-             int ilen;
-
-             interp = getinterp (sample, sample_len, (int *)NULL);
-             ilen = strlen (interp);
-             errno = i;
-             if (interp[ilen - 1] == '\r')
-               {
-                 interp = xrealloc (interp, ilen + 2);
-                 interp[ilen - 1] = '^';
-                 interp[ilen] = 'M';
-                 interp[ilen + 1] = '\0';
-               }
-             sys_error (_("%s: %s: bad interpreter"), command, interp ? interp : "");
-             FREE (interp);
-             return (EX_NOEXEC);
-           }
-#endif
-         errno = i;
-         file_error (command);
-       }
-      return ((i == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);        /* XXX Posix.2 says that exit status is 126 */
-    }
-
-  /* This file is executable.
-     If it begins with #!, then help out people with losing operating
-     systems.  Otherwise, check to see if it is a binary file by seeing
-     if the contents of the first line (or up to 80 characters) are in the
-     ASCII set.  If it's a text file, execute the contents as shell commands,
-     otherwise return 126 (EX_BINARY_FILE). */
-  READ_SAMPLE_BUF (command, sample, sample_len);
-
-  if (sample_len == 0)
-    return (EXECUTION_SUCCESS);
-
-  /* Is this supposed to be an executable script?
-     If so, the format of the line is "#! interpreter [argument]".
-     A single argument is allowed.  The BSD kernel restricts
-     the length of the entire line to 32 characters (32 bytes
-     being the size of the BSD exec header), but we allow 80
-     characters. */
-  if (sample_len > 0)
-    {
-#if !defined (HAVE_HASH_BANG_EXEC)
-      if (sample_len > 2 && sample[0] == '#' && sample[1] == '!')
-       return (execute_shell_script (sample, sample_len, command, args, env));
-      else
-#endif
-      if (check_binary_file (sample, sample_len))
-       {
-         internal_error (_("%s: cannot execute binary file: %s"), command, strerror (i));
-         return (EX_BINARY_FILE);
-       }
-    }
-
-  /* We have committed to attempting to execute the contents of this file
-     as shell commands. */
-
-  initialize_subshell ();
-
-  set_sigint_handler ();
-
-  /* Insert the name of this shell into the argument list. */
-  larray = strvec_len (args) + 1;
-  args = strvec_resize (args, larray + 1);
-
-  for (i = larray - 1; i; i--)
-    args[i] = args[i - 1];
-
-  args[0] = shell_name;
-  args[1] = command;
-  args[larray] = (char *)NULL;
-
-  if (args[0][0] == '-')
-    args[0]++;
-
-#if defined (RESTRICTED_SHELL)
-  if (restricted)
-    change_flag ('r', FLAG_OFF);
-#endif
-
-  if (subshell_argv)
-    {
-      /* Can't free subshell_argv[0]; that is shell_name. */
-      for (i = 1; i < subshell_argc; i++)
-       free (subshell_argv[i]);
-      free (subshell_argv);
-    }
-
-  dispose_command (currently_executing_command);       /* XXX */
-  currently_executing_command = (COMMAND *)NULL;
-
-  subshell_argc = larray;
-  subshell_argv = args;
-  subshell_envp = env;
-
-  unbind_args ();      /* remove the positional parameters */
-
-  longjmp (subshell_top_level, 1);
-  /*NOTREACHED*/
-}
-
-static int
-execute_intern_function (name, funcdef)
-     WORD_DESC *name;
-     FUNCTION_DEF *funcdef;
-{
-  SHELL_VAR *var;
-
-  if (check_identifier (name, posixly_correct) == 0)
-    {
-      if (posixly_correct && interactive_shell == 0)
-       {
-         last_command_exit_value = EX_BADUSAGE;
-         jump_to_top_level (ERREXIT);
-       }
-      return (EXECUTION_FAILURE);
-    }
-
-  /* Posix interpretation 383 */
-  if (posixly_correct && find_special_builtin (name->word))
-    {
-      internal_error (_("`%s': is a special builtin"), name->word);
-      last_command_exit_value = EX_BADUSAGE;
-      jump_to_top_level (ERREXIT);
-    }
-
-  var = find_function (name->word);
-  if (var && (readonly_p (var) || noassign_p (var)))
-    {
-      if (readonly_p (var))
-       internal_error (_("%s: readonly function"), var->name);
-      return (EXECUTION_FAILURE);
-    }
-
-#if defined (DEBUGGER)
-  bind_function_def (name->word, funcdef);
-#endif
-
-  bind_function (name->word, funcdef->command);
-  return (EXECUTION_SUCCESS);
-}
-
-#if defined (INCLUDE_UNUSED)
-#if defined (PROCESS_SUBSTITUTION)
-void
-close_all_files ()
-{
-  register int i, fd_table_size;
-
-  fd_table_size = getdtablesize ();
-  if (fd_table_size > 256)     /* clamp to a reasonable value */
-    fd_table_size = 256;
-
-  for (i = 3; i < fd_table_size; i++)
-    close (i);
-}
-#endif /* PROCESS_SUBSTITUTION */
-#endif
-
-static void
-close_pipes (in, out)
-     int in, out;
-{
-  if (in >= 0)
-    close (in);
-  if (out >= 0)
-    close (out);
-}
-
-static void
-dup_error (oldd, newd)
-     int oldd, newd;
-{
-  sys_error (_("cannot duplicate fd %d to fd %d"), oldd, newd);
-}
-
-/* Redirect input and output to be from and to the specified pipes.
-   NO_PIPE and REDIRECT_BOTH are handled correctly. */
-static void
-do_piping (pipe_in, pipe_out)
-     int pipe_in, pipe_out;
-{
-  if (pipe_in != NO_PIPE)
-    {
-      if (dup2 (pipe_in, 0) < 0)
-       dup_error (pipe_in, 0);
-      if (pipe_in > 0)
-       close (pipe_in);
-#ifdef __CYGWIN__
-      /* Let stdio know the fd may have changed from text to binary mode. */
-      freopen (NULL, "r", stdin);
-#endif /* __CYGWIN__ */
-    }
-  if (pipe_out != NO_PIPE)
-    {
-      if (pipe_out != REDIRECT_BOTH)
-       {
-         if (dup2 (pipe_out, 1) < 0)
-           dup_error (pipe_out, 1);
-         if (pipe_out == 0 || pipe_out > 1)
-           close (pipe_out);
-       }
-      else
-       {
-         if (dup2 (1, 2) < 0)
-           dup_error (1, 2);
-       }
-#ifdef __CYGWIN__
-      /* Let stdio know the fd may have changed from text to binary mode, and
-        make sure to preserve stdout line buffering. */
-      freopen (NULL, "w", stdout);
-      sh_setlinebuf (stdout);
-#endif /* __CYGWIN__ */
-    }
-}
diff --git a/init-termsigs.patch~ b/init-termsigs.patch~
deleted file mode 100644 (file)
index 94f87d5..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-*** ../bash-4.2-patched/sig.c  2011-03-12 13:14:06.000000000 -0500
---- sig.c      2013-01-05 18:00:28.000000000 -0500
-***************
-*** 1,5 ****
-  /* sig.c - interface for shell signal handlers and signal initialization. */
-  
-! /* Copyright (C) 1994-2010 Free Software Foundation, Inc.
-  
-     This file is part of GNU Bash, the Bourne Again SHell.
---- 1,5 ----
-  /* 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.
-***************
-*** 359,362 ****
---- 359,364 ----
-      }
-  #endif /* !HAVE_POSIX_SIGNALS */
-+ 
-+   termsigs_initialized = 0;
-  }
-  #undef XSIG
-***************
-*** 390,393 ****
---- 392,397 ----
-    if (interrupt_state)
-      {
-+       if (last_command_exit_value < 128)
-+      last_command_exit_value = 128 + SIGINT;
-        print_newline = 1;
-        DELINTERRUPT;
-***************
-*** 517,520 ****
---- 521,532 ----
-      }
-  
-+ #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);
-  }
-***************
-*** 538,545 ****
-      run_interrupt_trap ();
-  
-  #if defined (HISTORY)
-!   if (interactive_shell && sig != SIGABRT)
-      maybe_save_shell_history ();
-  #endif /* HISTORY */
-  
-  #if defined (JOB_CONTROL)
---- 550,559 ----
-      run_interrupt_trap ();
-  
-+ #if 0
-  #if defined (HISTORY)
-!   if (interactive_shell && (sig != SIGABRT && sig != SIGINT && sig != SIGHUP && sig != SIGTERM))
-      maybe_save_shell_history ();
-  #endif /* HISTORY */
-+ #endif
-  
-  #if defined (JOB_CONTROL)
-***************
-*** 582,585 ****
---- 596,606 ----
-        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);
-***************
-*** 618,622 ****
-  #if !defined (HAVE_POSIX_SIGNALS)
-  
-- #if defined (JOB_CONTROL)
-  /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
-  sigprocmask (operation, newset, oldset)
---- 639,642 ----
-***************
-*** 637,641 ****
-  
-      case SIG_SETMASK:
-!       sigsetmask (new);
-        break;
-  
---- 657,661 ----
-  
-      case SIG_SETMASK:
-!       old = sigsetmask (new);
-        break;
-  
-***************
-*** 647,651 ****
-      *oldset = old;
-  }
-- #endif /* JOB_CONTROL */
-  
-  #else
---- 667,670 ----
-***************
-*** 672,677 ****
---- 691,698 ----
-    /* 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
-  
-    sigemptyset (&act.sa_mask);
diff --git a/lib/intl/Makefile.in~ b/lib/intl/Makefile.in~
deleted file mode 100644 (file)
index c5245d4..0000000
+++ /dev/null
@@ -1,470 +0,0 @@
-# Makefile for directory with message catalog handling library of GNU gettext
-# Copyright (C) 1995-1998, 2000-2003, 2008,2009 Free Software Foundation, Inc.
-#
-
-#   This program is free software: you can redistribute it and/or modify
-#   it under the terms of the GNU General Public License as published by
-#   the Free Software Foundation, either version 3 of the License, or
-#   (at your option) any later version.
-
-#   This program is distributed in the hope that it will be useful,
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#   GNU General Public License for more details.
-
-#   You should have received a copy of the GNU General Public License
-#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-PACKAGE = @PACKAGE_NAME@
-VERSION = @PACKAGE_VERSION@
-
-SHELL = /bin/sh
-
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-top_builddir = @BUILD_DIR@
-VPATH = $(srcdir)
-
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-transform = @program_transform_name@
-
-datarootdir = @datarootdir@
-
-libdir = @libdir@
-includedir = @includedir@
-datadir = @datadir@
-localedir = @localedir@
-
-gettextsrcdir = $(datadir)/gettext/intl
-aliaspath = $(localedir)
-subdir = intl
-
-@SET_MAKE@
-
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-MKINSTALLDIRS = @MKINSTALLDIRS@
-mkinstalldirs = $(SHELL) $(MKINSTALLDIRS)
-
-l = @INTL_LIBTOOL_SUFFIX_PREFIX@
-
-AR = ar
-CC = @CC@
-LIBTOOL = @LIBTOOL@
-RANLIB = @RANLIB@
-YACC = @INTLBISON@ -y -d
-YFLAGS = --name-prefix=__gettext
-
-LOCAL_DEFS = @LOCAL_DEFS@
-
-DEFS = -DLOCALEDIR=\"$(localedir)\" -DLOCALE_ALIAS_PATH=\"$(aliaspath)\" \
--DLIBDIR=\"$(prefix)/libdata\" -DIN_LIBINTL \
--DENABLE_RELOCATABLE=1 -DIN_LIBRARY -DINSTALLDIR=\"$(libdir)\" -DNO_XMALLOC \
--Dset_relocation_prefix=libintl_set_relocation_prefix \
--Drelocate=libintl_relocate \
--DDEPENDS_ON_LIBICONV=1 @DEFS@ ${LOCAL_DEFS}
-CPPFLAGS = @CPPFLAGS@
-CFLAGS = @CFLAGS@
-LDFLAGS = @LDFLAGS@
-LIBS = @LIBS@
-
-COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS)
-
-HEADERS = \
-  gmo.h \
-  gettextP.h \
-  hash-string.h \
-  loadinfo.h \
-  plural-exp.h \
-  eval-plural.h \
-  localcharset.h \
-  relocatable.h \
-  os2compat.h \
-  libgnuintl.h.in
-SOURCES = \
-  bindtextdom.c \
-  dcgettext.c \
-  dgettext.c \
-  gettext.c \
-  finddomain.c \
-  loadmsgcat.c \
-  localealias.c \
-  textdomain.c \
-  l10nflist.c \
-  explodename.c \
-  dcigettext.c \
-  dcngettext.c \
-  dngettext.c \
-  ngettext.c \
-  plural.y \
-  plural-exp.c \
-  localcharset.c \
-  relocatable.c \
-  localename.c \
-  log.c \
-  osdep.c \
-  os2compat.c \
-  intl-compat.c
-OBJECTS = \
-  bindtextdom.$lo \
-  dcgettext.$lo \
-  dgettext.$lo \
-  gettext.$lo \
-  finddomain.$lo \
-  loadmsgcat.$lo \
-  localealias.$lo \
-  textdomain.$lo \
-  l10nflist.$lo \
-  explodename.$lo \
-  dcigettext.$lo \
-  dcngettext.$lo \
-  dngettext.$lo \
-  ngettext.$lo \
-  plural.$lo \
-  plural-exp.$lo \
-  localcharset.$lo \
-  relocatable.$lo \
-  localename.$lo \
-  log.$lo \
-  osdep.$lo \
-  intl-compat.$lo
-DISTFILES.common = Makefile.in \
-config.charset locale.alias ref-add.sin ref-del.sin $(HEADERS) $(SOURCES)
-DISTFILES.generated = plural.c
-DISTFILES.normal = VERSION
-DISTFILES.gettext = COPYING.LIB-2.0 COPYING.LIB-2.1 libintl.glibc \
-Makefile.vms libgnuintl.h.msvc-shared README.woe32 Makefile.msvc
-DISTFILES.obsolete = xopen-msg.sed linux-msg.sed po2tbl.sed.in cat-compat.c \
-COPYING.LIB-2 gettext.h libgettext.h plural-eval.c libgnuintl.h
-
-all: all-@USE_INCLUDED_LIBINTL@
-all-yes: libintl.$la libintl.h charset.alias ref-add.sed ref-del.sed
-all-no: all-no-@BUILD_INCLUDED_LIBINTL@
-all-no-yes: libgnuintl.$la
-all-no-no:
-
-libintl.a libgnuintl.a: $(OBJECTS)
-       rm -f $@
-       $(AR) cru $@ $(OBJECTS)
-       $(RANLIB) $@
-
-libintl.la libgnuintl.la: $(OBJECTS)
-       $(LIBTOOL) --mode=link \
-         $(CC) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ \
-         $(OBJECTS) @LTLIBICONV@ $(LIBS) \
-         -version-info $(LTV_CURRENT):$(LTV_REVISION):$(LTV_AGE) \
-         -rpath $(libdir) \
-         -no-undefined
-
-# Libtool's library version information for libintl.
-# Before making a gettext release, the gettext maintainer must change this
-# according to the libtool documentation, section "Library interface versions".
-# Maintainers of other packages that include the intl directory must *not*
-# change these values.
-LTV_CURRENT=5
-LTV_REVISION=0
-LTV_AGE=3
-
-.SUFFIXES:
-.SUFFIXES: .c .y .o .lo .sin .sed
-
-.c.o:
-       $(COMPILE) $<
-
-.y.c:
-       $(YACC) $(YFLAGS) --output $@ $<
-       rm -f $*.h
-
-bindtextdom.lo: $(srcdir)/bindtextdom.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/bindtextdom.c
-dcgettext.lo: $(srcdir)/dcgettext.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dcgettext.c
-dgettext.lo: $(srcdir)/dgettext.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dgettext.c
-gettext.lo: $(srcdir)/gettext.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/gettext.c
-finddomain.lo: $(srcdir)/finddomain.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/finddomain.c
-loadmsgcat.lo: $(srcdir)/loadmsgcat.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/loadmsgcat.c
-localealias.lo: $(srcdir)/localealias.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/localealias.c
-textdomain.lo: $(srcdir)/textdomain.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/textdomain.c
-l10nflist.lo: $(srcdir)/l10nflist.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/l10nflist.c
-explodename.lo: $(srcdir)/explodename.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/explodename.c
-dcigettext.lo: $(srcdir)/dcigettext.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dcigettext.c
-dcngettext.lo: $(srcdir)/dcngettext.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dcngettext.c
-dngettext.lo: $(srcdir)/dngettext.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dngettext.c
-ngettext.lo: $(srcdir)/ngettext.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/ngettext.c
-plural.lo: $(srcdir)/plural.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/plural.c
-plural-exp.lo: $(srcdir)/plural-exp.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/plural-exp.c
-localcharset.lo: $(srcdir)/localcharset.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/localcharset.c
-relocatable.lo: $(srcdir)/relocatable.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/relocatable.c
-localename.lo: $(srcdir)/localename.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/localename.c
-log.lo: $(srcdir)/log.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/log.c
-osdep.lo: $(srcdir)/osdep.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/osdep.c
-intl-compat.lo: $(srcdir)/intl-compat.c
-       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/intl-compat.c
-
-ref-add.sed: $(srcdir)/ref-add.sin
-       sed -e '/^#/d' -e 's/@''PACKAGE''@/@PACKAGE@/g' $(srcdir)/ref-add.sin > t-ref-add.sed
-       mv t-ref-add.sed ref-add.sed
-ref-del.sed: $(srcdir)/ref-del.sin
-       sed -e '/^#/d' -e 's/@''PACKAGE''@/@PACKAGE@/g' $(srcdir)/ref-del.sin > t-ref-del.sed
-       mv t-ref-del.sed ref-del.sed
-
-INCLUDES = -I. -I$(srcdir) -I${top_builddir} -I${top_srcdir}
-
-libgnuintl.h: $(srcdir)/libgnuintl.h.in
-       cp $(srcdir)/libgnuintl.h.in libgnuintl.h
-
-libintl.h: libgnuintl.h
-       cmp libgnuintl.h libintl.h || cp libgnuintl.h libintl.h
-
-charset.alias: $(srcdir)/config.charset
-       $(SHELL) $(srcdir)/config.charset '@host@' > t-$@
-       mv t-$@ $@
-
-check: all
-
-# We must not install the libintl.h/libintl.a files if we are on a
-# system which has the GNU gettext() function in its C library or in a
-# separate library.
-# If you want to use the one which comes with this version of the
-# package, you have to use `configure --with-included-gettext'.
-install: install-exec install-data
-install-exec: all
-       if { test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; } \
-          && test '@USE_INCLUDED_LIBINTL@' = yes; then \
-         $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \
-         $(INSTALL_DATA) libintl.h $(DESTDIR)$(includedir)/libintl.h; \
-         $(LIBTOOL) --mode=install \
-           $(INSTALL_DATA) libintl.$la $(DESTDIR)$(libdir)/libintl.$la; \
-         if test "@RELOCATABLE@" = yes; then \
-           dependencies=`sed -n -e 's,^dependency_libs=\(.*\),\1,p' < $(DESTDIR)$(libdir)/libintl.la | sed -e "s,^',," -e "s,'\$$,,"`; \
-           if test -n "$dependencies"; then \
-             rm -f $(DESTDIR)$(libdir)/libintl.la; \
-           fi; \
-         fi; \
-       else \
-         : ; \
-       fi
-       if test "$(PACKAGE)" = "gettext-tools" \
-          && test '@USE_INCLUDED_LIBINTL@' = no; then \
-         $(mkinstalldirs) $(DESTDIR)$(libdir); \
-         $(LIBTOOL) --mode=install \
-           $(INSTALL_DATA) libgnuintl.$la $(DESTDIR)$(libdir)/libgnuintl.$la; \
-         rm -f $(DESTDIR)$(libdir)/preloadable_libintl.so; \
-         $(INSTALL_DATA) $(DESTDIR)$(libdir)/libgnuintl.so $(DESTDIR)$(libdir)/preloadable_libintl.so; \
-         $(LIBTOOL) --mode=uninstall \
-           rm -f $(DESTDIR)$(libdir)/libgnuintl.$la; \
-       else \
-         : ; \
-       fi
-       if test '@USE_INCLUDED_LIBINTL@' = yes; then \
-         $(mkinstalldirs) $(DESTDIR)$(localedir); \
-         test -f $(DESTDIR)$(localedir)/locale.alias \
-           && orig=$(DESTDIR)$(localedir)/locale.alias \
-           || orig=$(srcdir)/locale.alias; \
-         temp=$(DESTDIR)$(localedir)/t-locale.alias; \
-         dest=$(DESTDIR)$(localedir)/locale.alias; \
-         sed -f ref-add.sed $$orig > $$temp; \
-         $(INSTALL_DATA) $$temp $$dest; \
-         rm -f $$temp; \
-       else \
-         : ; \
-       fi
-install-data: all
-       if test "$(PACKAGE)" = "gettext-tools"; then \
-         $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \
-         $(INSTALL_DATA) VERSION $(DESTDIR)$(gettextsrcdir)/VERSION; \
-         $(INSTALL_DATA) ChangeLog.inst $(DESTDIR)$(gettextsrcdir)/ChangeLog; \
-         dists="COPYING.LIB-2.0 COPYING.LIB-2.1 $(DISTFILES.common)"; \
-         for file in $$dists; do \
-           $(INSTALL_DATA) $(srcdir)/$$file \
-                           $(DESTDIR)$(gettextsrcdir)/$$file; \
-         done; \
-         chmod a+x $(DESTDIR)$(gettextsrcdir)/config.charset; \
-         dists="$(DISTFILES.generated)"; \
-         for file in $$dists; do \
-           if test -f $$file; then dir=.; else dir=$(srcdir); fi; \
-           $(INSTALL_DATA) $$dir/$$file \
-                           $(DESTDIR)$(gettextsrcdir)/$$file; \
-         done; \
-         dists="$(DISTFILES.obsolete)"; \
-         for file in $$dists; do \
-           rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
-         done; \
-       else \
-         : ; \
-       fi
-
-install-strip: install
-
-installdirs:
-       if { test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; } \
-          && test '@USE_INCLUDED_LIBINTL@' = yes; then \
-         $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \
-       else \
-         : ; \
-       fi
-       if test "$(PACKAGE)" = "gettext-tools" \
-          && test '@USE_INCLUDED_LIBINTL@' = no; then \
-         $(mkinstalldirs) $(DESTDIR)$(libdir); \
-       else \
-         : ; \
-       fi
-       if test '@USE_INCLUDED_LIBINTL@' = yes; then \
-         test @GLIBC21@ != no || $(mkinstalldirs) $(DESTDIR)$(libdir); \
-         $(mkinstalldirs) $(DESTDIR)$(localedir); \
-       else \
-         : ; \
-       fi
-       if test "$(PACKAGE)" = "gettext-tools"; then \
-         $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \
-       else \
-         : ; \
-       fi
-
-# Define this as empty until I found a useful application.
-installcheck:
-
-uninstall:
-       if { test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; } \
-          && test '@USE_INCLUDED_LIBINTL@' = yes; then \
-         rm -f $(DESTDIR)$(includedir)/libintl.h; \
-         $(LIBTOOL) --mode=uninstall \
-           rm -f $(DESTDIR)$(libdir)/libintl.$la; \
-       else \
-         : ; \
-       fi
-       if test "$(PACKAGE)" = "gettext-tools" \
-          && test '@USE_INCLUDED_LIBINTL@' = no; then \
-         rm -f $(DESTDIR)$(libdir)/preloadable_libintl.so; \
-       else \
-         : ; \
-       fi
-       if test '@USE_INCLUDED_LIBINTL@' = yes; then \
-         if test -f $(DESTDIR)$(prefix)/libdata/charset.alias; then \
-           temp=$(DESTDIR)$(prefix)/libdata/t-charset.alias; \
-           dest=$(DESTDIR)$(prefix)/libdata/charset.alias; \
-           sed -f ref-del.sed $$dest > $$temp; \
-           if grep '^# Packages using this file: $$' $$temp > /dev/null; then \
-             rm -f $$dest; \
-           else \
-             $(INSTALL_DATA) $$temp $$dest; \
-           fi; \
-           rm -f $$temp; \
-         fi; \
-         if test -f $(DESTDIR)$(localedir)/locale.alias; then \
-           temp=$(DESTDIR)$(localedir)/t-locale.alias; \
-           dest=$(DESTDIR)$(localedir)/locale.alias; \
-           sed -f ref-del.sed $$dest > $$temp; \
-           if grep '^# Packages using this file: $$' $$temp > /dev/null; then \
-             rm -f $$dest; \
-           else \
-             $(INSTALL_DATA) $$temp $$dest; \
-           fi; \
-           rm -f $$temp; \
-         fi; \
-       else \
-         : ; \
-       fi
-       if test "$(PACKAGE)" = "gettext-tools"; then \
-         for file in VERSION ChangeLog COPYING.LIB-2.0 COPYING.LIB-2.1 $(DISTFILES.common) $(DISTFILES.generated); do \
-           rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
-         done; \
-       else \
-         : ; \
-       fi
-
-info dvi ps pdf html:
-
-$(OBJECTS): ${top_builddir}/config.h libgnuintl.h
-bindtextdom.$lo dcgettext.$lo dcigettext.$lo dcngettext.$lo dgettext.$lo dngettext.$lo finddomain.$lo gettext.$lo intl-compat.$lo loadmsgcat.$lo localealias.$lo ngettext.$lo textdomain.$lo: $(srcdir)/gettextP.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h
-dcigettext.$lo loadmsgcat.$lo: $(srcdir)/hash-string.h
-explodename.$lo l10nflist.$lo: $(srcdir)/loadinfo.h
-dcigettext.$lo loadmsgcat.$lo plural.$lo plural-exp.$lo: $(srcdir)/plural-exp.h
-dcigettext.$lo: $(srcdir)/eval-plural.h
-localcharset.$lo: $(srcdir)/localcharset.h
-localealias.$lo localcharset.$lo relocatable.$lo: $(srcdir)/relocatable.h
-
-tags: TAGS
-
-TAGS: $(HEADERS) $(SOURCES)
-       here=`pwd`; cd $(srcdir) && etags -o $$here/TAGS $(HEADERS) $(SOURCES)
-
-ctags: CTAGS
-
-CTAGS: $(HEADERS) $(SOURCES)
-       here=`pwd`; cd $(srcdir) && ctags -o $$here/CTAGS $(HEADERS) $(SOURCES)
-
-id: ID
-
-ID: $(HEADERS) $(SOURCES)
-       here=`pwd`; cd $(srcdir) && mkid -f$$here/ID $(HEADERS) $(SOURCES)
-
-
-mostlyclean:
-       rm -f *.a *.la *.o *.obj *.lo core core.*
-       rm -f libgnuintl.h libintl.h charset.alias ref-add.sed ref-del.sed
-       rm -f -r .libs _libs
-
-clean: mostlyclean
-
-distclean: clean
-       rm -f Makefile ID TAGS
-       if test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; then \
-         rm -f ChangeLog.inst $(DISTFILES.normal); \
-       else \
-         : ; \
-       fi
-
-maintainer-clean: distclean
-       @echo "This command is intended for maintainers to use;"
-       @echo "it deletes files that may require special tools to rebuild."
-
-
-# GNU gettext needs not contain the file `VERSION' but contains some
-# other files which should not be distributed in other packages.
-distdir = ../$(PACKAGE)-$(VERSION)/$(subdir)
-dist distdir: Makefile
-       if test "$(PACKAGE)" = "gettext-tools"; then \
-         : ; \
-       else \
-         if test "$(PACKAGE)" = "gettext-runtime"; then \
-           additional="$(DISTFILES.gettext)"; \
-         else \
-           additional="$(DISTFILES.normal)"; \
-         fi; \
-         $(MAKE) $(DISTFILES.common) $(DISTFILES.generated) $$additional; \
-         for file in ChangeLog $(DISTFILES.common) $(DISTFILES.generated) $$additional; do \
-           if test -f $$file; then dir=.; else dir=$(srcdir); fi; \
-           cp -p $$dir/$$file $(distdir); \
-         done; \
-       fi
-
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-       cd $(top_builddir) && $(SHELL) ./config.status
-# This would be more efficient, but doesn't work any more with autoconf-2.57,
-# when AC_CONFIG_FILES([intl/Makefile:somedir/Makefile.in]) is used.
-#      cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-# Tell versions [3.59,3.63) of GNU make not to export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
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/lib/readline/doc/rltech.texi~ b/lib/readline/doc/rltech.texi~
deleted file mode 100644 (file)
index f2d2a51..0000000
+++ /dev/null
@@ -1,2471 +0,0 @@
-@comment %**start of header (This is for running Texinfo on a region.)
-@setfilename rltech.info
-@comment %**end of header (This is for running Texinfo on a region.)
-
-@ifinfo
-This document describes the GNU Readline Library, a utility for aiding
-in the consistency of user interface across discrete programs that need
-to provide a command line interface.
-
-Copyright (C) 1988--2012 Free Software Foundation, Inc.
-
-Permission is granted to make and distribute verbatim copies of
-this manual provided the copyright notice and this permission notice
-pare preserved on all copies.
-
-@ignore
-Permission is granted to process this file through TeX and print the
-results, provided the printed document carries copying permission
-notice identical to this one except for the removal of this paragraph
-(this paragraph not being relevant to the printed manual).
-@end ignore
-
-Permission is granted to copy and distribute modified versions of this
-manual under the conditions for verbatim copying, provided that the entire
-resulting derived work is distributed under the terms of a permission
-notice identical to this one.
-
-Permission is granted to copy and distribute translations of this manual
-into another language, under the above conditions for modified versions,
-except that this permission notice may be stated in a translation approved
-by the Foundation.
-@end ifinfo
-
-@node Programming with GNU Readline
-@chapter Programming with GNU Readline
-
-This chapter describes the interface between the @sc{gnu} Readline Library and
-other programs.  If you are a programmer, and you wish to include the
-features found in @sc{gnu} Readline
-such as completion, line editing, and interactive history manipulation
-in your own programs, this section is for you.
-
-@menu
-* Basic Behavior::     Using the default behavior of Readline.
-* Custom Functions::   Adding your own functions to Readline.
-* Readline Variables::                 Variables accessible to custom
-                                       functions.
-* Readline Convenience Functions::     Functions which Readline supplies to
-                                       aid in writing your own custom
-                                       functions.
-* Readline Signal Handling::   How Readline behaves when it receives signals.
-* Custom Completers::  Supplanting or supplementing Readline's
-                       completion functions.
-@end menu
-
-@node Basic Behavior
-@section Basic Behavior
-
-Many programs provide a command line interface, such as @code{mail},
-@code{ftp}, and @code{sh}.  For such programs, the default behaviour of
-Readline is sufficient.  This section describes how to use Readline in
-the simplest way possible, perhaps to replace calls in your code to
-@code{gets()} or @code{fgets()}.
-
-@findex readline
-@cindex readline, function
-
-The function @code{readline()} prints a prompt @var{prompt}
-and then reads and returns a single line of text from the user.
-If @var{prompt} is @code{NULL} or the empty string, no prompt is displayed.
-The line @code{readline} returns is allocated with @code{malloc()};
-the caller should @code{free()} the line when it has finished with it.
-The declaration for @code{readline} in ANSI C is
-
-@example
-@code{char *readline (const char *@var{prompt});}
-@end example
-
-@noindent
-So, one might say
-@example
-@code{char *line = readline ("Enter a line: ");}
-@end example
-@noindent
-in order to read a line of text from the user.
-The line returned has the final newline removed, so only the
-text remains.
-
-If @code{readline} encounters an @code{EOF} while reading the line, and the
-line is empty at that point, then @code{(char *)NULL} is returned.
-Otherwise, the line is ended just as if a newline had been typed.
-
-If you want the user to be able to get at the line later, (with
-@key{C-p} for example), you must call @code{add_history()} to save the
-line away in a @dfn{history} list of such lines.
-
-@example
-@code{add_history (line)};
-@end example
-
-@noindent
-For full details on the GNU History Library, see the associated manual.
-
-It is preferable to avoid saving empty lines on the history list, since
-users rarely have a burning need to reuse a blank line.  Here is
-a function which usefully replaces the standard @code{gets()} library
-function, and has the advantage of no static buffer to overflow:
-
-@example
-/* A static variable for holding the line. */
-static char *line_read = (char *)NULL;
-
-/* Read a string, and return a pointer to it.
-   Returns NULL on EOF. */
-char *
-rl_gets ()
-@{
-  /* If the buffer has already been allocated,
-     return the memory to the free pool. */
-  if (line_read)
-    @{
-      free (line_read);
-      line_read = (char *)NULL;
-    @}
-
-  /* Get a line from the user. */
-  line_read = readline ("");
-
-  /* If the line has any text in it,
-     save it on the history. */
-  if (line_read && *line_read)
-    add_history (line_read);
-
-  return (line_read);
-@}
-@end example
-
-This function gives the user the default behaviour of @key{TAB}
-completion: completion on file names.  If you do not want Readline to
-complete on filenames, you can change the binding of the @key{TAB} key
-with @code{rl_bind_key()}.
-
-@example
-@code{int rl_bind_key (int @var{key}, rl_command_func_t *@var{function});}
-@end example
-
-@code{rl_bind_key()} takes two arguments: @var{key} is the character that
-you want to bind, and @var{function} is the address of the function to
-call when @var{key} is pressed.  Binding @key{TAB} to @code{rl_insert()}
-makes @key{TAB} insert itself.
-@code{rl_bind_key()} returns non-zero if @var{key} is not a valid
-ASCII character code (between 0 and 255).
-
-Thus, to disable the default @key{TAB} behavior, the following suffices:
-@example
-@code{rl_bind_key ('\t', rl_insert);}
-@end example
-
-This code should be executed once at the start of your program; you
-might write a function called @code{initialize_readline()} which
-performs this and other desired initializations, such as installing
-custom completers (@pxref{Custom Completers}).
-
-@node Custom Functions
-@section Custom Functions
-
-Readline provides many functions for manipulating the text of
-the line, but it isn't possible to anticipate the needs of all
-programs.  This section describes the various functions and variables
-defined within the Readline library which allow a user program to add
-customized functionality to Readline.
-
-Before declaring any functions that customize Readline's behavior, or
-using any functionality Readline provides in other code, an
-application writer should include the file @code{<readline/readline.h>}
-in any file that uses Readline's features.  Since some of the definitions
-in @code{readline.h} use the @code{stdio} library, the file
-@code{<stdio.h>} should be included before @code{readline.h}.
-
-@code{readline.h} defines a C preprocessor variable that should
-be treated as an integer, @code{RL_READLINE_VERSION}, which may
-be used to conditionally compile application code depending on
-the installed Readline version.  The value is a hexadecimal
-encoding of the major and minor version numbers of the library,
-of the form 0x@var{MMmm}.  @var{MM} is the two-digit major
-version number; @var{mm} is the two-digit minor version number. 
-For Readline 4.2, for example, the value of
-@code{RL_READLINE_VERSION} would be @code{0x0402}. 
-
-@menu
-* Readline Typedefs::  C declarations to make code readable.
-* Function Writing::   Variables and calling conventions.
-@end menu
-
-@node Readline Typedefs
-@subsection Readline Typedefs
-
-For readabilty, we declare a number of new object types, all pointers
-to functions.
-
-The reason for declaring these new types is to make it easier to write
-code describing pointers to C functions with appropriately prototyped
-arguments and return values.
-
-For instance, say we want to declare a variable @var{func} as a pointer
-to a function which takes two @code{int} arguments and returns an
-@code{int} (this is the type of all of the Readline bindable functions).
-Instead of the classic C declaration
-
-@code{int (*func)();}
-
-@noindent
-or the ANSI-C style declaration
-
-@code{int (*func)(int, int);}
-
-@noindent
-we may write
-
-@code{rl_command_func_t *func;}
-
-The full list of function pointer types available is
-
-@table @code
-@item typedef int rl_command_func_t (int, int);
-
-@item typedef char *rl_compentry_func_t (const char *, int);
-
-@item typedef char **rl_completion_func_t (const char *, int, int);
-
-@item typedef char *rl_quote_func_t (char *, int, char *);
-
-@item typedef char *rl_dequote_func_t (char *, int);
-
-@item typedef int rl_compignore_func_t (char **);
-
-@item typedef void rl_compdisp_func_t (char **, int, int);
-
-@item typedef int rl_hook_func_t (void);
-
-@item typedef int rl_getc_func_t (FILE *);
-
-@item typedef int rl_linebuf_func_t (char *, int);
-
-@item typedef int rl_intfunc_t (int);
-@item #define rl_ivoidfunc_t rl_hook_func_t
-@item typedef int rl_icpfunc_t (char *);
-@item typedef int rl_icppfunc_t (char **);
-
-@item typedef void rl_voidfunc_t (void);
-@item typedef void rl_vintfunc_t (int);
-@item typedef void rl_vcpfunc_t (char *);
-@item typedef void rl_vcppfunc_t (char **);
-
-@end table
-
-@node Function Writing
-@subsection Writing a New Function
-
-In order to write new functions for Readline, you need to know the
-calling conventions for keyboard-invoked functions, and the names of the
-variables that describe the current state of the line read so far.
-
-The calling sequence for a command @code{foo} looks like
-
-@example
-@code{int foo (int count, int key)}
-@end example
-
-@noindent
-where @var{count} is the numeric argument (or 1 if defaulted) and
-@var{key} is the key that invoked this function.
-
-It is completely up to the function as to what should be done with the
-numeric argument.  Some functions use it as a repeat count, some
-as a flag, and others to choose alternate behavior (refreshing the current
-line as opposed to refreshing the screen, for example).  Some choose to
-ignore it.  In general, if a
-function uses the numeric argument as a repeat count, it should be able
-to do something useful with both negative and positive arguments.
-At the very least, it should be aware that it can be passed a
-negative argument.
-
-A command function should return 0 if its action completes successfully,
-and a non-zero value if some error occurs.
-This is the convention obeyed by all of the builtin Readline bindable
-command functions.
-
-@node Readline Variables
-@section Readline Variables
-
-These variables are available to function writers.
-
-@deftypevar {char *} rl_line_buffer
-This is the line gathered so far.  You are welcome to modify the
-contents of the line, but see @ref{Allowing Undoing}.  The
-function @code{rl_extend_line_buffer} is available to increase
-the memory allocated to @code{rl_line_buffer}.
-@end deftypevar
-
-@deftypevar int rl_point
-The offset of the current cursor position in @code{rl_line_buffer}
-(the @emph{point}).
-@end deftypevar
-
-@deftypevar int rl_end
-The number of characters present in @code{rl_line_buffer}.  When
-@code{rl_point} is at the end of the line, @code{rl_point} and
-@code{rl_end} are equal.
-@end deftypevar
-
-@deftypevar int rl_mark
-The @var{mark} (saved position) in the current line.  If set, the mark
-and point define a @emph{region}.
-@end deftypevar
-
-@deftypevar int rl_done
-Setting this to a non-zero value causes Readline to return the current
-line immediately.
-@end deftypevar
-
-@deftypevar int rl_num_chars_to_read
-Setting this to a positive value before calling @code{readline()} causes
-Readline to return after accepting that many characters, rather
-than reading up to a character bound to @code{accept-line}.
-@end deftypevar
-
-@deftypevar int rl_pending_input
-Setting this to a value makes it the next keystroke read.  This is a
-way to stuff a single character into the input stream.
-@end deftypevar
-
-@deftypevar int rl_dispatching
-Set to a non-zero value if a function is being called from a key binding;
-zero otherwise.  Application functions can test this to discover whether
-they were called directly or by Readline's dispatching mechanism.
-@end deftypevar
-
-@deftypevar int rl_erase_empty_line
-Setting this to a non-zero value causes Readline to completely erase
-the current line, including any prompt, any time a newline is typed as
-the only character on an otherwise-empty line.  The cursor is moved to
-the beginning of the newly-blank line.
-@end deftypevar
-
-@deftypevar {char *} rl_prompt
-The prompt Readline uses.  This is set from the argument to
-@code{readline()}, and should not be assigned to directly.
-The @code{rl_set_prompt()} function (@pxref{Redisplay}) may
-be used to modify the prompt string after calling @code{readline()}.
-@end deftypevar
-
-@deftypevar {char *} rl_display_prompt
-The string displayed as the prompt.  This is usually identical to
-@var{rl_prompt}, but may be changed temporarily by functions that
-use the prompt string as a message area, such as incremental search.
-@end deftypevar
-
-@deftypevar int rl_already_prompted
-If an application wishes to display the prompt itself, rather than have
-Readline do it the first time @code{readline()} is called, it should set
-this variable to a non-zero value after displaying the prompt.
-The prompt must also be passed as the argument to @code{readline()} so
-the redisplay functions can update the display properly.
-The calling application is responsible for managing the value; Readline
-never sets it.
-@end deftypevar
-
-@deftypevar {const char *} rl_library_version
-The version number of this revision of the library.
-@end deftypevar
-
-@deftypevar int rl_readline_version
-An integer encoding the current version of the library.  The encoding is
-of the form 0x@var{MMmm}, where @var{MM} is the two-digit major version
-number, and @var{mm} is the two-digit minor version number.
-For example, for Readline-4.2, @code{rl_readline_version} would have the
-value 0x0402.
-@end deftypevar
-
-@deftypevar {int} rl_gnu_readline_p
-Always set to 1, denoting that this is @sc{gnu} readline rather than some
-emulation.
-@end deftypevar
-
-@deftypevar {const char *} rl_terminal_name
-The terminal type, used for initialization.  If not set by the application,
-Readline sets this to the value of the @env{TERM} environment variable
-the first time it is called.
-@end deftypevar
-
-@deftypevar {const char *} rl_readline_name
-This variable is set to a unique name by each application using Readline.
-The value allows conditional parsing of the inputrc file
-(@pxref{Conditional Init Constructs}).
-@end deftypevar
-
-@deftypevar {FILE *} rl_instream
-The stdio stream from which Readline reads input.
-If @code{NULL}, Readline defaults to @var{stdin}.
-@end deftypevar
-
-@deftypevar {FILE *} rl_outstream
-The stdio stream to which Readline performs output.
-If @code{NULL}, Readline defaults to @var{stdout}.
-@end deftypevar
-
-@deftypevar int rl_prefer_env_winsize
-If non-zero, Readline gives values found in the @env{LINES} and
-@env{COLUMNS} environment variables greater precedence than values fetched
-from the kernel when computing the screen dimensions.
-@end deftypevar
-
-@deftypevar {rl_command_func_t *} rl_last_func
-The address of the last command function Readline executed.  May be used to
-test whether or not a function is being executed twice in succession, for
-example.
-@end deftypevar
-
-@deftypevar {rl_hook_func_t *} rl_startup_hook
-If non-zero, this is the address of a function to call just
-before @code{readline} prints the first prompt.
-@end deftypevar
-
-@deftypevar {rl_hook_func_t *} rl_pre_input_hook
-If non-zero, this is the address of a function to call after
-the first prompt has been printed and just before @code{readline}
-starts reading input characters.
-@end deftypevar
-
-@deftypevar {rl_hook_func_t *} rl_event_hook
-If non-zero, this is the address of a function to call periodically
-when Readline is waiting for terminal input.
-By default, this will be called at most ten times a second if there
-is no keyboard input.
-@end deftypevar
-
-@deftypevar {rl_getc_func_t *} rl_getc_function
-If non-zero, Readline will call indirectly through this pointer
-to get a character from the input stream.  By default, it is set to
-@code{rl_getc}, the default Readline character input function
-(@pxref{Character Input}).
-@end deftypevar
-
-@deftypevar {rl_hook_func_t *} rl_input_available_hook
-If non-zero, Readline will use this function's return value when it needs
-to determine whether or not there is available input on the current input
-source.
-Readline queries for available input when implementing intra-key-sequence
-timeouts during input and incremental searches.
-This may use an application-specific timeout before returning a value;
-Readline uses the value passed to @code{rl_set_keyboard_input_timeout()}
-or the value of the user-settable @var{keyseq-timeout} variable.
-This is designed for use by functions using Readline's callback interface
-(@pxref{Alternate Interface}), which may not use the traditional
-@code{read(2)} and file descriptor interface.
-@end deftypevar
-
-@deftypevar {rl_voidfunc_t *} rl_redisplay_function
-If non-zero, Readline will call indirectly through this pointer
-to update the display with the current contents of the editing buffer.
-By default, it is set to @code{rl_redisplay}, the default Readline
-redisplay function (@pxref{Redisplay}).
-@end deftypevar
-
-@deftypevar {rl_vintfunc_t *} rl_prep_term_function
-If non-zero, Readline will call indirectly through this pointer
-to initialize the terminal.  The function takes a single argument, an
-@code{int} flag that says whether or not to use eight-bit characters.
-By default, this is set to @code{rl_prep_terminal}
-(@pxref{Terminal Management}).
-@end deftypevar
-
-@deftypevar {rl_voidfunc_t *} rl_deprep_term_function
-If non-zero, Readline will call indirectly through this pointer
-to reset the terminal.  This function should undo the effects of
-@code{rl_prep_term_function}.
-By default, this is set to @code{rl_deprep_terminal}
-(@pxref{Terminal Management}).
-@end deftypevar
-
-@deftypevar {Keymap} rl_executing_keymap
-This variable is set to the keymap (@pxref{Keymaps}) in which the
-currently executing readline function was found.
-@end deftypevar 
-
-@deftypevar {Keymap} rl_binding_keymap
-This variable is set to the keymap (@pxref{Keymaps}) in which the
-last key binding occurred.
-@end deftypevar 
-
-@deftypevar {char *} rl_executing_macro
-This variable is set to the text of any currently-executing macro.
-@end deftypevar
-
-@deftypevar int rl_executing_key
-The key that caused the dispatch to the currently-executing Readline function.
-@end deftypevar
-
-@deftypevar {char *} rl_executing_keyseq
-The full key sequence that caused the dispatch to the currently-executing
-Readline function.
-@end deftypevar
-
-@deftypevar int rl_key_sequence_length
-The number of characters in @var{rl_executing_keyseq}.
-@end deftypevar
-
-@deftypevar {int} rl_readline_state
-A variable with bit values that encapsulate the current Readline state.
-A bit is set with the @code{RL_SETSTATE} macro, and unset with the
-@code{RL_UNSETSTATE} macro.  Use the @code{RL_ISSTATE} macro to test
-whether a particular state bit is set.  Current state bits include:
-
-@table @code
-@item RL_STATE_NONE
-Readline has not yet been called, nor has it begun to intialize.
-@item RL_STATE_INITIALIZING
-Readline is initializing its internal data structures.
-@item RL_STATE_INITIALIZED
-Readline has completed its initialization.
-@item RL_STATE_TERMPREPPED
-Readline has modified the terminal modes to do its own input and redisplay.
-@item RL_STATE_READCMD
-Readline is reading a command from the keyboard.
-@item RL_STATE_METANEXT
-Readline is reading more input after reading the meta-prefix character.
-@item RL_STATE_DISPATCHING
-Readline is dispatching to a command.
-@item RL_STATE_MOREINPUT
-Readline is reading more input while executing an editing command.
-@item RL_STATE_ISEARCH
-Readline is performing an incremental history search.
-@item RL_STATE_NSEARCH
-Readline is performing a non-incremental history search.
-@item RL_STATE_SEARCH
-Readline is searching backward or forward through the history for a string.
-@item RL_STATE_NUMERICARG
-Readline is reading a numeric argument.
-@item RL_STATE_MACROINPUT
-Readline is currently getting its input from a previously-defined keyboard
-macro.
-@item RL_STATE_MACRODEF
-Readline is currently reading characters defining a keyboard macro.
-@item RL_STATE_OVERWRITE
-Readline is in overwrite mode.
-@item RL_STATE_COMPLETING
-Readline is performing word completion.
-@item RL_STATE_SIGHANDLER
-Readline is currently executing the readline signal handler.
-@item RL_STATE_UNDOING
-Readline is performing an undo.
-@item RL_STATE_INPUTPENDING
-Readline has input pending due to a call to @code{rl_execute_next()}.
-@item RL_STATE_TTYCSAVED
-Readline has saved the values of the terminal's special characters.
-@item RL_STATE_CALLBACK
-Readline is currently using the alternate (callback) interface
-(@pxref{Alternate Interface}).
-@item RL_STATE_VIMOTION
-Readline is reading the argument to a vi-mode "motion" command.
-@item RL_STATE_MULTIKEY
-Readline is reading a multiple-keystroke command.
-@item RL_STATE_VICMDONCE
-Readline has entered vi command (movement) mode at least one time during
-the current call to @code{readline()}.
-@item RL_STATE_DONE
-Readline has read a key sequence bound to @code{accept-line}
-and is about to return the line to the caller.
-@end table
-
-@end deftypevar
-
-@deftypevar {int} rl_explicit_arg
-Set to a non-zero value if an explicit numeric argument was specified by
-the user.  Only valid in a bindable command function.
-@end deftypevar
-
-@deftypevar {int} rl_numeric_arg
-Set to the value of any numeric argument explicitly specified by the user
-before executing the current Readline function.  Only valid in a bindable
-command function.
-@end deftypevar
-
-@deftypevar {int} rl_editing_mode
-Set to a value denoting Readline's current editing mode.  A value of
-@var{1} means Readline is currently in emacs mode; @var{0}
-means that vi mode is active.
-@end deftypevar
-
-
-@node Readline Convenience Functions
-@section Readline Convenience Functions
-
-@menu
-* Function Naming::    How to give a function you write a name.
-* Keymaps::            Making keymaps.
-* Binding Keys::       Changing Keymaps.
-* Associating Function Names and Bindings::    Translate function names to
-                                               key sequences.
-* Allowing Undoing::   How to make your functions undoable.
-* Redisplay::          Functions to control line display.
-* Modifying Text::     Functions to modify @code{rl_line_buffer}.
-* Character Input::    Functions to read keyboard input.
-* Terminal Management::        Functions to manage terminal settings.
-* Utility Functions::  Generally useful functions and hooks.
-* Miscellaneous Functions::    Functions that don't fall into any category.
-* Alternate Interface::        Using Readline in a `callback' fashion.
-* A Readline Example::         An example Readline function.
-@end menu
-
-@node Function Naming
-@subsection Naming a Function
-
-The user can dynamically change the bindings of keys while using
-Readline.  This is done by representing the function with a descriptive
-name.  The user is able to type the descriptive name when referring to
-the function.  Thus, in an init file, one might find
-
-@example
-Meta-Rubout:   backward-kill-word
-@end example
-
-This binds the keystroke @key{Meta-Rubout} to the function
-@emph{descriptively} named @code{backward-kill-word}.  You, as the
-programmer, should bind the functions you write to descriptive names as
-well.  Readline provides a function for doing that:
-
-@deftypefun int rl_add_defun (const char *name, rl_command_func_t *function, int key)
-Add @var{name} to the list of named functions.  Make @var{function} be
-the function that gets called.  If @var{key} is not -1, then bind it to
-@var{function} using @code{rl_bind_key()}.
-@end deftypefun
-
-Using this function alone is sufficient for most applications.
-It is the recommended way to add a few functions to the default
-functions that Readline has built in.
-If you need to do something other than adding a function to Readline,
-you may need to use the underlying functions described below.
-
-@node Keymaps
-@subsection Selecting a Keymap
-
-Key bindings take place on a @dfn{keymap}.  The keymap is the
-association between the keys that the user types and the functions that
-get run.  You can make your own keymaps, copy existing keymaps, and tell
-Readline which keymap to use.
-
-@deftypefun Keymap rl_make_bare_keymap (void)
-Returns a new, empty keymap.  The space for the keymap is allocated with
-@code{malloc()}; the caller should free it by calling
-@code{rl_free_keymap()} when done.
-@end deftypefun
-
-@deftypefun Keymap rl_copy_keymap (Keymap map)
-Return a new keymap which is a copy of @var{map}.
-@end deftypefun
-
-@deftypefun Keymap rl_make_keymap (void)
-Return a new keymap with the printing characters bound to rl_insert,
-the lowercase Meta characters bound to run their equivalents, and
-the Meta digits bound to produce numeric arguments.
-@end deftypefun
-
-@deftypefun void rl_discard_keymap (Keymap keymap)
-Free the storage associated with the data in @var{keymap}.
-The caller should free @var{keymap}.
-@end deftypefun
-
-@deftypefun void rl_free_keymap (Keymap keymap)
-Free all storage associated with @var{keymap}.  This calls
-@code{rl_discard_keymap} to free subordindate keymaps and macros.
-@end deftypefun
-
-Readline has several internal keymaps.  These functions allow you to
-change which keymap is active.
-
-@deftypefun Keymap rl_get_keymap (void)
-Returns the currently active keymap.
-@end deftypefun
-
-@deftypefun void rl_set_keymap (Keymap keymap)
-Makes @var{keymap} the currently active keymap.
-@end deftypefun
-
-@deftypefun Keymap rl_get_keymap_by_name (const char *name)
-Return the keymap matching @var{name}.  @var{name} is one which would
-be supplied in a @code{set keymap} inputrc line (@pxref{Readline Init File}).
-@end deftypefun
-
-@deftypefun {char *} rl_get_keymap_name (Keymap keymap)
-Return the name matching @var{keymap}.  @var{name} is one which would
-be supplied in a @code{set keymap} inputrc line (@pxref{Readline Init File}).
-@end deftypefun
-
-@node Binding Keys
-@subsection Binding Keys
-
-Key sequences are associate with functions through the keymap.
-Readline has several internal keymaps: @code{emacs_standard_keymap},
-@code{emacs_meta_keymap}, @code{emacs_ctlx_keymap},
-@code{vi_movement_keymap}, and @code{vi_insertion_keymap}.
-@code{emacs_standard_keymap} is the default, and the examples in
-this manual assume that.
-
-Since @code{readline()} installs a set of default key bindings the first
-time it is called, there is always the danger that a custom binding
-installed before the first call to @code{readline()} will be overridden.
-An alternate mechanism is to install custom key bindings in an
-initialization function assigned to the @code{rl_startup_hook} variable
-(@pxref{Readline Variables}).
-
-These functions manage key bindings.
-
-@deftypefun int rl_bind_key (int key, rl_command_func_t *function)
-Binds @var{key} to @var{function} in the currently active keymap.
-Returns non-zero in the case of an invalid @var{key}.
-@end deftypefun
-
-@deftypefun int rl_bind_key_in_map (int key, rl_command_func_t *function, Keymap map)
-Bind @var{key} to @var{function} in @var{map}.
-Returns non-zero in the case of an invalid @var{key}.
-@end deftypefun
-
-@deftypefun int rl_bind_key_if_unbound (int key, rl_command_func_t *function)
-Binds @var{key} to @var{function} if it is not already bound in the
-currently active keymap.
-Returns non-zero in the case of an invalid @var{key} or if @var{key} is
-already bound.
-@end deftypefun
-
-@deftypefun int rl_bind_key_if_unbound_in_map (int key, rl_command_func_t *function, Keymap map)
-Binds @var{key} to @var{function} if it is not already bound in @var{map}.
-Returns non-zero in the case of an invalid @var{key} or if @var{key} is
-already bound.
-@end deftypefun
-
-@deftypefun int rl_unbind_key (int key)
-Bind @var{key} to the null function in the currently active keymap.
-Returns non-zero in case of error.
-@end deftypefun
-
-@deftypefun int rl_unbind_key_in_map (int key, Keymap map)
-Bind @var{key} to the null function in @var{map}.
-Returns non-zero in case of error.
-@end deftypefun
-
-@deftypefun int rl_unbind_function_in_map (rl_command_func_t *function, Keymap map)
-Unbind all keys that execute @var{function} in @var{map}.
-@end deftypefun
-
-@deftypefun int rl_unbind_command_in_map (const char *command, Keymap map)
-Unbind all keys that are bound to @var{command} in @var{map}.
-@end deftypefun
-
-@deftypefun int rl_bind_keyseq (const char *keyseq, rl_command_func_t *function)
-Bind the key sequence represented by the string @var{keyseq} to the function
-@var{function}, beginning in the current keymap.
-This makes new keymaps as necessary.
-The return value is non-zero if @var{keyseq} is invalid.
-@end deftypefun
-
-@deftypefun int rl_bind_keyseq_in_map (const char *keyseq, rl_command_func_t *function, Keymap map)
-Bind the key sequence represented by the string @var{keyseq} to the function
-@var{function}.  This makes new keymaps as necessary.
-Initial bindings are performed in @var{map}.
-The return value is non-zero if @var{keyseq} is invalid.
-@end deftypefun
-
-@deftypefun int rl_set_key (const char *keyseq, rl_command_func_t *function, Keymap map)
-Equivalent to @code{rl_bind_keyseq_in_map}.
-@end deftypefun
-
-@deftypefun int rl_bind_keyseq_if_unbound (const char *keyseq, rl_command_func_t *function)
-Binds @var{keyseq} to @var{function} if it is not already bound in the
-currently active keymap.
-Returns non-zero in the case of an invalid @var{keyseq} or if @var{keyseq} is
-already bound.
-@end deftypefun
-
-@deftypefun int rl_bind_keyseq_if_unbound_in_map (const char *keyseq, rl_command_func_t *function, Keymap map)
-Binds @var{keyseq} to @var{function} if it is not already bound in @var{map}.
-Returns non-zero in the case of an invalid @var{keyseq} or if @var{keyseq} is
-already bound.
-@end deftypefun
-
-@deftypefun int rl_generic_bind (int type, const char *keyseq, char *data, Keymap map)
-Bind the key sequence represented by the string @var{keyseq} to the arbitrary
-pointer @var{data}.  @var{type} says what kind of data is pointed to by
-@var{data}; this can be a function (@code{ISFUNC}), a macro
-(@code{ISMACR}), or a keymap (@code{ISKMAP}).  This makes new keymaps as
-necessary.  The initial keymap in which to do bindings is @var{map}.
-@end deftypefun
-
-@deftypefun int rl_parse_and_bind (char *line)
-Parse @var{line} as if it had been read from the @code{inputrc} file and
-perform any key bindings and variable assignments found
-(@pxref{Readline Init File}).
-@end deftypefun
-
-@deftypefun int rl_read_init_file (const char *filename)
-Read keybindings and variable assignments from @var{filename}
-(@pxref{Readline Init File}).
-@end deftypefun
-
-@node Associating Function Names and Bindings
-@subsection Associating Function Names and Bindings
-
-These functions allow you to find out what keys invoke named functions
-and the functions invoked by a particular key sequence.  You may also
-associate a new function name with an arbitrary function.
-
-@deftypefun {rl_command_func_t *} rl_named_function (const char *name)
-Return the function with name @var{name}.
-@end deftypefun
-
-@deftypefun {rl_command_func_t *} rl_function_of_keyseq (const char *keyseq, Keymap map, int *type)
-Return the function invoked by @var{keyseq} in keymap @var{map}.
-If @var{map} is @code{NULL}, the current keymap is used.  If @var{type} is
-not @code{NULL}, the type of the object is returned in the @code{int} variable
-it points to (one of @code{ISFUNC}, @code{ISKMAP}, or @code{ISMACR}).
-@end deftypefun
-
-@deftypefun {char **} rl_invoking_keyseqs (rl_command_func_t *function)
-Return an array of strings representing the key sequences used to
-invoke @var{function} in the current keymap.
-@end deftypefun
-
-@deftypefun {char **} rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map)
-Return an array of strings representing the key sequences used to
-invoke @var{function} in the keymap @var{map}.
-@end deftypefun
-
-@deftypefun void rl_function_dumper (int readable)
-Print the readline function names and the key sequences currently
-bound to them to @code{rl_outstream}.  If @var{readable} is non-zero,
-the list is formatted in such a way that it can be made part of an
-@code{inputrc} file and re-read.
-@end deftypefun
-
-@deftypefun void rl_list_funmap_names (void)
-Print the names of all bindable Readline functions to @code{rl_outstream}.
-@end deftypefun
-
-@deftypefun {const char **} rl_funmap_names (void)
-Return a NULL terminated array of known function names.  The array is
-sorted.  The array itself is allocated, but not the strings inside.  You
-should free the array, but not the pointers, using @code{free} or
-@code{rl_free} when you are done.
-@end deftypefun
-
-@deftypefun int rl_add_funmap_entry (const char *name, rl_command_func_t *function)
-Add @var{name} to the list of bindable Readline command names, and make
-@var{function} the function to be called when @var{name} is invoked.
-@end deftypefun
-
-@node Allowing Undoing
-@subsection Allowing Undoing
-
-Supporting the undo command is a painless thing, and makes your
-functions much more useful.  It is certainly easy to try
-something if you know you can undo it.
-
-If your function simply inserts text once, or deletes text once, and
-uses @code{rl_insert_text()} or @code{rl_delete_text()} to do it, then
-undoing is already done for you automatically.
-
-If you do multiple insertions or multiple deletions, or any combination
-of these operations, you should group them together into one operation.
-This is done with @code{rl_begin_undo_group()} and
-@code{rl_end_undo_group()}.
-
-The types of events that can be undone are:
-
-@smallexample
-enum undo_code @{ UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END @}; 
-@end smallexample
-
-Notice that @code{UNDO_DELETE} means to insert some text, and
-@code{UNDO_INSERT} means to delete some text.  That is, the undo code
-tells what to undo, not how to undo it.  @code{UNDO_BEGIN} and
-@code{UNDO_END} are tags added by @code{rl_begin_undo_group()} and
-@code{rl_end_undo_group()}.
-
-@deftypefun int rl_begin_undo_group (void)
-Begins saving undo information in a group construct.  The undo
-information usually comes from calls to @code{rl_insert_text()} and
-@code{rl_delete_text()}, but could be the result of calls to
-@code{rl_add_undo()}.
-@end deftypefun
-
-@deftypefun int rl_end_undo_group (void)
-Closes the current undo group started with @code{rl_begin_undo_group
-()}.  There should be one call to @code{rl_end_undo_group()}
-for each call to @code{rl_begin_undo_group()}.
-@end deftypefun
-
-@deftypefun void rl_add_undo (enum undo_code what, int start, int end, char *text)
-Remember how to undo an event (according to @var{what}).  The affected
-text runs from @var{start} to @var{end}, and encompasses @var{text}.
-@end deftypefun
-
-@deftypefun void rl_free_undo_list (void)
-Free the existing undo list.
-@end deftypefun
-
-@deftypefun int rl_do_undo (void)
-Undo the first thing on the undo list.  Returns @code{0} if there was
-nothing to undo, non-zero if something was undone.
-@end deftypefun
-
-Finally, if you neither insert nor delete text, but directly modify the
-existing text (e.g., change its case), call @code{rl_modifying()}
-once, just before you modify the text.  You must supply the indices of
-the text range that you are going to modify.
-
-@deftypefun int rl_modifying (int start, int end)
-Tell Readline to save the text between @var{start} and @var{end} as a
-single undo unit.  It is assumed that you will subsequently modify
-that text.
-@end deftypefun
-
-@node Redisplay
-@subsection Redisplay
-
-@deftypefun void rl_redisplay (void)
-Change what's displayed on the screen to reflect the current contents
-of @code{rl_line_buffer}.
-@end deftypefun
-
-@deftypefun int rl_forced_update_display (void)
-Force the line to be updated and redisplayed, whether or not
-Readline thinks the screen display is correct.
-@end deftypefun
-
-@deftypefun int rl_on_new_line (void)
-Tell the update functions that we have moved onto a new (empty) line,
-usually after ouputting a newline.
-@end deftypefun
-
-@deftypefun int rl_on_new_line_with_prompt (void)
-Tell the update functions that we have moved onto a new line, with
-@var{rl_prompt} already displayed.
-This could be used by applications that want to output the prompt string
-themselves, but still need Readline to know the prompt string length for
-redisplay.
-It should be used after setting @var{rl_already_prompted}.
-@end deftypefun
-
-@deftypefun int rl_reset_line_state (void)
-Reset the display state to a clean state and redisplay the current line
-starting on a new line.
-@end deftypefun
-
-@deftypefun int rl_crlf (void)
-Move the cursor to the start of the next screen line.
-@end deftypefun
-
-@deftypefun int rl_show_char (int c)
-Display character @var{c} on @code{rl_outstream}.
-If Readline has not been set to display meta characters directly, this
-will convert meta characters to a meta-prefixed key sequence.
-This is intended for use by applications which wish to do their own
-redisplay.
-@end deftypefun
-
-@deftypefun int rl_message (const char *, @dots{})
-The arguments are a format string as would be supplied to @code{printf},
-possibly containing conversion specifications such as @samp{%d}, and
-any additional arguments necessary to satisfy the conversion specifications.
-The resulting string is displayed in the @dfn{echo area}.  The echo area
-is also used to display numeric arguments and search strings.
-You should call @code{rl_save_prompt} to save the prompt information
-before calling this function.
-@end deftypefun
-
-@deftypefun int rl_clear_message (void)
-Clear the message in the echo area.  If the prompt was saved with a call to
-@code{rl_save_prompt} before the last call to @code{rl_message},
-call @code{rl_restore_prompt} before calling this function.
-@end deftypefun
-
-@deftypefun void rl_save_prompt (void)
-Save the local Readline prompt display state in preparation for
-displaying a new message in the message area with @code{rl_message()}.
-@end deftypefun
-
-@deftypefun void rl_restore_prompt (void)
-Restore the local Readline prompt display state saved by the most
-recent call to @code{rl_save_prompt}.
-if @code{rl_save_prompt} was called to save the prompt before a call
-to @code{rl_message}, this function should be called before the
-corresponding call to @code{rl_clear_message}.
-@end deftypefun
-
-@deftypefun int rl_expand_prompt (char *prompt)
-Expand any special character sequences in @var{prompt} and set up the
-local Readline prompt redisplay variables.
-This function is called by @code{readline()}.  It may also be called to
-expand the primary prompt if the @code{rl_on_new_line_with_prompt()}
-function or @code{rl_already_prompted} variable is used.
-It returns the number of visible characters on the last line of the
-(possibly multi-line) prompt.
-Applications may indicate that the prompt contains characters that take
-up no physical screen space when displayed by bracketing a sequence of
-such characters with the special markers @code{RL_PROMPT_START_IGNORE}
-and @code{RL_PROMPT_END_IGNORE} (declared in @file{readline.h}.  This may
-be used to embed terminal-specific escape sequences in prompts.
-@end deftypefun
-
-@deftypefun int rl_set_prompt (const char *prompt)
-Make Readline use @var{prompt} for subsequent redisplay.  This calls
-@code{rl_expand_prompt()} to expand the prompt and sets @code{rl_prompt}
-to the result.
-@end deftypefun
-
-@node Modifying Text
-@subsection Modifying Text
-
-@deftypefun int rl_insert_text (const char *text)
-Insert @var{text} into the line at the current cursor position.
-Returns the number of characters inserted.
-@end deftypefun
-
-@deftypefun int rl_delete_text (int start, int end)
-Delete the text between @var{start} and @var{end} in the current line.
-Returns the number of characters deleted.
-@end deftypefun
-
-@deftypefun {char *} rl_copy_text (int start, int end)
-Return a copy of the text between @var{start} and @var{end} in
-the current line.
-@end deftypefun
-
-@deftypefun int rl_kill_text (int start, int end)
-Copy the text between @var{start} and @var{end} in the current line
-to the kill ring, appending or prepending to the last kill if the
-last command was a kill command.  The text is deleted.
-If @var{start} is less than @var{end},
-the text is appended, otherwise prepended.  If the last command was
-not a kill, a new kill ring slot is used.
-@end deftypefun
-
-@deftypefun int rl_push_macro_input (char *macro)
-Cause @var{macro} to be inserted into the line, as if it had been invoked
-by a key bound to a macro.  Not especially useful; use
-@code{rl_insert_text()} instead.
-@end deftypefun
-
-@node Character Input
-@subsection Character Input
-
-@deftypefun int rl_read_key (void)
-Return the next character available from Readline's current input stream.
-This handles input inserted into
-the input stream via @var{rl_pending_input} (@pxref{Readline Variables})
-and @code{rl_stuff_char()}, macros, and characters read from the keyboard.
-While waiting for input, this function will call any function assigned to
-the @code{rl_event_hook} variable.
-@end deftypefun
-
-@deftypefun int rl_getc (FILE *stream)
-Return the next character available from @var{stream}, which is assumed to
-be the keyboard.
-@end deftypefun
-
-@deftypefun int rl_stuff_char (int c)
-Insert @var{c} into the Readline input stream.  It will be "read"
-before Readline attempts to read characters from the terminal with
-@code{rl_read_key()}.  Up to 512 characters may be pushed back.
-@code{rl_stuff_char} returns 1 if the character was successfully inserted;
-0 otherwise.
-@end deftypefun
-
-@deftypefun int rl_execute_next (int c)
-Make @var{c} be the next command to be executed when @code{rl_read_key()}
-is called.  This sets @var{rl_pending_input}.
-@end deftypefun
-
-@deftypefun int rl_clear_pending_input (void)
-Unset @var{rl_pending_input}, effectively negating the effect of any
-previous call to @code{rl_execute_next()}.  This works only if the
-pending input has not already been read with @code{rl_read_key()}.
-@end deftypefun
-
-@deftypefun int rl_set_keyboard_input_timeout (int u)
-While waiting for keyboard input in @code{rl_read_key()}, Readline will
-wait for @var{u} microseconds for input before calling any function
-assigned to @code{rl_event_hook}.  @var{u} must be greater than or equal
-to zero (a zero-length timeout is equivalent to a poll).
-The default waiting period is one-tenth of a second.
-Returns the old timeout value.
-@end deftypefun
-
-@node Terminal Management
-@subsection Terminal Management
-
-@deftypefun void rl_prep_terminal (int meta_flag)
-Modify the terminal settings for Readline's use, so @code{readline()}
-can read a single character at a time from the keyboard.
-The @var{meta_flag} argument should be non-zero if Readline should
-read eight-bit input.
-@end deftypefun
-
-@deftypefun void rl_deprep_terminal (void)
-Undo the effects of @code{rl_prep_terminal()}, leaving the terminal in
-the state in which it was before the most recent call to
-@code{rl_prep_terminal()}.
-@end deftypefun
-
-@deftypefun void rl_tty_set_default_bindings (Keymap kmap)
-Read the operating system's terminal editing characters (as would be
-displayed by @code{stty}) to their Readline equivalents.
-The bindings are performed in @var{kmap}.
-@end deftypefun
-
-@deftypefun void rl_tty_unset_default_bindings (Keymap kmap)
-Reset the bindings manipulated by @code{rl_tty_set_default_bindings} so
-that the terminal editing characters are bound to @code{rl_insert}.
-The bindings are performed in @var{kmap}.
-@end deftypefun
-
-@deftypefun int rl_reset_terminal (const char *terminal_name)
-Reinitialize Readline's idea of the terminal settings using
-@var{terminal_name} as the terminal type (e.g., @code{vt100}).
-If @var{terminal_name} is @code{NULL}, the value of the @code{TERM}
-environment variable is used.
-@end deftypefun
-
-@node Utility Functions
-@subsection Utility Functions
-
-@deftypefun int rl_save_state (struct readline_state *sp)
-Save a snapshot of Readline's internal state to @var{sp}.
-The contents of the @var{readline_state} structure are documented
-in @file{readline.h}.
-The caller is responsible for allocating the structure.
-@end deftypefun
-
-@deftypefun int rl_restore_state (struct readline_state *sp)
-Restore Readline's internal state to that stored in @var{sp}, which must
-have been saved by a call to @code{rl_save_state}.
-The contents of the @var{readline_state} structure are documented
-in @file{readline.h}.
-The caller is responsible for freeing the structure.
-@end deftypefun
-
-@deftypefun void rl_free (void *mem)
-Deallocate the memory pointed to by @var{mem}.  @var{mem} must have been
-allocated by @code{malloc}.
-@end deftypefun
-
-@deftypefun void rl_replace_line (const char *text, int clear_undo)
-Replace the contents of @code{rl_line_buffer} with @var{text}.
-The point and mark are preserved, if possible.
-If @var{clear_undo} is non-zero, the undo list associated with the
-current line is cleared.
-@end deftypefun
-
-@deftypefun void rl_extend_line_buffer (int len)
-Ensure that @code{rl_line_buffer} has enough space to hold @var{len}
-characters, possibly reallocating it if necessary.
-@end deftypefun
-
-@deftypefun int rl_initialize (void)
-Initialize or re-initialize Readline's internal state.
-It's not strictly necessary to call this; @code{readline()} calls it before
-reading any input.
-@end deftypefun
-
-@deftypefun int rl_ding (void)
-Ring the terminal bell, obeying the setting of @code{bell-style}.
-@end deftypefun
-
-@deftypefun int rl_alphabetic (int c)
-Return 1 if @var{c} is an alphabetic character.
-@end deftypefun
-
-@deftypefun void rl_display_match_list (char **matches, int len, int max)
-A convenience function for displaying a list of strings in
-columnar format on Readline's output stream.  @code{matches} is the list
-of strings, in argv format, such as a list of completion matches.
-@code{len} is the number of strings in @code{matches}, and @code{max}
-is the length of the longest string in @code{matches}.  This function uses
-the setting of @code{print-completions-horizontally} to select how the
-matches are displayed (@pxref{Readline Init File Syntax}).
-When displaying completions, this function sets the number of columns used
-for display to the value of @code{completion-display-width}, the value of
-the environment variable @env{COLUMNS}, or the screen width, in that order.
-@end deftypefun
-
-The following are implemented as macros, defined in @code{chardefs.h}.
-Applications should refrain from using them.
-
-@deftypefun int _rl_uppercase_p (int c)
-Return 1 if @var{c} is an uppercase alphabetic character.
-@end deftypefun
-
-@deftypefun int _rl_lowercase_p (int c)
-Return 1 if @var{c} is a lowercase alphabetic character.
-@end deftypefun
-
-@deftypefun int _rl_digit_p (int c)
-Return 1 if @var{c} is a numeric character.
-@end deftypefun
-
-@deftypefun int _rl_to_upper (int c)
-If @var{c} is a lowercase alphabetic character, return the corresponding
-uppercase character.
-@end deftypefun
-
-@deftypefun int _rl_to_lower (int c)
-If @var{c} is an uppercase alphabetic character, return the corresponding
-lowercase character.
-@end deftypefun
-
-@deftypefun int _rl_digit_value (int c)
-If @var{c} is a number, return the value it represents.
-@end deftypefun
-
-@node Miscellaneous Functions
-@subsection Miscellaneous Functions
-
-@deftypefun int rl_macro_bind (const char *keyseq, const char *macro, Keymap map)
-Bind the key sequence @var{keyseq} to invoke the macro @var{macro}.
-The binding is performed in @var{map}.  When @var{keyseq} is invoked, the
-@var{macro} will be inserted into the line.  This function is deprecated;
-use @code{rl_generic_bind()} instead.
-@end deftypefun
-
-@deftypefun void rl_macro_dumper (int readable)
-Print the key sequences bound to macros and their values, using
-the current keymap, to @code{rl_outstream}.
-If @var{readable} is non-zero, the list is formatted in such a way
-that it can be made part of an @code{inputrc} file and re-read.
-@end deftypefun
-
-@deftypefun int rl_variable_bind (const char *variable, const char *value)
-Make the Readline variable @var{variable} have @var{value}.
-This behaves as if the readline command
-@samp{set @var{variable} @var{value}} had been executed in an @code{inputrc}
-file (@pxref{Readline Init File Syntax}).
-@end deftypefun
-
-@deftypefun {char *} rl_variable_value (const char *variable)
-Return a string representing the value of the Readline variable @var{variable}.
-For boolean variables, this string is either @samp{on} or @samp{off}.
-@end deftypefun
-
-@deftypefun void rl_variable_dumper (int readable)
-Print the readline variable names and their current values
-to @code{rl_outstream}.
-If @var{readable} is non-zero, the list is formatted in such a way
-that it can be made part of an @code{inputrc} file and re-read.
-@end deftypefun
-
-@deftypefun int rl_set_paren_blink_timeout (int u)
-Set the time interval (in microseconds) that Readline waits when showing
-a balancing character when @code{blink-matching-paren} has been enabled.
-@end deftypefun
-
-@deftypefun {char *} rl_get_termcap (const char *cap)
-Retrieve the string value of the termcap capability @var{cap}.
-Readline fetches the termcap entry for the current terminal name and
-uses those capabilities to move around the screen line and perform other
-terminal-specific operations, like erasing a line.  Readline does not
-use all of a terminal's capabilities, and this function will return
-values for only those capabilities Readline uses.
-@end deftypefun
-
-@deftypefun {void} rl_clear_history (void)
-Clear the history list by deleting all of the entries, in the same manner
-as the History library's @code{clear_history()} function.
-This differs from @code{clear_history} because it frees private data
-Readline saves in the history list.
-@end deftypefun
-
-@node Alternate Interface
-@subsection Alternate Interface
-
-An alternate interface is available to plain @code{readline()}.  Some
-applications need to interleave keyboard I/O with file, device, or
-window system I/O, typically by using a main loop to @code{select()}
-on various file descriptors.  To accomodate this need, readline can
-also be invoked as a `callback' function from an event loop.  There
-are functions available to make this easy.
-
-@deftypefun void rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *lhandler)
-Set up the terminal for readline I/O and display the initial
-expanded value of @var{prompt}.  Save the value of @var{lhandler} to
-use as a function to call when a complete line of input has been entered.
-The function takes the text of the line as an argument.
-@end deftypefun
-
-@deftypefun void rl_callback_read_char (void)
-Whenever an application determines that keyboard input is available, it
-should call @code{rl_callback_read_char()}, which will read the next
-character from the current input source.
-If that character completes the line, @code{rl_callback_read_char} will
-invoke the @var{lhandler} function saved by @code{rl_callback_handler_install}
-to process the line.
-Before calling the @var{lhandler} function, the terminal settings are
-reset to the values they had before calling
-@code{rl_callback_handler_install}.
-If the @var{lhandler} function returns,
-the terminal settings are modified for Readline's use again.
-@code{EOF} is  indicated by calling @var{lhandler} with a
-@code{NULL} line.
-@end deftypefun
-
-@deftypefun void rl_callback_handler_remove (void)
-Restore the terminal to its initial state and remove the line handler.
-This may be called from within a callback as well as independently.
-If the @var{lhandler} installed by @code{rl_callback_handler_install}
-does not exit the program, either this function or the function referred
-to by the value of @code{rl_deprep_term_function} should be called before
-the program exits to reset the terminal settings.
-@end deftypefun
-
-@node A Readline Example
-@subsection A Readline Example
-
-Here is a function which changes lowercase characters to their uppercase
-equivalents, and uppercase characters to lowercase.  If
-this function was bound to @samp{M-c}, then typing @samp{M-c} would
-change the case of the character under point.  Typing @samp{M-1 0 M-c}
-would change the case of the following 10 characters, leaving the cursor on
-the last character changed.
-
-@example
-/* Invert the case of the COUNT following characters. */
-int
-invert_case_line (count, key)
-     int count, key;
-@{
-  register int start, end, i;
-
-  start = rl_point;
-
-  if (rl_point >= rl_end)
-    return (0);
-
-  if (count < 0)
-    @{
-      direction = -1;
-      count = -count;
-    @}
-  else
-    direction = 1;
-      
-  /* Find the end of the range to modify. */
-  end = start + (count * direction);
-
-  /* Force it to be within range. */
-  if (end > rl_end)
-    end = rl_end;
-  else if (end < 0)
-    end = 0;
-
-  if (start == end)
-    return (0);
-
-  if (start > end)
-    @{
-      int temp = start;
-      start = end;
-      end = temp;
-    @}
-
-  /* Tell readline that we are modifying the line,
-     so it will save the undo information. */
-  rl_modifying (start, end);
-
-  for (i = start; i != end; i++)
-    @{
-      if (_rl_uppercase_p (rl_line_buffer[i]))
-        rl_line_buffer[i] = _rl_to_lower (rl_line_buffer[i]);
-      else if (_rl_lowercase_p (rl_line_buffer[i]))
-        rl_line_buffer[i] = _rl_to_upper (rl_line_buffer[i]);
-    @}
-  /* Move point to on top of the last character changed. */
-  rl_point = (direction == 1) ? end - 1 : start;
-  return (0);
-@}
-@end example
-
-@node Readline Signal Handling
-@section Readline Signal Handling
-
-Signals are asynchronous events sent to a process by the Unix kernel,
-sometimes on behalf of another process.  They are intended to indicate
-exceptional events, like a user pressing the interrupt key on his terminal,
-or a network connection being broken.  There is a class of signals that can
-be sent to the process currently reading input from the keyboard.  Since
-Readline changes the terminal attributes when it is called, it needs to
-perform special processing when such a signal is received in order to
-restore the terminal to a sane state, or provide application writers with
-functions to do so manually. 
-
-Readline contains an internal signal handler that is installed for a
-number of signals (@code{SIGINT}, @code{SIGQUIT}, @code{SIGTERM},
-@code{SIGHUP}, 
-@code{SIGALRM}, @code{SIGTSTP}, @code{SIGTTIN}, and @code{SIGTTOU}).
-When one of these signals is received, the signal handler
-will reset the terminal attributes to those that were in effect before
-@code{readline()} was called, reset the signal handling to what it was
-before @code{readline()} was called, and resend the signal to the calling
-application.
-If and when the calling application's signal handler returns, Readline
-will reinitialize the terminal and continue to accept input.
-When a @code{SIGINT} is received, the Readline signal handler performs
-some additional work, which will cause any partially-entered line to be
-aborted (see the description of @code{rl_free_line_state()} below).
-
-There is an additional Readline signal handler, for @code{SIGWINCH}, which
-the kernel sends to a process whenever the terminal's size changes (for
-example, if a user resizes an @code{xterm}).  The Readline @code{SIGWINCH}
-handler updates Readline's internal screen size information, and then calls
-any @code{SIGWINCH} signal handler the calling application has installed. 
-Readline calls the application's @code{SIGWINCH} signal handler without
-resetting the terminal to its original state.  If the application's signal
-handler does more than update its idea of the terminal size and return (for
-example, a @code{longjmp} back to a main processing loop), it @emph{must}
-call @code{rl_cleanup_after_signal()} (described below), to restore the
-terminal state. 
-
-Readline provides two variables that allow application writers to
-control whether or not it will catch certain signals and act on them
-when they are received.  It is important that applications change the
-values of these variables only when calling @code{readline()}, not in
-a signal handler, so Readline's internal signal state is not corrupted.
-
-@deftypevar int rl_catch_signals
-If this variable is non-zero, Readline will install signal handlers for
-@code{SIGINT}, @code{SIGQUIT}, @code{SIGTERM}, @code{SIGHUP}, @code{SIGALRM},
-@code{SIGTSTP}, @code{SIGTTIN}, and @code{SIGTTOU}.
-
-The default value of @code{rl_catch_signals} is 1.
-@end deftypevar
-
-@deftypevar int rl_catch_sigwinch
-If this variable is non-zero, Readline will install a signal handler for
-@code{SIGWINCH}.
-
-The default value of @code{rl_catch_sigwinch} is 1.
-@end deftypevar
-
-If an application does not wish to have Readline catch any signals, or
-to handle signals other than those Readline catches (@code{SIGHUP},
-for example), 
-Readline provides convenience functions to do the necessary terminal
-and internal state cleanup upon receipt of a signal.
-
-@deftypefun void rl_cleanup_after_signal (void)
-This function will reset the state of the terminal to what it was before
-@code{readline()} was called, and remove the Readline signal handlers for
-all signals, depending on the values of @code{rl_catch_signals} and
-@code{rl_catch_sigwinch}.
-@end deftypefun
-
-@deftypefun void rl_free_line_state (void)
-This will free any partial state associated with the current input line
-(undo information, any partial history entry, any partially-entered
-keyboard macro, and any partially-entered numeric argument).  This
-should be called before @code{rl_cleanup_after_signal()}.  The
-Readline signal handler for @code{SIGINT} calls this to abort the
-current input line.
-@end deftypefun
-
-@deftypefun void rl_reset_after_signal (void)
-This will reinitialize the terminal and reinstall any Readline signal
-handlers, depending on the values of @code{rl_catch_signals} and
-@code{rl_catch_sigwinch}.
-@end deftypefun
-
-If an application does not wish Readline to catch @code{SIGWINCH}, it may
-call @code{rl_resize_terminal()} or @code{rl_set_screen_size()} to force
-Readline to update its idea of the terminal size when a @code{SIGWINCH}
-is received.
-
-@deftypefun void rl_echo_signal_char (int sig)
-If an application wishes to install its own signal handlers, but still
-have readline display characters that generate signals, calling this
-function with @var{sig} set to @code{SIGINT}, @code{SIGQUIT}, or
-@code{SIGTSTP} will display the character generating that signal.
-@end deftypefun
-
-@deftypefun void rl_resize_terminal (void)
-Update Readline's internal screen size by reading values from the kernel.
-@end deftypefun
-
-@deftypefun void rl_set_screen_size (int rows, int cols)
-Set Readline's idea of the terminal size to @var{rows} rows and
-@var{cols} columns.  If either @var{rows} or @var{columns} is less than
-or equal to 0, Readline's idea of that terminal dimension is unchanged.
-@end deftypefun
-
-If an application does not want to install a @code{SIGWINCH} handler, but
-is still interested in the screen dimensions, Readline's idea of the screen
-size may be queried.
-
-@deftypefun void rl_get_screen_size (int *rows, int *cols)
-Return Readline's idea of the terminal's size in the
-variables pointed to by the arguments.
-@end deftypefun
-
-@deftypefun void rl_reset_screen_size (void)
-Cause Readline to reobtain the screen size and recalculate its dimensions.
-@end deftypefun
-
-The following functions install and remove Readline's signal handlers.
-
-@deftypefun int rl_set_signals (void)
-Install Readline's signal handler for @code{SIGINT}, @code{SIGQUIT},
-@code{SIGTERM}, @code{SIGHUP}, @code{SIGALRM}, @code{SIGTSTP}, @code{SIGTTIN},
-@code{SIGTTOU}, and @code{SIGWINCH}, depending on the values of
-@code{rl_catch_signals} and @code{rl_catch_sigwinch}.
-@end deftypefun
-
-@deftypefun int rl_clear_signals (void)
-Remove all of the Readline signal handlers installed by
-@code{rl_set_signals()}.
-@end deftypefun
-
-@node Custom Completers
-@section Custom Completers
-@cindex application-specific completion functions
-
-Typically, a program that reads commands from the user has a way of
-disambiguating commands and data.  If your program is one of these, then
-it can provide completion for commands, data, or both.
-The following sections describe how your program and Readline
-cooperate to provide this service.
-
-@menu
-* How Completing Works::       The logic used to do completion.
-* Completion Functions::       Functions provided by Readline.
-* Completion Variables::       Variables which control completion.
-* A Short Completion Example:: An example of writing completer subroutines.
-@end menu
-
-@node How Completing Works
-@subsection How Completing Works
-
-In order to complete some text, the full list of possible completions
-must be available.  That is, it is not possible to accurately
-expand a partial word without knowing all of the possible words
-which make sense in that context.  The Readline library provides
-the user interface to completion, and two of the most common
-completion functions:  filename and username.  For completing other types
-of text, you must write your own completion function.  This section
-describes exactly what such functions must do, and provides an example.
-
-There are three major functions used to perform completion:
-
-@enumerate
-@item
-The user-interface function @code{rl_complete()}.  This function is
-called with the same arguments as other bindable Readline functions:
-@var{count} and @var{invoking_key}.
-It isolates the word to be completed and calls
-@code{rl_completion_matches()} to generate a list of possible completions.
-It then either lists the possible completions, inserts the possible
-completions, or actually performs the
-completion, depending on which behavior is desired.
-
-@item
-The internal function @code{rl_completion_matches()} uses an
-application-supplied @dfn{generator} function to generate the list of
-possible matches, and then returns the array of these matches.
-The caller should place the address of its generator function in
-@code{rl_completion_entry_function}.
-
-@item
-The generator function is called repeatedly from
-@code{rl_completion_matches()}, returning a string each time.  The
-arguments to the generator function are @var{text} and @var{state}.
-@var{text} is the partial word to be completed.  @var{state} is zero the
-first time the function is called, allowing the generator to perform
-any necessary initialization, and a positive non-zero integer for
-each subsequent call.  The generator function returns
-@code{(char *)NULL} to inform @code{rl_completion_matches()} that there are
-no more possibilities left.  Usually the generator function computes the
-list of possible completions when @var{state} is zero, and returns them
-one at a time on subsequent calls.  Each string the generator function
-returns as a match must be allocated with @code{malloc()}; Readline
-frees the strings when it has finished with them.
-Such a generator function is referred to as an
-@dfn{application-specific completion function}.
-
-@end enumerate
-
-@deftypefun int rl_complete (int ignore, int invoking_key)
-Complete the word at or before point.  You have supplied the function
-that does the initial simple matching selection algorithm (see
-@code{rl_completion_matches()}).  The default is to do filename completion.
-@end deftypefun
-
-@deftypevar {rl_compentry_func_t *} rl_completion_entry_function
-This is a pointer to the generator function for
-@code{rl_completion_matches()}.
-If the value of @code{rl_completion_entry_function} is
-@code{NULL} then the default filename generator
-function, @code{rl_filename_completion_function()}, is used.
-An @dfn{application-specific completion function} is a function whose
-address is assigned to @code{rl_completion_entry_function} and whose
-return values are used to  generate possible completions.
-@end deftypevar
-
-@node Completion Functions
-@subsection Completion Functions
-
-Here is the complete list of callable completion functions present in
-Readline.
-
-@deftypefun int rl_complete_internal (int what_to_do)
-Complete the word at or before point.  @var{what_to_do} says what to do
-with the completion.  A value of @samp{?} means list the possible
-completions.  @samp{TAB} means do standard completion.  @samp{*} means
-insert all of the possible completions.  @samp{!} means to display
-all of the possible completions, if there is more than one, as well as
-performing partial completion.  @samp{@@} is similar to @samp{!}, but
-possible completions are not listed if the possible completions share
-a common prefix.
-@end deftypefun
-
-@deftypefun int rl_complete (int ignore, int invoking_key)
-Complete the word at or before point.  You have supplied the function
-that does the initial simple matching selection algorithm (see
-@code{rl_completion_matches()} and @code{rl_completion_entry_function}).
-The default is to do filename
-completion.  This calls @code{rl_complete_internal()} with an
-argument depending on @var{invoking_key}.
-@end deftypefun
-
-@deftypefun int rl_possible_completions (int count, int invoking_key)
-List the possible completions.  See description of @code{rl_complete
-()}.  This calls @code{rl_complete_internal()} with an argument of
-@samp{?}.
-@end deftypefun
-
-@deftypefun int rl_insert_completions (int count, int invoking_key)
-Insert the list of possible completions into the line, deleting the
-partially-completed word.  See description of @code{rl_complete()}.
-This calls @code{rl_complete_internal()} with an argument of @samp{*}.
-@end deftypefun
-
-@deftypefun int rl_completion_mode (rl_command_func_t *cfunc)
-Returns the apppriate value to pass to @code{rl_complete_internal()}
-depending on whether @var{cfunc} was called twice in succession and
-the values of the @code{show-all-if-ambiguous} and
-@code{show-all-if-unmodified} variables.
-Application-specific completion functions may use this function to present
-the same interface as @code{rl_complete()}.
-@end deftypefun
-
-@deftypefun {char **} rl_completion_matches (const char *text, rl_compentry_func_t *entry_func)
-Returns an array of strings which is a list of completions for
-@var{text}.  If there are no completions, returns @code{NULL}.
-The first entry in the returned array is the substitution for @var{text}.
-The remaining entries are the possible completions.  The array is
-terminated with a @code{NULL} pointer.
-
-@var{entry_func} is a function of two args, and returns a
-@code{char *}.  The first argument is @var{text}.  The second is a
-state argument; it is zero on the first call, and non-zero on subsequent
-calls.  @var{entry_func} returns a @code{NULL}  pointer to the caller
-when there are no more matches.
-@end deftypefun
-
-@deftypefun {char *} rl_filename_completion_function (const char *text, int state)
-A generator function for filename completion in the general case.
-@var{text} is a partial filename.
-The Bash source is a useful reference for writing application-specific
-completion functions (the Bash completion functions call this and other
-Readline functions).
-@end deftypefun
-
-@deftypefun {char *} rl_username_completion_function (const char *text, int state)
-A completion generator for usernames.  @var{text} contains a partial
-username preceded by a random character (usually @samp{~}).  As with all
-completion generators, @var{state} is zero on the first call and non-zero
-for subsequent calls.
-@end deftypefun
-
-@node Completion Variables
-@subsection Completion Variables
-
-@deftypevar {rl_compentry_func_t *} rl_completion_entry_function
-A pointer to the generator function for @code{rl_completion_matches()}.
-@code{NULL} means to use @code{rl_filename_completion_function()},
-the default filename completer.
-@end deftypevar
-
-@deftypevar {rl_completion_func_t *} rl_attempted_completion_function
-A pointer to an alternative function to create matches.
-The function is called with @var{text}, @var{start}, and @var{end}.
-@var{start} and @var{end} are indices in @code{rl_line_buffer} defining
-the boundaries of @var{text}, which is a character string.
-If this function exists and returns @code{NULL}, or if this variable is
-set to @code{NULL}, then @code{rl_complete()} will call the value of
-@code{rl_completion_entry_function} to generate matches, otherwise the
-array of strings returned will be used.
-If this function sets the @code{rl_attempted_completion_over}
-variable to a non-zero value, Readline will not perform its default
-completion even if this function returns no matches.
-@end deftypevar
-
-@deftypevar {rl_quote_func_t *} rl_filename_quoting_function
-A pointer to a function that will quote a filename in an
-application-specific fashion.  This is called if filename completion is being
-attempted and one of the characters in @code{rl_filename_quote_characters}
-appears in a completed filename.  The function is called with
-@var{text}, @var{match_type}, and @var{quote_pointer}.  The @var{text}
-is the filename to be quoted.  The @var{match_type} is either
-@code{SINGLE_MATCH}, if there is only one completion match, or
-@code{MULT_MATCH}.  Some functions use this to decide whether or not to
-insert a closing quote character.  The @var{quote_pointer} is a pointer
-to any opening quote character the user typed.  Some functions choose
-to reset this character.
-@end deftypevar
-
-@deftypevar {rl_dequote_func_t *} rl_filename_dequoting_function
-A pointer to a function that will remove application-specific quoting
-characters from a filename before completion is attempted, so those
-characters do not interfere with matching the text against names in
-the filesystem.  It is called with @var{text}, the text of the word
-to be dequoted, and @var{quote_char}, which is the quoting character 
-that delimits the filename (usually @samp{'} or @samp{"}).  If
-@var{quote_char} is zero, the filename was not in an embedded string.
-@end deftypevar
-
-@deftypevar {rl_linebuf_func_t *} rl_char_is_quoted_p
-A pointer to a function to call that determines whether or not a specific
-character in the line buffer is quoted, according to whatever quoting
-mechanism the program calling Readline uses.  The function is called with
-two arguments: @var{text}, the text of the line, and @var{index}, the
-index of the character in the line.  It is used to decide whether a
-character found in @code{rl_completer_word_break_characters} should be
-used to break words for the completer.
-@end deftypevar
-
-@deftypevar {rl_compignore_func_t *} rl_ignore_some_completions_function
-This function, if defined, is called by the completer when real filename
-completion is done, after all the matching names have been generated.
-It is passed a @code{NULL} terminated array of matches.
-The first element (@code{matches[0]}) is the
-maximal substring common to all matches. This function can
-re-arrange the list of matches as required, but each element deleted
-from the array must be freed.
-@end deftypevar
-
-@deftypevar {rl_icppfunc_t *} rl_directory_completion_hook
-This function, if defined, is allowed to modify the directory portion
-of filenames Readline completes.
-It could be used to expand symbolic links or shell variables in pathnames.
-It is called with the address of a string (the current directory name) as an
-argument, and may modify that string.
-If the string is replaced with a new string, the old value should be freed.
-Any modified directory name should have a trailing slash.
-The modified value will be used as part of the completion, replacing
-the directory portion of the pathname the user typed.
-At the least, even if no other expansion is performed, this function should
-remove any quote characters from the directory name, because its result will
-be passed directly to @code{opendir()}.
-
-The directory completion hook returns an integer that should be non-zero if
-the function modifies its directory argument.
-The function should not modify the directory argument if it returns 0.
-@end deftypevar
-
-@deftypevar {rl_icppfunc_t *} rl_directory_rewrite_hook;
-If non-zero, this is the address of a function to call when completing
-a directory name.  This function takes the address of the directory name
-to be modified as an argument.  Unlike @code{rl_directory_completion_hook},
-it only modifies the directory name used in @code{opendir}, not what is
-displayed when the possible completions are printed or inserted.  It is
-called before rl_directory_completion_hook.
-At the least, even if no other expansion is performed, this function should
-remove any quote characters from the directory name, because its result will
-be passed directly to @code{opendir()}.
-
-The directory rewrite hook returns an integer that should be non-zero if
-the function modfies its directory argument.
-The function should not modify the directory argument if it returns 0.
-@end deftypevar
-
-@deftypevar {rl_icppfunc_t *} rl_filename_stat_hook
-If non-zero, this is the address of a function for the completer to
-call before deciding which character to append to a completed name.
-This function modifies its filename name argument, and the modified value
-is passed to @code{stat()} to determine the file's type and characteristics.
-This function does not need to remove quote characters from the filename.
-
-The stat hook returns an integer that should be non-zero if
-the function modfies its directory argument.
-The function should not modify the directory argument if it returns 0.
-@end deftypevar
-
-@deftypevar {rl_dequote_func_t *} rl_filename_rewrite_hook
-If non-zero, this is the address of a function called when reading
-directory entries from the filesystem for completion and comparing
-them to the partial word to be completed.  The function should
-perform any necesary application or system-specific conversion on
-the filename, such as converting between character sets or converting
-from a filesystem format to a character input format.
-The function takes two arguments: @var{fname}, the filename to be converted,
-and @var{fnlen}, its length in bytes.
-It must either return its first argument (if no conversion takes place)
-or the converted filename in newly-allocated memory.  The converted
-form is used to compare against the word to be completed, and, if it
-matches, is added to the list of matches.  Readline will free the
-allocated string.
-@end deftypevar
-
-@deftypevar {rl_compdisp_func_t *} rl_completion_display_matches_hook
-If non-zero, then this is the address of a function to call when
-completing a word would normally display the list of possible matches.
-This function is called in lieu of Readline displaying the list.
-It takes three arguments:
-(@code{char **}@var{matches}, @code{int} @var{num_matches}, @code{int} @var{max_length})
-where @var{matches} is the array of matching strings,
-@var{num_matches} is the number of strings in that array, and
-@var{max_length} is the length of the longest string in that array.
-Readline provides a convenience function, @code{rl_display_match_list},
-that takes care of doing the display to Readline's output stream.  That
-function may be called from this hook.
-@end deftypevar
-
-@deftypevar {const char *} rl_basic_word_break_characters
-The basic list of characters that signal a break between words for the
-completer routine.  The default value of this variable is the characters
-which break words for completion in Bash:
-@code{" \t\n\"\\'`@@$><=;|&@{("}.
-@end deftypevar
-
-@deftypevar {const char *} rl_basic_quote_characters
-A list of quote characters which can cause a word break.
-@end deftypevar
-
-@deftypevar {const char *} rl_completer_word_break_characters
-The list of characters that signal a break between words for
-@code{rl_complete_internal()}.  The default list is the value of
-@code{rl_basic_word_break_characters}.
-@end deftypevar
-
-@deftypevar {rl_cpvfunc_t *} rl_completion_word_break_hook
-If non-zero, this is the address of a function to call when Readline is
-deciding where to separate words for word completion.  It should return
-a character string like @code{rl_completer_word_break_characters} to be
-used to perform the current completion.  The function may choose to set
-@code{rl_completer_word_break_characters} itself.  If the function
-returns @code{NULL}, @code{rl_completer_word_break_characters} is used.
-@end deftypevar
-
-@deftypevar {const char *} rl_completer_quote_characters
-A list of characters which can be used to quote a substring of the line.
-Completion occurs on the entire substring, and within the substring
-@code{rl_completer_word_break_characters} are treated as any other character,
-unless they also appear within this list.
-@end deftypevar
-
-@deftypevar {const char *} rl_filename_quote_characters
-A list of characters that cause a filename to be quoted by the completer
-when they appear in a completed filename.  The default is the null string.
-@end deftypevar
-
-@deftypevar {const char *} rl_special_prefixes
-The list of characters that are word break characters, but should be
-left in @var{text} when it is passed to the completion function.
-Programs can use this to help determine what kind of completing to do.
-For instance, Bash sets this variable to "$@@" so that it can complete
-shell variables and hostnames.
-@end deftypevar
-
-@deftypevar int rl_completion_query_items
-Up to this many items will be displayed in response to a
-possible-completions call.  After that, readline asks the user if she is sure
-she wants to see them all.  The default value is 100.  A negative value 
-indicates that Readline should never ask the user.
-@end deftypevar
-
-@deftypevar {int} rl_completion_append_character
-When a single completion alternative matches at the end of the command
-line, this character is appended to the inserted completion text.  The
-default is a space character (@samp{ }).  Setting this to the null
-character (@samp{\0}) prevents anything being appended automatically.
-This can be changed in application-specific completion functions to
-provide the ``most sensible word separator character'' according to
-an application-specific command line syntax specification.
-@end deftypevar
-
-@deftypevar int rl_completion_suppress_append
-If non-zero, @var{rl_completion_append_character} is not appended to
-matches at the end of the command line, as described above.
-It is set to 0 before any application-specific completion function
-is called, and may only be changed within such a function.
-@end deftypevar
-
-@deftypevar int rl_completion_quote_character
-When Readline is completing quoted text, as delimited by one of the
-characters in @var{rl_completer_quote_characters}, it sets this variable
-to the quoting character found.
-This is set before any application-specific completion function is called.
-@end deftypevar
-
-@deftypevar int rl_completion_suppress_quote
-If non-zero, Readline does not append a matching quote character when
-performing completion on a quoted string.
-It is set to 0 before any application-specific completion function
-is called, and may only be changed within such a function.
-@end deftypevar
-
-@deftypevar int rl_completion_found_quote
-When Readline is completing quoted text, it sets this variable
-to a non-zero value if the word being completed contains or is delimited
-by any quoting characters, including backslashes.
-This is set before any application-specific completion function is called.
-@end deftypevar
-
-@deftypevar int rl_completion_mark_symlink_dirs
-If non-zero, a slash will be appended to completed filenames that are
-symbolic links to directory names, subject to the value of the
-user-settable @var{mark-directories} variable.
-This variable exists so that application-specific completion functions
-can override the user's global preference (set via the
-@var{mark-symlinked-directories} Readline variable) if appropriate.
-This variable is set to the user's preference before any
-application-specific completion function is called, so unless that
-function modifies the value, the user's preferences are honored.
-@end deftypevar
-
-@deftypevar int rl_ignore_completion_duplicates
-If non-zero, then duplicates in the matches are removed.
-The default is 1.
-@end deftypevar
-
-@deftypevar int rl_filename_completion_desired
-Non-zero means that the results of the matches are to be treated as
-filenames.  This is @emph{always} zero when completion is attempted,
-and can only be changed
-within an application-specific completion function.  If it is set to a
-non-zero value by such a function, directory names have a slash appended
-and Readline attempts to quote completed filenames if they contain any
-characters in @code{rl_filename_quote_characters} and
-@code{rl_filename_quoting_desired} is set to a non-zero value.
-@end deftypevar
-
-@deftypevar int rl_filename_quoting_desired
-Non-zero means that the results of the matches are to be quoted using
-double quotes (or an application-specific quoting mechanism) if the
-completed filename contains any characters in
-@code{rl_filename_quote_chars}.  This is @emph{always} non-zero
-when completion is attempted, and can only be changed within an
-application-specific completion function.
-The quoting is effected via a call to the function pointed to
-by @code{rl_filename_quoting_function}.
-@end deftypevar
-
-@deftypevar int rl_attempted_completion_over
-If an application-specific completion function assigned to
-@code{rl_attempted_completion_function} sets this variable to a non-zero
-value, Readline will not perform its default filename completion even
-if the application's completion function returns no matches.
-It should be set only by an application's completion function.
-@end deftypevar
-
-@deftypevar int rl_sort_completion_matches
-If an application sets this variable to 0, Readline will not sort the
-list of completions (which implies that it cannot remove any duplicate
-completions).  The default value is 1, which means that Readline will
-sort the completions and, depending on the value of
-@code{rl_ignore_completion_duplicates}, will attempt to remove duplicate
-matches.
-@end deftypevar
-
-@deftypevar int rl_completion_type
-Set to a character describing the type of completion Readline is currently
-attempting; see the description of @code{rl_complete_internal()}
-(@pxref{Completion Functions}) for the list of characters.
-This is set to the appropriate value before any application-specific
-completion function is called, allowing such functions to present
-the same interface as @code{rl_complete()}.
-@end deftypevar
-
-@deftypevar int rl_completion_invoking_key
-Set to the final character in the key sequence that invoked one of the
-completion functions that call @code{rl_complete_internal()}.  This is
-set to the appropriate value before any application-specific completion
-function is called.
-@end deftypevar
-
-@deftypevar int rl_inhibit_completion
-If this variable is non-zero, completion is inhibited.  The completion
-character will be inserted as any other bound to @code{self-insert}.
-@end deftypevar
-
-@node A Short Completion Example
-@subsection A Short Completion Example
-
-Here is a small application demonstrating the use of the GNU Readline
-library.  It is called @code{fileman}, and the source code resides in
-@file{examples/fileman.c}.  This sample application provides
-completion of command names, line editing features, and access to the
-history list.
-
-@page
-@smallexample
-/* fileman.c -- A tiny application which demonstrates how to use the
-   GNU Readline library.  This application interactively allows users
-   to manipulate files and their modes. */
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_FILE_H
-#  include <sys/file.h>
-#endif
-#include <sys/stat.h>
-
-#ifdef HAVE_UNISTD_H
-#  include <unistd.h>
-#endif
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <errno.h>
-
-#if defined (HAVE_STRING_H)
-#  include <string.h>
-#else /* !HAVE_STRING_H */
-#  include <strings.h>
-#endif /* !HAVE_STRING_H */
-
-#ifdef HAVE_STDLIB_H
-#  include <stdlib.h>
-#endif
-
-#include <time.h>
-
-#include <readline/readline.h>
-#include <readline/history.h>
-
-extern char *xmalloc PARAMS((size_t));
-
-/* The names of functions that actually do the manipulation. */
-int com_list PARAMS((char *));
-int com_view PARAMS((char *));
-int com_rename PARAMS((char *));
-int com_stat PARAMS((char *));
-int com_pwd PARAMS((char *));
-int com_delete PARAMS((char *));
-int com_help PARAMS((char *));
-int com_cd PARAMS((char *));
-int com_quit PARAMS((char *));
-
-/* A structure which contains information on the commands this program
-   can understand. */
-
-typedef struct @{
-  char *name;                  /* User printable name of the function. */
-  rl_icpfunc_t *func;          /* Function to call to do the job. */
-  char *doc;                   /* Documentation for this function.  */
-@} COMMAND;
-
-COMMAND commands[] = @{
-  @{ "cd", com_cd, "Change to directory DIR" @},
-  @{ "delete", com_delete, "Delete FILE" @},
-  @{ "help", com_help, "Display this text" @},
-  @{ "?", com_help, "Synonym for `help'" @},
-  @{ "list", com_list, "List files in DIR" @},
-  @{ "ls", com_list, "Synonym for `list'" @},
-  @{ "pwd", com_pwd, "Print the current working directory" @},
-  @{ "quit", com_quit, "Quit using Fileman" @},
-  @{ "rename", com_rename, "Rename FILE to NEWNAME" @},
-  @{ "stat", com_stat, "Print out statistics on FILE" @},
-  @{ "view", com_view, "View the contents of FILE" @},
-  @{ (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL @}
-@};
-
-/* Forward declarations. */
-char *stripwhite ();
-COMMAND *find_command ();
-
-/* The name of this program, as taken from argv[0]. */
-char *progname;
-
-/* When non-zero, this global means the user is done using this program. */
-int done;
-
-char *
-dupstr (s)
-     char *s;
-@{
-  char *r;
-
-  r = xmalloc (strlen (s) + 1);
-  strcpy (r, s);
-  return (r);
-@}
-
-main (argc, argv)
-     int argc;
-     char **argv;
-@{
-  char *line, *s;
-
-  progname = argv[0];
-
-  initialize_readline ();      /* Bind our completer. */
-
-  /* Loop reading and executing lines until the user quits. */
-  for ( ; done == 0; )
-    @{
-      line = readline ("FileMan: ");
-
-      if (!line)
-        break;
-
-      /* Remove leading and trailing whitespace from the line.
-         Then, if there is anything left, add it to the history list
-         and execute it. */
-      s = stripwhite (line);
-
-      if (*s)
-        @{
-          add_history (s);
-          execute_line (s);
-        @}
-
-      free (line);
-    @}
-  exit (0);
-@}
-
-/* Execute a command line. */
-int
-execute_line (line)
-     char *line;
-@{
-  register int i;
-  COMMAND *command;
-  char *word;
-
-  /* Isolate the command word. */
-  i = 0;
-  while (line[i] && whitespace (line[i]))
-    i++;
-  word = line + i;
-
-  while (line[i] && !whitespace (line[i]))
-    i++;
-
-  if (line[i])
-    line[i++] = '\0';
-
-  command = find_command (word);
-
-  if (!command)
-    @{
-      fprintf (stderr, "%s: No such command for FileMan.\n", word);
-      return (-1);
-    @}
-
-  /* Get argument to command, if any. */
-  while (whitespace (line[i]))
-    i++;
-
-  word = line + i;
-
-  /* Call the function. */
-  return ((*(command->func)) (word));
-@}
-
-/* Look up NAME as the name of a command, and return a pointer to that
-   command.  Return a NULL pointer if NAME isn't a command name. */
-COMMAND *
-find_command (name)
-     char *name;
-@{
-  register int i;
-
-  for (i = 0; commands[i].name; i++)
-    if (strcmp (name, commands[i].name) == 0)
-      return (&commands[i]);
-
-  return ((COMMAND *)NULL);
-@}
-
-/* Strip whitespace from the start and end of STRING.  Return a pointer
-   into STRING. */
-char *
-stripwhite (string)
-     char *string;
-@{
-  register char *s, *t;
-
-  for (s = string; whitespace (*s); s++)
-    ;
-    
-  if (*s == 0)
-    return (s);
-
-  t = s + strlen (s) - 1;
-  while (t > s && whitespace (*t))
-    t--;
-  *++t = '\0';
-
-  return s;
-@}
-
-/* **************************************************************** */
-/*                                                                  */
-/*                  Interface to Readline Completion                */
-/*                                                                  */
-/* **************************************************************** */
-
-char *command_generator PARAMS((const char *, int));
-char **fileman_completion PARAMS((const char *, int, int));
-
-/* Tell the GNU Readline library how to complete.  We want to try to complete
-   on command names if this is the first word in the line, or on filenames
-   if not. */
-initialize_readline ()
-@{
-  /* Allow conditional parsing of the ~/.inputrc file. */
-  rl_readline_name = "FileMan";
-
-  /* Tell the completer that we want a crack first. */
-  rl_attempted_completion_function = fileman_completion;
-@}
-
-/* Attempt to complete on the contents of TEXT.  START and END bound the
-   region of rl_line_buffer that contains the word to complete.  TEXT is
-   the word to complete.  We can use the entire contents of rl_line_buffer
-   in case we want to do some simple parsing.  Return the array of matches,
-   or NULL if there aren't any. */
-char **
-fileman_completion (text, start, end)
-     const char *text;
-     int start, end;
-@{
-  char **matches;
-
-  matches = (char **)NULL;
-
-  /* If this word is at the start of the line, then it is a command
-     to complete.  Otherwise it is the name of a file in the current
-     directory. */
-  if (start == 0)
-    matches = rl_completion_matches (text, command_generator);
-
-  return (matches);
-@}
-
-/* Generator function for command completion.  STATE lets us know whether
-   to start from scratch; without any state (i.e. STATE == 0), then we
-   start at the top of the list. */
-char *
-command_generator (text, state)
-     const char *text;
-     int state;
-@{
-  static int list_index, len;
-  char *name;
-
-  /* If this is a new word to complete, initialize now.  This includes
-     saving the length of TEXT for efficiency, and initializing the index
-     variable to 0. */
-  if (!state)
-    @{
-      list_index = 0;
-      len = strlen (text);
-    @}
-
-  /* Return the next name which partially matches from the command list. */
-  while (name = commands[list_index].name)
-    @{
-      list_index++;
-
-      if (strncmp (name, text, len) == 0)
-        return (dupstr(name));
-    @}
-
-  /* If no names matched, then return NULL. */
-  return ((char *)NULL);
-@}
-
-/* **************************************************************** */
-/*                                                                  */
-/*                       FileMan Commands                           */
-/*                                                                  */
-/* **************************************************************** */
-
-/* String to pass to system ().  This is for the LIST, VIEW and RENAME
-   commands. */
-static char syscom[1024];
-
-/* List the file(s) named in arg. */
-com_list (arg)
-     char *arg;
-@{
-  if (!arg)
-    arg = "";
-
-  sprintf (syscom, "ls -FClg %s", arg);
-  return (system (syscom));
-@}
-
-com_view (arg)
-     char *arg;
-@{
-  if (!valid_argument ("view", arg))
-    return 1;
-
-#if defined (__MSDOS__)
-  /* more.com doesn't grok slashes in pathnames */
-  sprintf (syscom, "less %s", arg);
-#else
-  sprintf (syscom, "more %s", arg);
-#endif
-  return (system (syscom));
-@}
-
-com_rename (arg)
-     char *arg;
-@{
-  too_dangerous ("rename");
-  return (1);
-@}
-
-com_stat (arg)
-     char *arg;
-@{
-  struct stat finfo;
-
-  if (!valid_argument ("stat", arg))
-    return (1);
-
-  if (stat (arg, &finfo) == -1)
-    @{
-      perror (arg);
-      return (1);
-    @}
-
-  printf ("Statistics for `%s':\n", arg);
-
-  printf ("%s has %d link%s, and is %d byte%s in length.\n",
-         arg,
-          finfo.st_nlink,
-          (finfo.st_nlink == 1) ? "" : "s",
-          finfo.st_size,
-          (finfo.st_size == 1) ? "" : "s");
-  printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime));
-  printf ("      Last access at: %s", ctime (&finfo.st_atime));
-  printf ("    Last modified at: %s", ctime (&finfo.st_mtime));
-  return (0);
-@}
-
-com_delete (arg)
-     char *arg;
-@{
-  too_dangerous ("delete");
-  return (1);
-@}
-
-/* Print out help for ARG, or for all of the commands if ARG is
-   not present. */
-com_help (arg)
-     char *arg;
-@{
-  register int i;
-  int printed = 0;
-
-  for (i = 0; commands[i].name; i++)
-    @{
-      if (!*arg || (strcmp (arg, commands[i].name) == 0))
-        @{
-          printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);
-          printed++;
-        @}
-    @}
-
-  if (!printed)
-    @{
-      printf ("No commands match `%s'.  Possibilties are:\n", arg);
-
-      for (i = 0; commands[i].name; i++)
-        @{
-          /* Print in six columns. */
-          if (printed == 6)
-            @{
-              printed = 0;
-              printf ("\n");
-            @}
-
-          printf ("%s\t", commands[i].name);
-          printed++;
-        @}
-
-      if (printed)
-        printf ("\n");
-    @}
-  return (0);
-@}
-
-/* Change to the directory ARG. */
-com_cd (arg)
-     char *arg;
-@{
-  if (chdir (arg) == -1)
-    @{
-      perror (arg);
-      return 1;
-    @}
-
-  com_pwd ("");
-  return (0);
-@}
-
-/* Print out the current working directory. */
-com_pwd (ignore)
-     char *ignore;
-@{
-  char dir[1024], *s;
-
-  s = getcwd (dir, sizeof(dir) - 1);
-  if (s == 0)
-    @{
-      printf ("Error getting pwd: %s\n", dir);
-      return 1;
-    @}
-
-  printf ("Current directory is %s\n", dir);
-  return 0;
-@}
-
-/* The user wishes to quit using this program.  Just set DONE non-zero. */
-com_quit (arg)
-     char *arg;
-@{
-  done = 1;
-  return (0);
-@}
-
-/* Function which tells you that you can't do this. */
-too_dangerous (caller)
-     char *caller;
-@{
-  fprintf (stderr,
-           "%s: Too dangerous for me to distribute.  Write it yourself.\n",
-           caller);
-@}
-
-/* Return non-zero if ARG is a valid argument for CALLER, else print
-   an error message and return zero. */
-int
-valid_argument (caller, arg)
-     char *caller, *arg;
-@{
-  if (!arg || !*arg)
-    @{
-      fprintf (stderr, "%s: Argument required.\n", caller);
-      return (0);
-    @}
-
-  return (1);
-@}
-@end smallexample
diff --git a/lib/readline/input.c~ b/lib/readline/input.c~
deleted file mode 100644 (file)
index a126f5a..0000000
+++ /dev/null
@@ -1,625 +0,0 @@
-/* input.c -- character input functions for readline. */
-
-/* Copyright (C) 1994-2011 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 (__TANDEM)
-#  include <floss.h>
-#endif
-
-#if defined (HAVE_CONFIG_H)
-#  include <config.h>
-#endif
-
-#include <sys/types.h>
-#include <fcntl.h>
-#if defined (HAVE_SYS_FILE_H)
-#  include <sys/file.h>
-#endif /* HAVE_SYS_FILE_H */
-
-#if defined (HAVE_UNISTD_H)
-#  include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#if defined (HAVE_STDLIB_H)
-#  include <stdlib.h>
-#else
-#  include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#include <signal.h>
-
-#include "posixselect.h"
-
-#if defined (FIONREAD_IN_SYS_IOCTL)
-#  include <sys/ioctl.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-#include "rlmbutil.h"
-
-/* Some standard library routines. */
-#include "readline.h"
-
-#include "rlprivate.h"
-#include "rlshell.h"
-#include "xmalloc.h"
-
-/* What kind of non-blocking I/O do we have? */
-#if !defined (O_NDELAY) && defined (O_NONBLOCK)
-#  define O_NDELAY O_NONBLOCK  /* Posix style */
-#endif
-
-/* Non-null means it is a pointer to a function to run while waiting for
-   character input. */
-rl_hook_func_t *rl_event_hook = (rl_hook_func_t *)NULL;
-
-/* A function to call if a read(2) is interrupted by a signal. */
-rl_hook_func_t *rl_signal_event_hook = (rl_hook_func_t *)NULL;
-
-/* A function to replace _rl_input_available for applications using the
-   callback interface. */
-rl_hook_func_t *rl_input_available_hook = (rl_hook_func_t *)NULL;
-
-rl_getc_func_t *rl_getc_function = rl_getc;
-
-static int _keyboard_input_timeout = 100000;           /* 0.1 seconds; it's in usec */
-
-static int ibuffer_space PARAMS((void));
-static int rl_get_char PARAMS((int *));
-static int rl_gather_tyi PARAMS((void));
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Character Input Buffering                   */
-/*                                                                 */
-/* **************************************************************** */
-
-static int pop_index, push_index;
-static unsigned char ibuffer[512];
-static int ibuffer_len = sizeof (ibuffer) - 1;
-
-#define any_typein (push_index != pop_index)
-
-int
-_rl_any_typein ()
-{
-  return any_typein;
-}
-
-/* Return the amount of space available in the buffer for stuffing
-   characters. */
-static int
-ibuffer_space ()
-{
-  if (pop_index > push_index)
-    return (pop_index - push_index - 1);
-  else
-    return (ibuffer_len - (push_index - pop_index));
-}
-
-/* Get a key from the buffer of characters to be read.
-   Return the key in KEY.
-   Result is non-zero if there was a key, or 0 if there wasn't. */
-static int
-rl_get_char (key)
-     int *key;
-{
-  if (push_index == pop_index)
-    return (0);
-
-  *key = ibuffer[pop_index++];
-#if 0
-  if (pop_index >= ibuffer_len)
-#else
-  if (pop_index > ibuffer_len)
-#endif
-    pop_index = 0;
-
-  return (1);
-}
-
-/* Stuff KEY into the *front* of the input buffer.
-   Returns non-zero if successful, zero if there is
-   no space left in the buffer. */
-int
-_rl_unget_char (key)
-     int key;
-{
-  if (ibuffer_space ())
-    {
-      pop_index--;
-      if (pop_index < 0)
-       pop_index = ibuffer_len;
-      ibuffer[pop_index] = key;
-      return (1);
-    }
-  return (0);
-}
-
-int
-_rl_pushed_input_available ()
-{
-  return (push_index != pop_index);
-}
-
-/* If a character is available to be read, then read it and stuff it into
-   IBUFFER.  Otherwise, just return.  Returns number of characters read
-   (0 if none available) and -1 on error (EIO). */
-static int
-rl_gather_tyi ()
-{
-  int tty;
-  register int tem, result;
-  int chars_avail, k;
-  char input;
-#if defined(HAVE_SELECT)
-  fd_set readfds, exceptfds;
-  struct timeval timeout;
-#endif
-
-  chars_avail = 0;
-  tty = fileno (rl_instream);
-
-#if defined (HAVE_SELECT)
-  FD_ZERO (&readfds);
-  FD_ZERO (&exceptfds);
-  FD_SET (tty, &readfds);
-  FD_SET (tty, &exceptfds);
-  USEC_TO_TIMEVAL (_keyboard_input_timeout, timeout);
-  result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout);
-  if (result <= 0)
-    return 0;  /* Nothing to read. */
-#endif
-
-  result = -1;
-#if defined (FIONREAD)
-  errno = 0;
-  result = ioctl (tty, FIONREAD, &chars_avail);
-  if (result == -1 && errno == EIO)
-    return -1;
-#endif
-
-#if defined (O_NDELAY)
-  if (result == -1)
-    {
-      tem = fcntl (tty, F_GETFL, 0);
-
-      fcntl (tty, F_SETFL, (tem | O_NDELAY));
-      chars_avail = read (tty, &input, 1);
-
-      fcntl (tty, F_SETFL, tem);
-      if (chars_avail == -1 && errno == EAGAIN)
-       return 0;
-      if (chars_avail == 0)    /* EOF */
-       {
-         rl_stuff_char (EOF);
-         return (0);
-       }
-    }
-#endif /* O_NDELAY */
-
-#if defined (__MINGW32__)
-  /* Use getch/_kbhit to check for available console input, in the same way
-     that we read it normally. */
-   chars_avail = isatty (tty) ? _kbhit () : 0;
-   result = 0;
-#endif
-
-  /* If there's nothing available, don't waste time trying to read
-     something. */
-  if (chars_avail <= 0)
-    return 0;
-
-  tem = ibuffer_space ();
-
-  if (chars_avail > tem)
-    chars_avail = tem;
-
-  /* One cannot read all of the available input.  I can only read a single
-     character at a time, or else programs which require input can be
-     thwarted.  If the buffer is larger than one character, I lose.
-     Damn! */
-  if (tem < ibuffer_len)
-    chars_avail = 0;
-
-  if (result != -1)
-    {
-      while (chars_avail--)
-       {
-         RL_CHECK_SIGNALS ();
-         k = (*rl_getc_function) (rl_instream);
-         if (rl_stuff_char (k) == 0)
-           break;                      /* some problem; no more room */
-         if (k == NEWLINE || k == RETURN)
-           break;
-       }
-    }
-  else
-    {
-      if (chars_avail)
-       rl_stuff_char (input);
-    }
-
-  return 1;
-}
-
-int
-rl_set_keyboard_input_timeout (u)
-     int u;
-{
-  int o;
-
-  o = _keyboard_input_timeout;
-  if (u >= 0)
-    _keyboard_input_timeout = u;
-  return (o);
-}
-
-/* Is there input available to be read on the readline input file
-   descriptor?  Only works if the system has select(2) or FIONREAD.
-   Uses the value of _keyboard_input_timeout as the timeout; if another
-   readline function wants to specify a timeout and not leave it up to
-   the user, it should use _rl_input_queued(timeout_value_in_microseconds)
-   instead. */
-int
-_rl_input_available ()
-{
-#if defined(HAVE_SELECT)
-  fd_set readfds, exceptfds;
-  struct timeval timeout;
-#endif
-#if !defined (HAVE_SELECT) && defined(FIONREAD)
-  int chars_avail;
-#endif
-  int tty;
-
-  if (rl_input_available_hook)
-    return (*rl_input_available_hook) ();
-
-  tty = fileno (rl_instream);
-
-#if defined (HAVE_SELECT)
-  FD_ZERO (&readfds);
-  FD_ZERO (&exceptfds);
-  FD_SET (tty, &readfds);
-  FD_SET (tty, &exceptfds);
-  timeout.tv_sec = 0;
-  timeout.tv_usec = _keyboard_input_timeout;
-  return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0);
-#else
-
-#if defined (FIONREAD)
-  if (ioctl (tty, FIONREAD, &chars_avail) == 0)
-    return (chars_avail);
-#endif
-
-#endif
-
-#if defined (__MINGW32__)
-  if (isatty (tty))
-    return (_kbhit ());
-#endif
-
-  return 0;
-}
-
-int
-_rl_input_queued (t)
-     int t;
-{
-  int old_timeout, r;
-
-  old_timeout = rl_set_keyboard_input_timeout (t);
-  r = _rl_input_available ();
-  rl_set_keyboard_input_timeout (old_timeout);
-  return r;
-}
-
-void
-_rl_insert_typein (c)
-     int c;     
-{      
-  int key, t, i;
-  char *string;
-
-  i = key = 0;
-  string = (char *)xmalloc (ibuffer_len + 1);
-  string[i++] = (char) c;
-
-  while ((t = rl_get_char (&key)) &&
-        _rl_keymap[key].type == ISFUNC &&
-        _rl_keymap[key].function == rl_insert)
-    string[i++] = key;
-
-  if (t)
-    _rl_unget_char (key);
-
-  string[i] = '\0';
-  rl_insert_text (string);
-  xfree (string);
-}
-
-/* Add KEY to the buffer of characters to be read.  Returns 1 if the
-   character was stuffed correctly; 0 otherwise. */
-int
-rl_stuff_char (key)
-     int key;
-{
-  if (ibuffer_space () == 0)
-    return 0;
-
-  if (key == EOF)
-    {
-      key = NEWLINE;
-      rl_pending_input = EOF;
-      RL_SETSTATE (RL_STATE_INPUTPENDING);
-    }
-  ibuffer[push_index++] = key;
-#if 0
-  if (push_index >= ibuffer_len)
-#else
-  if (push_index > ibuffer_len)
-#endif
-    push_index = 0;
-
-  return 1;
-}
-
-/* Make C be the next command to be executed. */
-int
-rl_execute_next (c)
-     int c;
-{
-  rl_pending_input = c;
-  RL_SETSTATE (RL_STATE_INPUTPENDING);
-  return 0;
-}
-
-/* Clear any pending input pushed with rl_execute_next() */
-int
-rl_clear_pending_input ()
-{
-  rl_pending_input = 0;
-  RL_UNSETSTATE (RL_STATE_INPUTPENDING);
-  return 0;
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                          Character Input                        */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Read a key, including pending input. */
-int
-rl_read_key ()
-{
-  int c, r;
-
-  if (rl_pending_input)
-    {
-      c = rl_pending_input;
-      rl_clear_pending_input ();
-    }
-  else
-    {
-      /* If input is coming from a macro, then use that. */
-      if (c = _rl_next_macro_key ())
-       return (c);
-
-      /* If the user has an event function, then call it periodically. */
-      if (rl_event_hook)
-       {
-         while (rl_event_hook)
-           {
-             if (rl_get_char (&c) != 0)
-               break;
-               
-             if ((r = rl_gather_tyi ()) < 0)   /* XXX - EIO */
-               {
-                 rl_done = 1;
-                 return ('\n');
-               }
-             else if (r > 0)                   /* read something */
-               continue;
-
-             RL_CHECK_SIGNALS ();
-             if (rl_done)              /* XXX - experimental */
-               return ('\n');
-             (*rl_event_hook) ();
-           }
-       }
-      else
-       {
-         if (rl_get_char (&c) == 0)
-           c = (*rl_getc_function) (rl_instream);
-/* fprintf(stderr, "rl_read_key: calling RL_CHECK_SIGNALS: _rl_caught_signal = %d", _rl_caught_signal); */
-         RL_CHECK_SIGNALS ();
-       }
-    }
-
-  return (c);
-}
-
-int
-rl_getc (stream)
-     FILE *stream;
-{
-  int result;
-  unsigned char c;
-
-  while (1)
-    {
-      RL_CHECK_SIGNALS ();
-
-      /* We know at this point that _rl_caught_signal == 0 */
-
-#if defined (__MINGW32__)
-      if (isatty (fileno (stream)))
-       return (getch ());
-#endif
-      result = read (fileno (stream), &c, sizeof (unsigned char));
-
-      if (result == sizeof (unsigned char))
-       return (c);
-
-      /* If zero characters are returned, then the file that we are
-        reading from is empty!  Return EOF in that case. */
-      if (result == 0)
-       return (EOF);
-
-#if defined (__BEOS__)
-      if (errno == EINTR)
-       continue;
-#endif
-
-#if defined (EWOULDBLOCK)
-#  define X_EWOULDBLOCK EWOULDBLOCK
-#else
-#  define X_EWOULDBLOCK -99
-#endif
-
-#if defined (EAGAIN)
-#  define X_EAGAIN EAGAIN
-#else
-#  define X_EAGAIN -99
-#endif
-
-      if (errno == X_EWOULDBLOCK || errno == X_EAGAIN)
-       {
-         if (sh_unset_nodelay_mode (fileno (stream)) < 0)
-           return (EOF);
-         continue;
-       }
-
-#undef X_EWOULDBLOCK
-#undef X_EAGAIN
-
-/* fprintf(stderr, "rl_getc: result = %d errno = %d\n", result, errno); */
-
-      /* If the error that we received was EINTR, then try again,
-        this is simply an interrupted system call to read ().  We allow
-        the read to be interrupted if we caught SIGHUP or SIGTERM (but
-        not SIGINT; let the signal handler deal with that), but if the
-        application sets an event hook, call it for other signals.
-        Otherwise (not EINTR), some error ocurred, also signifying EOF. */
-      if (errno != EINTR)
-       return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF);
-      else if (_rl_caught_signal == SIGHUP || _rl_caught_signal == SIGTERM)
-       return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF);
-      else if (_rl_caught_signal == SIGINT || _rl_caught_signal == SIGQUIT)
-        RL_CHECK_SIGNALS ();
-
-      if (rl_signal_event_hook)
-       (*rl_signal_event_hook) ();
-    }
-}
-
-#if defined (HANDLE_MULTIBYTE)
-/* read multibyte char */
-int
-_rl_read_mbchar (mbchar, size)
-     char *mbchar;
-     int size;
-{
-  int mb_len, c;
-  size_t mbchar_bytes_length;
-  wchar_t wc;
-  mbstate_t ps, ps_back;
-
-  memset(&ps, 0, sizeof (mbstate_t));
-  memset(&ps_back, 0, sizeof (mbstate_t));
-
-  mb_len = 0;  
-  while (mb_len < size)
-    {
-      RL_SETSTATE(RL_STATE_MOREINPUT);
-      c = rl_read_key ();
-      RL_UNSETSTATE(RL_STATE_MOREINPUT);
-
-      if (c < 0)
-       break;
-
-      mbchar[mb_len++] = c;
-
-      mbchar_bytes_length = mbrtowc (&wc, mbchar, mb_len, &ps);
-      if (mbchar_bytes_length == (size_t)(-1))
-       break;          /* invalid byte sequence for the current locale */
-      else if (mbchar_bytes_length == (size_t)(-2))
-       {
-         /* shorted bytes */
-         ps = ps_back;
-         continue;
-       } 
-      else if (mbchar_bytes_length == 0)
-       {
-         mbchar[0] = '\0';     /* null wide character */
-         mb_len = 1;
-         break;
-       }
-      else if (mbchar_bytes_length > (size_t)(0))
-       break;
-    }
-
-  return mb_len;
-}
-
-/* Read a multibyte-character string whose first character is FIRST into
-   the buffer MB of length MLEN.  Returns the last character read, which
-   may be FIRST.  Used by the search functions, among others.  Very similar
-   to _rl_read_mbchar. */
-int
-_rl_read_mbstring (first, mb, mlen)
-     int first;
-     char *mb;
-     int mlen;
-{
-  int i, c;
-  mbstate_t ps;
-
-  c = first;
-  memset (mb, 0, mlen);
-  for (i = 0; c >= 0 && i < mlen; i++)
-    {
-      mb[i] = (char)c;
-      memset (&ps, 0, sizeof (mbstate_t));
-      if (_rl_get_char_len (mb, &ps) == -2)
-       {
-         /* Read more for multibyte character */
-         RL_SETSTATE (RL_STATE_MOREINPUT);
-         c = rl_read_key ();
-         RL_UNSETSTATE (RL_STATE_MOREINPUT);
-       }
-      else
-       break;
-    }
-  return c;
-}
-#endif /* HANDLE_MULTIBYTE */
diff --git a/lib/readline/readline.c~ b/lib/readline/readline.c~
deleted file mode 100644 (file)
index 8e58d83..0000000
+++ /dev/null
@@ -1,1347 +0,0 @@
-/* readline.c -- a general facility for reading lines of input
-   with emacs style editing and completion. */
-
-/* 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>
-#include "posixstat.h"
-#include <fcntl.h>
-#if defined (HAVE_SYS_FILE_H)
-#  include <sys/file.h>
-#endif /* HAVE_SYS_FILE_H */
-
-#if defined (HAVE_UNISTD_H)
-#  include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#if defined (HAVE_STDLIB_H)
-#  include <stdlib.h>
-#else
-#  include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#if defined (HAVE_LOCALE_H)
-#  include <locale.h>
-#endif
-
-#include <stdio.h>
-#include "posixjmp.h"
-#include <errno.h>
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-#include "rlmbutil.h"
-
-#if defined (__EMX__)
-#  define INCL_DOSPROCESS
-#  include <os2.h>
-#endif /* __EMX__ */
-
-/* Some standard library routines. */
-#include "readline.h"
-#include "history.h"
-
-#include "rlprivate.h"
-#include "rlshell.h"
-#include "xmalloc.h"
-
-#ifndef RL_LIBRARY_VERSION
-#  define RL_LIBRARY_VERSION "5.1"
-#endif
-
-#ifndef RL_READLINE_VERSION
-#  define RL_READLINE_VERSION  0x0501
-#endif
-
-extern void _rl_free_history_entry PARAMS((HIST_ENTRY *));
-
-/* Forward declarations used in this file. */
-static char *readline_internal PARAMS((void));
-static void readline_initialize_everything PARAMS((void));
-
-static void bind_arrow_keys_internal PARAMS((Keymap));
-static void bind_arrow_keys PARAMS((void));
-
-static void readline_default_bindings PARAMS((void));
-static void reset_default_bindings PARAMS((void));
-
-static int _rl_subseq_result PARAMS((int, Keymap, int, int));
-static int _rl_subseq_getchar PARAMS((int));
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Line editing input utility                  */
-/*                                                                 */
-/* **************************************************************** */
-
-const char *rl_library_version = RL_LIBRARY_VERSION;
-
-int rl_readline_version = RL_READLINE_VERSION;
-
-/* True if this is `real' readline as opposed to some stub substitute. */
-int rl_gnu_readline_p = 1;
-
-/* A pointer to the keymap that is currently in use.
-   By default, it is the standard emacs keymap. */
-Keymap _rl_keymap = emacs_standard_keymap;
-
-/* The current style of editing. */
-int rl_editing_mode = emacs_mode;
-
-/* The current insert mode:  input (the default) or overwrite */
-int rl_insert_mode = RL_IM_DEFAULT;
-
-/* Non-zero if we called this function from _rl_dispatch().  It's present
-   so functions can find out whether they were called from a key binding
-   or directly from an application. */
-int rl_dispatching;
-
-/* Non-zero if the previous command was a kill command. */
-int _rl_last_command_was_kill = 0;
-
-/* The current value of the numeric argument specified by the user. */
-int rl_numeric_arg = 1;
-
-/* Non-zero if an argument was typed. */
-int rl_explicit_arg = 0;
-
-/* Temporary value used while generating the argument. */
-int rl_arg_sign = 1;
-
-/* Non-zero means we have been called at least once before. */
-static int rl_initialized;
-
-#if 0
-/* If non-zero, this program is running in an EMACS buffer. */
-static int running_in_emacs;
-#endif
-
-/* Flags word encapsulating the current readline state. */
-int rl_readline_state = RL_STATE_NONE;
-
-/* The current offset in the current input line. */
-int rl_point;
-
-/* Mark in the current input line. */
-int rl_mark;
-
-/* Length of the current input line. */
-int rl_end;
-
-/* Make this non-zero to return the current input_line. */
-int rl_done;
-
-/* The last function executed by readline. */
-rl_command_func_t *rl_last_func = (rl_command_func_t *)NULL;
-
-/* Top level environment for readline_internal (). */
-procenv_t _rl_top_level;
-
-/* The streams we interact with. */
-FILE *_rl_in_stream, *_rl_out_stream;
-
-/* The names of the streams that we do input and output to. */
-FILE *rl_instream = (FILE *)NULL;
-FILE *rl_outstream = (FILE *)NULL;
-
-/* Non-zero means echo characters as they are read.  Defaults to no echo;
-   set to 1 if there is a controlling terminal, we can get its attributes,
-   and the attributes include `echo'.  Look at rltty.c:prepare_terminal_settings
-   for the code that sets it. */
-int _rl_echoing_p = 0;
-
-/* Current prompt. */
-char *rl_prompt = (char *)NULL;
-int rl_visible_prompt_length = 0;
-
-/* Set to non-zero by calling application if it has already printed rl_prompt
-   and does not want readline to do it the first time. */
-int rl_already_prompted = 0;
-
-/* The number of characters read in order to type this complete command. */
-int rl_key_sequence_length = 0;
-
-/* If non-zero, then this is the address of a function to call just
-   before readline_internal_setup () prints the first prompt. */
-rl_hook_func_t *rl_startup_hook = (rl_hook_func_t *)NULL;
-
-/* If non-zero, this is the address of a function to call just before
-   readline_internal_setup () returns and readline_internal starts
-   reading input characters. */
-rl_hook_func_t *rl_pre_input_hook = (rl_hook_func_t *)NULL;
-
-/* What we use internally.  You should always refer to RL_LINE_BUFFER. */
-static char *the_line;
-
-/* The character that can generate an EOF.  Really read from
-   the terminal driver... just defaulted here. */
-int _rl_eof_char = CTRL ('D');
-
-/* Non-zero makes this the next keystroke to read. */
-int rl_pending_input = 0;
-
-/* Pointer to a useful terminal name. */
-const char *rl_terminal_name = (const char *)NULL;
-
-/* Non-zero means to always use horizontal scrolling in line display. */
-int _rl_horizontal_scroll_mode = 0;
-
-/* Non-zero means to display an asterisk at the starts of history lines
-   which have been modified. */
-int _rl_mark_modified_lines = 0;  
-
-/* The style of `bell' notification preferred.  This can be set to NO_BELL,
-   AUDIBLE_BELL, or VISIBLE_BELL. */
-int _rl_bell_preference = AUDIBLE_BELL;
-     
-/* String inserted into the line by rl_insert_comment (). */
-char *_rl_comment_begin;
-
-/* Keymap holding the function currently being executed. */
-Keymap rl_executing_keymap;
-
-/* Keymap we're currently using to dispatch. */
-Keymap _rl_dispatching_keymap;
-
-/* Non-zero means to erase entire line, including prompt, on empty input lines. */
-int rl_erase_empty_line = 0;
-
-/* Non-zero means to read only this many characters rather than up to a
-   character bound to accept-line. */
-int rl_num_chars_to_read;
-
-/* Line buffer and maintenence. */
-char *rl_line_buffer = (char *)NULL;
-int rl_line_buffer_len = 0;
-
-/* Key sequence `contexts' */
-_rl_keyseq_cxt *_rl_kscxt = 0;
-
-int rl_executing_key;
-char *rl_executing_keyseq = 0;
-int _rl_executing_keyseq_size = 0;
-
-/* Timeout (specified in milliseconds) when reading characters making up an
-   ambiguous multiple-key sequence */
-int _rl_keyseq_timeout = 500;
-
-#define RESIZE_KEYSEQ_BUFFER() \
-  do \
-    { \
-      if (rl_key_sequence_length + 2 >= _rl_executing_keyseq_size) \
-       { \
-         _rl_executing_keyseq_size += 16; \
-         rl_executing_keyseq = xrealloc (rl_executing_keyseq, _rl_executing_keyseq_size); \
-       } \
-    } \
-  while (0);
-        
-/* Forward declarations used by the display, termcap, and history code. */
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     `Forward' declarations                      */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Non-zero means do not parse any lines other than comments and
-   parser directives. */
-unsigned char _rl_parsing_conditionalized_out = 0;
-
-/* Non-zero means to convert characters with the meta bit set to
-   escape-prefixed characters so we can indirect through
-   emacs_meta_keymap or vi_escape_keymap. */
-int _rl_convert_meta_chars_to_ascii = 1;
-
-/* Non-zero means to output characters with the meta bit set directly
-   rather than as a meta-prefixed escape sequence. */
-int _rl_output_meta_chars = 0;
-
-/* Non-zero means to look at the termios special characters and bind
-   them to equivalent readline functions at startup. */
-int _rl_bind_stty_chars = 1;
-
-/* Non-zero means to go through the history list at every newline (or
-   whenever rl_done is set and readline returns) and revert each line to
-   its initial state. */
-int _rl_revert_all_at_newline = 0;
-
-/* Non-zero means to honor the termios ECHOCTL bit and echo control
-   characters corresponding to keyboard-generated signals. */
-int _rl_echo_control_chars = 1;
-
-/* Non-zero means to prefix the displayed prompt with a character indicating
-   the editing mode: @ for emacs, : for vi-command, + for vi-insert. */
-int _rl_show_mode_in_prompt = 0;
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Top Level Functions                         */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Non-zero means treat 0200 bit in terminal input as Meta bit. */
-int _rl_meta_flag = 0; /* Forward declaration */
-
-/* Set up the prompt and expand it.  Called from readline() and
-   rl_callback_handler_install (). */
-int
-rl_set_prompt (prompt)
-     const char *prompt;
-{
-  FREE (rl_prompt);
-  rl_prompt = prompt ? savestring (prompt) : (char *)NULL;
-  rl_display_prompt = rl_prompt ? rl_prompt : "";
-
-  rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
-  return 0;
-}
-  
-/* Read a line of input.  Prompt with PROMPT.  An empty PROMPT means
-   none.  A return value of NULL means that EOF was encountered. */
-char *
-readline (prompt)
-     const char *prompt;
-{
-  char *value;
-#if 0
-  int in_callback;
-#endif
-
-  /* If we are at EOF return a NULL string. */
-  if (rl_pending_input == EOF)
-    {
-      rl_clear_pending_input ();
-      return ((char *)NULL);
-    }
-
-#if 0
-  /* If readline() is called after installing a callback handler, temporarily
-     turn off the callback state to avoid ensuing messiness.  Patch supplied
-     by the gdb folks.  XXX -- disabled.  This can be fooled and readline
-     left in a strange state by a poorly-timed longjmp. */
-  if (in_callback = RL_ISSTATE (RL_STATE_CALLBACK))
-    RL_UNSETSTATE (RL_STATE_CALLBACK);
-#endif
-
-  rl_set_prompt (prompt);
-
-  rl_initialize ();
-  if (rl_prep_term_function)
-    (*rl_prep_term_function) (_rl_meta_flag);
-
-#if defined (HANDLE_SIGNALS)
-  rl_set_signals ();
-#endif
-
-  value = readline_internal ();
-  if (rl_deprep_term_function)
-    (*rl_deprep_term_function) ();
-
-#if defined (HANDLE_SIGNALS)
-  rl_clear_signals ();
-#endif
-
-#if 0
-  if (in_callback)
-    RL_SETSTATE (RL_STATE_CALLBACK);
-#endif
-
-#if HAVE_DECL_AUDIT_TTY && defined (ENABLE_TTY_AUDIT_SUPPORT)
-  if (value)
-    _rl_audit_tty (value);
-#endif
-
-  return (value);
-}
-
-#if defined (READLINE_CALLBACKS)
-#  define STATIC_CALLBACK
-#else
-#  define STATIC_CALLBACK static
-#endif
-
-STATIC_CALLBACK void
-readline_internal_setup ()
-{
-  char *nprompt;
-
-  _rl_in_stream = rl_instream;
-  _rl_out_stream = rl_outstream;
-
-  /* Enable the meta key only for the duration of readline(), if this
-     terminal has one. */
-  if (_rl_enable_meta)
-    _rl_enable_meta_key ();
-
-  if (rl_startup_hook)
-    (*rl_startup_hook) ();
-
-#if defined (VI_MODE)
-  if (rl_editing_mode == vi_mode)
-    rl_vi_insert_mode (1, 'i');
-#endif /* VI_MODE */
-
-  /* If we're not echoing, we still want to at least print a prompt, because
-     rl_redisplay will not do it for us.  If the calling application has a
-     custom redisplay function, though, let that function handle it. */
-  if (_rl_echoing_p == 0 && rl_redisplay_function == rl_redisplay)
-    {
-      if (rl_prompt && rl_already_prompted == 0)
-       {
-         nprompt = _rl_strip_prompt (rl_prompt);
-         fprintf (_rl_out_stream, "%s", nprompt);
-         fflush (_rl_out_stream);
-         xfree (nprompt);
-       }
-    }
-  else
-    {
-      if (rl_prompt && rl_already_prompted)
-       rl_on_new_line_with_prompt ();
-      else
-       rl_on_new_line ();
-      (*rl_redisplay_function) ();
-    }
-
-  if (rl_pre_input_hook)
-    (*rl_pre_input_hook) ();
-
-  RL_CHECK_SIGNALS ();
-}
-
-STATIC_CALLBACK char *
-readline_internal_teardown (eof)
-     int eof;
-{
-  char *temp;
-  HIST_ENTRY *entry;
-
-  RL_CHECK_SIGNALS ();
-
-  /* Restore the original of this history line, iff the line that we
-     are editing was originally in the history, AND the line has changed. */
-  entry = current_history ();
-
-  if (entry && rl_undo_list)
-    {
-      temp = savestring (the_line);
-      rl_revert_line (1, 0);
-      entry = replace_history_entry (where_history (), the_line, (histdata_t)NULL);
-      _rl_free_history_entry (entry);
-
-      strcpy (the_line, temp);
-      xfree (temp);
-    }
-
-  if (_rl_revert_all_at_newline)
-    _rl_revert_all_lines ();
-
-  /* At any rate, it is highly likely that this line has an undo list.  Get
-     rid of it now. */
-  if (rl_undo_list)
-    rl_free_undo_list ();
-
-  /* Disable the meta key, if this terminal has one. */
-  _rl_disable_meta_key ();
-
-  /* Restore normal cursor, if available. */
-  _rl_set_insert_mode (RL_IM_INSERT, 0);
-
-  return (eof ? (char *)NULL : savestring (the_line));
-}
-
-void
-_rl_internal_char_cleanup ()
-{
-#if defined (VI_MODE)
-  /* In vi mode, when you exit insert mode, the cursor moves back
-     over the previous character.  We explicitly check for that here. */
-  if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap)
-    rl_vi_check ();
-#endif /* VI_MODE */
-
-  if (rl_num_chars_to_read && rl_end >= rl_num_chars_to_read)
-    {
-      (*rl_redisplay_function) ();
-      _rl_want_redisplay = 0;
-      rl_newline (1, '\n');
-    }
-
-  if (rl_done == 0)
-    {
-      (*rl_redisplay_function) ();
-      _rl_want_redisplay = 0;
-    }
-
-  /* If the application writer has told us to erase the entire line if
-     the only character typed was something bound to rl_newline, do so. */
-  if (rl_erase_empty_line && rl_done && rl_last_func == rl_newline &&
-      rl_point == 0 && rl_end == 0)
-    _rl_erase_entire_line ();
-}
-
-STATIC_CALLBACK int
-#if defined (READLINE_CALLBACKS)
-readline_internal_char ()
-#else
-readline_internal_charloop ()
-#endif
-{
-  static int lastc, eof_found;
-  int c, code, lk;
-
-  lastc = -1;
-  eof_found = 0;
-
-#if !defined (READLINE_CALLBACKS)
-  while (rl_done == 0)
-    {
-#endif
-      lk = _rl_last_command_was_kill;
-
-#if defined (HAVE_POSIX_SIGSETJMP)
-      code = sigsetjmp (_rl_top_level, 0);
-#else
-      code = setjmp (_rl_top_level);
-#endif
-
-      if (code)
-       {
-         (*rl_redisplay_function) ();
-         _rl_want_redisplay = 0;
-         /* If we get here, we're not being called from something dispatched
-            from _rl_callback_read_char(), which sets up its own value of
-            _rl_top_level (saving and restoring the old, of course), so
-            we can just return here. */
-         if (RL_ISSTATE (RL_STATE_CALLBACK))
-           return (0);
-       }
-
-      if (rl_pending_input == 0)
-       {
-         /* Then initialize the argument and number of keys read. */
-         _rl_reset_argument ();
-         rl_key_sequence_length = 0;
-         rl_executing_keyseq[0] = 0;
-       }
-
-      RL_SETSTATE(RL_STATE_READCMD);
-      c = rl_read_key ();
-      RL_UNSETSTATE(RL_STATE_READCMD);
-
-      /* look at input.c:rl_getc() for the circumstances under which this will
-        be returned; punt immediately on read error without converting it to
-        a newline. */
-      if (c == READERR)
-       {
-#if defined (READLINE_CALLBACKS)
-         RL_SETSTATE(RL_STATE_DONE);
-         return (rl_done = 1);
-#else
-         eof_found = 1;
-         break;
-#endif
-       }
-
-      /* EOF typed to a non-blank line is a <NL>. */
-      if (c == EOF && rl_end)
-       c = NEWLINE;
-
-      /* The character _rl_eof_char typed to blank line, and not as the
-        previous character is interpreted as EOF. */
-      if (((c == _rl_eof_char && lastc != c) || c == EOF) && !rl_end)
-       {
-#if defined (READLINE_CALLBACKS)
-         RL_SETSTATE(RL_STATE_DONE);
-         return (rl_done = 1);
-#else
-         eof_found = 1;
-         break;
-#endif
-       }
-
-      lastc = c;
-      _rl_dispatch ((unsigned char)c, _rl_keymap);
-      RL_CHECK_SIGNALS ();
-
-      /* If there was no change in _rl_last_command_was_kill, then no kill
-        has taken place.  Note that if input is pending we are reading
-        a prefix command, so nothing has changed yet. */
-      if (rl_pending_input == 0 && lk == _rl_last_command_was_kill)
-       _rl_last_command_was_kill = 0;
-
-      _rl_internal_char_cleanup ();
-
-#if defined (READLINE_CALLBACKS)
-      return 0;
-#else
-    }
-
-  return (eof_found);
-#endif
-}
-
-#if defined (READLINE_CALLBACKS)
-static int
-readline_internal_charloop ()
-{
-  int eof = 1;
-
-  while (rl_done == 0)
-    eof = readline_internal_char ();
-  return (eof);
-}
-#endif /* READLINE_CALLBACKS */
-
-/* Read a line of input from the global rl_instream, doing output on
-   the global rl_outstream.
-   If rl_prompt is non-null, then that is our prompt. */
-static char *
-readline_internal ()
-{
-  int eof;
-
-  readline_internal_setup ();
-  eof = readline_internal_charloop ();
-  return (readline_internal_teardown (eof));
-}
-
-void
-_rl_init_line_state ()
-{
-  rl_point = rl_end = rl_mark = 0;
-  the_line = rl_line_buffer;
-  the_line[0] = 0;
-}
-
-void
-_rl_set_the_line ()
-{
-  the_line = rl_line_buffer;
-}
-
-#if defined (READLINE_CALLBACKS)
-_rl_keyseq_cxt *
-_rl_keyseq_cxt_alloc ()
-{
-  _rl_keyseq_cxt *cxt;
-
-  cxt = (_rl_keyseq_cxt *)xmalloc (sizeof (_rl_keyseq_cxt));
-
-  cxt->flags = cxt->subseq_arg = cxt->subseq_retval = 0;
-
-  cxt->okey = 0;
-  cxt->ocxt = _rl_kscxt;
-  cxt->childval = 42;          /* sentinel value */
-
-  return cxt;
-}
-
-void
-_rl_keyseq_cxt_dispose (cxt)
-    _rl_keyseq_cxt *cxt;
-{
-  xfree (cxt);
-}
-
-void
-_rl_keyseq_chain_dispose ()
-{
-  _rl_keyseq_cxt *cxt;
-
-  while (_rl_kscxt)
-    {
-      cxt = _rl_kscxt;
-      _rl_kscxt = _rl_kscxt->ocxt;
-      _rl_keyseq_cxt_dispose (cxt);
-    }
-}
-#endif
-
-static int
-_rl_subseq_getchar (key)
-     int key;
-{
-  int k;
-
-  if (key == ESC)
-    RL_SETSTATE(RL_STATE_METANEXT);
-  RL_SETSTATE(RL_STATE_MOREINPUT);
-  k = rl_read_key ();
-  RL_UNSETSTATE(RL_STATE_MOREINPUT);
-  if (key == ESC)
-    RL_UNSETSTATE(RL_STATE_METANEXT);
-
-  return k;
-}
-
-#if defined (READLINE_CALLBACKS)
-int
-_rl_dispatch_callback (cxt)
-     _rl_keyseq_cxt *cxt;
-{
-  int nkey, r;
-
-  /* For now */
-  /* The first time this context is used, we want to read input and dispatch
-     on it.  When traversing the chain of contexts back `up', we want to use
-     the value from the next context down.  We're simulating recursion using
-     a chain of contexts. */
-  if ((cxt->flags & KSEQ_DISPATCHED) == 0)
-    {
-      nkey = _rl_subseq_getchar (cxt->okey);
-      if (nkey < 0)
-       {
-         _rl_abort_internal ();
-         return -1;
-       }
-      r = _rl_dispatch_subseq (nkey, cxt->dmap, cxt->subseq_arg);
-      cxt->flags |= KSEQ_DISPATCHED;
-    }
-  else
-    r = cxt->childval;
-
-  /* For now */
-  if (r != -3) /* don't do this if we indicate there will be other matches */
-    r = _rl_subseq_result (r, cxt->oldmap, cxt->okey, (cxt->flags & KSEQ_SUBSEQ));
-
-  RL_CHECK_SIGNALS ();
-  if (r == 0)                  /* success! */
-    {
-      _rl_keyseq_chain_dispose ();
-      RL_UNSETSTATE (RL_STATE_MULTIKEY);
-      return r;
-    }
-
-  if (r != -3)                 /* magic value that says we added to the chain */
-    _rl_kscxt = cxt->ocxt;
-  if (_rl_kscxt)
-    _rl_kscxt->childval = r;
-  if (r != -3)
-    _rl_keyseq_cxt_dispose (cxt);
-
-  return r;
-}
-#endif /* READLINE_CALLBACKS */
-  
-/* Do the command associated with KEY in MAP.
-   If the associated command is really a keymap, then read
-   another key, and dispatch into that map. */
-int
-_rl_dispatch (key, map)
-     register int key;
-     Keymap map;
-{
-  _rl_dispatching_keymap = map;
-  return _rl_dispatch_subseq (key, map, 0);
-}
-
-int
-_rl_dispatch_subseq (key, map, got_subseq)
-     register int key;
-     Keymap map;
-     int got_subseq;
-{
-  int r, newkey;
-  char *macro;
-  rl_command_func_t *func;
-#if defined (READLINE_CALLBACKS)
-  _rl_keyseq_cxt *cxt;
-#endif
-
-  if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
-    {
-      if (map[ESC].type == ISKMAP)
-       {
-         if (RL_ISSTATE (RL_STATE_MACRODEF))
-           _rl_add_macro_char (ESC);
-         RESIZE_KEYSEQ_BUFFER ();
-         rl_executing_keyseq[rl_key_sequence_length++] = ESC;
-         map = FUNCTION_TO_KEYMAP (map, ESC);
-         key = UNMETA (key);
-         return (_rl_dispatch (key, map));
-       }
-      else
-       rl_ding ();
-      return 0;
-    }
-
-  if (RL_ISSTATE (RL_STATE_MACRODEF))
-    _rl_add_macro_char (key);
-
-  r = 0;
-  switch (map[key].type)
-    {
-    case ISFUNC:
-      func = map[key].function;
-      if (func)
-       {
-         /* Special case rl_do_lowercase_version (). */
-         if (func == rl_do_lowercase_version)
-           return (_rl_dispatch (_rl_to_lower (key), map));
-
-         rl_executing_keymap = map;
-         rl_executing_key = key;
-
-         RESIZE_KEYSEQ_BUFFER();
-         rl_executing_keyseq[rl_key_sequence_length++] = key;
-         rl_executing_keyseq[rl_key_sequence_length] = '\0';
-
-         rl_dispatching = 1;
-         RL_SETSTATE(RL_STATE_DISPATCHING);
-         (*func) (rl_numeric_arg * rl_arg_sign, key);
-         RL_UNSETSTATE(RL_STATE_DISPATCHING);
-         rl_dispatching = 0;
-
-         /* If we have input pending, then the last command was a prefix
-            command.  Don't change the state of rl_last_func.  Otherwise,
-            remember the last command executed in this variable. */
-         if (rl_pending_input == 0 && map[key].function != rl_digit_argument)
-           rl_last_func = map[key].function;
-
-         RL_CHECK_SIGNALS ();
-       }
-      else if (map[ANYOTHERKEY].function)
-       {
-         /* OK, there's no function bound in this map, but there is a
-            shadow function that was overridden when the current keymap
-            was created.  Return -2 to note  that. */
-         if (RL_ISSTATE (RL_STATE_MACROINPUT))
-           _rl_prev_macro_key ();
-         else
-           _rl_unget_char  (key);
-         return -2;
-       }
-      else if (got_subseq)
-       {
-         /* Return -1 to note that we're in a subsequence, but  we don't
-            have a matching key, nor was one overridden.  This means
-            we need to back up the recursion chain and find the last
-            subsequence that is bound to a function. */
-         if (RL_ISSTATE (RL_STATE_MACROINPUT))
-           _rl_prev_macro_key ();
-         else
-           _rl_unget_char (key);
-         return -1;
-       }
-      else
-       {
-#if defined (READLINE_CALLBACKS)
-         RL_UNSETSTATE (RL_STATE_MULTIKEY);
-         _rl_keyseq_chain_dispose ();
-#endif
-         _rl_abort_internal ();
-         return -1;
-       }
-      break;
-
-    case ISKMAP:
-      if (map[key].function != 0)
-       {
-#if defined (VI_MODE)
-         /* The only way this test will be true is if a subsequence has been
-            bound starting with ESC, generally the arrow keys.  What we do is
-            check whether there's input in the queue, which there generally
-            will be if an arrow key has been pressed, and, if there's not,
-            just dispatch to (what we assume is) rl_vi_movement_mode right
-            away.  This is essentially an input test with a zero timeout (by
-            default) or a timeout determined by the value of `keyseq-timeout' */
-         /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
-            takes microseconds, so multiply by 1000 */
-         if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap
-             && _rl_input_queued ((_rl_keyseq_timeout > 0) ? _rl_keyseq_timeout*1000 : 0) == 0)
-{
-fprintf(stderr, "intra-character timeout 1 for key %d\n", key);
-           return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)));
-}
-#endif
-
-         RESIZE_KEYSEQ_BUFFER ();
-         rl_executing_keyseq[rl_key_sequence_length++] = key;
-         _rl_dispatching_keymap = FUNCTION_TO_KEYMAP (map, key);
-
-         /* Allocate new context here.  Use linked contexts (linked through
-            cxt->ocxt) to simulate recursion */
-#if defined (READLINE_CALLBACKS)
-         if (RL_ISSTATE (RL_STATE_CALLBACK))
-           {
-             /* Return 0 only the first time, to indicate success to
-                _rl_callback_read_char.  The rest of the time, we're called
-                from _rl_dispatch_callback, so we return -3 to indicate
-                special handling is necessary. */
-             r = RL_ISSTATE (RL_STATE_MULTIKEY) ? -3 : 0;
-             cxt = _rl_keyseq_cxt_alloc ();
-
-             if (got_subseq)
-               cxt->flags |= KSEQ_SUBSEQ;
-             cxt->okey = key;
-             cxt->oldmap = map;
-             cxt->dmap = _rl_dispatching_keymap;
-             cxt->subseq_arg = got_subseq || cxt->dmap[ANYOTHERKEY].function;
-
-             RL_SETSTATE (RL_STATE_MULTIKEY);
-             _rl_kscxt = cxt;
-
-             return r;         /* don't indicate immediate success */
-           }
-#endif
-
-         /* Tentative inter-character timeout for potential multi-key
-            sequences?  If no input within timeout, abort sequence and
-            act as if we got non-matching input. */
-         /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
-            takes microseconds, so multiply by 1000 */
-         if (_rl_keyseq_timeout > 0 &&
-               (RL_ISSTATE (RL_STATE_INPUTPENDING|RL_STATE_MACROINPUT) == 0) &&
-               _rl_pushed_input_available () == 0 &&
-               _rl_dispatching_keymap[ANYOTHERKEY].function &&
-               _rl_input_queued (_rl_keyseq_timeout*1000) == 0)
-{
-fprintf(stderr, "intra-character timeout 2 for key %d\n", key);
-           return (_rl_subseq_result (-2, map, key, got_subseq));
-}
-
-         newkey = _rl_subseq_getchar (key);
-         if (newkey < 0)
-           {
-             _rl_abort_internal ();
-             return -1;
-           }
-
-         r = _rl_dispatch_subseq (newkey, _rl_dispatching_keymap, got_subseq || map[ANYOTHERKEY].function);
-         return _rl_subseq_result (r, map, key, got_subseq);
-       }
-      else
-       {
-         _rl_abort_internal ();
-         return -1;
-       }
-      break;
-
-    case ISMACR:
-      if (map[key].function != 0)
-       {
-         rl_executing_keyseq[rl_key_sequence_length] = '\0';
-         macro = savestring ((char *)map[key].function);
-         _rl_with_macro_input (macro);
-         return 0;
-       }
-      break;
-    }
-#if defined (VI_MODE)
-  if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap &&
-      key != ANYOTHERKEY &&
-      _rl_vi_textmod_command (key))
-    _rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign);
-#endif
-
-  return (r);
-}
-
-static int
-_rl_subseq_result (r, map, key, got_subseq)
-     int r;
-     Keymap map;
-     int key, got_subseq;
-{
-  Keymap m;
-  int type, nt;
-  rl_command_func_t *func, *nf;
-
-  if (r == -2)
-    /* We didn't match anything, and the keymap we're indexed into
-       shadowed a function previously bound to that prefix.  Call
-       the function.  The recursive call to _rl_dispatch_subseq has
-       already taken care of pushing any necessary input back onto
-       the input queue with _rl_unget_char. */
-    {
-      m = _rl_dispatching_keymap;
-      type = m[ANYOTHERKEY].type;
-      func = m[ANYOTHERKEY].function;
-      if (type == ISFUNC && func == rl_do_lowercase_version)
-       r = _rl_dispatch (_rl_to_lower (key), map);
-      else if (type == ISFUNC && func == rl_insert)
-       {
-         /* If the function that was shadowed was self-insert, we
-            somehow need a keymap with map[key].func == self-insert.
-            Let's use this one. */
-         nt = m[key].type;
-         nf = m[key].function;
-
-         m[key].type = type;
-         m[key].function = func;
-         r = _rl_dispatch (key, m);
-         m[key].type = nt;
-         m[key].function = nf;
-       }
-      else
-       r = _rl_dispatch (ANYOTHERKEY, m);
-    }
-  else if (r && map[ANYOTHERKEY].function)
-    {
-      /* We didn't match (r is probably -1), so return something to
-        tell the caller that it should try ANYOTHERKEY for an
-        overridden function. */
-      if (RL_ISSTATE (RL_STATE_MACROINPUT))
-       _rl_prev_macro_key ();
-      else
-       _rl_unget_char (key);
-      _rl_dispatching_keymap = map;
-      return -2;
-    }
-  else if (r && got_subseq)
-    {
-      /* OK, back up the chain. */
-      if (RL_ISSTATE (RL_STATE_MACROINPUT))
-       _rl_prev_macro_key ();
-      else
-       _rl_unget_char (key);
-      _rl_dispatching_keymap = map;
-      return -1;
-    }
-
-  return r;
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Initializations                             */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Initialize readline (and terminal if not already). */
-int
-rl_initialize ()
-{
-  /* If we have never been called before, initialize the
-     terminal and data structures. */
-  if (!rl_initialized)
-    {
-      RL_SETSTATE(RL_STATE_INITIALIZING);
-      readline_initialize_everything ();
-      RL_UNSETSTATE(RL_STATE_INITIALIZING);
-      rl_initialized++;
-      RL_SETSTATE(RL_STATE_INITIALIZED);
-    }
-
-  /* Initalize the current line information. */
-  _rl_init_line_state ();
-
-  /* We aren't done yet.  We haven't even gotten started yet! */
-  rl_done = 0;
-  RL_UNSETSTATE(RL_STATE_DONE);
-
-  /* Tell the history routines what is going on. */
-  _rl_start_using_history ();
-
-  /* Make the display buffer match the state of the line. */
-  rl_reset_line_state ();
-
-  /* No such function typed yet. */
-  rl_last_func = (rl_command_func_t *)NULL;
-
-  /* Parsing of key-bindings begins in an enabled state. */
-  _rl_parsing_conditionalized_out = 0;
-
-#if defined (VI_MODE)
-  if (rl_editing_mode == vi_mode)
-    _rl_vi_initialize_line ();
-#endif
-
-  /* Each line starts in insert mode (the default). */
-  _rl_set_insert_mode (RL_IM_DEFAULT, 1);
-
-  return 0;
-}
-
-#if 0
-#if defined (__EMX__)
-static void
-_emx_build_environ ()
-{
-  TIB *tibp;
-  PIB *pibp;
-  char *t, **tp;
-  int c;
-
-  DosGetInfoBlocks (&tibp, &pibp);
-  t = pibp->pib_pchenv;
-  for (c = 1; *t; c++)
-    t += strlen (t) + 1;
-  tp = environ = (char **)xmalloc ((c + 1) * sizeof (char *));
-  t = pibp->pib_pchenv;
-  while (*t)
-    {
-      *tp++ = t;
-      t += strlen (t) + 1;
-    }
-  *tp = 0;
-}
-#endif /* __EMX__ */
-#endif
-
-/* Initialize the entire state of the world. */
-static void
-readline_initialize_everything ()
-{
-#if 0
-#if defined (__EMX__)
-  if (environ == 0)
-    _emx_build_environ ();
-#endif
-#endif
-
-#if 0
-  /* Find out if we are running in Emacs -- UNUSED. */
-  running_in_emacs = sh_get_env_value ("EMACS") != (char *)0;
-#endif
-
-  /* Set up input and output if they are not already set up. */
-  if (!rl_instream)
-    rl_instream = stdin;
-
-  if (!rl_outstream)
-    rl_outstream = stdout;
-
-  /* Bind _rl_in_stream and _rl_out_stream immediately.  These values
-     may change, but they may also be used before readline_internal ()
-     is called. */
-  _rl_in_stream = rl_instream;
-  _rl_out_stream = rl_outstream;
-
-  /* Allocate data structures. */
-  if (rl_line_buffer == 0)
-    rl_line_buffer = (char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
-
-  /* Initialize the terminal interface. */
-  if (rl_terminal_name == 0)
-    rl_terminal_name = sh_get_env_value ("TERM");
-  _rl_init_terminal_io (rl_terminal_name);
-
-  /* Bind tty characters to readline functions. */
-  readline_default_bindings ();
-
-  /* Initialize the function names. */
-  rl_initialize_funmap ();
-
-  /* Decide whether we should automatically go into eight-bit mode. */
-  _rl_init_eightbit ();
-      
-  /* Read in the init file. */
-  rl_read_init_file ((char *)NULL);
-
-  /* XXX */
-  if (_rl_horizontal_scroll_mode && _rl_term_autowrap)
-    {
-      _rl_screenwidth--;
-      _rl_screenchars -= _rl_screenheight;
-    }
-
-  /* Override the effect of any `set keymap' assignments in the
-     inputrc file. */
-  rl_set_keymap_from_edit_mode ();
-
-  /* Try to bind a common arrow key prefix, if not already bound. */
-  bind_arrow_keys ();
-
-  /* If the completion parser's default word break characters haven't
-     been set yet, then do so now. */
-  if (rl_completer_word_break_characters == (char *)NULL)
-    rl_completer_word_break_characters = (char *)rl_basic_word_break_characters;
-
-#if defined (COLOR_SUPPORT)
-  if (_rl_colored_stats)
-    _rl_parse_colors ();
-#endif
-
-  rl_executing_keyseq = malloc (_rl_executing_keyseq_size = 16);
-  if (rl_executing_keyseq)
-    rl_executing_keyseq[0] = '\0';
-}
-
-/* If this system allows us to look at the values of the regular
-   input editing characters, then bind them to their readline
-   equivalents, iff the characters are not bound to keymaps. */
-static void
-readline_default_bindings ()
-{
-  if (_rl_bind_stty_chars)
-    rl_tty_set_default_bindings (_rl_keymap);
-}
-
-/* Reset the default bindings for the terminal special characters we're
-   interested in back to rl_insert and read the new ones. */
-static void
-reset_default_bindings ()
-{
-  if (_rl_bind_stty_chars)
-    {
-      rl_tty_unset_default_bindings (_rl_keymap);
-      rl_tty_set_default_bindings (_rl_keymap);
-    }
-}
-
-/* Bind some common arrow key sequences in MAP. */
-static void
-bind_arrow_keys_internal (map)
-     Keymap map;
-{
-  Keymap xkeymap;
-
-  xkeymap = _rl_keymap;
-  _rl_keymap = map;
-
-#if defined (__MSDOS__)
-  rl_bind_keyseq_if_unbound ("\033[0A", rl_get_previous_history);
-  rl_bind_keyseq_if_unbound ("\033[0B", rl_backward_char);
-  rl_bind_keyseq_if_unbound ("\033[0C", rl_forward_char);
-  rl_bind_keyseq_if_unbound ("\033[0D", rl_get_next_history);
-#endif
-
-  rl_bind_keyseq_if_unbound ("\033[A", rl_get_previous_history);
-  rl_bind_keyseq_if_unbound ("\033[B", rl_get_next_history);
-  rl_bind_keyseq_if_unbound ("\033[C", rl_forward_char);
-  rl_bind_keyseq_if_unbound ("\033[D", rl_backward_char);
-  rl_bind_keyseq_if_unbound ("\033[H", rl_beg_of_line);
-  rl_bind_keyseq_if_unbound ("\033[F", rl_end_of_line);
-
-  rl_bind_keyseq_if_unbound ("\033OA", rl_get_previous_history);
-  rl_bind_keyseq_if_unbound ("\033OB", rl_get_next_history);
-  rl_bind_keyseq_if_unbound ("\033OC", rl_forward_char);
-  rl_bind_keyseq_if_unbound ("\033OD", rl_backward_char);
-  rl_bind_keyseq_if_unbound ("\033OH", rl_beg_of_line);
-  rl_bind_keyseq_if_unbound ("\033OF", rl_end_of_line);
-
-#if defined (__MINGW32__)
-  rl_bind_keyseq_if_unbound ("\340H", rl_get_previous_history);
-  rl_bind_keyseq_if_unbound ("\340P", rl_get_next_history);
-  rl_bind_keyseq_if_unbound ("\340M", rl_forward_char);
-  rl_bind_keyseq_if_unbound ("\340K", rl_backward_char);
-  rl_bind_keyseq_if_unbound ("\340G", rl_beg_of_line);
-  rl_bind_keyseq_if_unbound ("\340O", rl_end_of_line);
-  rl_bind_keyseq_if_unbound ("\340S", rl_delete);
-  rl_bind_keyseq_if_unbound ("\340R", rl_overwrite_mode);  
-#endif
-
-  _rl_keymap = xkeymap;
-}
-
-/* Try and bind the common arrow key prefixes after giving termcap and
-   the inputrc file a chance to bind them and create `real' keymaps
-   for the arrow key prefix. */
-static void
-bind_arrow_keys ()
-{
-  bind_arrow_keys_internal (emacs_standard_keymap);
-
-#if defined (VI_MODE)
-  bind_arrow_keys_internal (vi_movement_keymap);
-  /* Unbind vi_movement_keymap[ESC] to allow users to repeatedly hit ESC
-     in vi command mode while still allowing the arrow keys to work. */
-  if (vi_movement_keymap[ESC].type == ISKMAP)
-    rl_bind_keyseq_in_map ("\033", (rl_command_func_t *)NULL, vi_movement_keymap);
-  bind_arrow_keys_internal (vi_insertion_keymap);
-#endif
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*             Saving and Restoring Readline's state               */
-/*                                                                 */
-/* **************************************************************** */
-
-int
-rl_save_state (sp)
-     struct readline_state *sp;
-{
-  if (sp == 0)
-    return -1;
-
-  sp->point = rl_point;
-  sp->end = rl_end;
-  sp->mark = rl_mark;
-  sp->buffer = rl_line_buffer;
-  sp->buflen = rl_line_buffer_len;
-  sp->ul = rl_undo_list;
-  sp->prompt = rl_prompt;
-
-  sp->rlstate = rl_readline_state;
-  sp->done = rl_done;
-  sp->kmap = _rl_keymap;
-
-  sp->lastfunc = rl_last_func;
-  sp->insmode = rl_insert_mode;
-  sp->edmode = rl_editing_mode;
-  sp->kseqlen = rl_key_sequence_length;
-  sp->inf = rl_instream;
-  sp->outf = rl_outstream;
-  sp->pendingin = rl_pending_input;
-  sp->macro = rl_executing_macro;
-
-  sp->catchsigs = rl_catch_signals;
-  sp->catchsigwinch = rl_catch_sigwinch;
-
-  return (0);
-}
-
-int
-rl_restore_state (sp)
-     struct readline_state *sp;
-{
-  if (sp == 0)
-    return -1;
-
-  rl_point = sp->point;
-  rl_end = sp->end;
-  rl_mark = sp->mark;
-  the_line = rl_line_buffer = sp->buffer;
-  rl_line_buffer_len = sp->buflen;
-  rl_undo_list = sp->ul;
-  rl_prompt = sp->prompt;
-
-  rl_readline_state = sp->rlstate;
-  rl_done = sp->done;
-  _rl_keymap = sp->kmap;
-
-  rl_last_func = sp->lastfunc;
-  rl_insert_mode = sp->insmode;
-  rl_editing_mode = sp->edmode;
-  rl_key_sequence_length = sp->kseqlen;
-  rl_instream = sp->inf;
-  rl_outstream = sp->outf;
-  rl_pending_input = sp->pendingin;
-  rl_executing_macro = sp->macro;
-
-  rl_catch_signals = sp->catchsigs;
-  rl_catch_sigwinch = sp->catchsigwinch;
-
-  return (0);
-}
diff --git a/lib/readline/readline.h~ b/lib/readline/readline.h~
deleted file mode 100644 (file)
index 9b2eec6..0000000
+++ /dev/null
@@ -1,914 +0,0 @@
-/* Readline.h -- the names of functions callable from within readline. */
-
-/* Copyright (C) 1987-2013 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/>.
-*/
-
-#if !defined (_READLINE_H_)
-#define _READLINE_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined (READLINE_LIBRARY)
-#  include "rlstdc.h"
-#  include "rltypedefs.h"
-#  include "keymaps.h"
-#  include "tilde.h"
-#else
-#  include <readline/rlstdc.h>
-#  include <readline/rltypedefs.h>
-#  include <readline/keymaps.h>
-#  include <readline/tilde.h>
-#endif
-
-/* Hex-encoded Readline version number. */
-#define RL_READLINE_VERSION    0x0602          /* Readline 6.2 */
-#define RL_VERSION_MAJOR       6
-#define RL_VERSION_MINOR       2
-
-/* Readline data structures. */
-
-/* Maintaining the state of undo.  We remember individual deletes and inserts
-   on a chain of things to do. */
-
-/* The actions that undo knows how to undo.  Notice that UNDO_DELETE means
-   to insert some text, and UNDO_INSERT means to delete some text.   I.e.,
-   the code tells undo what to undo, not how to undo it. */
-enum undo_code { UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END };
-
-/* What an element of THE_UNDO_LIST looks like. */
-typedef struct undo_list {
-  struct undo_list *next;
-  int start, end;              /* Where the change took place. */
-  char *text;                  /* The text to insert, if undoing a delete. */
-  enum undo_code what;         /* Delete, Insert, Begin, End. */
-} UNDO_LIST;
-
-/* The current undo list for RL_LINE_BUFFER. */
-extern UNDO_LIST *rl_undo_list;
-
-/* The data structure for mapping textual names to code addresses. */
-typedef struct _funmap {
-  const char *name;
-  rl_command_func_t *function;
-} FUNMAP;
-
-extern FUNMAP **funmap;
-
-/* **************************************************************** */
-/*                                                                 */
-/*          Functions available to bind to key sequences           */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Bindable commands for numeric arguments. */
-extern int rl_digit_argument PARAMS((int, int));
-extern int rl_universal_argument PARAMS((int, int));
-
-/* Bindable commands for moving the cursor. */
-extern int rl_forward_byte PARAMS((int, int));
-extern int rl_forward_char PARAMS((int, int));
-extern int rl_forward PARAMS((int, int));
-extern int rl_backward_byte PARAMS((int, int));
-extern int rl_backward_char PARAMS((int, int));
-extern int rl_backward PARAMS((int, int));
-extern int rl_beg_of_line PARAMS((int, int));
-extern int rl_end_of_line PARAMS((int, int));
-extern int rl_forward_word PARAMS((int, int));
-extern int rl_backward_word PARAMS((int, int));
-extern int rl_refresh_line PARAMS((int, int));
-extern int rl_clear_screen PARAMS((int, int));
-extern int rl_skip_csi_sequence PARAMS((int, int));
-extern int rl_arrow_keys PARAMS((int, int));
-
-/* Bindable commands for inserting and deleting text. */
-extern int rl_insert PARAMS((int, int));
-extern int rl_quoted_insert PARAMS((int, int));
-extern int rl_tab_insert PARAMS((int, int));
-extern int rl_newline PARAMS((int, int));
-extern int rl_do_lowercase_version PARAMS((int, int));
-extern int rl_rubout PARAMS((int, int));
-extern int rl_delete PARAMS((int, int));
-extern int rl_rubout_or_delete PARAMS((int, int));
-extern int rl_delete_horizontal_space PARAMS((int, int));
-extern int rl_delete_or_show_completions PARAMS((int, int));
-extern int rl_insert_comment PARAMS((int, int));
-
-/* Bindable commands for changing case. */
-extern int rl_upcase_word PARAMS((int, int));
-extern int rl_downcase_word PARAMS((int, int));
-extern int rl_capitalize_word PARAMS((int, int));
-
-/* Bindable commands for transposing characters and words. */
-extern int rl_transpose_words PARAMS((int, int));
-extern int rl_transpose_chars PARAMS((int, int));
-
-/* Bindable commands for searching within a line. */
-extern int rl_char_search PARAMS((int, int));
-extern int rl_backward_char_search PARAMS((int, int));
-
-/* Bindable commands for readline's interface to the command history. */
-extern int rl_beginning_of_history PARAMS((int, int));
-extern int rl_end_of_history PARAMS((int, int));
-extern int rl_get_next_history PARAMS((int, int));
-extern int rl_get_previous_history PARAMS((int, int));
-
-/* Bindable commands for managing the mark and region. */
-extern int rl_set_mark PARAMS((int, int));
-extern int rl_exchange_point_and_mark PARAMS((int, int));
-
-/* Bindable commands to set the editing mode (emacs or vi). */
-extern int rl_vi_editing_mode PARAMS((int, int));
-extern int rl_emacs_editing_mode PARAMS((int, int));
-
-/* Bindable commands to change the insert mode (insert or overwrite) */
-extern int rl_overwrite_mode PARAMS((int, int));
-
-/* Bindable commands for managing key bindings. */
-extern int rl_re_read_init_file PARAMS((int, int));
-extern int rl_dump_functions PARAMS((int, int));
-extern int rl_dump_macros PARAMS((int, int));
-extern int rl_dump_variables PARAMS((int, int));
-
-/* Bindable commands for word completion. */
-extern int rl_complete PARAMS((int, int));
-extern int rl_possible_completions PARAMS((int, int));
-extern int rl_insert_completions PARAMS((int, int));
-extern int rl_old_menu_complete PARAMS((int, int));
-extern int rl_menu_complete PARAMS((int, int));
-extern int rl_backward_menu_complete PARAMS((int, int));
-
-/* Bindable commands for killing and yanking text, and managing the kill ring. */
-extern int rl_kill_word PARAMS((int, int));
-extern int rl_backward_kill_word PARAMS((int, int));
-extern int rl_kill_line PARAMS((int, int));
-extern int rl_backward_kill_line PARAMS((int, int));
-extern int rl_kill_full_line PARAMS((int, int));
-extern int rl_unix_word_rubout PARAMS((int, int));
-extern int rl_unix_filename_rubout PARAMS((int, int));
-extern int rl_unix_line_discard PARAMS((int, int));
-extern int rl_copy_region_to_kill PARAMS((int, int));
-extern int rl_kill_region PARAMS((int, int));
-extern int rl_copy_forward_word PARAMS((int, int));
-extern int rl_copy_backward_word PARAMS((int, int));
-extern int rl_yank PARAMS((int, int));
-extern int rl_yank_pop PARAMS((int, int));
-extern int rl_yank_nth_arg PARAMS((int, int));
-extern int rl_yank_last_arg PARAMS((int, int));
-/* Not available unless __CYGWIN__ is defined. */
-#ifdef __CYGWIN__
-extern int rl_paste_from_clipboard PARAMS((int, int));
-#endif
-
-/* Bindable commands for incremental searching. */
-extern int rl_reverse_search_history PARAMS((int, int));
-extern int rl_forward_search_history PARAMS((int, int));
-
-/* Bindable keyboard macro commands. */
-extern int rl_start_kbd_macro PARAMS((int, int));
-extern int rl_end_kbd_macro PARAMS((int, int));
-extern int rl_call_last_kbd_macro PARAMS((int, int));
-extern int rl_print_last_kbd_macro PARAMS((int, int));
-
-/* Bindable undo commands. */
-extern int rl_revert_line PARAMS((int, int));
-extern int rl_undo_command PARAMS((int, int));
-
-/* Bindable tilde expansion commands. */
-extern int rl_tilde_expand PARAMS((int, int));
-
-/* Bindable terminal control commands. */
-extern int rl_restart_output PARAMS((int, int));
-extern int rl_stop_output PARAMS((int, int));
-
-/* Miscellaneous bindable commands. */
-extern int rl_abort PARAMS((int, int));
-extern int rl_tty_status PARAMS((int, int));
-
-/* Bindable commands for incremental and non-incremental history searching. */
-extern int rl_history_search_forward PARAMS((int, int));
-extern int rl_history_search_backward PARAMS((int, int));
-extern int rl_history_substr_search_forward PARAMS((int, int));
-extern int rl_history_substr_search_backward PARAMS((int, int));
-extern int rl_noninc_forward_search PARAMS((int, int));
-extern int rl_noninc_reverse_search PARAMS((int, int));
-extern int rl_noninc_forward_search_again PARAMS((int, int));
-extern int rl_noninc_reverse_search_again PARAMS((int, int));
-
-/* Bindable command used when inserting a matching close character. */
-extern int rl_insert_close PARAMS((int, int));
-
-/* Not available unless READLINE_CALLBACKS is defined. */
-extern void rl_callback_handler_install PARAMS((const char *, rl_vcpfunc_t *));
-extern void rl_callback_read_char PARAMS((void));
-extern void rl_callback_handler_remove PARAMS((void));
-
-/* Things for vi mode. Not available unless readline is compiled -DVI_MODE. */
-/* VI-mode bindable commands. */
-extern int rl_vi_redo PARAMS((int, int));
-extern int rl_vi_undo PARAMS((int, int));
-extern int rl_vi_yank_arg PARAMS((int, int));
-extern int rl_vi_fetch_history PARAMS((int, int));
-extern int rl_vi_search_again PARAMS((int, int));
-extern int rl_vi_search PARAMS((int, int));
-extern int rl_vi_complete PARAMS((int, int));
-extern int rl_vi_tilde_expand PARAMS((int, int));
-extern int rl_vi_prev_word PARAMS((int, int));
-extern int rl_vi_next_word PARAMS((int, int));
-extern int rl_vi_end_word PARAMS((int, int));
-extern int rl_vi_insert_beg PARAMS((int, int));
-extern int rl_vi_append_mode PARAMS((int, int));
-extern int rl_vi_append_eol PARAMS((int, int));
-extern int rl_vi_eof_maybe PARAMS((int, int));
-extern int rl_vi_insertion_mode PARAMS((int, int));
-extern int rl_vi_insert_mode PARAMS((int, int));
-extern int rl_vi_movement_mode PARAMS((int, int));
-extern int rl_vi_arg_digit PARAMS((int, int));
-extern int rl_vi_change_case PARAMS((int, int));
-extern int rl_vi_put PARAMS((int, int));
-extern int rl_vi_column PARAMS((int, int));
-extern int rl_vi_delete_to PARAMS((int, int));
-extern int rl_vi_change_to PARAMS((int, int));
-extern int rl_vi_yank_to PARAMS((int, int));
-extern int rl_vi_rubout PARAMS((int, int));
-extern int rl_vi_delete PARAMS((int, int));
-extern int rl_vi_back_to_indent PARAMS((int, int));
-extern int rl_vi_first_print PARAMS((int, int));
-extern int rl_vi_char_search PARAMS((int, int));
-extern int rl_vi_match PARAMS((int, int));
-extern int rl_vi_change_char PARAMS((int, int));
-extern int rl_vi_subst PARAMS((int, int));
-extern int rl_vi_overstrike PARAMS((int, int));
-extern int rl_vi_overstrike_delete PARAMS((int, int));
-extern int rl_vi_replace PARAMS((int, int));
-extern int rl_vi_set_mark PARAMS((int, int));
-extern int rl_vi_goto_mark PARAMS((int, int));
-
-/* VI-mode utility functions. */
-extern int rl_vi_check PARAMS((void));
-extern int rl_vi_domove PARAMS((int, int *));
-extern int rl_vi_bracktype PARAMS((int));
-
-extern void rl_vi_start_inserting PARAMS((int, int, int));
-
-/* VI-mode pseudo-bindable commands, used as utility functions. */
-extern int rl_vi_fWord PARAMS((int, int));
-extern int rl_vi_bWord PARAMS((int, int));
-extern int rl_vi_eWord PARAMS((int, int));
-extern int rl_vi_fword PARAMS((int, int));
-extern int rl_vi_bword PARAMS((int, int));
-extern int rl_vi_eword PARAMS((int, int));
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Well Published Functions                    */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Readline functions. */
-/* Read a line of input.  Prompt with PROMPT.  A NULL PROMPT means none. */
-extern char *readline PARAMS((const char *));
-
-extern int rl_set_prompt PARAMS((const char *));
-extern int rl_expand_prompt PARAMS((char *));
-
-extern int rl_initialize PARAMS((void));
-
-/* Undocumented; unused by readline */
-extern int rl_discard_argument PARAMS((void));
-
-/* Utility functions to bind keys to readline commands. */
-extern int rl_add_defun PARAMS((const char *, rl_command_func_t *, int));
-extern int rl_bind_key PARAMS((int, rl_command_func_t *));
-extern int rl_bind_key_in_map PARAMS((int, rl_command_func_t *, Keymap));
-extern int rl_unbind_key PARAMS((int));
-extern int rl_unbind_key_in_map PARAMS((int, Keymap));
-extern int rl_bind_key_if_unbound PARAMS((int, rl_command_func_t *));
-extern int rl_bind_key_if_unbound_in_map PARAMS((int, rl_command_func_t *, Keymap));
-extern int rl_unbind_function_in_map PARAMS((rl_command_func_t *, Keymap));
-extern int rl_unbind_command_in_map PARAMS((const char *, Keymap));
-extern int rl_bind_keyseq PARAMS((const char *, rl_command_func_t *));
-extern int rl_bind_keyseq_in_map PARAMS((const char *, rl_command_func_t *, Keymap));
-extern int rl_bind_keyseq_if_unbound PARAMS((const char *, rl_command_func_t *));
-extern int rl_bind_keyseq_if_unbound_in_map PARAMS((const char *, rl_command_func_t *, Keymap));
-extern int rl_generic_bind PARAMS((int, const char *, char *, Keymap));
-
-extern char *rl_variable_value PARAMS((const char *));
-extern int rl_variable_bind PARAMS((const char *, const char *));
-
-/* Backwards compatibility, use rl_bind_keyseq_in_map instead. */
-extern int rl_set_key PARAMS((const char *, rl_command_func_t *, Keymap));
-
-/* Backwards compatibility, use rl_generic_bind instead. */
-extern int rl_macro_bind PARAMS((const char *, const char *, Keymap));
-
-/* Undocumented in the texinfo manual; not really useful to programs. */
-extern int rl_translate_keyseq PARAMS((const char *, char *, int *));
-extern char *rl_untranslate_keyseq PARAMS((int));
-
-extern rl_command_func_t *rl_named_function PARAMS((const char *));
-extern rl_command_func_t *rl_function_of_keyseq PARAMS((const char *, Keymap, int *));
-
-extern void rl_list_funmap_names PARAMS((void));
-extern char **rl_invoking_keyseqs_in_map PARAMS((rl_command_func_t *, Keymap));
-extern char **rl_invoking_keyseqs PARAMS((rl_command_func_t *));
-extern void rl_function_dumper PARAMS((int));
-extern void rl_macro_dumper PARAMS((int));
-extern void rl_variable_dumper PARAMS((int));
-
-extern int rl_read_init_file PARAMS((const char *));
-extern int rl_parse_and_bind PARAMS((char *));
-
-/* Functions for manipulating keymaps. */
-extern Keymap rl_make_bare_keymap PARAMS((void));
-extern Keymap rl_copy_keymap PARAMS((Keymap));
-extern Keymap rl_make_keymap PARAMS((void));
-extern void rl_discard_keymap PARAMS((Keymap));
-
-extern Keymap rl_get_keymap_by_name PARAMS((const char *));
-extern char *rl_get_keymap_name PARAMS((Keymap));
-extern void rl_set_keymap PARAMS((Keymap));
-extern Keymap rl_get_keymap PARAMS((void));
-/* Undocumented; used internally only. */
-extern void rl_set_keymap_from_edit_mode PARAMS((void));
-extern char *rl_get_keymap_name_from_edit_mode PARAMS((void));
-
-/* Functions for manipulating the funmap, which maps command names to functions. */
-extern int rl_add_funmap_entry PARAMS((const char *, rl_command_func_t *));
-extern const char **rl_funmap_names PARAMS((void));
-/* Undocumented, only used internally -- there is only one funmap, and this
-   function may be called only once. */
-extern void rl_initialize_funmap PARAMS((void));
-
-/* Utility functions for managing keyboard macros. */
-extern void rl_push_macro_input PARAMS((char *));
-
-/* Functions for undoing, from undo.c */
-extern void rl_add_undo PARAMS((enum undo_code, int, int, char *));
-extern void rl_free_undo_list PARAMS((void));
-extern int rl_do_undo PARAMS((void));
-extern int rl_begin_undo_group PARAMS((void));
-extern int rl_end_undo_group PARAMS((void));
-extern int rl_modifying PARAMS((int, int));
-
-/* Functions for redisplay. */
-extern void rl_redisplay PARAMS((void));
-extern int rl_on_new_line PARAMS((void));
-extern int rl_on_new_line_with_prompt PARAMS((void));
-extern int rl_forced_update_display PARAMS((void));
-extern int rl_clear_message PARAMS((void));
-extern int rl_reset_line_state PARAMS((void));
-extern int rl_crlf PARAMS((void));
-
-#if defined (USE_VARARGS) && defined (PREFER_STDARG)
-extern int rl_message (const char *, ...)  __attribute__((__format__ (printf, 1, 2)));
-#else
-extern int rl_message ();
-#endif
-
-extern int rl_show_char PARAMS((int));
-
-/* Undocumented in texinfo manual. */
-extern int rl_character_len PARAMS((int, int));
-
-/* Save and restore internal prompt redisplay information. */
-extern void rl_save_prompt PARAMS((void));
-extern void rl_restore_prompt PARAMS((void));
-
-/* Modifying text. */
-extern void rl_replace_line PARAMS((const char *, int));
-extern int rl_insert_text PARAMS((const char *));
-extern int rl_delete_text PARAMS((int, int));
-extern int rl_kill_text PARAMS((int, int));
-extern char *rl_copy_text PARAMS((int, int));
-
-/* Terminal and tty mode management. */
-extern void rl_prep_terminal PARAMS((int));
-extern void rl_deprep_terminal PARAMS((void));
-extern void rl_tty_set_default_bindings PARAMS((Keymap));
-extern void rl_tty_unset_default_bindings PARAMS((Keymap));
-
-extern int rl_reset_terminal PARAMS((const char *));
-extern void rl_resize_terminal PARAMS((void));
-extern void rl_set_screen_size PARAMS((int, int));
-extern void rl_get_screen_size PARAMS((int *, int *));
-extern void rl_reset_screen_size PARAMS((void));
-
-extern char *rl_get_termcap PARAMS((const char *));
-
-/* Functions for character input. */
-extern int rl_stuff_char PARAMS((int));
-extern int rl_execute_next PARAMS((int));
-extern int rl_clear_pending_input PARAMS((void));
-extern int rl_read_key PARAMS((void));
-extern int rl_getc PARAMS((FILE *));
-extern int rl_set_keyboard_input_timeout PARAMS((int));
-
-/* `Public' utility functions . */
-extern void rl_extend_line_buffer PARAMS((int));
-extern int rl_ding PARAMS((void));
-extern int rl_alphabetic PARAMS((int));
-extern void rl_free PARAMS((void *));
-
-/* Readline signal handling, from signals.c */
-extern int rl_set_signals PARAMS((void));
-extern int rl_clear_signals PARAMS((void));
-extern void rl_cleanup_after_signal PARAMS((void));
-extern void rl_reset_after_signal PARAMS((void));
-extern void rl_free_line_state PARAMS((void));
-
-extern void rl_echo_signal_char PARAMS((int)); 
-
-extern int rl_set_paren_blink_timeout PARAMS((int));
-
-/* Undocumented. */
-extern int rl_maybe_save_line PARAMS((void));
-extern int rl_maybe_unsave_line PARAMS((void));
-extern int rl_maybe_replace_line PARAMS((void));
-
-/* Completion functions. */
-extern int rl_complete_internal PARAMS((int));
-extern void rl_display_match_list PARAMS((char **, int, int));
-
-extern char **rl_completion_matches PARAMS((const char *, rl_compentry_func_t *));
-extern char *rl_username_completion_function PARAMS((const char *, int));
-extern char *rl_filename_completion_function PARAMS((const char *, int));
-
-extern int rl_completion_mode PARAMS((rl_command_func_t *));
-
-#if 0
-/* Backwards compatibility (compat.c).  These will go away sometime. */
-extern void free_undo_list PARAMS((void));
-extern int maybe_save_line PARAMS((void));
-extern int maybe_unsave_line PARAMS((void));
-extern int maybe_replace_line PARAMS((void));
-
-extern int ding PARAMS((void));
-extern int alphabetic PARAMS((int));
-extern int crlf PARAMS((void));
-
-extern char **completion_matches PARAMS((char *, rl_compentry_func_t *));
-extern char *username_completion_function PARAMS((const char *, int));
-extern char *filename_completion_function PARAMS((const char *, int));
-#endif
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Well Published Variables                    */
-/*                                                                 */
-/* **************************************************************** */
-
-/* The version of this incarnation of the readline library. */
-extern const char *rl_library_version;         /* e.g., "4.2" */
-extern int rl_readline_version;                        /* e.g., 0x0402 */
-
-/* True if this is real GNU readline. */
-extern int rl_gnu_readline_p;
-
-/* Flags word encapsulating the current readline state. */
-extern int rl_readline_state;
-
-/* Says which editing mode readline is currently using.  1 means emacs mode;
-   0 means vi mode. */
-extern int rl_editing_mode;
-
-/* Insert or overwrite mode for emacs mode.  1 means insert mode; 0 means
-   overwrite mode.  Reset to insert mode on each input line. */
-extern int rl_insert_mode;
-
-/* The name of the calling program.  You should initialize this to
-   whatever was in argv[0].  It is used when parsing conditionals. */
-extern const char *rl_readline_name;
-
-/* The prompt readline uses.  This is set from the argument to
-   readline (), and should not be assigned to directly. */
-extern char *rl_prompt;
-
-/* The prompt string that is actually displayed by rl_redisplay.  Public so
-   applications can more easily supply their own redisplay functions. */
-extern char *rl_display_prompt;
-
-/* The line buffer that is in use. */
-extern char *rl_line_buffer;
-
-/* The location of point, and end. */
-extern int rl_point;
-extern int rl_end;
-
-/* The mark, or saved cursor position. */
-extern int rl_mark;
-
-/* Flag to indicate that readline has finished with the current input
-   line and should return it. */
-extern int rl_done;
-
-/* If set to a character value, that will be the next keystroke read. */
-extern int rl_pending_input;
-
-/* Non-zero if we called this function from _rl_dispatch().  It's present
-   so functions can find out whether they were called from a key binding
-   or directly from an application. */
-extern int rl_dispatching;
-
-/* Non-zero if the user typed a numeric argument before executing the
-   current function. */
-extern int rl_explicit_arg;
-
-/* The current value of the numeric argument specified by the user. */
-extern int rl_numeric_arg;
-
-/* The address of the last command function Readline executed. */
-extern rl_command_func_t *rl_last_func;
-
-/* The name of the terminal to use. */
-extern const char *rl_terminal_name;
-
-/* The input and output streams. */
-extern FILE *rl_instream;
-extern FILE *rl_outstream;
-
-/* If non-zero, Readline gives values of LINES and COLUMNS from the environment
-   greater precedence than values fetched from the kernel when computing the
-   screen dimensions. */
-extern int rl_prefer_env_winsize;
-
-/* If non-zero, then this is the address of a function to call just
-   before readline_internal () prints the first prompt. */
-extern rl_hook_func_t *rl_startup_hook;
-
-/* If non-zero, this is the address of a function to call just before
-   readline_internal_setup () returns and readline_internal starts
-   reading input characters. */
-extern rl_hook_func_t *rl_pre_input_hook;
-      
-/* The address of a function to call periodically while Readline is
-   awaiting character input, or NULL, for no event handling. */
-extern rl_hook_func_t *rl_event_hook;
-
-/* The address of a function to call if a read is interrupted by a signal. */
-extern rl_hook_func_t *rl_signal_event_hook;
-
-/* The address of a function to call if Readline needs to know whether or not
-   there is data available from the current input source. */
-extern rl_hook_func_t *rl_input_available_hook;
-
-/* The address of the function to call to fetch a character from the current
-   Readline input stream */
-extern rl_getc_func_t *rl_getc_function;
-
-extern rl_voidfunc_t *rl_redisplay_function;
-
-extern rl_vintfunc_t *rl_prep_term_function;
-extern rl_voidfunc_t *rl_deprep_term_function;
-
-/* Dispatch variables. */
-extern Keymap rl_executing_keymap;
-extern Keymap rl_binding_keymap;
-
-extern int rl_executing_key;
-extern char *rl_executing_keyseq;
-extern int rl_key_sequence_length;
-
-/* Display variables. */
-/* If non-zero, readline will erase the entire line, including any prompt,
-   if the only thing typed on an otherwise-blank line is something bound to
-   rl_newline. */
-extern int rl_erase_empty_line;
-
-/* If non-zero, the application has already printed the prompt (rl_prompt)
-   before calling readline, so readline should not output it the first time
-   redisplay is done. */
-extern int rl_already_prompted;
-
-/* A non-zero value means to read only this many characters rather than
-   up to a character bound to accept-line. */
-extern int rl_num_chars_to_read;
-
-/* The text of a currently-executing keyboard macro. */
-extern char *rl_executing_macro;
-
-/* Variables to control readline signal handling. */
-/* If non-zero, readline will install its own signal handlers for
-   SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
-extern int rl_catch_signals;
-
-/* If non-zero, readline will install a signal handler for SIGWINCH
-   that also attempts to call any calling application's SIGWINCH signal
-   handler.  Note that the terminal is not cleaned up before the
-   application's signal handler is called; use rl_cleanup_after_signal()
-   to do that. */
-extern int rl_catch_sigwinch;
-
-/* Completion variables. */
-/* Pointer to the generator function for completion_matches ().
-   NULL means to use rl_filename_completion_function (), the default
-   filename completer. */
-extern rl_compentry_func_t *rl_completion_entry_function;
-
-/* Optional generator for menu completion.  Default is
-   rl_completion_entry_function (rl_filename_completion_function). */
- extern rl_compentry_func_t *rl_menu_completion_entry_function;
-
-/* If rl_ignore_some_completions_function is non-NULL it is the address
-   of a function to call after all of the possible matches have been
-   generated, but before the actual completion is done to the input line.
-   The function is called with one argument; a NULL terminated array
-   of (char *).  If your function removes any of the elements, they
-   must be free()'ed. */
-extern rl_compignore_func_t *rl_ignore_some_completions_function;
-
-/* Pointer to alternative function to create matches.
-   Function is called with TEXT, START, and END.
-   START and END are indices in RL_LINE_BUFFER saying what the boundaries
-   of TEXT are.
-   If this function exists and returns NULL then call the value of
-   rl_completion_entry_function to try to match, otherwise use the
-   array of strings returned. */
-extern rl_completion_func_t *rl_attempted_completion_function;
-
-/* The basic list of characters that signal a break between words for the
-   completer routine.  The initial contents of this variable is what
-   breaks words in the shell, i.e. "n\"\\'`@$>". */
-extern const char *rl_basic_word_break_characters;
-
-/* The list of characters that signal a break between words for
-   rl_complete_internal.  The default list is the contents of
-   rl_basic_word_break_characters.  */
-extern /*const*/ char *rl_completer_word_break_characters;
-
-/* Hook function to allow an application to set the completion word
-   break characters before readline breaks up the line.  Allows
-   position-dependent word break characters. */
-extern rl_cpvfunc_t *rl_completion_word_break_hook;
-
-/* List of characters which can be used to quote a substring of the line.
-   Completion occurs on the entire substring, and within the substring   
-   rl_completer_word_break_characters are treated as any other character,
-   unless they also appear within this list. */
-extern const char *rl_completer_quote_characters;
-
-/* List of quote characters which cause a word break. */
-extern const char *rl_basic_quote_characters;
-
-/* List of characters that need to be quoted in filenames by the completer. */
-extern const char *rl_filename_quote_characters;
-
-/* List of characters that are word break characters, but should be left
-   in TEXT when it is passed to the completion function.  The shell uses
-   this to help determine what kind of completing to do. */
-extern const char *rl_special_prefixes;
-
-/* If non-zero, then this is the address of a function to call when
-   completing on a directory name.  The function is called with
-   the address of a string (the current directory name) as an arg.  It
-   changes what is displayed when the possible completions are printed
-   or inserted.  The directory completion hook should perform
-   any necessary dequoting.  This function should return 1 if it modifies
-   the directory name pointer passed as an argument.  If the directory
-   completion hook returns 0, it should not modify the directory name
-   pointer passed as an argument. */
-extern rl_icppfunc_t *rl_directory_completion_hook;
-
-/* If non-zero, this is the address of a function to call when completing
-   a directory name.  This function takes the address of the directory name
-   to be modified as an argument.  Unlike rl_directory_completion_hook, it
-   only modifies the directory name used in opendir(2), not what is displayed
-   when the possible completions are printed or inserted.  If set, it takes
-   precedence over rl_directory_completion_hook.  The directory rewrite
-   hook should perform any necessary dequoting.  This function has the same
-   return value properties as the directory_completion_hook.
-
-   I'm not happy with how this works yet, so it's undocumented.  I'm trying
-   it in bash to see how well it goes. */
-extern rl_icppfunc_t *rl_directory_rewrite_hook;
-
-/* If non-zero, this is the address of a function for the completer to call
-   before deciding which character to append to a completed name.  It should
-   modify the directory name passed as an argument if appropriate, and return
-   non-zero if it modifies the name.  This should not worry about dequoting
-   the filename; that has already happened by the time it gets here. */
-extern rl_icppfunc_t *rl_filename_stat_hook;
-
-/* If non-zero, this is the address of a function to call when reading
-   directory entries from the filesystem for completion and comparing
-   them to the partial word to be completed.  The function should
-   either return its first argument (if no conversion takes place) or
-   newly-allocated memory.  This can, for instance, convert filenames
-   between character sets for comparison against what's typed at the
-   keyboard.  The returned value is what is added to the list of
-   matches.  The second argument is the length of the filename to be
-   converted. */
-extern rl_dequote_func_t *rl_filename_rewrite_hook;
-
-/* Backwards compatibility with previous versions of readline. */
-#define rl_symbolic_link_hook rl_directory_completion_hook
-
-/* If non-zero, then this is the address of a function to call when
-   completing a word would normally display the list of possible matches.
-   This function is called instead of actually doing the display.
-   It takes three arguments: (char **matches, int num_matches, int max_length)
-   where MATCHES is the array of strings that matched, NUM_MATCHES is the
-   number of strings in that array, and MAX_LENGTH is the length of the
-   longest string in that array. */
-extern rl_compdisp_func_t *rl_completion_display_matches_hook;
-
-/* Non-zero means that the results of the matches are to be treated
-   as filenames.  This is ALWAYS zero on entry, and can only be changed
-   within a completion entry finder function. */
-extern int rl_filename_completion_desired;
-
-/* Non-zero means that the results of the matches are to be quoted using
-   double quotes (or an application-specific quoting mechanism) if the
-   filename contains any characters in rl_word_break_chars.  This is
-   ALWAYS non-zero on entry, and can only be changed within a completion
-   entry finder function. */
-extern int rl_filename_quoting_desired;
-
-/* Set to a function to quote a filename in an application-specific fashion.
-   Called with the text to quote, the type of match found (single or multiple)
-   and a pointer to the quoting character to be used, which the function can
-   reset if desired. */
-extern rl_quote_func_t *rl_filename_quoting_function;
-
-/* Function to call to remove quoting characters from a filename.  Called
-   before completion is attempted, so the embedded quotes do not interfere
-   with matching names in the file system. */
-extern rl_dequote_func_t *rl_filename_dequoting_function;
-
-/* Function to call to decide whether or not a word break character is
-   quoted.  If a character is quoted, it does not break words for the
-   completer. */
-extern rl_linebuf_func_t *rl_char_is_quoted_p;
-
-/* Non-zero means to suppress normal filename completion after the
-   user-specified completion function has been called. */
-extern int rl_attempted_completion_over;
-
-/* Set to a character describing the type of completion being attempted by
-   rl_complete_internal; available for use by application completion
-   functions. */
-extern int rl_completion_type;
-
-/* Set to the last key used to invoke one of the completion functions */
-extern int rl_completion_invoking_key;
-
-/* Up to this many items will be displayed in response to a
-   possible-completions call.  After that, we ask the user if she
-   is sure she wants to see them all.  The default value is 100. */
-extern int rl_completion_query_items;
-
-/* Character appended to completed words when at the end of the line.  The
-   default is a space.  Nothing is added if this is '\0'. */
-extern int rl_completion_append_character;
-
-/* If set to non-zero by an application completion function,
-   rl_completion_append_character will not be appended. */
-extern int rl_completion_suppress_append;
-
-/* Set to any quote character readline thinks it finds before any application
-   completion function is called. */
-extern int rl_completion_quote_character;
-
-/* Set to a non-zero value if readline found quoting anywhere in the word to
-   be completed; set before any application completion function is called. */
-extern int rl_completion_found_quote;
-
-/* If non-zero, the completion functions don't append any closing quote.
-   This is set to 0 by rl_complete_internal and may be changed by an
-   application-specific completion function. */
-extern int rl_completion_suppress_quote;
-
-/* If non-zero, readline will sort the completion matches.  On by default. */
-extern int rl_sort_completion_matches;
-
-/* If non-zero, a slash will be appended to completed filenames that are
-   symbolic links to directory names, subject to the value of the
-   mark-directories variable (which is user-settable).  This exists so
-   that application completion functions can override the user's preference
-   (set via the mark-symlinked-directories variable) if appropriate.
-   It's set to the value of _rl_complete_mark_symlink_dirs in
-   rl_complete_internal before any application-specific completion
-   function is called, so without that function doing anything, the user's
-   preferences are honored. */
-extern int rl_completion_mark_symlink_dirs;
-
-/* If non-zero, then disallow duplicates in the matches. */
-extern int rl_ignore_completion_duplicates;
-
-/* If this is non-zero, completion is (temporarily) inhibited, and the
-   completion character will be inserted as any other. */
-extern int rl_inhibit_completion;
-
-/* Input error; can be returned by (*rl_getc_function) if readline is reading
-   a top-level command (RL_ISSTATE (RL_STATE_READCMD)). */
-#define READERR                        (-2)
-
-/* Definitions available for use by readline clients. */
-#define RL_PROMPT_START_IGNORE '\001'
-#define RL_PROMPT_END_IGNORE   '\002'
-
-/* Possible values for do_replace argument to rl_filename_quoting_function,
-   called by rl_complete_internal. */
-#define NO_MATCH        0
-#define SINGLE_MATCH    1
-#define MULT_MATCH      2
-
-/* Possible state values for rl_readline_state */
-#define RL_STATE_NONE          0x000000                /* no state; before first call */
-
-#define RL_STATE_INITIALIZING  0x0000001       /* initializing */
-#define RL_STATE_INITIALIZED   0x0000002       /* initialization done */
-#define RL_STATE_TERMPREPPED   0x0000004       /* terminal is prepped */
-#define RL_STATE_READCMD       0x0000008       /* reading a command key */
-#define RL_STATE_METANEXT      0x0000010       /* reading input after ESC */
-#define RL_STATE_DISPATCHING   0x0000020       /* dispatching to a command */
-#define RL_STATE_MOREINPUT     0x0000040       /* reading more input in a command function */
-#define RL_STATE_ISEARCH       0x0000080       /* doing incremental search */
-#define RL_STATE_NSEARCH       0x0000100       /* doing non-inc search */
-#define RL_STATE_SEARCH                0x0000200       /* doing a history search */
-#define RL_STATE_NUMERICARG    0x0000400       /* reading numeric argument */
-#define RL_STATE_MACROINPUT    0x0000800       /* getting input from a macro */
-#define RL_STATE_MACRODEF      0x0001000       /* defining keyboard macro */
-#define RL_STATE_OVERWRITE     0x0002000       /* overwrite mode */
-#define RL_STATE_COMPLETING    0x0004000       /* doing completion */
-#define RL_STATE_SIGHANDLER    0x0008000       /* in readline sighandler */
-#define RL_STATE_UNDOING       0x0010000       /* doing an undo */
-#define RL_STATE_INPUTPENDING  0x0020000       /* rl_execute_next called */
-#define RL_STATE_TTYCSAVED     0x0040000       /* tty special chars saved */
-#define RL_STATE_CALLBACK      0x0080000       /* using the callback interface */
-#define RL_STATE_VIMOTION      0x0100000       /* reading vi motion arg */
-#define RL_STATE_MULTIKEY      0x0200000       /* reading multiple-key command */
-#define RL_STATE_VICMDONCE     0x0400000       /* entered vi command mode at least once */
-#define RL_STATE_REDISPLAYING  0x0800000       /* updating terminal display */
-
-#define RL_STATE_DONE          0x1000000       /* done; accepted line */
-
-#define RL_SETSTATE(x)         (rl_readline_state |= (x))
-#define RL_UNSETSTATE(x)       (rl_readline_state &= ~(x))
-#define RL_ISSTATE(x)          (rl_readline_state & (x))
-
-struct readline_state {
-  /* line state */
-  int point;
-  int end;
-  int mark;
-  char *buffer;
-  int buflen;
-  UNDO_LIST *ul;
-  char *prompt;
-
-  /* global state */
-  int rlstate;
-  int done;
-  Keymap kmap;
-
-  /* input state */
-  rl_command_func_t *lastfunc;
-  int insmode;
-  int edmode;
-  int kseqlen;
-  FILE *inf;
-  FILE *outf;
-  int pendingin;
-  char *macro;
-
-  /* signal state */
-  int catchsigs;
-  int catchsigwinch;
-
-  /* search state */
-
-  /* completion state */
-
-  /* options state */
-
-  /* reserved for future expansion, so the struct size doesn't change */
-  char reserved[64];
-};
-
-extern int rl_save_state PARAMS((struct readline_state *));
-extern int rl_restore_state PARAMS((struct readline_state *));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _READLINE_H_ */
diff --git a/lib/readline/signals.c~ b/lib/readline/signals.c~
deleted file mode 100644 (file)
index f96ab69..0000000
+++ /dev/null
@@ -1,701 +0,0 @@
-/* signals.c -- signal handling support for readline. */
-
-/* Copyright (C) 1987-2011 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 <stdio.h>             /* Just for NULL.  Yuck. */
-#include <sys/types.h>
-#include <signal.h>
-
-#if defined (HAVE_UNISTD_H)
-#  include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-
-#if defined (GWINSZ_IN_SYS_IOCTL)
-#  include <sys/ioctl.h>
-#endif /* GWINSZ_IN_SYS_IOCTL */
-
-/* Some standard library routines. */
-#include "readline.h"
-#include "history.h"
-
-#include "rlprivate.h"
-
-#if defined (HANDLE_SIGNALS)
-
-#if !defined (RETSIGTYPE)
-#  if defined (VOID_SIGHANDLER)
-#    define RETSIGTYPE void
-#  else
-#    define RETSIGTYPE int
-#  endif /* !VOID_SIGHANDLER */
-#endif /* !RETSIGTYPE */
-
-#if defined (VOID_SIGHANDLER)
-#  define SIGHANDLER_RETURN return
-#else
-#  define SIGHANDLER_RETURN return (0)
-#endif
-
-/* This typedef is equivalent to the one for Function; it allows us
-   to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
-typedef RETSIGTYPE SigHandler ();
-
-#if defined (HAVE_POSIX_SIGNALS)
-typedef struct sigaction sighandler_cxt;
-#  define rl_sigaction(s, nh, oh)      sigaction(s, nh, oh)
-#else
-typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt;
-#  define sigemptyset(m)
-#endif /* !HAVE_POSIX_SIGNALS */
-
-#ifndef SA_RESTART
-#  define SA_RESTART 0
-#endif
-
-static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
-static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
-static void rl_maybe_restore_sighandler PARAMS((int, sighandler_cxt *));
-
-static RETSIGTYPE rl_signal_handler PARAMS((int));
-static RETSIGTYPE _rl_handle_signal PARAMS((int));
-     
-/* Exported variables for use by applications. */
-
-/* If non-zero, readline will install its own signal handlers for
-   SIGINT, SIGTERM, SIGHUP, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
-int rl_catch_signals = 1;
-
-/* If non-zero, readline will install a signal handler for SIGWINCH. */
-#ifdef SIGWINCH
-int rl_catch_sigwinch = 1;
-#else
-int rl_catch_sigwinch = 0;     /* for the readline state struct in readline.c */
-#endif
-
-/* Private variables. */
-int _rl_interrupt_immediately = 0;
-int volatile _rl_caught_signal = 0;    /* should be sig_atomic_t, but that requires including <signal.h> everywhere */
-
-/* If non-zero, print characters corresponding to received signals as long as
-   the user has indicated his desire to do so (_rl_echo_control_chars). */
-int _rl_echoctl = 0;
-
-int _rl_intr_char = 0;
-int _rl_quit_char = 0;
-int _rl_susp_char = 0;
-
-static int signals_set_flag;
-static int sigwinch_set_flag;
-
-/* **************************************************************** */
-/*                                                                 */
-/*                        Signal Handling                          */
-/*                                                                 */
-/* **************************************************************** */
-
-static sighandler_cxt old_int, old_term, old_hup, old_alrm, old_quit;
-#if defined (SIGTSTP)
-static sighandler_cxt old_tstp, old_ttou, old_ttin;
-#endif
-#if defined (SIGWINCH)
-static sighandler_cxt old_winch;
-#endif
-
-_rl_sigcleanup_func_t *_rl_sigcleanup;
-void *_rl_sigcleanarg;
-
-/* Readline signal handler functions. */
-
-/* Called from RL_CHECK_SIGNALS() macro */
-RETSIGTYPE
-_rl_signal_handler (sig)
-     int sig;
-{
-  _rl_caught_signal = 0;       /* XXX */
-
-fprintf(stderr, "_rl_signal_handler (%d)\n", sig);
-#if defined (SIGWINCH)
-  if (sig == SIGWINCH)
-    rl_resize_terminal ();
-  else
-#endif
-    _rl_handle_signal (sig);
-  SIGHANDLER_RETURN;
-}
-
-static RETSIGTYPE
-rl_signal_handler (sig)
-     int sig;
-{
-  if (_rl_interrupt_immediately)
-    {
-      _rl_interrupt_immediately = 0;
-      _rl_handle_signal (sig);
-    }
-  else
-    _rl_caught_signal = sig;
-
-  SIGHANDLER_RETURN;
-}
-
-static RETSIGTYPE
-_rl_handle_signal (sig)
-     int sig;
-{
-#if defined (HAVE_POSIX_SIGNALS)
-  sigset_t set;
-#else /* !HAVE_POSIX_SIGNALS */
-#  if defined (HAVE_BSD_SIGNALS)
-  long omask;
-#  else /* !HAVE_BSD_SIGNALS */
-  sighandler_cxt dummy_cxt;    /* needed for rl_set_sighandler call */
-#  endif /* !HAVE_BSD_SIGNALS */
-#endif /* !HAVE_POSIX_SIGNALS */
-
-  RL_SETSTATE(RL_STATE_SIGHANDLER);
-
-#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
-  /* Since the signal will not be blocked while we are in the signal
-     handler, ignore it until rl_clear_signals resets the catcher. */
-#  if defined (SIGALRM)
-  if (sig == SIGINT || sig == SIGALRM)
-#  else
-  if (sig == SIGINT)
-#  endif
-    rl_set_sighandler (sig, SIG_IGN, &dummy_cxt);
-#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
-
-  /* If there's a sig cleanup function registered, call it and `deregister'
-     the cleanup function to avoid multiple calls */
-  if (_rl_sigcleanup)
-    {
-      (*_rl_sigcleanup) (sig, _rl_sigcleanarg);
-      _rl_sigcleanup = 0;
-      _rl_sigcleanarg = 0;
-    }
-    
-  switch (sig)
-    {
-    case SIGINT:
-      _rl_reset_completion_state ();
-      rl_free_line_state ();
-      /* FALLTHROUGH */
-
-    case SIGTERM:
-    case SIGHUP:
-#if defined (SIGTSTP)
-    case SIGTSTP:
-    case SIGTTOU:
-    case SIGTTIN:
-#endif /* SIGTSTP */
-#if defined (SIGALRM)
-    case SIGALRM:
-#endif
-#if defined (SIGQUIT)
-    case SIGQUIT:
-#endif
-      rl_echo_signal_char (sig);
-      rl_cleanup_after_signal ();
-
-#if defined (HAVE_POSIX_SIGNALS)
-      sigemptyset (&set);
-      sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
-      sigdelset (&set, sig);
-#else /* !HAVE_POSIX_SIGNALS */
-#  if defined (HAVE_BSD_SIGNALS)
-      omask = sigblock (0);
-#  endif /* HAVE_BSD_SIGNALS */
-#endif /* !HAVE_POSIX_SIGNALS */
-
-#if defined (__EMX__)
-      signal (sig, SIG_ACK);
-#endif
-
-#if defined (HAVE_KILL)
-      kill (getpid (), sig);
-#else
-      raise (sig);             /* assume we have raise */
-#endif
-
-      /* Let the signal that we just sent through.  */
-#if defined (HAVE_POSIX_SIGNALS)
-      sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
-#else /* !HAVE_POSIX_SIGNALS */
-#  if defined (HAVE_BSD_SIGNALS)
-      sigsetmask (omask & ~(sigmask (sig)));
-#  endif /* HAVE_BSD_SIGNALS */
-#endif /* !HAVE_POSIX_SIGNALS */
-
-      rl_reset_after_signal ();
-    }
-
-  RL_UNSETSTATE(RL_STATE_SIGHANDLER);
-  SIGHANDLER_RETURN;
-}
-
-#if defined (SIGWINCH)
-static RETSIGTYPE
-rl_sigwinch_handler (sig)
-     int sig;
-{
-  SigHandler *oh;
-
-#if defined (MUST_REINSTALL_SIGHANDLERS)
-  sighandler_cxt dummy_winch;
-
-  /* We don't want to change old_winch -- it holds the state of SIGWINCH
-     disposition set by the calling application.  We need this state
-     because we call the application's SIGWINCH handler after updating
-     our own idea of the screen size. */
-  rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch);
-#endif
-
-  RL_SETSTATE(RL_STATE_SIGHANDLER);
-  _rl_caught_signal = sig;
-
-  /* If another sigwinch handler has been installed, call it. */
-  oh = (SigHandler *)old_winch.sa_handler;
-  if (oh &&  oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL)
-    (*oh) (sig);
-
-  RL_UNSETSTATE(RL_STATE_SIGHANDLER);
-  SIGHANDLER_RETURN;
-}
-#endif  /* SIGWINCH */
-
-/* Functions to manage signal handling. */
-
-#if !defined (HAVE_POSIX_SIGNALS)
-static int
-rl_sigaction (sig, nh, oh)
-     int sig;
-     sighandler_cxt *nh, *oh;
-{
-  oh->sa_handler = signal (sig, nh->sa_handler);
-  return 0;
-}
-#endif /* !HAVE_POSIX_SIGNALS */
-
-/* Set up a readline-specific signal handler, saving the old signal
-   information in OHANDLER.  Return the old signal handler, like
-   signal(). */
-static SigHandler *
-rl_set_sighandler (sig, handler, ohandler)
-     int sig;
-     SigHandler *handler;
-     sighandler_cxt *ohandler;
-{
-  sighandler_cxt old_handler;
-#if defined (HAVE_POSIX_SIGNALS)
-  struct sigaction act;
-
-  act.sa_handler = handler;
-#  if defined (SIGWINCH)
-  act.sa_flags = (sig == SIGWINCH) ? SA_RESTART : 0;
-#  else
-  act.sa_flags = 0;
-#  endif /* SIGWINCH */
-  sigemptyset (&act.sa_mask);
-  sigemptyset (&ohandler->sa_mask);
-  sigaction (sig, &act, &old_handler);
-#else
-  old_handler.sa_handler = (SigHandler *)signal (sig, handler);
-#endif /* !HAVE_POSIX_SIGNALS */
-
-  /* XXX -- assume we have memcpy */
-  /* If rl_set_signals is called twice in a row, don't set the old handler to
-     rl_signal_handler, because that would cause infinite recursion. */
-  if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler)
-    memcpy (ohandler, &old_handler, sizeof (sighandler_cxt));
-
-  return (ohandler->sa_handler);
-}
-
-/* Set disposition of SIG to HANDLER, returning old state in OHANDLER.  Don't
-   change disposition if OHANDLER indicates the signal was ignored. */
-static void
-rl_maybe_set_sighandler (sig, handler, ohandler)
-     int sig;
-     SigHandler *handler;
-     sighandler_cxt *ohandler;
-{
-  sighandler_cxt dummy;
-  SigHandler *oh;
-
-  sigemptyset (&dummy.sa_mask);
-  dummy.sa_flags = 0;
-  oh = rl_set_sighandler (sig, handler, ohandler);
-  if (oh == (SigHandler *)SIG_IGN)
-    rl_sigaction (sig, ohandler, &dummy);
-}
-
-/* Set the disposition of SIG to HANDLER, if HANDLER->sa_handler indicates the
-   signal was not being ignored.  MUST only be called for signals whose
-   disposition was changed using rl_maybe_set_sighandler or for which the
-   SIG_IGN check was performed inline (e.g., SIGALRM below). */
-static void
-rl_maybe_restore_sighandler (sig, handler)
-     int sig;
-     sighandler_cxt *handler;
-{
-  sighandler_cxt dummy;
-
-  sigemptyset (&dummy.sa_mask);
-  dummy.sa_flags = 0;
-  if (handler->sa_handler != SIG_IGN)
-    rl_sigaction (sig, handler, &dummy);
-}
-
-int
-rl_set_signals ()
-{
-  sighandler_cxt dummy;
-  SigHandler *oh;
-#if defined (HAVE_POSIX_SIGNALS)
-  static int sigmask_set = 0;
-  static sigset_t bset, oset;
-#endif
-
-#if defined (HAVE_POSIX_SIGNALS)
-  if (rl_catch_signals && sigmask_set == 0)
-    {
-      sigemptyset (&bset);
-
-      sigaddset (&bset, SIGINT);
-      sigaddset (&bset, SIGTERM);
-      sigaddset (&bset, SIGHUP);
-#if defined (SIGQUIT)
-      sigaddset (&bset, SIGQUIT);
-#endif
-#if defined (SIGALRM)
-      sigaddset (&bset, SIGALRM);
-#endif
-#if defined (SIGTSTP)
-      sigaddset (&bset, SIGTSTP);
-#endif
-#if defined (SIGTTIN)
-      sigaddset (&bset, SIGTTIN);
-#endif
-#if defined (SIGTTOU)
-      sigaddset (&bset, SIGTTOU);
-#endif
-      sigmask_set = 1;
-    }      
-#endif /* HAVE_POSIX_SIGNALS */
-
-  if (rl_catch_signals && signals_set_flag == 0)
-    {
-#if defined (HAVE_POSIX_SIGNALS)
-      sigemptyset (&oset);
-      sigprocmask (SIG_BLOCK, &bset, &oset);
-#endif
-
-      rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int);
-      rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
-      rl_maybe_set_sighandler (SIGHUP, rl_signal_handler, &old_hup);
-#if defined (SIGQUIT)
-      rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit);
-#endif
-
-#if defined (SIGALRM)
-      oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm);
-      if (oh == (SigHandler *)SIG_IGN)
-       rl_sigaction (SIGALRM, &old_alrm, &dummy);
-#if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
-      /* If the application using readline has already installed a signal
-        handler with SA_RESTART, SIGALRM will cause reads to be restarted
-        automatically, so readline should just get out of the way.  Since
-        we tested for SIG_IGN above, we can just test for SIG_DFL here. */
-      if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART))
-       rl_sigaction (SIGALRM, &old_alrm, &dummy);
-#endif /* HAVE_POSIX_SIGNALS */
-#endif /* SIGALRM */
-
-#if defined (SIGTSTP)
-      rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
-#endif /* SIGTSTP */
-
-#if defined (SIGTTOU)
-      rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
-#endif /* SIGTTOU */
-
-#if defined (SIGTTIN)
-      rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
-#endif /* SIGTTIN */
-
-      signals_set_flag = 1;
-
-#if defined (HAVE_POSIX_SIGNALS)
-      sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
-#endif
-    }
-
-#if defined (SIGWINCH)
-  if (rl_catch_sigwinch && sigwinch_set_flag == 0)
-    {
-      rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch);
-      sigwinch_set_flag = 1;
-    }
-#endif /* SIGWINCH */
-
-  return 0;
-}
-
-int
-rl_clear_signals ()
-{
-  sighandler_cxt dummy;
-
-  if (rl_catch_signals && signals_set_flag == 1)
-    {
-      sigemptyset (&dummy.sa_mask);
-
-      /* Since rl_maybe_set_sighandler doesn't override a SIG_IGN handler,
-        we should in theory not have to restore a handler where
-        old_xxx.sa_handler == SIG_IGN.  That's what rl_maybe_restore_sighandler
-        does.  Fewer system calls should reduce readline's per-line
-        overhead */
-      rl_maybe_restore_sighandler (SIGINT, &old_int);
-      rl_maybe_restore_sighandler (SIGTERM, &old_term);
-      rl_maybe_restore_sighandler (SIGHUP, &old_hup);
-#if defined (SIGQUIT)
-      rl_maybe_restore_sighandler (SIGQUIT, &old_quit);
-#endif
-#if defined (SIGALRM)
-      rl_maybe_restore_sighandler (SIGALRM, &old_alrm);
-#endif
-
-#if defined (SIGTSTP)
-      rl_maybe_restore_sighandler (SIGTSTP, &old_tstp);
-#endif /* SIGTSTP */
-
-#if defined (SIGTTOU)
-      rl_maybe_restore_sighandler (SIGTTOU, &old_ttou);
-#endif /* SIGTTOU */
-
-#if defined (SIGTTIN)
-      rl_maybe_restore_sighandler (SIGTTIN, &old_ttin);
-#endif /* SIGTTIN */
-
-      signals_set_flag = 0;
-    }
-
-#if defined (SIGWINCH)
-  if (rl_catch_sigwinch && sigwinch_set_flag == 1)
-    {
-      sigemptyset (&dummy.sa_mask);
-      rl_sigaction (SIGWINCH, &old_winch, &dummy);
-      sigwinch_set_flag = 0;
-    }
-#endif
-
-  return 0;
-}
-
-/* Clean up the terminal and readline state after catching a signal, before
-   resending it to the calling application. */
-void
-rl_cleanup_after_signal ()
-{
-  _rl_clean_up_for_exit ();
-  if (rl_deprep_term_function)
-    (*rl_deprep_term_function) ();
-  rl_clear_pending_input ();
-  rl_clear_signals ();
-}
-
-/* Reset the terminal and readline state after a signal handler returns. */
-void
-rl_reset_after_signal ()
-{
-  if (rl_prep_term_function)
-    (*rl_prep_term_function) (_rl_meta_flag);
-  rl_set_signals ();
-}
-
-/* Free up the readline variable line state for the current line (undo list,
-   any partial history entry, any keyboard macros in progress, and any
-   numeric arguments in process) after catching a signal, before calling
-   rl_cleanup_after_signal(). */ 
-void
-rl_free_line_state ()
-{
-  register HIST_ENTRY *entry;
-
-  rl_free_undo_list ();
-
-  entry = current_history ();
-  if (entry)
-    entry->data = (char *)NULL;
-
-  _rl_kill_kbd_macro ();
-  rl_clear_message ();
-  _rl_reset_argument ();
-}
-
-#endif  /* HANDLE_SIGNALS */
-
-/* **************************************************************** */
-/*                                                                 */
-/*                        SIGINT Management                        */
-/*                                                                 */
-/* **************************************************************** */
-
-#if defined (HAVE_POSIX_SIGNALS)
-static sigset_t sigint_set, sigint_oset;
-static sigset_t sigwinch_set, sigwinch_oset;
-#else /* !HAVE_POSIX_SIGNALS */
-#  if defined (HAVE_BSD_SIGNALS)
-static int sigint_oldmask;
-static int sigwinch_oldmask;
-#  endif /* HAVE_BSD_SIGNALS */
-#endif /* !HAVE_POSIX_SIGNALS */
-
-static int sigint_blocked;
-static int sigwinch_blocked;
-
-/* Cause SIGINT to not be delivered until the corresponding call to
-   release_sigint(). */
-void
-_rl_block_sigint ()
-{
-  if (sigint_blocked)
-    return;
-
-  sigint_blocked = 1;
-}
-
-/* Allow SIGINT to be delivered. */
-void
-_rl_release_sigint ()
-{
-  if (sigint_blocked == 0)
-    return;
-
-  sigint_blocked = 0;
-  RL_CHECK_SIGNALS ();
-}
-
-/* Cause SIGWINCH to not be delivered until the corresponding call to
-   release_sigwinch(). */
-void
-_rl_block_sigwinch ()
-{
-  if (sigwinch_blocked)
-    return;
-
-#if defined (SIGWINCH)
-
-#if defined (HAVE_POSIX_SIGNALS)
-  sigemptyset (&sigwinch_set);
-  sigemptyset (&sigwinch_oset);
-  sigaddset (&sigwinch_set, SIGWINCH);
-  sigprocmask (SIG_BLOCK, &sigwinch_set, &sigwinch_oset);
-#else /* !HAVE_POSIX_SIGNALS */
-#  if defined (HAVE_BSD_SIGNALS)
-  sigwinch_oldmask = sigblock (sigmask (SIGWINCH));
-#  else /* !HAVE_BSD_SIGNALS */
-#    if defined (HAVE_USG_SIGHOLD)
-  sighold (SIGWINCH);
-#    endif /* HAVE_USG_SIGHOLD */
-#  endif /* !HAVE_BSD_SIGNALS */
-#endif /* !HAVE_POSIX_SIGNALS */
-
-#endif /* SIGWINCH */
-
-  sigwinch_blocked = 1;
-}
-
-/* Allow SIGWINCH to be delivered. */
-void
-_rl_release_sigwinch ()
-{
-  if (sigwinch_blocked == 0)
-    return;
-
-#if defined (SIGWINCH)
-
-#if defined (HAVE_POSIX_SIGNALS)
-  sigprocmask (SIG_SETMASK, &sigwinch_oset, (sigset_t *)NULL);
-#else
-#  if defined (HAVE_BSD_SIGNALS)
-  sigsetmask (sigwinch_oldmask);
-#  else /* !HAVE_BSD_SIGNALS */
-#    if defined (HAVE_USG_SIGHOLD)
-  sigrelse (SIGWINCH);
-#    endif /* HAVE_USG_SIGHOLD */
-#  endif /* !HAVE_BSD_SIGNALS */
-#endif /* !HAVE_POSIX_SIGNALS */
-
-#endif /* SIGWINCH */
-
-  sigwinch_blocked = 0;
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*             Echoing special control characters                  */
-/*                                                                 */
-/* **************************************************************** */
-void
-rl_echo_signal_char (sig)
-     int sig;
-{
-  char cstr[3];
-  int cslen, c;
-
-  if (_rl_echoctl == 0 || _rl_echo_control_chars == 0)
-    return;
-
-  switch (sig)
-    {
-    case SIGINT:  c = _rl_intr_char; break;
-#if defined (SIGQUIT)
-    case SIGQUIT: c = _rl_quit_char; break;
-#endif
-#if defined (SIGTSTP)
-    case SIGTSTP: c = _rl_susp_char; break;
-#endif
-    default: return;
-    }
-
-  if (CTRL_CHAR (c) || c == RUBOUT)
-    {
-      cstr[0] = '^';
-      cstr[1] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
-      cstr[cslen = 2] = '\0';
-    }
-  else
-    {
-      cstr[0] = c;
-      cstr[cslen = 1] = '\0';
-    }
-
-  _rl_output_some_chars (cstr, cslen);
-}
diff --git a/quit.h~ b/quit.h~
deleted file mode 100644 (file)
index 6c91e03..0000000
--- a/quit.h~
+++ /dev/null
@@ -1,65 +0,0 @@
-/* quit.h -- How to handle SIGINT gracefully. */
-
-/* Copyright (C) 1993-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/>.
-*/
-
-#if !defined (_QUIT_H_)
-#define _QUIT_H_
-
-/* Non-zero means SIGINT has already ocurred. */
-extern volatile int interrupt_state;
-extern volatile int terminating_signal;
-
-/* 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 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)) \
-{ \
-itrace("CHECK_WAIT_INTR: calling longjmp to wait_intr_buf: sig = %d",wait_signal_received); \
-      longjmp (wait_intr_buf, 1); \
-} \
-  } while (0)
-
-#endif /* _QUIT_H_ */
diff --git a/redir.c~ b/redir.c~
deleted file mode 100644 (file)
index 65d31f3..0000000
--- a/redir.c~
+++ /dev/null
@@ -1,1373 +0,0 @@
-/* redir.c -- Functions to perform input and output redirection. */
-
-/* Copyright (C) 1997-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/>.
-*/
-
-#include "config.h"
-
-#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
-  #pragma alloca
-#endif /* _AIX && RISC6000 && !__GNUC__ */
-
-#include <stdio.h>
-#include "bashtypes.h"
-#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
-#  include <sys/file.h>
-#endif
-#include "filecntl.h"
-#include "posixstat.h"
-
-#if defined (HAVE_UNISTD_H)
-#  include <unistd.h>
-#endif
-
-#include <errno.h>
-
-#if !defined (errno)
-extern int errno;
-#endif
-
-#include "bashansi.h"
-#include "bashintl.h"
-#include "memalloc.h"
-
-#define NEED_FPURGE_DECL
-
-#include "shell.h"
-#include "flags.h"
-#include "execute_cmd.h"
-#include "redir.h"
-
-#if defined (BUFFERED_INPUT)
-#  include "input.h"
-#endif
-
-#define SHELL_FD_BASE  10
-
-int expanding_redir;
-
-extern int posixly_correct;
-extern int last_command_exit_value;
-extern int executing_builtin;
-extern REDIRECT *redirection_undo_list;
-extern REDIRECT *exec_redirection_undo_list;
-
-/* Static functions defined and used in this file. */
-static void add_exec_redirect __P((REDIRECT *));
-static int add_undo_redirect __P((int, enum r_instruction, int));
-static int add_undo_close_redirect __P((int));
-static int expandable_redirection_filename __P((REDIRECT *));
-static int stdin_redirection __P((enum r_instruction, int));
-static int undoablefd __P((int));
-static int do_redirection_internal __P((REDIRECT *, int));
-
-static int write_here_document __P((int, WORD_DESC *));
-static int write_here_string __P((int, WORD_DESC *));
-static int here_document_to_fd __P((WORD_DESC *, enum r_instruction));
-
-static int redir_special_open __P((int, char *, int, int, enum r_instruction));
-static int noclobber_open __P((char *, int, int, enum r_instruction));
-static int redir_open __P((char *, int, int, enum r_instruction));
-
-static int redir_varassign __P((REDIRECT *, int));
-static int redir_varvalue __P((REDIRECT *));
-
-/* Spare redirector used when translating [N]>&WORD[-] or [N]<&WORD[-] to
-   a new redirection and when creating the redirection undo list. */
-static REDIRECTEE rd;
-
-/* Set to errno when a here document cannot be created for some reason.
-   Used to print a reasonable error message. */
-static int heredoc_errno;
-
-#define REDIRECTION_ERROR(r, e, fd) \
-do { \
-  if ((r) < 0) \
-    { \
-      if (fd >= 0) \
-       close (fd); \
-      last_command_exit_value = EXECUTION_FAILURE;\
-      return ((e) == 0 ? EINVAL : (e));\
-    } \
-} while (0)
-
-void
-redirection_error (temp, error)
-     REDIRECT *temp;
-     int error;
-{
-  char *filename, *allocname;
-  int oflags;
-
-  allocname = 0;
-  if (temp->rflags & REDIR_VARASSIGN)
-    filename = allocname = savestring (temp->redirector.filename->word);
-  else if (temp->redirector.dest < 0)
-    /* This can happen when read_token_word encounters overflow, like in
-       exec 4294967297>x */
-    filename = _("file descriptor out of range");
-#ifdef EBADF
-  /* This error can never involve NOCLOBBER */
-  else if (error != NOCLOBBER_REDIRECT && temp->redirector.dest >= 0 && error == EBADF)
-    {
-      /* If we're dealing with two file descriptors, we have to guess about
-         which one is invalid; in the cases of r_{duplicating,move}_input and
-         r_{duplicating,move}_output we're here because dup2() failed. */
-      switch (temp->instruction)
-        {
-        case r_duplicating_input:
-        case r_duplicating_output:
-        case r_move_input:
-        case r_move_output:
-         filename = allocname = itos (temp->redirectee.dest);
-         break;
-       case r_duplicating_input_word:
-         if (temp->redirector.dest == 0)       /* Guess */
-           filename = temp->redirectee.filename->word; /* XXX */
-         else
-           filename = allocname = itos (temp->redirector.dest);
-         break;
-       case r_duplicating_output_word:
-         if (temp->redirector.dest == 1)       /* Guess */
-           filename = temp->redirectee.filename->word; /* XXX */
-         else
-           filename = allocname = itos (temp->redirector.dest);
-         break;
-       default:
-         filename = allocname = itos (temp->redirector.dest);
-         break;
-        }
-    }
-#endif
-  else if (expandable_redirection_filename (temp))
-    {
-expandable_filename:
-      oflags = temp->redirectee.filename->flags;
-      if (posixly_correct && interactive_shell == 0)
-       temp->redirectee.filename->flags |= W_NOGLOB;
-      temp->redirectee.filename->flags |= W_NOCOMSUB;
-      filename = allocname = redirection_expand (temp->redirectee.filename);
-      temp->redirectee.filename->flags = oflags;
-      if (filename == 0)
-       filename = temp->redirectee.filename->word;
-    }
-  else if (temp->redirectee.dest < 0)
-    filename = _("file descriptor out of range");
-  else
-    filename = allocname = itos (temp->redirectee.dest);
-
-  switch (error)
-    {
-    case AMBIGUOUS_REDIRECT:
-      internal_error (_("%s: ambiguous redirect"), filename);
-      break;
-
-    case NOCLOBBER_REDIRECT:
-      internal_error (_("%s: cannot overwrite existing file"), filename);
-      break;
-
-#if defined (RESTRICTED_SHELL)
-    case RESTRICTED_REDIRECT:
-      internal_error (_("%s: restricted: cannot redirect output"), filename);
-      break;
-#endif /* RESTRICTED_SHELL */
-
-    case HEREDOC_REDIRECT:
-      internal_error (_("cannot create temp file for here-document: %s"), strerror (heredoc_errno));
-      break;
-
-    case BADVAR_REDIRECT:
-      internal_error (_("%s: cannot assign fd to variable"), filename);
-      break;
-
-    default:
-      internal_error ("%s: %s", filename, strerror (error));
-      break;
-    }
-
-  FREE (allocname);
-}
-
-/* Perform the redirections on LIST.  If flags & RX_ACTIVE, then actually
-   make input and output file descriptors, otherwise just do whatever is
-   neccessary for side effecting.  flags & RX_UNDOABLE says to remember
-   how to undo the redirections later, if non-zero.  If flags & RX_CLEXEC
-   is non-zero, file descriptors opened in do_redirection () have their
-   close-on-exec flag set. */
-int
-do_redirections (list, flags)
-     REDIRECT *list;
-     int flags;
-{
-  int error;
-  REDIRECT *temp;
-
-  if (flags & RX_UNDOABLE)
-    {
-      if (redirection_undo_list)
-       {
-         dispose_redirects (redirection_undo_list);
-         redirection_undo_list = (REDIRECT *)NULL;
-       }
-      if (exec_redirection_undo_list)
-       dispose_exec_redirects ();
-    }
-
-  for (temp = list; temp; temp = temp->next)
-    {
-      error = do_redirection_internal (temp, flags);
-      if (error)
-       {
-         redirection_error (temp, error);
-         return (error);
-       }
-    }
-  return (0);
-}
-
-/* Return non-zero if the redirection pointed to by REDIRECT has a
-   redirectee.filename that can be expanded. */
-static int
-expandable_redirection_filename (redirect)
-     REDIRECT *redirect;
-{
-  switch (redirect->instruction)
-    {
-    case r_output_direction:
-    case r_appending_to:
-    case r_input_direction:
-    case r_inputa_direction:
-    case r_err_and_out:
-    case r_append_err_and_out:
-    case r_input_output:
-    case r_output_force:
-    case r_duplicating_input_word:
-    case r_duplicating_output_word:
-    case r_move_input_word:
-    case r_move_output_word:
-      return 1;
-
-    default:
-      return 0;
-    }
-}
-
-/* Expand the word in WORD returning a string.  If WORD expands to
-   multiple words (or no words), then return NULL. */
-char *
-redirection_expand (word)
-     WORD_DESC *word;
-{
-  char *result;
-  WORD_LIST *tlist1, *tlist2;
-  WORD_DESC *w;
-  int old;
-
-  w = copy_word (word);
-  if (posixly_correct)
-    w->flags |= W_NOSPLIT;
-
-  tlist1 = make_word_list (w, (WORD_LIST *)NULL);
-  expanding_redir = 1;
-  /* Now that we've changed the variable search order to ignore the temp
-     environment, see if we need to change the cached IFS values. */
-  sv_ifs ("IFS");
-  tlist2 = expand_words_no_vars (tlist1);
-  expanding_redir = 0;
-  /* Now we need to change the variable search order back to include the temp
-     environment.  We force the temp environment search by forcing
-     executing_builtin to 1.  This is what makes `read' get the right values
-     for the IFS-related cached variables, for example. */
-  old = executing_builtin;
-  executing_builtin = 1;
-  sv_ifs ("IFS");
-  executing_builtin = old;
-  dispose_words (tlist1);
-
-  if (!tlist2 || tlist2->next)
-    {
-      /* We expanded to no words, or to more than a single word.
-        Dispose of the word list and return NULL. */
-      if (tlist2)
-       dispose_words (tlist2);
-      return ((char *)NULL);
-    }
-  result = string_list (tlist2);  /* XXX savestring (tlist2->word->word)? */
-  dispose_words (tlist2);
-  return (result);
-}
-
-static int
-write_here_string (fd, redirectee)
-     int fd;
-     WORD_DESC *redirectee;
-{
-  char *herestr;
-  int herelen, n, e, old;
-
-  expanding_redir = 1;
-  /* Now that we've changed the variable search order to ignore the temp
-     environment, see if we need to change the cached IFS values. */
-  sv_ifs ("IFS");
-  herestr = expand_string_to_string (redirectee->word, 0);
-  expanding_redir = 0;
-  /* Now we need to change the variable search order back to include the temp
-     environment.  We force the temp environment search by forcing
-     executing_builtin to 1.  This is what makes `read' get the right values
-     for the IFS-related cached variables, for example. */
-  old = executing_builtin;
-  executing_builtin = 1;
-  sv_ifs ("IFS");
-  executing_builtin = old;
-
-  herelen = STRLEN (herestr);
-
-  n = write (fd, herestr, herelen);
-  if (n == herelen)
-    {
-      n = write (fd, "\n", 1);
-      herelen = 1;
-    }
-  e = errno;
-  FREE (herestr);
-  if (n != herelen)
-    {
-      if (e == 0)
-       e = ENOSPC;
-      return e;
-    }
-  return 0;
-}  
-
-/* Write the text of the here document pointed to by REDIRECTEE to the file
-   descriptor FD, which is already open to a temp file.  Return 0 if the
-   write is successful, otherwise return errno. */
-static int
-write_here_document (fd, redirectee)
-     int fd;
-     WORD_DESC *redirectee;
-{
-  char *document;
-  int document_len, fd2, old;
-  FILE *fp;
-  register WORD_LIST *t, *tlist;
-
-  /* Expand the text if the word that was specified had
-     no quoting.  The text that we expand is treated
-     exactly as if it were surrounded by double quotes. */
-
-  if (redirectee->flags & W_QUOTED)
-    {
-      document = redirectee->word;
-      document_len = strlen (document);
-      /* Set errno to something reasonable if the write fails. */
-      if (write (fd, document, document_len) < document_len)
-       {
-         if (errno == 0)
-           errno = ENOSPC;
-         return (errno);
-       }
-      else
-       return 0;
-    }
-
-  expanding_redir = 1;
-  /* Now that we've changed the variable search order to ignore the temp
-     environment, see if we need to change the cached IFS values. */
-  sv_ifs ("IFS");
-  tlist = expand_string (redirectee->word, Q_HERE_DOCUMENT);
-  expanding_redir = 0;
-  /* Now we need to change the variable search order back to include the temp
-     environment.  We force the temp environment search by forcing
-     executing_builtin to 1.  This is what makes `read' get the right values
-     for the IFS-related cached variables, for example. */
-  old = executing_builtin;
-  executing_builtin = 1;
-  sv_ifs ("IFS");
-  executing_builtin = old;
-
-  if (tlist)
-    {
-      /* Try using buffered I/O (stdio) and writing a word
-        at a time, letting stdio do the work of buffering
-        for us rather than managing our own strings.  Most
-        stdios are not particularly fast, however -- this
-        may need to be reconsidered later. */
-      if ((fd2 = dup (fd)) < 0 || (fp = fdopen (fd2, "w")) == NULL)
-       {
-         if (fd2 >= 0)
-           close (fd2);
-         return (errno);
-       }
-      errno = 0;
-      for (t = tlist; t; t = t->next)
-       {
-         /* This is essentially the body of
-            string_list_internal expanded inline. */
-         document = t->word->word;
-         document_len = strlen (document);
-         if (t != tlist)
-           putc (' ', fp);     /* separator */
-         fwrite (document, document_len, 1, fp);
-         if (ferror (fp))
-           {
-             if (errno == 0)
-               errno = ENOSPC;
-             fd2 = errno;
-             fclose(fp);
-             dispose_words (tlist);
-             return (fd2);
-           }
-       }
-      dispose_words (tlist);
-      if (fclose (fp) != 0)
-       {
-         if (errno == 0)
-           errno = ENOSPC;
-         return (errno);
-       }
-    }
-  return 0;
-}
-
-/* Create a temporary file holding the text of the here document pointed to
-   by REDIRECTEE, and return a file descriptor open for reading to the temp
-   file.  Return -1 on any error, and make sure errno is set appropriately. */
-static int
-here_document_to_fd (redirectee, ri)
-     WORD_DESC *redirectee;
-     enum r_instruction ri;
-{
-  char *filename;
-  int r, fd, fd2;
-
-  fd = sh_mktmpfd ("sh-thd", MT_USERANDOM|MT_USETMPDIR, &filename);
-
-  /* If we failed for some reason other than the file existing, abort */
-  if (fd < 0)
-    {
-      FREE (filename);
-      return (fd);
-    }
-
-  errno = r = 0;               /* XXX */
-  /* write_here_document returns 0 on success, errno on failure. */
-  if (redirectee->word)
-    r = (ri != r_reading_string) ? write_here_document (fd, redirectee)
-                                : write_here_string (fd, redirectee);
-
-  if (r)
-    {
-      close (fd);
-      unlink (filename);
-      free (filename);
-      errno = r;
-      return (-1);
-    }
-
-  /* In an attempt to avoid races, we close the first fd only after opening
-     the second. */
-  /* Make the document really temporary.  Also make it the input. */
-  fd2 = open (filename, O_RDONLY|O_BINARY, 0600);
-
-  if (fd2 < 0)
-    {
-      r = errno;
-      unlink (filename);
-      free (filename);
-      close (fd);
-      errno = r;
-      return -1;
-    }
-
-  close (fd);
-  if (unlink (filename) < 0)
-    {
-      r = errno;
-      close (fd2);
-      free (filename);
-      errno = r;
-      return (-1);
-    }
-
-  free (filename);
-  return (fd2);
-}
-
-#define RF_DEVFD       1
-#define RF_DEVSTDERR   2
-#define RF_DEVSTDIN    3
-#define RF_DEVSTDOUT   4
-#define RF_DEVTCP      5
-#define RF_DEVUDP      6
-
-/* A list of pattern/value pairs for filenames that the redirection
-   code handles specially. */
-static STRING_INT_ALIST _redir_special_filenames[] = {
-#if !defined (HAVE_DEV_FD)
-  { "/dev/fd/[0-9]*", RF_DEVFD },
-#endif
-#if !defined (HAVE_DEV_STDIN)
-  { "/dev/stderr", RF_DEVSTDERR },
-  { "/dev/stdin", RF_DEVSTDIN },
-  { "/dev/stdout", RF_DEVSTDOUT },
-#endif
-#if defined (NETWORK_REDIRECTIONS)
-  { "/dev/tcp/*/*", RF_DEVTCP },
-  { "/dev/udp/*/*", RF_DEVUDP },
-#endif
-  { (char *)NULL, -1 }
-};
-
-static int
-redir_special_open (spec, filename, flags, mode, ri)
-     int spec;
-     char *filename;
-     int flags, mode;
-     enum r_instruction ri;
-{
-  int fd;
-#if !defined (HAVE_DEV_FD)
-  intmax_t lfd;
-#endif
-
-  fd = -1;
-  switch (spec)
-    {
-#if !defined (HAVE_DEV_FD)
-    case RF_DEVFD:
-      if (all_digits (filename+8) && legal_number (filename+8, &lfd) && lfd == (int)lfd)
-       {
-         fd = lfd;
-         fd = fcntl (fd, F_DUPFD, SHELL_FD_BASE);
-       }
-      else
-       fd = AMBIGUOUS_REDIRECT;
-      break;
-#endif
-
-#if !defined (HAVE_DEV_STDIN)
-    case RF_DEVSTDIN:
-      fd = fcntl (0, F_DUPFD, SHELL_FD_BASE);
-      break;
-    case RF_DEVSTDOUT:
-      fd = fcntl (1, F_DUPFD, SHELL_FD_BASE);
-      break;
-    case RF_DEVSTDERR:
-      fd = fcntl (2, F_DUPFD, SHELL_FD_BASE);
-      break;
-#endif
-
-#if defined (NETWORK_REDIRECTIONS)
-    case RF_DEVTCP:
-    case RF_DEVUDP:
-#if defined (HAVE_NETWORK)
-      fd = netopen (filename);
-#else
-      internal_warning (_("/dev/(tcp|udp)/host/port not supported without networking"));
-      fd = open (filename, flags, mode);
-#endif
-      break;
-#endif /* NETWORK_REDIRECTIONS */
-    }
-
-  return fd;
-}
-      
-/* Open FILENAME with FLAGS in noclobber mode, hopefully avoiding most
-   race conditions and avoiding the problem where the file is replaced
-   between the stat(2) and open(2). */
-static int
-noclobber_open (filename, flags, mode, ri)
-     char *filename;
-     int flags, mode;
-     enum r_instruction ri;
-{
-  int r, fd;
-  struct stat finfo, finfo2;
-
-  /* If the file exists and is a regular file, return an error
-     immediately. */
-  r = stat (filename, &finfo);
-  if (r == 0 && (S_ISREG (finfo.st_mode)))
-    return (NOCLOBBER_REDIRECT);
-
-  /* If the file was not present (r != 0), make sure we open it
-     exclusively so that if it is created before we open it, our open
-     will fail.  Make sure that we do not truncate an existing file.
-     Note that we don't turn on O_EXCL unless the stat failed -- if
-     the file was not a regular file, we leave O_EXCL off. */
-  flags &= ~O_TRUNC;
-  if (r != 0)
-    {
-      fd = open (filename, flags|O_EXCL, mode);
-      return ((fd < 0 && errno == EEXIST) ? NOCLOBBER_REDIRECT : fd);
-    }
-  fd = open (filename, flags, mode);
-
-  /* If the open failed, return the file descriptor right away. */
-  if (fd < 0)
-    return (errno == EEXIST ? NOCLOBBER_REDIRECT : fd);
-
-  /* OK, the open succeeded, but the file may have been changed from a
-     non-regular file to a regular file between the stat and the open.
-     We are assuming that the O_EXCL open handles the case where FILENAME
-     did not exist and is symlinked to an existing file between the stat
-     and open. */
-
-  /* If we can open it and fstat the file descriptor, and neither check
-     revealed that it was a regular file, and the file has not been replaced,
-     return the file descriptor. */
-  if ((fstat (fd, &finfo2) == 0) && (S_ISREG (finfo2.st_mode) == 0) &&
-      r == 0 && (S_ISREG (finfo.st_mode) == 0) &&
-      same_file (filename, filename, &finfo, &finfo2))
-    return fd;
-
-  /* The file has been replaced.  badness. */
-  close (fd);  
-  errno = EEXIST;
-  return (NOCLOBBER_REDIRECT);
-}
-
-static int
-redir_open (filename, flags, mode, ri)
-     char *filename;
-     int flags, mode;
-     enum r_instruction ri;
-{
-  int fd, r;
-
-  r = find_string_in_alist (filename, _redir_special_filenames, 1);
-  if (r >= 0)
-    return (redir_special_open (r, filename, flags, mode, ri));
-
-  /* If we are in noclobber mode, you are not allowed to overwrite
-     existing files.  Check before opening. */
-  if (noclobber && CLOBBERING_REDIRECT (ri))
-    {
-      fd = noclobber_open (filename, flags, mode, ri);
-      if (fd == NOCLOBBER_REDIRECT)
-       return (NOCLOBBER_REDIRECT);
-    }
-  else
-    {
-      fd = open (filename, flags, mode);
-#if defined (AFS)
-      if ((fd < 0) && (errno == EACCES))
-       {
-         fd = open (filename, flags & ~O_CREAT, mode);
-         errno = EACCES;       /* restore errno */
-       }
-#endif /* AFS */
-    }
-
-  return fd;
-}
-
-static int
-undoablefd (fd)
-     int fd;
-{
-  int clexec;
-
-  clexec = fcntl (fd, F_GETFD, 0);
-  if (clexec == -1 || (fd >= SHELL_FD_BASE && clexec == 1))
-    return 0;
-  return 1;
-}
-
-/* Do the specific redirection requested.  Returns errno or one of the
-   special redirection errors (*_REDIRECT) in case of error, 0 on success.
-   If flags & RX_ACTIVE is zero, then just do whatever is neccessary to
-   produce the appropriate side effects.   flags & RX_UNDOABLE, if non-zero,
-   says to remember how to undo each redirection.  If flags & RX_CLEXEC is
-   non-zero, then we set all file descriptors > 2 that we open to be
-   close-on-exec.  */
-static int
-do_redirection_internal (redirect, flags)
-     REDIRECT *redirect;
-     int flags;
-{
-  WORD_DESC *redirectee;
-  int redir_fd, fd, redirector, r, oflags;
-  intmax_t lfd;
-  char *redirectee_word;
-  enum r_instruction ri;
-  REDIRECT *new_redirect;
-  REDIRECTEE sd;
-
-  redirectee = redirect->redirectee.filename;
-  redir_fd = redirect->redirectee.dest;
-  redirector = redirect->redirector.dest;
-  ri = redirect->instruction;
-
-  if (redirect->flags & RX_INTERNAL)
-    flags |= RX_INTERNAL;
-
-  if (TRANSLATE_REDIRECT (ri))
-    {
-      /* We have [N]>&WORD[-] or [N]<&WORD[-] (or {V}>&WORD[-] or {V}<&WORD-).
-         and WORD, then translate the redirection into a new one and 
-        continue. */
-      redirectee_word = redirection_expand (redirectee);
-
-      /* XXX - what to do with [N]<&$w- where w is unset or null?  ksh93
-              closes N. */
-      if (redirectee_word == 0)
-       return (AMBIGUOUS_REDIRECT);
-      else if (redirectee_word[0] == '-' && redirectee_word[1] == '\0')
-       {
-         sd = redirect->redirector;
-         rd.dest = 0;
-         new_redirect = make_redirection (sd, r_close_this, rd, 0);
-       }
-      else if (all_digits (redirectee_word))
-       {
-         sd = redirect->redirector;
-         if (legal_number (redirectee_word, &lfd) && (int)lfd == lfd)
-           rd.dest = lfd;
-         else
-           rd.dest = -1;       /* XXX */
-         switch (ri)
-           {
-           case r_duplicating_input_word:
-             new_redirect = make_redirection (sd, r_duplicating_input, rd, 0);
-             break;
-           case r_duplicating_output_word:
-             new_redirect = make_redirection (sd, r_duplicating_output, rd, 0);
-             break;
-           case r_move_input_word:
-             new_redirect = make_redirection (sd, r_move_input, rd, 0);
-             break;
-           case r_move_output_word:
-             new_redirect = make_redirection (sd, r_move_output, rd, 0);
-             break;
-           }
-       }
-      else if (ri == r_duplicating_output_word && (redirect->rflags & REDIR_VARASSIGN) == 0 && redirector == 1)
-       {
-         sd = redirect->redirector;
-         rd.filename = make_bare_word (redirectee_word);
-         new_redirect = make_redirection (sd, r_err_and_out, rd, 0);
-       }
-      else
-       {
-         free (redirectee_word);
-         return (AMBIGUOUS_REDIRECT);
-       }
-
-      free (redirectee_word);
-
-      /* Set up the variables needed by the rest of the function from the
-        new redirection. */
-      if (new_redirect->instruction == r_err_and_out)
-       {
-         char *alloca_hack;
-
-         /* Copy the word without allocating any memory that must be
-            explicitly freed. */
-         redirectee = (WORD_DESC *)alloca (sizeof (WORD_DESC));
-         xbcopy ((char *)new_redirect->redirectee.filename,
-                (char *)redirectee, sizeof (WORD_DESC));
-
-         alloca_hack = (char *)
-           alloca (1 + strlen (new_redirect->redirectee.filename->word));
-         redirectee->word = alloca_hack;
-         strcpy (redirectee->word, new_redirect->redirectee.filename->word);
-       }
-      else
-       /* It's guaranteed to be an integer, and shouldn't be freed. */
-       redirectee = new_redirect->redirectee.filename;
-
-      redir_fd = new_redirect->redirectee.dest;
-      redirector = new_redirect->redirector.dest;
-      ri = new_redirect->instruction;
-
-      /* Overwrite the flags element of the old redirect with the new value. */
-      redirect->flags = new_redirect->flags;
-      dispose_redirects (new_redirect);
-    }
-
-  switch (ri)
-    {
-    case r_output_direction:
-    case r_appending_to:
-    case r_input_direction:
-    case r_inputa_direction:
-    case r_err_and_out:                /* command &>filename */
-    case r_append_err_and_out: /* command &>> filename */
-    case r_input_output:
-    case r_output_force:
-      if (posixly_correct && interactive_shell == 0)
-       {
-         oflags = redirectee->flags;
-         redirectee->flags |= W_NOGLOB;
-       }
-      redirectee_word = redirection_expand (redirectee);
-      if (posixly_correct && interactive_shell == 0)
-       redirectee->flags = oflags;
-
-      if (redirectee_word == 0)
-       return (AMBIGUOUS_REDIRECT);
-
-#if defined (RESTRICTED_SHELL)
-      if (restricted && (WRITE_REDIRECT (ri)))
-       {
-         free (redirectee_word);
-         return (RESTRICTED_REDIRECT);
-       }
-#endif /* RESTRICTED_SHELL */
-
-      fd = redir_open (redirectee_word, redirect->flags, 0666, ri);
-      free (redirectee_word);
-
-      if (fd == NOCLOBBER_REDIRECT)
-       return (fd);
-
-      if (fd < 0)
-       return (errno);
-
-      if (flags & RX_ACTIVE)
-       {
-         if (redirect->rflags & REDIR_VARASSIGN)
-           {
-             redirector = fcntl (fd, F_DUPFD, SHELL_FD_BASE);          /* XXX try this for now */
-             r = errno;
-             if (redirector < 0)
-               sys_error (_("redirection error: cannot duplicate fd"));
-             REDIRECTION_ERROR (redirector, r, fd);
-           }
-
-         if ((flags & RX_UNDOABLE) && (redirect->rflags & REDIR_VARASSIGN) == 0)
-           {
-             /* Only setup to undo it if the thing to undo is active. */
-             if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1))
-               r = add_undo_redirect (redirector, ri, -1);
-             else
-               r = add_undo_close_redirect (redirector);
-             REDIRECTION_ERROR (r, errno, fd);
-           }
-
-#if defined (BUFFERED_INPUT)
-         check_bash_input (redirector);
-#endif
-
-         /* Make sure there is no pending output before we change the state
-            of the underlying file descriptor, since the builtins use stdio
-            for output. */
-         if (redirector == 1 && fileno (stdout) == redirector)
-           {
-             fflush (stdout);
-             fpurge (stdout);
-           }
-         else if (redirector == 2 && fileno (stderr) == redirector)
-           {
-             fflush (stderr);
-             fpurge (stderr);
-           }
-
-         if (redirect->rflags & REDIR_VARASSIGN)
-           {
-             if ((r = redir_varassign (redirect, redirector)) < 0)
-               {
-                 close (redirector);
-                 close (fd);
-                 return (r);   /* XXX */
-               }
-           }
-         else if ((fd != redirector) && (dup2 (fd, redirector) < 0))
-           return (errno);
-
-#if defined (BUFFERED_INPUT)
-         /* Do not change the buffered stream for an implicit redirection
-            of /dev/null to fd 0 for asynchronous commands without job
-            control (r_inputa_direction). */
-         if (ri == r_input_direction || ri == r_input_output)
-           duplicate_buffered_stream (fd, redirector);
-#endif /* BUFFERED_INPUT */
-
-         /*
-          * If we're remembering, then this is the result of a while, for
-          * or until loop with a loop redirection, or a function/builtin
-          * executing in the parent shell with a redirection.  In the
-          * function/builtin case, we want to set all file descriptors > 2
-          * to be close-on-exec to duplicate the effect of the old
-          * for i = 3 to NOFILE close(i) loop.  In the case of the loops,
-          * both sh and ksh leave the file descriptors open across execs.
-          * The Posix standard mentions only the exec builtin.
-          */
-         if ((flags & RX_CLEXEC) && (redirector > 2))
-           SET_CLOSE_ON_EXEC (redirector);
-       }
-
-      if (fd != redirector)
-       {
-#if defined (BUFFERED_INPUT)
-         if (INPUT_REDIRECT (ri))
-           close_buffered_fd (fd);
-         else
-#endif /* !BUFFERED_INPUT */
-           close (fd);         /* Don't close what we just opened! */
-       }
-
-      /* If we are hacking both stdout and stderr, do the stderr
-        redirection here.  XXX - handle {var} here? */
-      if (ri == r_err_and_out || ri == r_append_err_and_out)
-       {
-         if (flags & RX_ACTIVE)
-           {
-             if (flags & RX_UNDOABLE)
-               add_undo_redirect (2, ri, -1);
-             if (dup2 (1, 2) < 0)
-               return (errno);
-           }
-       }
-      break;
-
-    case r_reading_until:
-    case r_deblank_reading_until:
-    case r_reading_string:
-      /* REDIRECTEE is a pointer to a WORD_DESC containing the text of
-        the new input.  Place it in a temporary file. */
-      if (redirectee)
-       {
-         fd = here_document_to_fd (redirectee, ri);
-
-         if (fd < 0)
-           {
-             heredoc_errno = errno;
-             return (HEREDOC_REDIRECT);
-           }
-
-         if (redirect->rflags & REDIR_VARASSIGN)
-           {
-             redirector = fcntl (fd, F_DUPFD, SHELL_FD_BASE);          /* XXX try this for now */
-             r = errno;
-             if (redirector < 0)
-               sys_error (_("redirection error: cannot duplicate fd"));
-             REDIRECTION_ERROR (redirector, r, fd);
-           }
-
-         if (flags & RX_ACTIVE)
-           {
-             if ((flags & RX_UNDOABLE) && (redirect->rflags & REDIR_VARASSIGN) == 0)
-               {
-                 /* Only setup to undo it if the thing to undo is active. */
-                 if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1))
-                   r = add_undo_redirect (redirector, ri, -1);
-                 else
-                   r = add_undo_close_redirect (redirector);
-                 REDIRECTION_ERROR (r, errno, fd);
-               }
-
-#if defined (BUFFERED_INPUT)
-             check_bash_input (redirector);
-#endif
-             if (redirect->rflags & REDIR_VARASSIGN)
-               {
-                 if ((r = redir_varassign (redirect, redirector)) < 0)
-                   {
-                     close (redirector);
-                     close (fd);
-                     return (r);       /* XXX */
-                   }
-               }
-             else if (fd != redirector && dup2 (fd, redirector) < 0)
-               {
-                 r = errno;
-                 close (fd);
-                 return (r);
-               }
-
-#if defined (BUFFERED_INPUT)
-             duplicate_buffered_stream (fd, redirector);
-#endif
-
-             if ((flags & RX_CLEXEC) && (redirector > 2))
-               SET_CLOSE_ON_EXEC (redirector);
-           }
-
-         if (fd != redirector)
-#if defined (BUFFERED_INPUT)
-           close_buffered_fd (fd);
-#else
-           close (fd);
-#endif
-       }
-      break;
-
-    case r_duplicating_input:
-    case r_duplicating_output:
-    case r_move_input:
-    case r_move_output:
-      if ((flags & RX_ACTIVE) && (redirect->rflags & REDIR_VARASSIGN))
-        {
-         redirector = fcntl (redir_fd, F_DUPFD, SHELL_FD_BASE);                /* XXX try this for now */
-         r = errno;
-         if (redirector < 0)
-           sys_error (_("redirection error: cannot duplicate fd"));
-         REDIRECTION_ERROR (redirector, r, -1);
-        }
-
-      if ((flags & RX_ACTIVE) && (redir_fd != redirector))
-       {
-         if ((flags & RX_UNDOABLE) && (redirect->rflags & REDIR_VARASSIGN) == 0)
-           {
-             /* Only setup to undo it if the thing to undo is active. */
-             if (fcntl (redirector, F_GETFD, 0) != -1)
-               r = add_undo_redirect (redirector, ri, redir_fd);
-             else
-               r = add_undo_close_redirect (redirector);
-             REDIRECTION_ERROR (r, errno, -1);
-           }
-#if defined (BUFFERED_INPUT)
-         check_bash_input (redirector);
-#endif
-         if (redirect->rflags & REDIR_VARASSIGN)
-           {
-             if ((r = redir_varassign (redirect, redirector)) < 0)
-               {
-                 close (redirector);
-                 return (r);   /* XXX */
-               }
-           }
-         /* This is correct.  2>&1 means dup2 (1, 2); */
-         else if (dup2 (redir_fd, redirector) < 0)
-           return (errno);
-
-#if defined (BUFFERED_INPUT)
-         if (ri == r_duplicating_input || ri == r_move_input)
-           duplicate_buffered_stream (redir_fd, redirector);
-#endif /* BUFFERED_INPUT */
-
-         /* First duplicate the close-on-exec state of redirectee.  dup2
-            leaves the flag unset on the new descriptor, which means it
-            stays open.  Only set the close-on-exec bit for file descriptors
-            greater than 2 in any case, since 0-2 should always be open
-            unless closed by something like `exec 2<&-'.  It should always
-            be safe to set fds > 2 to close-on-exec if they're being used to
-            save file descriptors < 2, since we don't need to preserve the
-            state of the close-on-exec flag for those fds -- they should
-            always be open. */
-         /* if ((already_set || set_unconditionally) && (ok_to_set))
-               set_it () */
-#if 0
-         if (((fcntl (redir_fd, F_GETFD, 0) == 1) || redir_fd < 2 || (flags & RX_CLEXEC)) &&
-              (redirector > 2))
-#else
-         if (((fcntl (redir_fd, F_GETFD, 0) == 1) || (redir_fd < 2 && (flags & RX_INTERNAL)) || (flags & RX_CLEXEC)) &&
-              (redirector > 2))
-#endif
-           SET_CLOSE_ON_EXEC (redirector);
-
-         /* When undoing saving of non-standard file descriptors (>=3) using
-            file descriptors >= SHELL_FD_BASE, we set the saving fd to be
-            close-on-exec and use a flag to decide how to set close-on-exec
-            when the fd is restored. */
-         if ((redirect->flags & RX_INTERNAL) && (redirect->flags & RX_SAVCLEXEC) && redirector >= 3 && (redir_fd >= SHELL_FD_BASE || (redirect->flags & RX_SAVEFD)))
-           SET_OPEN_ON_EXEC (redirector);
-           
-         /* dup-and-close redirection */
-         if (ri == r_move_input || ri == r_move_output)
-           {
-             xtrace_fdchk (redir_fd);
-
-             close (redir_fd);
-#if defined (COPROCESS_SUPPORT)
-             coproc_fdchk (redir_fd);  /* XXX - loses coproc fds */
-#endif
-           }
-       }
-      break;
-
-    case r_close_this:
-      if (flags & RX_ACTIVE)
-       {
-         if (redirect->rflags & REDIR_VARASSIGN)
-           {
-             redirector = redir_varvalue (redirect);
-             if (redirector < 0)
-               return AMBIGUOUS_REDIRECT;
-           }
-
-         r = 0;
-         /* XXX - only if REDIR_VARASSIGN not set? */
-         if ((flags & RX_UNDOABLE) && (fcntl (redirector, F_GETFD, 0) != -1))
-           {
-             r = add_undo_redirect (redirector, ri, -1);
-             REDIRECTION_ERROR (r, errno, redirector);
-           }
-
-#if defined (COPROCESS_SUPPORT)
-         coproc_fdchk (redirector);
-#endif
-         xtrace_fdchk (redirector);
-
-#if defined (BUFFERED_INPUT)
-         check_bash_input (redirector);
-         r = close_buffered_fd (redirector);
-#else /* !BUFFERED_INPUT */
-         r = close (redirector);
-#endif /* !BUFFERED_INPUT */
-#if 0  /* bash-4.3 */
-         if (r < 0 && (flags & RX_INTERNAL) && (errno == EIO || errno == ENOSPC))
-           REDIRECTION_ERROR (r, errno, -1);
-#endif
-       }
-      break;
-
-    case r_duplicating_input_word:
-    case r_duplicating_output_word:
-      break;
-    }
-  return (0);
-}
-
-/* Remember the file descriptor associated with the slot FD,
-   on REDIRECTION_UNDO_LIST.  Note that the list will be reversed
-   before it is executed.  Any redirections that need to be undone
-   even if REDIRECTION_UNDO_LIST is discarded by the exec builtin
-   are also saved on EXEC_REDIRECTION_UNDO_LIST.  FDBASE says where to
-   start the duplicating.  If it's less than SHELL_FD_BASE, we're ok,
-   and can use SHELL_FD_BASE (-1 == don't care).  If it's >= SHELL_FD_BASE,
-   we have to make sure we don't use fdbase to save a file descriptor,
-   since we're going to use it later (e.g., make sure we don't save fd 0
-   to fd 10 if we have a redirection like 0<&10).  If the value of fdbase
-   puts the process over its fd limit, causing fcntl to fail, we try
-   again with SHELL_FD_BASE.  Return 0 on success, -1 on error. */
-static int
-add_undo_redirect (fd, ri, fdbase)
-     int fd;
-     enum r_instruction ri;
-     int fdbase;
-{
-  int new_fd, clexec_flag, savefd_flag;
-  REDIRECT *new_redirect, *closer, *dummy_redirect;
-  REDIRECTEE sd;
-
-  savefd_flag = 0;
-  new_fd = fcntl (fd, F_DUPFD, (fdbase < SHELL_FD_BASE) ? SHELL_FD_BASE : fdbase+1);
-  if (new_fd < 0)
-    new_fd = fcntl (fd, F_DUPFD, SHELL_FD_BASE);
-  if (new_fd < 0)
-    {
-      new_fd = fcntl (fd, F_DUPFD, 0);
-      savefd_flag = 1;
-    }
-
-  if (new_fd < 0)
-    {
-      sys_error (_("redirection error: cannot duplicate fd"));
-      return (-1);
-    }
-
-  clexec_flag = fcntl (fd, F_GETFD, 0);
-
-  sd.dest = new_fd;
-  rd.dest = 0;
-  closer = make_redirection (sd, r_close_this, rd, 0);
-  closer->flags |= RX_INTERNAL;
-  dummy_redirect = copy_redirects (closer);
-
-  sd.dest = fd;
-  rd.dest = new_fd;
-  if (fd == 0)
-    new_redirect = make_redirection (sd, r_duplicating_input, rd, 0);
-  else
-    new_redirect = make_redirection (sd, r_duplicating_output, rd, 0);
-  new_redirect->flags |= RX_INTERNAL;
-  if (savefd_flag)
-    new_redirect->flags |= RX_SAVEFD;
-  if (clexec_flag == 0 && fd >= 3 && (new_fd >= SHELL_FD_BASE || savefd_flag))
-    new_redirect->flags |= RX_SAVCLEXEC;
-  new_redirect->next = closer;
-
-  closer->next = redirection_undo_list;
-  redirection_undo_list = new_redirect;
-
-  /* Save redirections that need to be undone even if the undo list
-     is thrown away by the `exec' builtin. */
-  add_exec_redirect (dummy_redirect);
-
-  /* experimental:  if we're saving a redirection to undo for a file descriptor
-     above SHELL_FD_BASE, add a redirection to be undone if the exec builtin
-     causes redirections to be discarded.  There needs to be a difference
-     between fds that are used to save other fds and then are the target of
-     user redirections and fds that are just the target of user redirections.
-     We use the close-on-exec flag to tell the difference; fds > SHELL_FD_BASE
-     that have the close-on-exec flag set are assumed to be fds used internally
-     to save others. */
-  if (fd >= SHELL_FD_BASE && ri != r_close_this && clexec_flag)
-    {
-      sd.dest = fd;
-      rd.dest = new_fd;
-      new_redirect = make_redirection (sd, r_duplicating_output, rd, 0);
-      new_redirect->flags |= RX_INTERNAL;
-
-      add_exec_redirect (new_redirect);
-    }
-
-  /* File descriptors used only for saving others should always be
-     marked close-on-exec.  Unfortunately, we have to preserve the
-     close-on-exec state of the file descriptor we are saving, since
-     fcntl (F_DUPFD) sets the new file descriptor to remain open
-     across execs.  If, however, the file descriptor whose state we
-     are saving is <= 2, we can just set the close-on-exec flag,
-     because file descriptors 0-2 should always be open-on-exec,
-     and the restore above in do_redirection() will take care of it. */
-  if (clexec_flag || fd < 3)
-    SET_CLOSE_ON_EXEC (new_fd);
-  else if (redirection_undo_list->flags & RX_SAVCLEXEC)
-    SET_CLOSE_ON_EXEC (new_fd);
-
-  return (0);
-}
-
-/* Set up to close FD when we are finished with the current command
-   and its redirections.  Return 0 on success, -1 on error. */
-static int
-add_undo_close_redirect (fd)
-     int fd;
-{
-  REDIRECT *closer;
-  REDIRECTEE sd;
-
-  sd.dest = fd;
-  rd.dest = 0;
-  closer = make_redirection (sd, r_close_this, rd, 0);
-  closer->flags |= RX_INTERNAL;
-  closer->next = redirection_undo_list;
-  redirection_undo_list = closer;
-
-  return 0;
-}
-
-static void
-add_exec_redirect (dummy_redirect)
-     REDIRECT *dummy_redirect;
-{
-  dummy_redirect->next = exec_redirection_undo_list;
-  exec_redirection_undo_list = dummy_redirect;
-}
-
-/* Return 1 if the redirection specified by RI and REDIRECTOR alters the
-   standard input. */
-static int
-stdin_redirection (ri, redirector)
-     enum r_instruction ri;
-     int redirector;
-{
-  switch (ri)
-    {
-    case r_input_direction:
-    case r_inputa_direction:
-    case r_input_output:
-    case r_reading_until:
-    case r_deblank_reading_until:
-    case r_reading_string:
-      return (1);
-    case r_duplicating_input:
-    case r_duplicating_input_word:
-    case r_close_this:
-      return (redirector == 0);
-    case r_output_direction:
-    case r_appending_to:
-    case r_duplicating_output:
-    case r_err_and_out:
-    case r_append_err_and_out:
-    case r_output_force:
-    case r_duplicating_output_word:
-      return (0);
-    }
-  return (0);
-}
-
-/* Return non-zero if any of the redirections in REDIRS alter the standard
-   input. */
-int
-stdin_redirects (redirs)
-     REDIRECT *redirs;
-{
-  REDIRECT *rp;
-  int n;
-
-  for (n = 0, rp = redirs; rp; rp = rp->next)
-    if ((rp->rflags & REDIR_VARASSIGN) == 0)
-      n += stdin_redirection (rp->instruction, rp->redirector.dest);
-  return n;
-}
-/* bind_var_to_int handles array references */
-static int
-redir_varassign (redir, fd)
-     REDIRECT *redir;
-     int fd;
-{
-  WORD_DESC *w;
-  SHELL_VAR *v;
-
-  w = redir->redirector.filename;
-  v = bind_var_to_int (w->word, fd);
-  if (v == 0 || readonly_p (v) || noassign_p (v))
-    return BADVAR_REDIRECT;
-
-  stupidly_hack_special_variables (w->word);
-  return 0;
-}
-
-/* Handles {array[ind]} for redirection words */
-static int
-redir_varvalue (redir)
-     REDIRECT *redir;
-{
-  SHELL_VAR *v;
-  char *val, *w;
-  intmax_t vmax;
-  int i;
-#if defined (ARRAY_VARS)
-  char *sub;
-  int len, vr;
-#endif
-
-  w = redir->redirector.filename->word;                /* shorthand */
-  /* XXX - handle set -u here? */
-#if defined (ARRAY_VARS)
-  if (vr = valid_array_reference (w))
-    v = array_variable_part (w, &sub, &len);
-  else
-#endif
-  v = find_variable (w);
-  if (v == 0 || invisible_p (v))
-    return -1;
-
-#if defined (ARRAY_VARS)
-  /* get_variable_value handles references to array variables without
-     subscripts */
-  if (vr && (array_p (v) || assoc_p (v)))
-    val = get_array_value (w, 0, (int *)NULL, (arrayind_t *)0);
-  else
-#endif
-  val = get_variable_value (v);
-  if (val == 0 || *val == 0)
-    return -1;
-
-  if (legal_number (val, &vmax) < 0)
-    return -1;
-
-  i = vmax;    /* integer truncation */
-  return i;
-}
diff --git a/sig.c~ b/sig.c~
deleted file mode 100644 (file)
index 0e7c7c7..0000000
--- a/sig.c~
+++ /dev/null
@@ -1,700 +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;
-
-/* 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);
-      set_signal_handler (SIGTERM, SIG_IGN);
-      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 should not be necessary on systems using sigsetjmp/siglongjmp. */
-  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 0
-#if defined (HISTORY)
-  if (interactive_shell && (sig != SIGABRT && sig != SIGINT && sig != SIGHUP && sig != SIGTERM))
-    maybe_save_shell_history ();
-#endif /* HISTORY */
-#endif
-
-#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)
-  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
-}
-
-/* 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
-
-  sigemptyset (&act.sa_mask);
-  sigemptyset (&oact.sa_mask);
-  sigaction (sig, &act, &oact);
-  return (oact.sa_handler);
-}
-#endif /* HAVE_POSIX_SIGNALS */
diff --git a/subst.c.save b/subst.c.save
deleted file mode 100644 (file)
index 1a7e79d..0000000
+++ /dev/null
@@ -1,9546 +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-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/>.
-*/
-
-#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];
-
-#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_GLOBEXP)
-    {
-      f &= ~W_GLOBEXP;
-      fprintf (stderr, "W_GLOBEXP%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);
-      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 && array_p (v) == 0)
-       v = convert_var_to_array (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;
-#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));
-       }
-      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[*]? */
-      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;
-
-#if 0
-  if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
-    ret = string_list_dollar_star (quote_list (save));
-  else if ((mflags & MATCH_STARSUB) == MATCH_STARSUB)
-    ret = string_list_dollar_star (save);
-  else if ((mflags & MATCH_QUOTED) == MATCH_QUOTED)
-    ret = string_list_dollar_at (save, qflags);
-  else
-    ret = string_list_dollar_star (save);
-#else
-  ret = string_list_pos_params (pchar, save, qflags);
-#endif
-
-  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), &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 (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 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;
-  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;
-
-         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 0
-         if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
-#else
-         if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
-#endif
-           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)
-               {
-#if 0
-                 if (quoted_dollar_at && (word->flags & W_NOSPLIT2))
-                   temp = string_list_internal (quote_list (list), " ");
-                 else
-#endif
-                 /* 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 0
-         if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
-#else
-         if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
-#endif
-           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 (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";
-
-  /* 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]);
-             tword->flags |= W_GLOBEXP;        /* XXX */
-             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");
-         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;
-    }
-
-#if 0
-  tint = list_length (new_list) + 1;
-  RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
-  for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
-    glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
-  glob_argv_flags[tint] = '\0';
-#endif
-
-  return (new_list);
-}
diff --git a/subst.c~ b/subst.c~
deleted file mode 100644 (file)
index 1708b78..0000000
--- a/subst.c~
+++ /dev/null
@@ -1,9530 +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-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/>.
-*/
-
-#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);
-      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 && array_p (v) == 0)
-       v = convert_var_to_array (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;
-#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));
-       }
-      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[*]? */
-      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), &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 (ifs_is_set == 0 || ifs_is_null)
-{
-itrace("param_expand: set W_SPLITSPACE flag");
-               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->flags & W_SPLITSPACE)
- itrace("expand_word_internal: param_expand return word has 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 (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");
-         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/RUN-ONE-TEST~ b/tests/RUN-ONE-TEST~
deleted file mode 100755 (executable)
index 3efcf32..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-BUILD_DIR=/usr/local/build/chet/bash/bash-current
-THIS_SH=$BUILD_DIR/bash
-PATH=$PATH:$BUILD_DIR
-
-export THIS_SH PATH
-
-rm -f /tmp/xx
-
-/bin/sh "$@"
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 866f228..0000000
--- a/trap.c~
+++ /dev/null
@@ -1,1201 +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 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_and_traps ()
-{
-  QUIT;
-  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]);
-itrace("restore_signal_handler: setting signal for %d to 0x%x", 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)
-{          
-itrace("trap_list[%d] == IGNORE_SIG", i);
-           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/variables.c~ b/variables.c~
deleted file mode 100644 (file)
index 1f05f00..0000000
+++ /dev/null
@@ -1,5232 +0,0 @@
-/* variables.c -- Functions for hacking shell variables. */
-
-/* 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/>.
-*/
-
-#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);
-
-         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
-           {
-             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);
-      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'. */
-      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 0
-  if (ifsname (name))
-    setifs (var);
-else
-#endif
-  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