]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
Imported from ../bash-2.05b.tar.gz. devel-base-dist
authorJari Aalto <jari.aalto@cante.net>
Wed, 17 Jul 2002 14:10:11 +0000 (14:10 +0000)
committerJari Aalto <jari.aalto@cante.net>
Sat, 12 Sep 2009 16:46:55 +0000 (16:46 +0000)
362 files changed:
AUTHORS
CHANGES
COMPAT
CWRU/changelog
CWRU/misc/bison
CWRU/misc/errlist.c
CWRU/misc/hpux10-dlfcn.h
CWRU/misc/open-files.c
CWRU/misc/pid.c [deleted file]
CWRU/misc/sigs.c
CWRU/misc/sigstat.c
INSTALL
MANIFEST
Makefile.in
NEWS
NOTES
POSIX [moved from CWRU/POSIX.NOTES with 91% similarity]
RBASH [new file with mode: 0644]
README
aclocal.m4
alias.c
array.c
array.h
arrayfunc.c
arrayfunc.h
bashhist.c
bashhist.h
bashline.c
bashline.h
bashtypes.h
bracecomp.c
braces.c
builtins.h
builtins/Makefile.in
builtins/alias.def
builtins/bashgetopt.c
builtins/bashgetopt.h
builtins/bind.def
builtins/break.def
builtins/builtin.def
builtins/cd.def
builtins/colon.def
builtins/command.def
builtins/common.c
builtins/common.h
builtins/complete.def
builtins/declare.def
builtins/echo.def
builtins/enable.def
builtins/eval.def
builtins/evalfile.c
builtins/evalstring.c
builtins/exec.def
builtins/exit.def
builtins/fc.def
builtins/fg_bg.def
builtins/getopt.c
builtins/getopts.def
builtins/hash.def
builtins/help.def
builtins/history.def
builtins/inlib.def
builtins/jobs.def
builtins/kill.def
builtins/let.def
builtins/mkbuiltins.c
builtins/printf.def
builtins/pushd.def
builtins/read.def
builtins/reserved.def
builtins/return.def
builtins/set.def
builtins/setattr.def
builtins/shift.def
builtins/shopt.def
builtins/source.def
builtins/suspend.def
builtins/test.def
builtins/times.def
builtins/trap.def
builtins/type.def
builtins/ulimit.def
builtins/umask.def
builtins/wait.def
command.h
config-bot.h
config-top.h
config.h.in
configure
configure.in
copy_cmd.c
dispose_cmd.c
doc/FAQ
doc/Makefile.in
doc/bash.1
doc/bashref.info
doc/bashref.texi
doc/builtins.1
error.c
error.h
eval.c
examples/bashdb/bashdb [changed mode: 0644->0755]
examples/bashdb/bashdb.el [new file with mode: 0644]
examples/complete/complete-examples
examples/functions/inetaddr
examples/functions/isvalidip [new file with mode: 0644]
examples/functions/manpage
examples/functions/mhfold
examples/loadables/Makefile.in
examples/loadables/finfo.c
examples/loadables/getconf.c
examples/loadables/print.c
examples/obashdb/PERMISSION [new file with mode: 0644]
examples/obashdb/README [moved from examples/bashdb/README with 100% similarity]
examples/obashdb/bashdb [new file with mode: 0644]
examples/obashdb/bashdb.fns [moved from examples/bashdb/bashdb.fns with 100% similarity]
examples/obashdb/bashdb.pre [moved from examples/bashdb/bashdb.pre with 100% similarity]
examples/scripts.v2/pmtop
examples/scripts.v2/ren [new file with mode: 0644]
examples/scripts/bcsh.sh
examples/scripts/self-repro [new file with mode: 0644]
examples/scripts/vtree2
examples/startup-files/apple/aliases
execute_cmd.c
expr.c
externs.h
findcmd.c
flags.c
flags.h
general.c
general.h
hashcmd.c
hashcmd.h
hashlib.c
hashlib.h
include/chartypes.h
include/ocache.h [new file with mode: 0644]
include/posixdir.h
include/shmbutil.h [new file with mode: 0644]
include/stdc.h
input.h
jobs.c
jobs.h
lib/glob/Makefile.in
lib/glob/collsyms.h
lib/glob/glob.c
lib/glob/glob.h
lib/glob/glob_loop.c [new file with mode: 0644]
lib/glob/sm_loop.c [new file with mode: 0644]
lib/glob/smatch.c [new file with mode: 0644]
lib/glob/strmatch.c
lib/glob/xmbsrtowcs.c [new file with mode: 0644]
lib/malloc/Makefile.in
lib/malloc/imalloc.h
lib/malloc/malloc.c
lib/malloc/mstats.h
lib/malloc/shmalloc.h
lib/malloc/stats.c
lib/malloc/stub.c
lib/malloc/table.c
lib/malloc/table.h
lib/malloc/trace.c
lib/malloc/watch.c [new file with mode: 0644]
lib/malloc/watch.h [new file with mode: 0644]
lib/readline/Makefile.in
lib/readline/bind.c
lib/readline/chardefs.h
lib/readline/complete.c
lib/readline/display.c
lib/readline/doc/Makefile
lib/readline/doc/hist.texinfo
lib/readline/doc/hstech.texinfo
lib/readline/doc/hsuser.texinfo
lib/readline/doc/manvers.texinfo
lib/readline/doc/rlman.texinfo
lib/readline/doc/rltech.texinfo
lib/readline/doc/rluser.texinfo
lib/readline/doc/rluserman.texinfo
lib/readline/emacs_keymap.c
lib/readline/examples/Inputrc
lib/readline/examples/Makefile
lib/readline/examples/fileman.c
lib/readline/examples/histexamp.c
lib/readline/examples/manexamp.c
lib/readline/examples/rl.c
lib/readline/examples/rlcat.c [new file with mode: 0644]
lib/readline/examples/rltest.c
lib/readline/funmap.c
lib/readline/histexpand.c
lib/readline/histfile.c
lib/readline/histlib.h
lib/readline/history.c
lib/readline/histsearch.c
lib/readline/input.c
lib/readline/isearch.c
lib/readline/keymaps.h
lib/readline/kill.c
lib/readline/macro.c
lib/readline/mbutil.c [new file with mode: 0644]
lib/readline/misc.c [new file with mode: 0644]
lib/readline/parens.c
lib/readline/posixdir.h
lib/readline/readline.c
lib/readline/readline.h
lib/readline/rlconf.h
lib/readline/rldefs.h
lib/readline/rlmbutil.h [new file with mode: 0644]
lib/readline/rlprivate.h
lib/readline/rltty.c
lib/readline/search.c
lib/readline/signals.c
lib/readline/terminal.c
lib/readline/text.c [new file with mode: 0644]
lib/readline/tilde.c
lib/readline/tilde.h
lib/readline/undo.c
lib/readline/util.c
lib/readline/vi_keymap.c
lib/readline/vi_mode.c
lib/sh/Makefile.in
lib/sh/clktck.c
lib/sh/fmtullong.c
lib/sh/fmtulong.c
lib/sh/fmtumax.c [new file with mode: 0644]
lib/sh/getenv.c
lib/sh/itos.c
lib/sh/makepath.c
lib/sh/memset.c [new file with mode: 0644]
lib/sh/mktime.c [new file with mode: 0644]
lib/sh/netconn.c [new file with mode: 0644]
lib/sh/netopen.c
lib/sh/oslib.c
lib/sh/pathcanon.c
lib/sh/rename.c
lib/sh/shquote.c
lib/sh/snprintf.c
lib/sh/spell.c
lib/sh/strftime.c [new file with mode: 0644]
lib/sh/stringlist.c
lib/sh/stringvec.c
lib/sh/strtrans.c
lib/sh/tmpfile.c
lib/sh/xstrchr.c [new file with mode: 0644]
lib/sh/zcatfd.c [new file with mode: 0644]
lib/sh/zread.c
lib/sh/zwrite.c
lib/termcap/version.c
lib/tilde/Makefile.in
lib/tilde/tilde.c
lib/tilde/tilde.h
list.c
locale.c
mailcheck.c
make_cmd.c
make_cmd.h
mksyntax.c
nojobs.c
parse.y
parser-built
pathexp.c
pcomplete.c
pcomplete.h
pcomplib.c
print_cmd.c
redir.c
shell.c
shell.h
sig.c
sig.h
stringlib.c
subst.c
subst.h
support/Makefile.in
support/bashbug.sh
support/bashversion.c
support/config.guess
support/config.sub [changed mode: 0755->0644]
support/fixlinks
support/install.sh
support/man2html.c
support/mkclone
support/mkconffiles
support/mkdirs
support/mksignames.c
support/mkversion.sh
support/printenv.c
support/printenv.sh
support/recho.c
support/rlvers.sh
support/shobj-conf
support/xenix-link.sh
support/zecho.c
syntax.h
test.c
tests/arith.right
tests/array.right
tests/array.tests
tests/builtins.right
tests/cond.right
tests/dstack.right
tests/errors.right
tests/exec.right
tests/getopts.right
tests/glob-test
tests/herestr.right [new file with mode: 0644]
tests/herestr.tests [new file with mode: 0644]
tests/histexp.right
tests/history.right
tests/history.tests
tests/ifs-1.right [deleted file]
tests/ifs-1.test [deleted file]
tests/ifs-2.right [deleted file]
tests/ifs-2.test [deleted file]
tests/ifs-3.right [deleted file]
tests/ifs-3.test [deleted file]
tests/ifs.right [new file with mode: 0644]
tests/ifs.tests [new file with mode: 0644]
tests/jobs.right
tests/more-exp.right
tests/more-exp.tests
tests/new-exp.right
tests/new-exp.tests
tests/nquote1.right [new file with mode: 0644]
tests/nquote1.tests [new file with mode: 0644]
tests/nquote2.right [new file with mode: 0644]
tests/nquote2.tests [new file with mode: 0644]
tests/nquote3.right [new file with mode: 0644]
tests/nquote3.tests [new file with mode: 0644]
tests/printf.right
tests/read.right
tests/read.tests
tests/read4.sub [new file with mode: 0644]
tests/redir.right
tests/redir.tests
tests/redir5.sub [new file with mode: 0644]
tests/rsh.right
tests/run-herestr [new file with mode: 0644]
tests/run-ifs [new file with mode: 0644]
tests/run-ifs-tests [deleted file]
tests/run-nquote1 [new file with mode: 0644]
tests/run-nquote2 [new file with mode: 0644]
tests/run-nquote3 [new file with mode: 0644]
tests/run-redir
tests/shopt.right
tests/test.right
tests/trap.right
tests/trap.tests
tests/type.right
tests/type.tests
tests/varenv.right
tests/varenv.sh
tests/varenv2.sub [new file with mode: 0644]
trap.c
unwind_prot.c
unwind_prot.h
variables.c
variables.h
version.c
xmalloc.c
xmalloc.h
y.tab.c
y.tab.h

diff --git a/AUTHORS b/AUTHORS
index eb4a7f0529859895301b64c1802d178b296cc825..656a07de926541329e50ec9f33bf564518a5116c 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -406,3 +406,48 @@ tests/misc/sigint.t3.sh Chet Ramey
 tests/misc/sigint.t4.sh Chet Ramey
 tests/misc/test-minus-e.1       Chet Ramey
 tests/misc/test-minus-e.2       Chet Ramey
+lib/sh/Makefile.in     Chet Ramey
+lib/sh/clktck.c                Chet Ramey
+lib/sh/clock.c         Chet Ramey
+lib/sh/fmtullong.c     Chet Ramey
+lib/sh/fmtulong.c      Chet Ramey
+lib/sh/getcwd.c                Chet Ramey, Roland McGrath
+lib/sh/getenv.c                Chet Ramey, Brian Fox
+lib/sh/inet_aton.c     Chet Ramey, Ulrich Drepper, Paul Vixie
+lib/sh/itos.c          Chet Ramey
+lib/sh/mailstat.c      Chet Ramey
+lib/sh/makepath.c      Chet Ramey
+lib/sh/mktime.c                Chet Ramey, Paul Eggert
+lib/sh/netconn.c       Chet Ramey
+lib/sh/netopen.c       Chet Ramey
+lib/sh/oslib.c         Chet Ramey, Brian Fox
+lib/sh/pathcanon.c     Chet Ramey
+lib/sh/pathphys.c      Chet Ramey
+lib/sh/rename.c                Chet Ramey
+lib/sh/setlinebuf.c    Chet Ramey, Brian Fox
+lib/sh/shquote.c       Chet Ramey
+lib/sh/shtty.c         Chet Ramey
+lib/sh/snprintf.c      Chet Ramey, Unknown
+lib/sh/spell.c         Chet Ramey
+lib/sh/strcasecmp.c    Chet Ramey, Brian Fox
+lib/sh/strerror.c      Chet Ramey, Brian Fox
+lib/sh/strftime.c      Arnold Robbins
+lib/sh/strindex.c      Chet Ramey
+lib/sh/stringlist.c    Chet Ramey
+lib/sh/stringvec.c     Chet Ramey
+lib/sh/strpbrk.c       Roland McGrath
+lib/sh/strtod.c                Chet Ramey, Roland McGrath
+lib/sh/strtoimax.c     Chet Ramey, Paul Eggert
+lib/sh/strtol.c                Chet Ramey, Paul Eggert
+lib/sh/strtoll.c       Chet Ramey, Paul Eggert
+lib/sh/strtoul.c       Chet Ramey, Paul Eggert
+lib/sh/strtoull.c      Chet Ramey, Paul Eggert
+lib/sh/strtoumax.c     Chet Ramey, Paul Eggert
+lib/sh/strtrans.c      Chet Ramey
+lib/sh/times.c         Chet Ramey, Brian Fox
+lib/sh/timeval.c       Chet Ramey
+lib/sh/tmpfile.c       Chet Ramey
+lib/sh/vprint.c                Chet Ramey, Brian Fox
+lib/sh/xstrchr.c       Chet Ramey, Mitsuru Chinen
+lib/sh/zread.c         Chet Ramey
+lib/sh/zwrite.c                Chet Ramey
diff --git a/CHANGES b/CHANGES
index 0f2d4a5524e89956eb7aa52d6c74e12cf90f9c69..1a751280be5ba8e368aa10f12f3ae420ecc0b16a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,464 @@
+This document details the changes between this version, bash-2.05b-release,
+and the previous version, bash-2.05b-beta2.
+
+1.  Changes to Bash
+
+a.  Fixed an off-by-one error in the function that translates job
+    specifications.
+
+b.  Note that we're running under Emacs and disable line editing if
+    $EMACS == `t'.
+
+------------------------------------------------------------------------------
+This document details the changes between this version, bash-2.05b-beta2,
+and the previous version, bash-2.05b-beta1.
+
+1.  Changes to Bash
+
+a.  Fixed the /= and %= arithmetic operators to catch division by zero.
+
+b.  Added putenv, setenv, unsetenv to getenv replacement for completeness.
+
+c.  Fixed a bug that could cause the -O expand_aliases invocation option
+    to not take effect.
+
+d.  Fixed a problem with process substitution that resulted in incorrect
+    behavior when the number of process substitutions in an individual
+    command approached 64.
+
+2.  Changes to Readline
+
+a.  Fixed a problem with backward-char-search when on a system with support
+    for multibyte characters when running in a locale without any multibyte
+    characters.
+
+------------------------------------------------------------------------------
+This document details the changes between this version, bash-2.05b-beta1,
+and the previous version, bash-2.05b-alpha1.
+
+1.  Changes to Bash
+
+a.  Fixed a problem when parsing a POSIX.2 character class name while
+    evaluating a bracket expression containing multibyte characters.
+
+b.  Changed the help text for `bind' to make it clear that any command
+    that may be placed in ~/.inputrc is a valid argument to `bind'.
+
+c.  Added `help' builtin entries for `((', `[[', and arithmetic for.
+
+d.  malloc updated again:
+       o slightly better overflow and underflow detection by putting the
+         chunk size at the beginning and end of the chunk and making
+         sure they match in free/realloc
+       o partial page allocated to make things page-aligned no longer
+         completely wasted
+       o block coalescing now enabled by default
+       o splitting and coalescing enabled for 32-byte chunks, the most
+         common size requested
+       o fixed a problem that resulted in spurious underflow messages and
+         aborts
+       o bin sizes are precomputed and stored in an array rather than
+         being computed at run time
+       o malloc will return memory blocks back to the system if the block
+         being freed is at the top of the heap and of sufficient size to
+         make it worthwhile
+       o malloc/free/realloc now inline memset instead of calling the
+         libc function; uses Duff's device for good performance
+
+e.  Check for getservent(); make the service name completion code dependent
+    on its presence.
+
+f.  Changed the readline callback that executes a command bound to a key
+    sequence to not save the executed command on the history list and to
+    save and restore the parsing state.
+
+g.  Changes to lib/sh/snprintf.c:  fixed some bugs in the `g' and `G'
+    floating point format display; implemented the "'" flag character
+    that turns on thousands' grouping; fixed behavior on systems where
+    MB_CUR_MAX does not evaluate to a constant.
+
+h.  The `unset' builtin no longer returns a failure status when asked to
+    unset a previously-unset variable or function.
+
+i.  Changes to the build system to make it easier to cross-compile bash
+    for different systems.
+
+j.  Added `,' to  the characters that are backslash-escaped during filename
+    completion, to avoid problems with complete-into-braces and RCS filenames
+    containing commas.
+
+k.  Some changes to the multibyte character support code to avoid many calls
+    to strlen().
+
+l.  Bash now correctly honors setting LANG to some value when LC_ALL does not
+    already have a value.
+
+m.  Fixed a bug that could cause SIGSEGV when processing nested traps with
+    trap handlers.
+
+n.  The `source/.' builtin now restores the positional parameters when it
+    returns unless they were changed using the `set' builtin during the file's
+    execution.
+
+o.  Fixed a bug that caused a syntax error when a command was terminated by
+    EOF.
+
+2.  New Features in Bash
+
+a.  There is now support for placing the long help text into separate files
+    installed into ${datadir}/bash.  Not enabled by default; can be turned
+    on with `--enable-separate-helpfiles' option to configure.
+
+b.  All builtins that take operands accept a `--' pseudo-option, except
+    `echo'.
+
+c.  The `echo' builtin now accepts \0xxx (zero to three octal digits following
+    the `0') in addition to \xxx (one to three octal digits) for SUSv3/XPG6/
+    POSIX.1-2001 compliance.
+
+3.  Changes to Readline
+
+a.  Fixed a small problem in _rl_insert_char with multibyte characters.
+
+b.  Fixes from IBM for line wrapping problems when using multibyte characters.
+
+c.  Fixed a problem which caused the display to be messed up when the last
+    line of a multi-line prompt (possibly containing invisible characters)
+    was longer than the screen width.
+
+d.  Fixed a problem with the vi-mode `r' command that ocurred on systems with
+    support for multibyte characters when running in a locale without any
+    multibyte characters.
+
+------------------------------------------------------------------------------
+This document details the changes between this version, bash-2.05b-alpha1,
+and the previous version, bash-2.05a-release.
+
+1.  Changes to Bash
+
+a.  Some changes to work around inlining differences between compilers.
+
+b.  Added more prototypes for internal shell typedefs, to catch argument
+    passing errors when using pointers to functions.
+
+c.  The `cd' builtin now fails in posix mode when a valid directory cannot be
+    constructed from a relative pathname argument and the $PWD using pathname
+    canonicalization, and the -P option has not been supplied.  Previously,
+    the shell would attempt to use what the user typed, leading to weird
+    values for $PWD and discrepancies between the value of $PWD and the
+    actual working directory.
+
+d.  The `cd' builtin now resets $PWD when canonicalization fails but a chdir
+    to the pathname passed as an argument succeeds (when not in posix mode).
+
+e.  The `fc' builtin has been fixed, as POSIX requires, to use the closest
+    history position in range when given an out-of-range argument.
+
+f.  The history file loading code was changed to allow lines to be saved in
+    the history list from the shell startup files.
+
+g.  `history -s args' now works bettern in compound commands.
+
+h.  The tilde expansion code was fixed to better recognize when it's being
+    invoked in an assignment context, which enables expansion after `='
+    and `:'.
+
+i.  Fixed the command name completion code so a slash is no longer appended
+    to a single match if there happens to be a directory with that name in
+    $PWD.
+
+j.  Fixed compound array assignment to no longer perform alias expansion, to
+    allow reserved words as array members, and to not produce extra output
+    when the `-v' option had been enabled.
+
+k.  Fixed the programmable completion code to better handle newlines in lists
+    of possible completions (e.g., `complete -W').
+
+l.  Removed the reserved words from the `bash-builtins' manual page.
+
+m.  Parser error reporting now attempts to do a better job of identifying the
+    token in error rather than doing straight textual analysis.
+
+n.  Fixes for Inf/NaN, locales, wide/multibyte characters and zero-length
+    arguments in the library snprintf(3) replacement.
+
+o.  `read -e' no longer does command name completion on the first word on
+    the line being read.
+
+p.  `select' now returns failure if the read of the user's selection fails.
+
+q.  Fixed a bug that could cause a core dump when setting $PIPESTATUS.
+
+r.  Fixes to not allocate so many job slots when the shell is running a loop
+    with job control enabled in a subshell of an interactive shell.
+
+s.  Fixed a bug in the trap code that caused traps to be inherited by
+    command substitutions in some cases.
+
+t.  Fixed a bug that could cause alias expansion to inappropriately expand
+    the word following the alias.
+
+u.  Fixed a bug in the `kill' builtin that mishandled negative pid arguments.
+
+v.  The parser is less lenient when parsing assignment statements where the
+    characters before the `=' don't comprise a valid identifier.
+
+w.  The arithmetic expression evaluation code now honors the setting of the
+    `-u' option when expanding variable names.
+
+x.  Fixed the arithmetic evaluation code to allow array subscripts to be
+    assigned (`let b[7]=42') and auto-incremented and auto-decremented
+    (e.g., b[7]++).
+
+y.  Reimplemented the existing prompt string date and time expansions using
+    strftime(3), which changed the output of \@ in some locales.
+
+z.  Fixed a bug that could cause a core dump when a special shell variable
+    (like RANDOM) was converted to an array with a variable assignment.
+
+aa. Fixed a bug that would reset the handler for a signal the user had
+    trapped to a function that would exit the shell when setting the exit
+    trap in a non-interactive shell.
+
+bb. Changed the execve(2) wrapper code to check whether or not a failing
+    command is a directory before looking at whether a `#!' interpreter
+    failed for some reason.
+
+cc. Fixed a bug in the command printing code so it no longer inserts a `;'
+    after a newline, which produces a syntax error when reused as input.
+
+dd. The code that expands $PS4 no longer inherits the `-x' flag.
+
+ee. The bash-specific completion functions may now take advantage of the
+    double-TAB and M-?  features of the standard readline completion
+    functions.
+
+ff. The mail checking code no longer prints a message if the checked file's
+    size has not increased, even if the access time is less than the modification time.
+
+gg. Rewrote the variable symbol table code: there is now a stack of
+    contexts, each possibly including a separate symbol table; there can
+    be more than one temporary environment supplied to nested invocations
+    of `./source'; the temporary environments no longer require so much
+    special-case code; shell functions now handle the temporary environment
+    and local variables more consistently; function scope exit is faster now
+    that the entire symbol table does not have to be traversed to dispose of
+    local variables; it is now easier to push vars from the temporary
+    environment to the shell's variable table in posix mode; some duplicated
+    code has been removed.
+
+hh. Regularized the error message printing code; builtin_error is now called
+    more consistently, and common error message strings are handled by small
+    functions.  This should make eventual message translation easier.
+
+ii. Error messages now include the line number in a script when the shell
+    is not interactive.
+
+jj. Array subscript expansion now takes place even when the array variable is
+    unset, so side effects will take place.
+
+kk. Fixed a bug in the SICGHLD child-reaping code so that it won't find
+    jobs already marked as terminated if the OS reuses pids quickly enough.
+
+ll. Fixed a bug that could cause a signal to not interrupt the `wait'
+    builtin while it was waiting for a background process to terminate.
+
+mm. A couple of changes to make it easier for multiple shells to share history
+    files using `history -n', `history -r', and `history -w'.
+
+nn. The `getopts' builtin always increments OPTIND to point to the next
+    option to be handled when an option is returned, whether it's valid
+    or not, as POSIX 1003.x-2001 requires.
+
+oo. Changed some parts of the expansion code to avoid allocating and
+    immediately freeing memory without using the results for anything.
+
+pp. The shell now keeps track of $IFS internally, updating its internal map
+    each time the variable is assigned a new value (or at local scope exit).
+    This saves thousands of hash lookups for IFS, which, while individually
+    cheap, add up.
+
+qq. Rewrote the hash table code:  searching and insertion are much faster now,
+    and it uses a better string hashing function; augmented the function
+    interface to simplify other parts of the code and remove duplicated code
+
+rr. The shell now uses a simple, generic `object cache' for allocating and
+    caching words and word lists, which were the major users of
+    malloc/free.
+
+ss. Fixed the assignment statement parsing code to allow whitespace and
+    newlines in subscripts when performing array element assignment.
+
+tt. The shell now issues many fewer calls to sigprocmask and other signal
+    masking system calls.
+
+uu. Fixed the `test' and conditional command file comparison operators to
+    work right when one file has a non-positive timestamp and the other
+    does not exist.
+
+vv. Fixed some cases where the special characters '\001' and '\177' in the
+    values of variables or positional parameters caused incorrect expansion
+    results.
+
+2.  Changes to Readline
+
+a.  Fixed output of comment-begin character when listing variable values.
+
+b.  Added some default key bindings for common escape sequences produced by
+    HOME and END keys.
+
+c.  Fixed the mark handling code to be more emacs-compatible.
+
+d.  A bug was fixed in the code that prints possible completions to keep it
+    from printing empty strings in certain circumstances.
+
+e.  Change the key sequence printing code to print ESC as M\- if ESC is a
+    meta-prefix character -- it's easier for users to understand than \e.
+
+f.  Fixed unstifle_history() to return values that match the documentation.
+
+g.  Fixed the event loop (rl_event_hook) to handle the case where the input
+    file descriptor is invalidated.
+
+h.  Fixed the prompt display code to work better when the application has a
+    custom redisplay function.
+
+i.  Changes to make reading and writing the history file a little faster, and
+    to cope with huge history files without calling abort(3) from xmalloc.
+
+j.  The vi-mode `S' and `s' commands are now undone correctly.
+
+3.  New Features in Bash
+
+a.  If set, TMOUT is the default timeout for the `read' builtin.
+
+b.  `type' has two new options:  `-f' suppresses shell function lookup, and
+    `-P' forces a $PATH search.
+
+c.  New code to handle multibyte characters.
+
+d.  `select' was changed to be more ksh-compatible, in that the menu is
+    reprinted each time through the loop only if REPLY is set to NULL.
+    The previous behavior is available as a compile-time option.
+
+e.  `complete -d' and `complete -o dirnames' now force a slash to be
+    appended to names which are symlinks to directories.
+
+f.  There is now a bindable edit-and-execute-command readline command,
+    like the vi-mode `v' command, bound to C-xC-e in emacs mode.
+
+g.  Added support for ksh93-like [:word:] character class in pattern matching.
+
+h.  The  $'...' quoting construct now expands \cX to Control-X.
+
+i.  A new \D{...} prompt expansion; passes the `...' to strftime and inserts
+    the result into the expanded prompt.
+
+j.  The shell now performs arithmetic in the largest integer size the
+    machine supports (intmax_t), instead of long.
+
+k.  If a numeric argument is supplied to one of the bash globbing completion
+    functions, a `*' is appended to the word before expansion is attempted.
+
+l.  The bash globbing completion functions now allow completions to be listed
+    with double tabs or if `show-all-if-ambiguous' is set.
+
+m.  New `-o nospace' option for `complete' and `compgen' builtins; suppresses
+    readline's appending a space to the completed word.
+
+n.  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).
+
+p.  There is a new configuration option `--enable-mem-scramble', controls
+    bash malloc behavior of writing garbage characters into memory at
+    allocation and free time.
+
+q.  The `complete' and `compgen' builtins now have a new `-s/-A service'
+    option to complete on names from /etc/services.
+
+r.  `read' has a new `-u fd' option to read from a specified file descriptor.
+
+s.  Fix the completion code so that expansion errors in a directory name
+    don't cause a longjmp back to the command loop.
+
+t.  Fixed word completion inside command substitution to work a little more
+    intuitively.
+
+u.  The `printf' %q format specifier now uses $'...' quoting to print the
+    argument if it contains non-printing characters.
+
+v.  The `declare' and `typeset' builtins have a new `-t' option.  When applied
+    to functions, it causes the DEBUG trap to be inherited by the named
+    function.  Currently has no effect on variables.
+
+w.  The DEBUG trap is now run *before* simple commands, ((...)) commands,
+    [[...]] conditional commands, and for ((...)) loops.
+
+x.  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.
+
+y.  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.  Code
+    from Gary Vaughan.
+
+z.  New [n]<&word- and [n]>&word- redirections from ksh93 -- move fds (dup
+    and close).
+
+aa. There is a new `-l' invocation option, equivalent to `--login'.
+
+bb. The `hash' builtin has a new `-l' option to list contents in a reusable
+    format, and a `-d' option to remove a name from the hash table.
+
+4.  New Features in Readline
+
+a.  Support for key `subsequences':  allows, e.g., ESC and ESC-a to both
+    be bound to readline functions.  Now the arrow keys may be used in vi
+    insert mode.
+
+b.  When listing completions, and the number of lines displayed is more than
+    the screen length, readline uses an internal pager to display the results.
+    This is controlled by the `page-completions' variable (default on).
+
+c.  New code to handle editing and displaying multibyte characters.
+
+d.  The behavior introduced in bash-2.05a of deciding whether or not to
+    append a slash to a completed name that is a symlink to a directory has
+    been made optional, controlled by the `mark-symlinked-directories'
+    variable (default is the 2.05a behavior).
+
+e.  The `insert-comment' command now acts as a toggle if given a numeric
+    argument:  if the first characters on the line don't specify a
+    comment, insert one; if they do, delete the comment text
+
+f.  New application-settable completion variable:
+    rl_completion_mark_symlink_dirs, allows an application's completion
+    function to temporarily override the user's preference for appending
+    slashes to names which are symlinks to directories.
+
+g.  New function available to application completion functions:
+    rl_completion_mode, to tell how the completion function was invoked
+    and decide which argument to supply to rl_complete_internal (to list
+    completions, etc.).
+
+h.  Readline now has an overwrite mode, toggled by the `overwrite-mode'
+    bindable command, which could be bound to `Insert'.
+
+i.  New application-settable completion variable:
+    rl_completion_suppress_append, inhibits appending of
+    rl_completion_append_character to completed words.
+
+j.  New key bindings when reading an incremental search string:  ^W yanks
+    the currently-matched word out of the current line into the search
+    string; ^Y yanks the rest of the current line into the search string,
+    DEL or ^H deletes characters from the search string.
+
+------------------------------------------------------------------------------
 This document details the changes between this version, bash-2.05a-release,
 and the previous version, bash-2.05a-rc1.
 
diff --git a/COMPAT b/COMPAT
index cb6681e3acd8af467d429508ba825b7a6e7c8865..c2778fe074853183400732e977cc0dccc71156aa 100644 (file)
--- a/COMPAT
+++ b/COMPAT
@@ -1,5 +1,5 @@
 This document details the incompatibilites between this version of bash,
-bash-2.05a, and the previous widely-available version, bash-1.14 (which
+bash-2.05b, and the previous widely-available version, bash-1.14 (which
 is still the `standard' version for many Linux distributions).  These
 were discovered by users of bash-2.x, so this list is not comprehensive.
 Some of these incompatibilities occur between the current version and
@@ -44,8 +44,8 @@ versions 2.0 and above.
 
 3.  The options to `bind' have changed to make them more consistent with
     the rest of the bash builtins.  If you are using `bind -d' to list
-    the readline keybindings in a form that can be re-read, use `bind -p'
-    instead.  If you were using `bind -v' to list the keybindings, use
+    the readline key bindings in a form that can be re-read, use `bind -p'
+    instead.  If you were using `bind -v' to list the key bindings, use
     `bind -P' instead.
 
 4.  The `long' invocation options must now be prefixed by `--' instead
@@ -64,7 +64,7 @@ versions 2.0 and above.
 
        "\C-\\": self-insert
 
-6.  A number of people complained above having to use ESC to terminate an
+6.  A number of people complained about having to use ESC to terminate an
     incremental search, and asked for an alternate mechanism.  Bash-2.03
     uses the value of the settable readline variable `isearch-terminators'
     to decide which characters should terminate an incremental search.  If
@@ -146,6 +146,11 @@ versions 2.0 and above.
        AaBb...Zz
 
     so a range specification like [A-Z] will match every letter except `z'.
+    Other locales 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.
index 67829991ea45735466a9629ee636a353f478bc20..d090bf4f9ca0f58b7bc03a8a416b4efc0e63c119 100644 (file)
@@ -2631,7 +2631,7 @@ lib/sh/netopen.c
 Makefile.in
        - pass DEBUG=${DEBUG} down to makes in some subdirectories
 
-{builtins,lib{glob,sh}}/Makefile.in
+{builtins,lib/{glob,sh}}/Makefile.in
        - append ${DEBUG} to LOCAL_CFLAGS value, passed by top-level Makefile
 
 builtins/printf.def
@@ -2938,3 +2938,3319 @@ unwind_prot.c
 lib/readline/chardefs.h
        - make _rl_digit_p succeed only for ascii digits, since that's what
          most callers assume
+
+                                  11/13
+                                  -----
+doc/bashref.texi
+       - added `ERR' trap and [-+]O invocation option to section listing
+         differences from the Bourne shell
+
+                                  11/15
+                                  -----
+[bash-2.05a released]
+
+                                  11/19
+                                  -----
+include/stdc.h
+       - new define, INLINE, defined as `inline' for gcc and empty otherwise
+
+subst.c
+       - make skip_double_quoted, sub_append_string have INLINE attribute
+
+trap.c
+       - use BASH_NSIG as upper limit for signal names in signal_name()
+
+lib/readline/bind.c
+       - use RL_COMMENT_BEGIN_DEFAULT in output for rl-comment-begin value
+
+error.c
+       - fix sys_error to save value of errno around calls to fprintf
+
+doc/Makefile.in
+       - added rules to create PDF files from postscript and dvi input
+
+MANIFEST.doc
+       - added {article,bash,bashref,rose94}.pdf
+
+doc/bash.1
+       - rearranged some `.PD 0' and `.TP' directives so man2html will
+         handle them better (shouldn't affect groff output)
+
+support/man2html.c
+       - small fix to handle quoted string arguments to directives like
+         `.BR' without mangling the output
+
+                                  11/20
+                                  -----
+{arrayfunc,variables}.c
+       - changed calling sequence for dynamic array variable `assign'
+         functions to (SHELL_VAR *self, char *value, arrayind_t ind)
+       - changed calling sequence for dynamic variable assign functions
+         to the same as array variable assign_func.  Now this can be
+         prototyped
+
+variables.h
+       - the assign_func member of a `struct variable' is now of type
+         `sh_var_assign_func_t', which is prototyped
+       - the dynamic_value member of a `struct variable' is now of type
+         `sh_var_value_func_t', which is prototyped
+
+variables.c
+       - changed to use `sh_var_assign_func_t' and `sh_var_value_func_t'
+
+builtins/cd.def
+       - when in posix mode, if the new directory name formed by PWD and
+         the argument passed by the user cannot be canonicalized, and the
+         -P option has not been supplied, return failure immediately
+       - if canonicalization failed, but the fallback to the directory
+         name specified by the user succeeds, reset the current working
+         directory
+
+lib/readline/{input.c,rlprivate.h}
+       - renamed rl_unget_char to _rl_unget_char; made library global
+
+lib/readline/{{bind,readline}.c,{keymaps,rlprivate}.h}
+       - support for `key subsequences'; allows a key sequence and a function
+         mapped to a subsequence of that key sequence.  Primarily to allow
+         arrow keys to be bound in readline vi insert mode, while preserving
+         the ESC function to switch to command mode.
+
+lib/readline/{input.c,rlprivate.h}
+       - new function, _rl_input_queued(T), does a check with select or
+         FIONREAD with a timeout of `T' (which is generally 0)
+
+lib/readline/readline.c
+       - change _rl_dispatch_subseq to test for input in the queue if we
+         get ESC while in vi insertion mode if the keymap entry type for
+         ESC is ISKMAP.  If _rl_input_queued returns non-zero, we assume
+         that an arrow key sequence has been pressed and go ahead with the
+         subsequence.  If it returns zero, we assume that the user pressed
+         ESC to switch into command mode, and dispatch to that right away.
+         This avoids forcing the user to press another key before switching
+         into command mode
+
+                                  11/21
+                                  -----
+lib/readline/readline.c
+       - bind common arrow key sequences in vi insertion keymap
+
+lib/readline/terminal.c
+       - bind termcap definition's arrow keys in vi insertion keymap
+
+lib/readline/bind.c
+       - check for rl_vi_movement_mode in _rl_bind_if_unbound, so
+         binding the arrow keys can work
+
+lib/readline/readline.c
+       - since _rl_bind_if_unbound does the check of what's currently
+         bound to the key sequence, the check in bind_arrow_keys_internal
+         was redundant
+       - bind_arrow_keys_internal now takes a Keymap argument and handles
+         saving and restoring _rl_keymap; changed bind_arrow_keys
+         accordingly
+
+builtins/fc.def
+       - fix from Paul Eggert to substitute the nearest history number in
+         range if an out-of-range value is supplied.  POSIX requires this
+
+lib/sh/pathcanon.c
+       - fix from Corrina Vinschen for the special `cygdrive' prefix on
+         Cygwin
+
+bashhist.c
+       - split the history adding code into more pieces:
+           check_history_control (char *line) checks LINE against the value
+           of HISTCONTROL, returning 1 if LINE should be saved and 0 if not
+
+           check_add_history (char *line) calls check_history_control and
+           history_should_ignore (line) and saves the line with
+           bash_add_history if the checks indicate that it should be saved
+
+           maybe_add_history just calls check_add_history to set the value
+           of first_line_saved
+
+bashhist.h
+       - extern declaration for check_add_history()
+
+shell.c
+       - don't call load_history() from the interactive shell startup
+         code if history_lines_this_session is > 0, indicating that we've
+         already saved some lines in the history and that we probably
+         don't want to overwrite them
+
+builtins/history.def
+       - call check_add_history from push_history, so `history -s xx'
+         works even when in a compound command whose first line has not
+         been saved.  (Caveat:  in a compound command when the first
+         line has been saved, the line supplied to history -s will become
+         part of the compound command's history entry.  Of course, the
+         delete_history call could remove the compound command from the
+         history entirely)
+
+bashline.c
+       - use sh_makepath instead of xmalloc/sprintf in
+         command_word_completion_function
+
+lib/readline/complete.c
+       - get_y_or_n now takes an int FOR_PAGER argument; caller changed
+         If FOR_PAGER is non-zero, get_y_or_n returns appropriate values
+         for a more-like pager:  `newline' or `return' return 2; `q' or
+         `Q' return 0
+       - there is now a mini internal more-like pager for displaying a
+         list of completions that exceeds the screen height (new function
+         _rl_internal_pager, called from rl_display_match_list)
+
+                                  11/24
+                                  -----
+command.h
+       - new flag, W_TILDEEXP, says to do tilde expansion on an
+         assignment word
+
+execute_cmd.c
+       - fix_assignment_words now sets W_TILDEEXP for assignment word
+         arguments to `assignment builtins'
+
+general.c
+       - bash_tilde_expand now takes a second argument indicating whether
+         or not it's being invoked in an `assignment context'
+
+general.h
+       - change extern declaration for bash_tilde_expand
+
+{bashline,execute_cmd,findcmd,general,variables}.c
+builtins/evalfile.c
+lib/sh/makepath.c
+       - fix callers of bash_tilde_expand appropriately
+
+subst.c
+       - fix callers of bash_tilde_expansion appropriately
+       - add (currently commented-out) code that would tilde expand assignment
+         statement arguments to assignment builtins (W_TILDEEXP flag set)
+         even when the shell is in posix mode
+
+bashline.c
+       - fix attempt_shell_completion to turn off
+         rl_filename_completion_desired when doing command name completion,
+         so no slash gets appended to the name if there happens to be a
+         directory with the same name in the current directory
+
+                                  11/26
+                                  -----
+lib/readline/rltech.texinfo
+       - a couple of additions to the rl_stuff_char description
+
+parse.y
+       - turn off echo_input_at_read in parse_string_to_word_list, so `set -v'
+         doesn't give extra lines of output when doing compound array
+         assignment
+
+subst.c
+       - fix split_at_delims to handle skipping over a `\n' if it's a
+         delimiter (use spctabnl(c) instead of whitespace(c))
+
+                                  11/27
+                                  -----
+support/config.{guess,sub}
+       - updated (with bash changes) to latest version from gnu.org
+
+sig.h
+       - add prototype for set_signal_handler declaration
+
+builtins/setattr.def
+       - add prototype to extern declaration of declare_builtin
+
+builtins/times.def
+       - add no_options call, since times takes no options
+
+lib/sh/spell.c
+       - add prototypes to forward declarations for midist and spdist
+
+lib/sh/strtrans.c
+       - add explicit int return type to ansic_shouldquote declaration
+
+lib/readline/rldefs.h, lib/readline/{macro,readline,util,undo}.c
+       - move define for SWAP to rldefs.h, removed from various C files
+
+lib/readline/vi_mode.c
+       - removed define for exchange(), changed to use SWAP instead
+
+lib/readline/bind.c
+       - added some static forward function declarations
+       - find_boolean_var, find_string_var now take a `const char *' argument
+
+lib/readline/signals.c
+       - added static forward declaration for rl_maybe_set_sighandler
+
+lib/readline/readline.c
+       - add some common key bindings for the HOME and END keys in
+         bind_arrow_keys_internal
+
+lib/readline/terminal.c
+       - fetch the `@7' termcap string; it's sent by the END key
+       - attempt to bind the terminal's END key to rl_end_of_line in
+         bind_termcap_arrow_keys; I don't know why I was using `kH'
+         instead of `@7'
+
+doc/builtins.1
+       - remove `case', `for', `if', `until', `while' from NAME section;
+         those are not shell builtins
+
+                                  11/28
+                                  -----
+stringlib.c
+       - new function, find_token_in_alist, takes a token value and an
+         ALIST argument, and returns the string correspoinding to the
+         token if found in the alist
+
+externs.h
+       - new extern declaration for find_token_in_alist()
+
+subst.c
+       - string_list_internal is no longer static
+
+subst.h
+       - new extern declaration for string_list_internal()
+
+parse.y
+       - new alist array of other tokens returned by read_token which are
+         not reserved words in word_token_alist[]
+       - reworked error reporting:  new functions print_offending_line,
+         which prints the line containing the syntax error,
+         error_token_from_token, which takes the current token and tries to
+         figure out its textual representation, and error_token_from_text,
+         which does the old job of finding the bad token by analyzing the
+         text of shell_input_line at the current index
+       - report_syntax_error now tries to figure out the token that caused
+         the syntax error by first looking at current_token and falling
+         back to the old method of textual analysis if that fails
+       - report_syntax_error doesn't say the token resulting from the textual
+         analysis of the input line is an `unexpected token'; it just
+         says there is a `syntax error near xxx'
+       - changed conditional command error reporting to use the value
+         returned by error_token_from_token if it's not null instead of
+         just using the token value in the message, since current_token
+         ends up being set to -1, and the text of the message from
+         report_syntax_error might not be exactly right
+       - change parse_string_to_word_list to set current_token to the
+         offending token returned by read_token before calling yyerror()
+         to make the error reporting do the right thing
+
+aclocal.m4
+       - fixed typo in BASH_CHECK_LIB_TERMCAP
+
+configure.in
+       - add check for isinf(3); define HAVE_ISINF_IN_LIBC if found
+
+config.h.in
+       - add define for HAVE_ISINF_IN_LIBC
+
+lib/sh/snprintf.c
+       - check for Inf and NaN, using isinf and isnan if they're found in
+         libc
+       - use the current locale for thousands separator and decimal point
+       - recognize "'" flag; not implemented yet
+       - fix for snprintf/vsnprintf with length of 0 and string argument of
+         0 with non-zero length
+
+builtins/read.def
+       - TMOUT is now the default timeout for `read' (and select) if set,
+         like ksh93 when reading from the terminal
+       - edit_line (called by read -e) now just does readline's filename
+         completion by setting rl_attempted_completion_function to NULL,
+         since e.g., doing command completion for the first word on the
+         line wasn't really useful
+
+execute_cmd.c
+       - changed select_command to return failure status if select_query
+         returns NULL, indicating that read_builtin returned
+         EXECUTION_FAILURE
+
+doc/{bash.1,bashref.texi}
+       - documented new TMOUT behavior 
+       - slight change to the description of the test `-ef' option
+
+doc/bashref.texi
+       - added item to posix mode section describing failure behavior of
+         cd when invoked in logical mode and the pathname formed by
+         combining $PWD and the directory argument does not refer to an
+         existing directory
+
+                                  11/29
+                                  -----
+execute_cmd.c
+       - fix execute_function to call dispose_function_env after
+         merge_function_env if the shell is in posix mode (fixes debian
+         bash bug #117673)
+
+lib/readline/readline.c
+       - rl_forward -> rl_forward_char; rl_forward function for compatibility
+       - rl_backward -> rl_backward_char; rl_forward function for
+         compatibility
+       - new functions, rl_forward_byte, rl_backward_byte, for future use
+
+lib/readline/readline.h
+       - extern declarations for rl_forward_char, rl_backward_char,
+         rl_forward_byte, rl_backward_byte
+
+lib/readline/{emacs_keymap,funmap,vi_keymap,vi_mode
+       - rl_forward -> rl_forward_char
+       - rl_backward -> rl_backward_char
+
+lib/readline/funmap.c
+       - new bindable names, `backward-byte' and `forward-byte'
+
+aclocal.m4
+       - new function, BASH_CHECK_MULTIBYTE, encapsulates checks for
+         multibyte code
+
+config.h.in
+       - add necessary defines for multibyte include files and functions
+
+configure.in
+       - add call to BASH_CHECK_MULTIBYTE
+
+config-bot.h
+       - add code to define HANDLE_MULTIBYTE if prerequisites are met
+
+lib/sh/xstrchr.c
+       - new file, xstrchr() is strchr(3) that handles multibyte characters
+
+bashhist.c
+       - first_line_saved -> current_command_first_line_saved; variable is
+         now global
+
+bashhist.h
+       - extern declaration for current_command_first_line_saved
+
+                                  11/30
+                                  -----
+bashhist.c
+       - break the code that actually calls add_history out of
+         bash_add_history into a new function, really_add_history;
+         bash_add_history now calls really_add_history
+       - check_add_history takes a second `force' argument telling it
+         whether to call bash_add_history (force == 0) or really_add_history
+         (force != 0)
+
+builtins/history.def
+       - in push_history, call delete_last_history if the current command
+         has more than one line, the first line was saved, and
+         command-oriented history is active.  This takes care of deleting
+         the right history element if `history -s' is used within a
+         compound or multiline command
+       - in push_history, call check_add_history with second argument of 1
+         to skip check of current_command_line_count and add the arguments
+         to history -s as a single separate history entry
+
+                                  12/3
+                                  ----
+lib/readline/complete.c
+       - append a slash to completed names which are symlinks to directories
+         if the new variable _rl_complete_mark_symlink_dirs is non-zero
+
+lib/readline/rlprivate.h
+       - extern declaration for _rl_complete_mark_symlink_dirs
+
+lib/readline/bind.c
+       - new bindable variable, `mark-symlinked-directories', mirrors the
+         value of _rl_complete_mark_symlink_dirs
+
+doc/bash.1, lib/readline/doc/{readline.3,rluser.texinfo}
+       - documented new `mark-symlinked-directories' variable
+
+                                  12/4
+                                  ----
+variables.[ch]
+       - set_pipestatus_array now takes a second argument with the number
+         of processes in the array
+       - changed set_pipestatus_array to just modify the value in place if
+         the existing array has one element and the new array has one
+         element, and to modify existing values in place if new array has
+         more elements than existing array
+
+variables.c, jobs.c
+       - changed set_pipestatus_array callers
+
+jobs.c
+       - moved call to setjstatus() from set_job_status_and_cleanup to
+         wait_for, since set_job_status_and_cleanup is part of the SIGCHLD
+         signal handler call path, and race conditions accessing the
+         PIPESTATUS array will result for things like
+
+               while true; do date; done | cat > /dev/null
+
+                                  12/5
+                                  ----
+xmalloc.h
+       - don't redefine xmalloc, xrealloc, and xfree if DISABLE_MALLOC_WRAPPERS
+         is #defined
+
+config.h.in
+       - #undef for DISABLE_MALLOC_WRAPPERS
+
+configure.in
+       - define DISABLE_MALLOC_WRAPPERS if the --with-purify option is
+         supplied
+
+lib/malloc/trace.c
+       - new function, malloc_trace_bin(N), traces allocations and frees
+         to bucket N (uses the same type of bitmap as `busy')
+
+lib/malloc/table.c
+       - fix wraparound search problem in find_entry when searching for a
+         free entry when the table is full
+
+                                  12/6
+                                  ----
+lib/malloc/table.c
+       - keep an `overflow bucket' around to use when the table is full,
+         so find_entry always returns a valid pointer when FIND_ALLOC
+         is set
+       - new static variable to keep a count of the number of MT_ALLOC
+         entries in the mem_table
+
+lib/sh/{oslib,clktck}.c
+       - if HAVE_LIMITS_H is defined, include <limits.h>
+
+lib/sh/oslib.c
+       - new function, getmaxgroups() returns max number of simultaneous
+         groups
+       - new function, getmaxchild(), returns max number of simultaneous
+         user processes
+
+general.c
+       - removed forest of #defines for getmaxgroups()
+
+externs.h
+       - new extern declaration for getmaxgroups()
+       - new extern declaration for getmaxchild()
+       - new extern declaration for isnetconn()
+
+lib/sh/netconn.c,shell.c
+       - new file, isnetconn() from shell.c moved here
+
+Makefile.in, lib/sh/Makefile.in
+       - necessary changes for netconn.c
+
+builtins/ulimit.def
+       - changed getmaxuprc() to just call getmaxchild() and massage the
+         return value appropriately
+
+{jobs,nojobs}.c
+       - use the value returned by getmaxchild() in
+         mark_dead_jobs_as_notified instead of static CHILD_MAX
+
+jobs.c
+       - new function, compact_jobs_list, removes some number of jobs from
+         the jobs table and reallocates the table, copying the jobs that
+         are left from the old table to the new.  Compaction happens from
+         the beginning of the list and removes dead jobs, and we make sure
+         to keep the last CHILD_MAX jobs as POSIX.2 requires
+       - call compact_jobs_list from stop_pipeline if we're in a subshell,
+         there are no free jobs in the jobs table, and the jobs table is
+         at or above some maximum limit
+
+execute_cmd.c
+       - change eval_arith_for_expr to set this_command_name to `((' before
+         calling evalexp, since it might be changed by evaluating the
+         loop body between evalexp calls
+
+trap.c
+       - change reset_signal to turn off the SIG_TRAPPED flag for the
+         given signal, so shell builtins and functions running in command
+         substitutions don't run the signal handlers (traps are not supposed
+         to be inherited by command substitutions)
+
+parse.y
+       - changed parse_string_to_word_list to turn off alias expansion
+         while parsing the array assignment
+
+                                  12/9
+                                  ----
+alias.c
+       - fix add_alias so that redefining an alias's value also resets the
+         EXPANDNEXT flag
+
+                                  12/10
+                                  -----
+parse.y
+       - new function, token_is_assignment, called to check whether the text
+         before `=' makes up a valid assignment token before trying to parse
+         a compound assignment statement
+       - new function, parse_compound_assignment, to parse a compound
+         assignment statement instead of using parse_matched_pair; handles
+         comments and error reporting in the parser instead of waiting until
+         expansion time
+       - changed parse_compound_assignment and parse_string_to_word_list to
+         allow reserved words in compound array assignments
+
+lib/readline/doc/rltech.texinfo
+       - changed the documentation for rl_callback_read_char and
+         rl_callback_handler_remove to say what happens to the terminal
+         settings and what needs to be done to reset them
+
+                                  12/11
+                                  -----
+bashline.c
+       - add emacs_edit_and_execute_command, bound to C-xC-e, like vi-mode
+         `v' command
+       - add bindable command name `edit-and-execute-command', bound to
+         run emacs_edit_and_execute_command()
+
+lib/glob/strmatch.c
+       - add support for ksh93-like [:word:] character class (isalnum + `_')
+
+doc/{bash.1,bashref.texi}
+       - add note to section describing lists to clarify that a sequence of
+         one or more newlines may be used to delimit a command, equivalent
+         to a semicolon
+       - document new [:word:] pattern matching character class
+
+doc/bash.1, lib/readline/doc/rluser.texinfo
+       - document `edit-and-execute-command' and its default emacs-mode
+         binding
+
+include/chartypes.h
+       - add defines for TOCTRL and UNCTRL if they're not already defined
+
+lib/readline/chardefs.h
+       - #undef UNCTRL if it's defined to avoid cpp redefinition warnings
+
+lib/sh/strtrans.c
+       - add \cX (Control-X) escape for $'...' to ansicstr()
+       - change ansic_quote() to allocate at least four chars for each char
+         in the string argument, to account for \0xx octal values
+       - change ansic_quote() to no longer call sprintf for non-printable
+         characters; just translate the string to octal directly
+
+print_cmd.c
+       - change xtrace_print_word_list to call ansic_quote() if
+         ansic_shouldquote() indicates that there are nonprinting characters
+         in a word
+
+builtins/type.def
+       - changed deprecated long option parsing to just replace the word
+         in the list with the equivalent short option (-type -> -t) instead
+         of removing words from the list
+       - changed describe_command to take a single flags argument instead
+         of two int args; changed caller
+       - type now has two new options:  -f suppresses function lookup (like
+         command), and -P forces a PATH search for the name(s)
+
+builtins/common.h
+       - flags for describe_command are here
+       - changed extern declaration of describe_command
+
+builtins/command.def
+       - changed call to describe_command to use flags from common.h, and
+         the right number of arguments
+
+doc/{bash.1,bashref.texi}
+       - documented new -f and -P options to `type'
+
+                                  12/12
+                                  -----
+lib/readline/rldefs.h
+       - fixed prototype for _rl_strnicmp
+
+execute_cmd.c
+       - select_query now takes a new argument, an int flag saying whether
+         or not to print the menu the first time through the loop.  An
+         empty line in response to the prompt will always cause the menu
+         to be reprinted
+       - changed execute_select_command to cause select_query to reprint
+         the menu only if REPLY is set to NULL, if KSH_COMPATIBLE_SELECT
+         is defined
+
+config-top.h
+       - define KSH_COMPATIBLE_SELECT, with a comment about its meaning
+
+lib/readline/readline.c
+       - change rl_insert_comment to toggle if given an explicit numeric
+         argument:  if the first characters on the line don't specify a
+         comment, insert one; if they do, delete the comment text
+
+doc/bash.1, lib/readline/doc/{readline.3,rluser.texinfo}
+       - documented new behavior of insert-comment with a numeric argument
+
+                                  12/13
+                                  -----
+lib/malloc/watch.c
+       - new file, implements watchpoint functions
+
+lib/malloc/watch.h
+       - new file, define some `events' for watchpoints and extern function
+         and variable declarations for watchpoint code
+
+lib/malloc/imalloc.h
+       - #define MALLOC_WATCH if MALLOC_DEBUG is defined
+       - add __P define as in include/stdc.h if not already defined
+
+lib/malloc/malloc.c
+       - remove __P define, now in imalloc.h
+       - include watch.h if MALLOC_WATCH is defined
+       - added calls to _malloc_ckwatch in internal_malloc, internal_free,
+         and internal_realloc
+
+include/stdc.h
+       - augment __P define to allow prototypes if PROTOTYPES is defined
+
+lib/readline/rlstdc.h
+       - augment PARAMS define to allow prototypes if PROTOTYPES is defined
+
+lib/malloc/Makefile.in, Makefile.in
+       necessary changes to include watch.c in libmalloc
+
+lib/readline/readline.c
+       - fix rl_delete_text to make sure that the starting position is >= 0
+       - _rl_init_line_state (called by readline via readline_initialize)
+         now sets rl_mark to 0
+       - rl_get_{next,previous}_history set rl_mark to 0 if rl_point is at
+         the end of the line and rl_end otherwise in emacs mode
+
+lib/readline/kill.c
+       - rl_yank_nth_arg_internal and rl_paste_clipboard now set the mark
+         at point before calling rl_insert_text, like rl_yank
+       - rl_kill_full_line now resets rl_mark to 0
+       - rl_kill_line and rl_backward_kill_line now set rl_mark to the
+         point after the kill in emacs mode
+       - rl_kill_word and rl_backward_kill_word now set rl_mark to the
+         point after the kill in emacs mode
+       - rl_unix_word_rubout and rl_unix_line_discard now set rl_mark to
+         the point after the kill in emacs mode
+
+lib/readline/search.c
+       - noninc_search saves and restores the mark, since it can be changed
+         while reading the search string
+       - noninc_dosearch sets the mark at the end of the line, making the
+         region bound the `inserted' text since rl_point is set to 0
+       - rl_history_search_internal sets the mark at the end of the line,
+         for the same reason
+
+lib/readline/isearch.c
+       - rl_search_history now saves and restores the mark
+       - if no matching lines are found at all when doing an isearch, leave
+         point where it was instead of moving it to the end of the line
+
+                                  12/17
+                                  -----
+lib/readline/rlmbutil.h
+       - new file, place for multi-byte character defines and extern
+         declarations
+
+lib/readline/{bind.c,readline.c,rlprivate.h}
+       - new bindable variable, `byte-oriented', tracks value of
+         rl_byte_oriented variable
+
+lib/readline/mbutil.c
+       - new file, with multibyte char utility functions
+
+lib/readline/{complete,display,readline,util,vi_mode}.c
+       - new code for multibyte characters, derived from IBM patch
+
+                                  12/18
+                                  -----
+lib/sh/tmpfile.c
+       - include posixtime.h for time() extern declaration
+
+support/bashversion.c
+       - include <unistd.h> if it's available
+
+lib/readline/{histexpand,input,isearch,search}.c
+       - new code for multibyte characters, derived from IBM patch
+
+lib/readline/readline.h
+       - include rltypedefs.h
+
+                                  12/19
+                                  -----
+lib/readline/complete.c
+       - slight change to mark-directories code to avoid adding a slash if
+         point is at the end of the line (rl_line_buffer[rl_point] == '\0')
+         and the previous character was a slash
+       - change printable_part to not return empty pathnames, which could
+         happen when completing filenames and a filename with a trailing
+         slash was passed as the argument.  If the portion following the
+         trailing slash is NULL, ignore it and look for a previous slash.
+         If there's no previous slash, just return the filename argument
+       - new variable, rl_completion_mark_symlink_dirs, mirrors the value
+         of (user-settable with a variable) _rl_complete_mark_symlink_dirs
+         but may be modified by application-specific completion functions
+         when appropriate (set in rl_complete_internal and rl_menu_complete)
+
+lib/readline/readline.h
+       - extern declaration for rl_completion_mark_symlink_dirs
+
+pcomplete.c
+       - if one of the actions is CA_DIRECTORY, set
+         rl_completion_mark_symlink_dirs to indicate that we want the
+         trailing slash (might have to relax this)
+
+lib/readline/doc/rltech.texinfo
+       - documented rl_completion_mark_symlink_dirs variable
+
+lib/readline/doc/rluser.texinfo, doc/bash.1
+       - documented the fact that `complete -d' and `complete -o dirnames'
+         force readline to append a slash to symlinks to directories
+
+builtins/enable.def
+       - changed enable_shell_builtin to disallow enabling disabled
+         builtins in a restricted shell
+
+doc/{bash.1,bashref.texi}
+       - documented new enable behavior in restricted shells
+
+doc/Makefile.in
+       - new rule to make an `RBASH' file documenting the restrictions
+         imposed by a restricted shell
+
+expr.c
+       - broke the code that evaluates variables and returns results out
+         of readtok() into a new function: expr_streval()
+       - expr_streval() now performs the standard unset variable error
+         behavior if `set -u' has been executed and it's asked to look
+         up an unset variable
+       - broke the code that frees up the expression context stack into
+         a new function: expr_unwind()
+
+variables.c
+       - fixed bind_int_variable so it handles array element assignment,
+         so expressions like `b[7]++' and `b[0] = 42' work right
+       - new function, get_variable_value, returns the string value of
+         the SHELL_VAR * passed as an argument
+       - get_string_value now calls get_variable_value with a non-null
+         result from find_variable
+
+                                  12/20
+                                  -----
+lib/readline/rlmbutil.h, mbutil.c
+       - combined _rl_find_next_mbchar and _rl_find_next_nonzero_mbchar into
+         a single function
+       - combined _rl_find_prev_mbchar and _rl_find_prev_nonzero_mbchar into
+         a single function
+
+lib/readline/{display,readline,vi_mode}.c
+       - changed callers of _rl_find_next_mbchar and
+         _rl_find_next_nonzero_mbchar
+
+lib/readline/{complete,display,histexpand,readline,vi_mode}.c
+       - changed callers of _rl_find_prev_mbchar and
+         _rl_find_prev_nonzero_mbchar
+
+                                  12/20
+                                  -----
+lib/sh/mktime.c
+       - new file, from glibc/gawk, compiled in if system doesn't have a
+         working mktime(3)
+
+lib/sh/strftime.c
+       - new file, from gawk, compiled in if system doesn't have a
+         working strftime(3)
+
+lib/sh/Makefile.in, Makefile.in
+       - changes for mktime.c, strftime.c
+
+configure.in
+       - call AC_FUNC_MKTIME, AC_STRUCT_TM, AC_STRUCT_TIMEZONE
+       - call AC_REPLACE_FUNC(strftime)
+
+config.h.in
+       - add defines for TM_IN_SYS_TIME, HAVE_TZSET, HAVE_TM_ZONE,
+         HAVE_STRUCT_TM_TM_ZONE, HAVE_STRFTIME
+
+externs.h
+       - provide an extern declaration for strftime if HAVE_STRFTIME is
+         not defined and NEED_STRFTIME_DECL is
+
+lib/tilde/tilde.h
+       - header files should not include <config.h>
+
+parse.y
+       - replace code in decode_prompt_string that chops up value returned
+         by ctime(3) with calls to strftime -- as a result, the expansion
+         of \@ has changed slightly (since it depends on the locale)
+       - added new \D{format} prompt string escape; `format' is passed to
+         strftime(3).  Empty format is the same as `%X' (locale-specific
+         representation of the current time)
+       - combined cases for '\\', '\a', '\e', and '\r' in same case branch
+         in decode_prompt_string
+
+doc/{bash.1,bashref.texi}
+       - documented new \D{format} prompt string expansion
+
+builtins/printf.def
+       - use ISO C PRIdMAX instead of INTMAX_CONV
+       - pass length of format modifiers to mklong instead of computing it
+         with strlen()
+
+lib/sh/{fmtulong,fmtullong}.c
+       - changes from Paul Eggert to make more general
+
+arrayfunc.c
+       - when converting a variable to an array, make sure to unset the
+         dynamic_value and assign_func members of the struct variable,
+         since they're not valid anymore
+
+                                  12/27
+                                  -----
+configure.in
+       - use AC_HELP_STRING in AC_ARG_WITH and AC_ARG_ENABLE 
+       - remove AC_ARG_ENABLE for largefile, since AC_SYS_LARGEFILE adds
+         one
+
+                                1/2/2002
+                                --------
+{alias,bashline,execute_cmd,general,shell,subst,variables,arrayfunc}.c,general.h
+       - changed some calls to strchr to calls to xstrchr for multibyte
+         characters
+
+include/shmbutil.h
+       - add extern declaration for xstrchr to avoid including externs.h
+         where it's not appropriate
+
+{braces,make_cmd,pathexp,subst,arrayfunc}.c, lib/sh/xstrchr.c
+       - include shmbutil.h
+
+{stringlib,subst}.c, {externs,subst}.h
+       - moved substring() from subst.c to stringlib.c, moved declaration
+         from subst.h to externs.h
+
+lib/sh/xmbsrtowcs.c
+       - new file, replacement function for mbsrtowcs
+
+lib/sh/Makefile.in
+       - add entries for xmbsrtowcs.c
+
+Makefile.in
+       - add dependencies on shmbutil.h to appropriate object files
+
+lib/glob/strmatch.c
+       - break character-class testing out into separate function:
+         is_cclass, in prep for multibyte changes
+
+{braces,make_cmd}.c
+       - changes for multibyte characters
+
+builtins/printf.def
+       - changes from Paul Eggert to just use intmax_t everywhere an
+         int/long/quad is needed and print with "%ld" if the number
+         fits in a long and %PRIdMAX otherwise
+       - remove getlong, getulong, getllong, getullong, since they're
+         no longer needed
+       - use a new type `floatmax_t' to print floating point numbers, the
+         widest-available floating point type (like `intmax_t'); new
+         function `getfloatmax' that calls strtold or strtod as appropriate
+       - remove getdouble, getldouble, since they're no longer needed
+
+lib/sh/fmtumax.c
+       - new file, string-to-[u]intmax_t conversion, just includes
+         fmtulong.c with the right defines
+
+Makefile.in, lib/sh/Makefile.in
+       - additions for fmtumax.c
+
+bashtypes.h
+       - include <inttypes.h> if it's available
+
+expr.c
+       - arithmetic is now in intmax_t instead of long
+
+externs.h
+       - extern declaration for fmtumax
+       - change extern declarations for evalexp, itos, inttostr,
+         uitos, uinttostr since they now return or use intmax_t instead
+         of long
+
+{execute_cmd,general,mailcheck,subst,variables}.c, parse.y
+{array,general,subst,test,variables}.h
+lib/sh/{itos,netopen}.c
+builtins/{bashgetopt,common}.c, builtins/common.h
+builtins/{break,fc,history,jobs,let,printf,pushd,read,shift,wait}.def
+       - changes for intmax_t shell arithmetic conversion
+
+doc/{bashref.texi,bash.1}
+       - documented long->intmax_t shell arithmetic conversion
+
+sig.c
+       - in initialize_terminating_signals, if we've already trapped a
+         terminating signal, don't reset the signal handler for it
+
+                                   1/3
+                                   ---
+{arrayfunc,pathexp}.c, parse.y
+       - changes for multibyte chars
+
+parse.y, lib/sh/strtrans.c
+       - moved ansiexpand from parse.y to lib/sh/strtrans.c
+
+parse.y, locale.c
+       - moved mk_msgstr and localeexpand from parse.y to locale.c
+
+parse.y
+       - new function, yy_input_name, returns name of input file from
+         bash_input.name
+       - broke the code that parses ((...)) constructs out of read_token
+         into a new function, parse_dparen()
+
+externs.h
+       - new extern declaration for ansiexpand(), mk_msgstr(), and
+         localeexpand()
+
+input.h
+       - new extern declaration for yy_input_name()
+
+{error,locale}.c
+       - use yy_input_name for error and other messages
+
+execute_cmd.c
+       - change shell_execve to make sure that the file is executable
+         before looking at the interpreter to find out why the execve()
+         failed (avoids misleading error message)
+
+lib/glob/glob.c
+       - move code that matches leading `.' and skips those filenames into
+         a separate function: skipname(), so there can be unibyte and
+         multibyte versions of that function
+
+                                   1/7
+                                   ---
+subst.c
+       - more changes for multibyte characters
+
+print_cmd.c
+       - change semicolon() so it doesn't output a `;' immediately after a
+         newline, since that results in a null command, which is a syntax
+         error
+
+variables.c
+       - fix indirection_level_string to turn off set -x while evaluating
+         PS4
+
+                                   1/8
+                                   ---
+builtins/set.def
+       - make -o options into one struct, instead of separate structs for
+         option names corresponding to flags and non-flag option names.
+         This has the side effect of sorting the option names in output
+
+lib/glob/glob.c
+       - new function, mbskipname(), multibyte char version of skipname()
+       - removed all #ifndef SHELL code, this will never be used outside
+         the shell
+
+include/posixdir.h
+       - move REAL_DIR_ENTRY define here from lib/glob/glob.c
+
+lib/glob/glob_loop.c
+       - new file, included in glob.c for unibyte and multibyte versions of
+         glob_pattern_p
+       - added some forward static function declarations with prototypes
+       - more changes for multibyte character handling
+
+lib/glob/Makefile.in
+       - make glob.c depend on glob_loop.c
+       - changes for xmbsrtowcs.[co]
+
+lib/glob/xmbsrtowcs.c
+       - moved here from lib/sh, since the matching functions use it, and
+         libglob.a is linked after libsh.a
+
+                                   1/9
+                                   ---
+lib/glob/smatch.c
+       - new file, with strmatch (now xstrmatch) and associated functions,
+         with changes for multibyte chars
+
+lib/glob/sm_loop.c
+       - new file, included by smatch.c, with `generic' versions of matching
+         functions that are compiled twice:  once each for single-byte and
+         multibyte characters
+
+lib/glob/strmatch.c
+       - strip out everything except strmatch(), which either calls fnmatch
+         (if HAVE_LIBC_FNM_EXTMATCH is defined) or xstrmatch
+
+lib/glob/collsyms.c
+       - changes for multibyte chars
+
+lib/glob/Makefile.in, Makefile.in
+       - changes for new source files
+
+                                  1/10
+                                  ----
+lib/readline/complete.c
+       - new function, rl_completion_mode (rl_command_func_t *func), returns
+         the appropriate value to pass to rl_complete_internal depending on
+         FUNC and the value of `show-all-if-ambiguous'.  This allows
+         application completion functions to present the same interface as
+         rl_complete
+
+lib/readline/readline.h
+       - new extern declaration for rl_completion_mode()
+
+lib/readline/doc/rltech.texinfo
+       - documented rl_completion_mode
+
+lib/readline/readline.[ch]
+       - bumped the version number to 4.3, changing the relevant cpp defines
+
+configure.in
+       - require that an installed readline version be at least readline-4.3
+
+bashline.c
+       - converted bash-specific completion functions to use
+         rl_completion_mode instead of passing TAB unconditionally
+
+builtins/bashgetopt.c
+       - the `#' option specifier now means a required numeric argument,
+         not an optional one
+
+builtins/type.def
+       - when converting [-]-{path,type,all} to -[pta], don't bother
+         freeing and reallocating the option string; just change opt[1]
+         and null opt[2]
+
+lib/sh/snprintf.c
+       - support %ls/%S and %lc/%C for wide strings and characters,
+         respectively, if HANDLE_MULTIBYTE is defined
+
+mailcheck.c
+       - don't print a message about new mail if the file has not grown,
+         even if the access time is less than the modification time
+
+                                  1/14
+                                  ----
+lib/readline/readline.c
+       - new function, rl_replace_line, to replace the readline line buffer
+         with the text supplied as an argument
+       - new function, rl_replace_from_history, replaces readline line
+         buffer with text from history entry passed as argument (undocumented,
+         not in readline.h because it requires a definition of
+         HIST_ENTRY for the prototype)
+
+lib/readline/readlne.h
+       - new extern declaration for rl_replace_line
+
+lib/readline/doc/rltech.texinfo
+       - documented rl_replace_line
+
+lib/readline/{isearch,readline,search}.c
+       - use rl_replace_line and rl_replace_from_history where appropriate
+
+lib/readline/readline.c
+       - broke the code that sets point after moving through the history
+         (_rl_history_preserve_point and _rl_history_saved_point) out
+         into a separate function, _rl_history_set_point()
+
+lib/readline/{complete.c,rlprivate.h}
+       - find_completion_word -> _rl_find_completion_word
+       - free_match_list -> _rl_free_match_list
+
+lib/readline/complete.c
+       - postprocess_matches and _rl_free_match_list now return immediately
+         if passed a null match list
+
+variables.c
+       - new function, find_local_variable, finds a local variable by name
+         at the current variable context
+       - in find_variable_internal, call find_local_variable before searching
+         any of the temporary environments if variable_context > 0 (meaning
+         we're in a shell function).  This lets a local variable
+         override a variable whose value was passed in the `function
+         environment'
+
+                                  1/15
+                                  ----
+variables.h, execute_cmd.c
+       - declare variables describing the temporary environments in
+         variables.h instead of in C files
+
+findcmd.c, builtins/setattr.def
+       - instead of calling find_tempenv_variable, use find_variable_internal
+         and check whether the returned SHELL_VAR * has the tempvar
+         attribute
+
+variables.c
+       - tentative change to lookup order in find_variable_internal so that
+         function local variables are found before variables in
+         function_env when executing a shell function
+       - change make_local_variable to handle making a local variable when
+         a variable with the same name already appears in one of the
+         temporary environments
+       - broke the body of make_var_array out into a new function:
+               static char **make_env_array_from_var_list (SHELL_VAR **vars)
+       - new function, make_var_array_internal, takes a hash table to look
+         in and a pointer to a mapping function and returns a char **
+         environment-style list
+       - make_var_array now just calls make_var_array_internal
+       - new mapping function, local_and_exported, returns all local variables
+         in the current variable context with the export attribute set
+       - new function, make_local_export_array, returns an environment-style
+         char ** array of exported local variables in current context
+       - change environment creation order in maybe_make_export_env to
+         add variables to the environment in opposite order that
+         find_variable_internal uses.  This means that local variables in
+         shell functions override variables with the same name in the
+         function_env
+       - change make_local_variable to set the initial value of the
+         variable it creates to NULL to make the `is set' and `is null'
+         tests that the expansion code does work right
+       - change make_local_variable to inherit the value of a variable with
+         the same name from the temporary enviroment
+
+                                  1/16
+                                  ----
+Makefile.in
+       - link bashversion with buildversion.o instead of version.o, for
+         cross-compiling.  version.o is for the target system;
+         buildversion.o is for the build system
+
+error.c
+       - add line numbers to internal_error() messages if the shell is
+         not interactive and running a shell script or a -c command
+       - report_error now prints non-zero line numbers for non-interactive
+         shells
+
+test.c
+       - test_syntax_error now calls builtin_error() instead of printing
+         its own messages
+
+builtins/common.c
+       - builtin_error now prints line numbers if a non-interactive shell
+         is running a shell script or a -c command
+
+print_cmd.c
+       - in cprintf, remove free_argp, since it's not used
+
+builtins/history.def
+       - make `history -n' increment the number of history lines in this
+         session by the number of lines read from the history file
+
+arrayfunc.c
+       - fix array_value_internal to expand the subscript even if the
+         variable is unset, so side effects produced by the arithmetic
+         evaluation will take place
+
+lib/readline/doc/{rluser,rltech}.texinfo
+       - some fixes for printing in @smallbook format from Brian
+         Youmans
+
+                                  1/17
+                                  ----
+jobs.h
+       - new PRUNNING, PSTOPPED, PDEADPROC defines for PROCESSes, analogous
+         to RUNNING, STOPPED, and DEADJOB defines for jobs
+
+jobs.c
+       - use PS_RUNNING, PS_DONE, PS_STOPPED values for `running' field
+         of a PROCESS
+       - find_pipeline and find_job now take an additional flags argument
+         that, if non-zero, means to find only running processes; changed
+         all callers
+       - changed calls to find_pipeline and find_job made from waitchld
+         to find only running processes
+       - find_pipeline takes a third argument: an int *.  If it looks in
+         the jobs list to find the pid, and the arg is non-null, it passes
+         the job index back to the caller.  Used to avoid calls to
+         find_pipeline immediately followed by find_job with the same PID
+
+nojobs.c
+       - a couple of changes to make sure that set_pid_status is never
+         called with a pid argument of 0 or -1
+
+trap.c
+       - change trap_handler to longjmp to wait_intr_buf (set by wait_builtin)
+         if a signal is received for which a trap has been set during
+         execution of the wait builtin (need to include builtins.h and
+         builtins/builtext.h and declare some extern variables for the
+         right things to check)
+       - new variable to keep track of which signal caused the longjmp to
+         wait_intr_buf, set by trap_handler (wait_signal_received)
+
+builtins/wait.def
+       - set the return value of wait when a longjmp(wait_intr_buf, 1) is
+         done to 128 + wait_signal_received
+
+{jobs,nojobs}.c
+       - set wait_signal_received to SIGINT in wait_sigint_handler before
+         the longjmp(wait_intr_buf, 1)
+
+                                  1/18
+                                  ----
+bashline.c
+       - turn off rl_filename_completion_desired when completing a command
+         name with a single match only if the first char of that match is
+         not a `/'
+       - if there are multiple identical matches for a command name in
+         attempt_shell_completion, turn off rl_filename_completion_desired
+         if the first char is not a `/' to avoid readline appending a
+         slash if there's a directory with the same name in the current
+         directory
+
+                                  1/22
+                                  ----
+lib/readline/complete.c
+       - new variable, _rl_page_completions, to control whether we want to
+         run the internal pager when listing completions (defaults to 1)
+
+lib/readline/rlprivate.h
+       - extern declaration for _rl_page_completions
+
+lib/readline/bind.c
+       - new bindable variable, `page-completions', controls value of
+         _rl_page_completions
+
+lib/readline/doc/{rluser.texinfo,readline.3}, doc/bash.1
+       - documented `page-completions' variable
+
+Makefile.in
+       - use $(INSTALL_SCRIPT) instead of $(INSTALL_PROGRAM) to install
+         `bashbug'
+
+aclocal.m4
+       - fix small quoting problem in RL_LIB_READLINE_VERSION macro
+
+lib/readline/terminal.c
+       - fetch and save terminal's `vs' and `ve' cursor control attributes
+       - fetch and save terminal's `kI' attribute (string sent by Insert)
+       - new function, _rl_set_cursor, sets cursor to normal (insert mode)
+         or very visible (overwrite mode)
+
+lib/readline/readline.c
+       - new global variable, rl_insert_mode
+       - new function to toggle overwrite mode, rl_overwrite_mode
+       - each new line starts in insert mode
+       - switching to vi mode or emacs mode resets to insert mode
+       - reset cursor to normal before returning line
+       - _rl_replace_text now returns the number of characters inserted,
+         the return value from rl_insert_text
+       - new function, _rl_insert_or_replace_text (const char *string, int insert),
+         either inserts STRING or replaces the number of chars in STRING
+         with STRING starting at rl_point, depending on value of INSERT
+       - renamed rl_insert to _rl_insert_char, rl_insert just calls
+         _rl_insert_char with the same arguments when in insert mode
+       - new function, _rl_overwrite_char, handles self-insert in overwrite
+         mode.  Does multibyte chars by reading an entire multibyte character
+         before entering overwrite loop
+       - new function, _rl_overwrite_rubout, handles RUBOUT when in
+         overwrite mode, called from rl_rubout
+       - new function, _rl_rubout_char, old body of rl_rubout; rl_rubout
+         calls this when not in overwrite mode 
+
+lib/readline/readline.h
+       - extern declarations for rl_insert_mode and rl_overwrite_mode()
+
+lib/readline/rldefs.h
+       - define constants for values of rl_insert_mode
+
+lib/readline/rlprivate.h
+       - extern declarations for _rl_set_cursor and _rl_set_insert_mode
+       - change type of _rl_replace_text to return int
+       - extern declarations for _rl_insert_char, _rl_rubout_char
+
+lib/readline/funmap.c
+       - new bindable name `overwrite-mode', bound to rl_overwrite_mode
+
+lib/readline/rlconf.h
+       - define CURSOR_MODE if you want the cursor to show insert or
+         overwrite mode (only available if both `vs' and `ve' capabilities
+         are present)
+
+lib/readline/{complete,parens,readline,search,vi_mode}.c
+       - change calls to rl_insert to _rl_insert_char
+
+lib/readline/{readline,search}.c
+       - change calls to rl_rubout to _rl_rubout_char to avoid overwrite
+         mode problems
+
+lib/readline/vi_mode.c
+       - fix rl_vi_overstrike to just call _rl_overwrite_char, which
+         handles multibyte chars
+
+lib/readline/doc/{rluser.texinfo,readline.3}, doc/bash.1
+       - document new `overwrite-mode' command
+
+                                  1/23
+                                  ----
+lib/readline/readline.c
+       - return 0 immediately from rl_insert_text if the string to insert
+         is NULL or ""
+
+bashline.c
+       - if a numeric argument is given to one of the bash-specific glob
+         pattern completion functions (including TAB), append a `*' to
+         the word before generating matches
+       - in attempt_shell_completion, when doing glob completion, only
+         set the match list to NULL if rl_completion_type == TAB and
+         there is more than one completion.  This permits listing completions
+         with double tabs and displaying ambiguous completions
+       - new function, bash_glob_complete_word, appends a `*' to the word
+         to be completed and then globs it.  It uses a new filename
+         quoting function (bash_glob_quote_filename) to avoid quoting
+         globbing characters in the filename if there are no matches or
+         multiple matches
+
+lib/readline/complete.c
+       - set completion_changed_buffer to 0 in rl_complete_internal if
+         no matches were produced by the completion generator function
+       - new variable, rl_completion_suppress_append, suppresses appending
+         of rl_completion_append_character.  Settable by application
+         completion functions, always 0 when application completion
+         functions are called (set to 0 by rl_complete_internal and
+         rl_menu_complete)
+       - broke the code that assigns default values to readline completion
+         variables out of rl_complete_internal and rl_menu_complete into
+         a new function, set_completion_defaults (int what_to_do)
+
+lib/readline/readline.h
+       - extern declaration for rl_completion_suppress_append
+
+lib/readline/doc/rluser.texinfo, doc/bash.1
+       - documented behavior of glob-expand-word and glob-list-expansions
+         when supplied a numeric argument
+       - documented glob-complete-word
+
+lib/readline/doc/rltech.texinfo
+       - documented rl_completion_suppress_append
+
+                                  1/24
+                                  ----
+lib/readline/text.c
+       - new file, text and character handling functions from readline.c
+
+lib/readline/misc.c
+       - new file, miscellanous bindable functions and their supporting
+         code from readline.c
+
+Makefile.in, lib/readline/Makefile.in
+       - changes for text.c, misc.c
+
+lib/readline/bind.c
+       - change ISKMAP case of rl_invoking_keyseqs_in_map to output
+         ESC as "\M-" instead of "\e" -- it's closer to the documentation
+       - change _rl_get_keyname to output ESC as \e instead of \C-[
+         (it's easier to understand)
+
+pcomplete.h
+       - new flag, COPT_NOSPACE
+
+builtins/complete.def
+       - new `-o nospace' option for complete and compgen (though it doesn't
+         really do anything for compgen, since that doesn't hand anything
+         off to readline)
+
+bashline.c
+       - if a programmable completion specifies COPT_NOSPACE, set
+         rl_completion_suppress_append = 1
+
+lib/readline/doc/rluser.texinfo
+       - documented new `-o nospace' option to complete and compgen
+
+doc/{bash.1,bashref.texi}
+       - documented $'\cX' escape sequence (forgot to before)
+
+                                  1/28
+                                  ----
+variables.c
+       - make_new_variable now takes the HASH_TABLE * as its second
+         argument; changed callers
+       - new function, bind_variable_in_table, takes the HASH_TABLE * as
+         its third paramter; bind_variable calls bind_variable_in_table
+         with shell_variables as third argument
+
+variables.h
+       - new struct var_context, variable context (per-scope -- global,
+         function local, etc.)
+
+variables.[ch],builtins/common.[ch]
+       - moved functions that push and pop a variable context from
+         builtins/common.c to variables.c; move extern function
+         declarations to variables.h
+       - new function, all_local_variables
+       - variable_in_context is now static, used only by all_local_variables
+
+variables.[ch],execute_cmd.c
+       - push_context now takes the function name as an argument for
+         future use
+       - push_context takes an indication of whether or not the function is
+         executing in a subshell and saves the positional parameters only
+         if not in a subshell
+       - new functions for managing a stack of variable contexts and
+         scopes:  new_var_context, dispose_var_context, push_var_context,
+         pop_var_context, push_scope, pop_scope
+
+builtins/declare.def
+       - call all_local_variables instead of map_over (...) in declare_internal
+       - don't call make_local_variable if we're looking at functions
+         ((flags_on & att_function) != 0), since it's wasted
+       - make sure VAR is set to NULL if check for variable_context fails
+         and we didn't just create or fetch a local variable in
+         declare_internal
+       - in non-function branch of declare_internal, only call find_variable
+         if VAR is NULL -- if it's not null, we just created or fetched a
+         local variable and don't need to do it again
+
+                                  1/29
+                                  ----
+variables.[ch]
+       - the temporary environments (temporary_env, builtin_env, function_env)
+         are now HASH_TABLEs instead of argv-style arrays of strings (this
+         is an intermediate step on the way to the new lcc-inspired symbol
+         table scope structure)
+       - new internal attribute for variables: att_propagate.  This means
+         to propagate the value out of the temporary environment up the
+         (for now implicit) chain of variable scopes when the containing
+         temporary environment is deleted
+
+variables.c
+       - assign_in_env now adds to the HASH_TABLE temporary_env instead
+         of making environment-style strings in an array of strings
+       - changed the way the temporary environments are merged into the
+         shell variable table to account for the new HASH_TABLE temp
+         environments
+       - changed the way the export environment is created due to the new
+         structure of the temporary environments
+       - new function, bind_variable_internal (name, value, table), binds
+         NAME to have VALUE in TABLE without searching the temporary
+         environments
+       - removed: shell_var_from_env_string, bind_name_in_env_array
+       - variable_in_context now checks the att_local attribute and makes
+         sure the variable is not invisible
+       - local_and_exported now makes sure the variable is not invisible
+
+execute_cmd.c
+       - we no longer need to copy the temporary environment to function_env
+         or builtin_env, we can simply use variable assignments
+
+{findcmd,subst,variables}.c, builtins/{declare,setattr}.def
+       - since variables from the temporary environments are no longer turned
+         into SHELL_VARs on the fly, don't dispose the SHELL_VAR returned
+         by find_variable or find_variable_internal
+       - need to savestring() the value returned by find_variable if it has
+         the tempvar attribute before calling bind_variable on it, because
+         bind_variable will search and bind into the temporary environments
+         and will free the old value before binding the new.  For temporary
+         environments, these two pointers will be the same, and
+         bind_tempenv_variable will end up using freed memory
+
+builtins/{declare,setattr}.def
+       - set the att_propagate attribute when exporting or making readonly
+         variables from the temp environment (i.e., `var=value declare -x var'
+         or `var=value export var' sets the propagate attribute on the entry
+         for `var' in the temporary environment HASH_TABLE)
+
+lib/readline/isearch.c
+       - ^W when reading isearch string yanks the current word out of the
+         current line into the search string, skipping the portion already
+         matched
+       - ^Y when reading isearch string yanks the rest of the current line
+         into the search string, skipping the portion already matched
+
+                                  1/30
+                                  ----
+{print_cmd,variables}.c
+       - moved indirection_level_string() from variables.c to print_cmd.c
+
+{externs,variables}.h
+       - moved extern declaration of indirection_level_string to externs.h
+
+{general,variables}.c
+       - moved assignment() from variables.c to general.c
+
+{general,variables}.h
+       - moved extern declaration of assignment() to general.h
+
+{externs,input}.h
+       - moved extern declaration of decode_prompt_string to externs.h
+
+print_cmd.c
+       - include flags.h, don't include stdc.h
+
+variables.c
+       - moved some functions around to group functions better
+       - changed new_shell_variable to explicitly initialize each member
+         of the created struct variable instead of calling bzero()
+       - make_new_variable now just calls new_shell_variable instead
+         of duplicating what it does
+       - removed some code in bind_function that duplicated what
+         new_variable does on the newly-created SHELL_VAR
+       - since there are no local function variables (functions are always
+         made at the global scope), kill_all_local_variables() doesn't
+         need to consider functions
+
+                                  1/31
+                                  ----
+variables.c
+       - sort the array of special variables
+       - short-circuit the search in stupidly_hack_special_variables if
+         the passed name can't be found in the rest of the array
+         (that is, if name[0] < special_vars[i].name[0])
+
+lib/readline/history.c
+       - unstifle_history() was returning values exactly opposite of
+         the documentation
+
+lib/readline/doc/{hsuser.texinfo,history.3}
+       - clarified the unstifle_history() documentation a little
+
+                                   2/4
+                                   ---
+variables.c
+       - in bind_variable, don't call bind_tempenv_variable after a
+         find_tempenv_variable succeeds -- just change the value inline.
+         There's no reason to look it up twice
+       - change makunbound to only call stupidly_hack_special_variables
+         if we're not unsetting a function
+
+variables.[ch]
+       - new function, unbind_function, like makunbound but doesn't mess
+         with previous contexts or calling stupidly_hack_special_variables
+
+builtins/set.def
+       - change unset_builtin to call either unbind_func or unbind_variable
+
+builtins/getopts.def
+       - call unbind_variable(name) instead of makunbound(name, shell_variables)
+
+                                   2/5
+                                   ---
+lib/glob/sm_loop.c
+       - use malloc instead of xmalloc in BRACKMATCH and handle failures
+
+error.c
+       - add extern declaration of executing_line_number with prototype,
+         since execute_cmd.h can't be included without including other
+         files
+
+lib/readline/parens.c
+       - include <unistd.h>
+
+lib/malloc/stats.c
+       - include <unistd.h>
+       - add extern declaration of malloc_free_blocks() with prototype
+
+pathexp.c
+       - added some forward declarations with prototypes for static functions
+
+lib/readline/rlprivate.h
+       - removed declarations of rl_untranslate_keyseq, rl_discard_argument,
+         rl_stop_output, rl_alphabetic since they appear in readline.h
+
+                                   2/6
+                                   ---
+{arrayfunc,execute_cmd,pcomplete,shell}.c
+       - change calls to makunbound(name, shell_variables) to
+         unbind_variable (name)
+
+                                   2/7
+                                   ---
+builtins/getopt.c
+       - don't defer incrementing of OPTIND when an invalid option is
+         encountered until the next call to sh_getopt() -- what if OPTIND
+         is reset before that next call?  This means that OPTIND is always
+         incremented to the next option to be handled when an option is
+         returned, whether it's valid or not.  This is what POSIX-2002
+         says to do.
+
+syntax.h
+       - new #define, CSUBSTOP
+
+mksyntax.c
+       - add "-=?+" with value CSUBSTOP to the syntax table.  These are the
+         valid expansion operators OP in ${param[:]OPword}
+
+subst.c
+       - use table lookup for CSUBSTOP in VALID_PARAM_EXPAND_CHAR
+       - new flags for the string extraction functions:  EX_NOALLOC.  This
+         indicates that the functions are being used only to skip over
+         strings and the result won't be used, so the substring shouldn't
+         be allocated, copied, and freed
+       - new flag for string_extract:  EX_VARNAME.  This serves the same
+         purpose as the old `varname' parameter.  parameter_brace_expand()
+         changed appropriately
+       - extract_delimited_string and extract_dollar_brace_string now take
+         an additional `flags' argument, which may include EX_NOALLOC
+       - changed callers of extract_delimited_string and
+         extract_dollar_brace_string appropriately
+       - string_extract now understands EX_NOALLOC; callers changed
+       - some smaller code cleanups
+       - converted char_is_quoted(), unclosed_pair(), and skip_to_delim()
+         to understand multibyte characters
+
+                                  2/11
+                                  ----
+variables.[ch]
+       - moved to a symbol organization inspired by lcc.  The basic structure
+         is no longer a HASH_TABLE, but a VAR_CONTEXT, which includes a hash
+         table as one of its members.  VAR_CONTEXTs are linked together to do
+         variable scoping.  One nice thing about this is that the entire
+         symbol table doesn't need to be searched at function scope exit to
+         remove local variables.  Fixes problems with only one instance of
+         builtin_env and function_env, even though it really is a stack
+       - shell_variables is now a VAR_CONTEXT *, with a global_variables
+         variable that points to the bottom of the stack for fast access
+       - function-scope local variables (assignments specified on the command
+         line before a function call) and function-local variables (declared
+         with the `local' builtin) have been unified in the same variable
+         context, replacing function_env
+       - assignment statements preceding the `.' and `eval' builtins are now
+         a separate variable scope VAR_CONTEXT, replacing builtin_env
+       - temporary_env (a HASH_TABLE) is now the only separate environment
+       - changes to export environment creation, variable binding, variable
+         lookup, local variable propagation all changed to work with the
+         new symbol table/scope structure
+       - a SHELL_VAR no longer has a `prev_context' member; it's not needed
+
+execute_cmd.c
+       - changes to push_context calls to include any temporary variables in
+         temporary_env; pop_context takes care of propagating any temporary
+         variables if necessary
+       - calls to push_scope if `eval' or `.' is called with a list of
+         preceding variable assignments, and pop_scope called at end of
+         builtin's execution.  pop_scope takes care of merging temporary
+         variables into the shell environment when appropriate
+
+builtins/{setattr,declare}.def
+       - changes to account for variable assignments preceding `local',
+         `export', `readonly', `declare', etc. to work with the new
+         variable scoping implementation
+
+shell.c
+       - since shell_variables is now a VAR_CONTEXT, call
+         delete_all_contexts() when the shell is reinitializing instead of
+         delete_all_variables()
+
+builtins/common.c
+       - new function, get_job_by_name(), used by execute_simple_command()
+         for the `auto_resume' stuff and get_job_spec()
+
+builtins/common.h
+       - new set of #defined constants for flags argument to
+         get_job_by_name()
+
+                                  2/12
+                                  ----
+command.h
+       - new redirection operator: r_reading_string for `here strings'
+
+parse.y
+       - new token, LESS_LESS_LESS, for new redirection `here string'
+         operator: [N]<<< word
+       - recognize LESS_LESS_LESS and create the appropriate redirection
+
+{dispose_cmd,copy_cmd,make_cmd,print_cmd}.c
+       - recognize r_reading_string and do the right thing (dispose_redirects,
+         copy_redirect, print_redirection, and make_redirection, respectively)
+
+redir.c
+       - here_document_to_fd now takes the redirection operator as its
+         second argument
+       - new function, write_here_string, expands a here string and writes it
+         to the here document file descriptor
+       - here_document_to_fd calls write_here_string for r_reading_string
+         operator
+       - handle r_reading_string in do_redirection_internal() and
+         stdin_redirection()
+
+                                  2/18
+                                  ----
+doc/{bash.1,bashref.texi}
+       - documented here strings
+
+{configure,Makefile}.in
+       - bumped version number up to bash-2.05b and the release status
+         to alpha1
+
+expr.c
+       - make expr_streval understand that variables with the `invisible'
+         attribute are really unset, and accessing such a variable when
+         `set -u' is set should be an error
+
+variables.h
+       - new accessor macros: var_isset(var) and var_isnull(var), test
+         whether var->value is NULL
+
+{eval,subst,variables}.c, builtins/{declare,setattr}.def
+       - be more consistent about using value_cell(var) instead of
+         directly referencing var->value
+       - use var_isset and var_isnull where appropriate
+
+builtins/help.def
+       - augmented a couple of help strings with pointers to `info' and
+         `man -k'
+
+                                  2/14
+                                  ----
+variables.h
+       - new macros to use when setting variable values directly instead of
+         through bind_variable and its siblings
+
+{arrayfunc,variables}.c
+       - use var_setarray and other lvalue macros instead of assigning to
+         var->value directly
+
+builtins/setattr.def
+       - change show_var_attributes to show function definitions separately
+         from function attributes.  This allows the output of `declare -f'
+         (with other flags), `export -f', and `readonly -f' to be reused as
+         shell input, instead of the old
+
+               declare -f[flags] func()
+               {
+                       foo
+               }
+
+         which has syntax errors.  When in posix mode, `export -fp' and
+         `readonly -fp' still don't print function definitions
+
+                                  2/16
+                                  ----
+parse.y
+       - comment out calls to discard_parser_constructs; no need to call
+         empty functions
+
+                                  2/18
+                                  ----
+lib/sh/memset.c
+       - replacement function for memset(3)
+
+lib/sh/Makefile.in, Makefile.in
+       - additions for memset.c
+
+configure.in,config.h.in
+       - check for memset, define HAVE_MEMSET if found, add memset.o to
+         LIBOBJS if not
+
+lib/malloc/malloc.c
+       - removed zmemset(), replaced with calls to memset(3)
+
+{subst,execute_cmd,lib/sh/netopen}.c
+       - replaced calls to bzero with calls to memset
+
+subst.c
+       - word_split() now takes a second argument: the value of $IFS, so
+         it doesn't have to look up IFS every time
+       - word_list_split() now calls getifs() and passes the result to
+         each call to word_split() as its second arg
+       - do a quick scan for CTLNUL in remove_quoted_nulls before allocating
+         new string, copying old string to it, copying over original string
+         and freeing new string
+
+eval.c
+       - don't bother calling dispose_used_env_vars if temporary_env is NULL
+
+execute_cmd.c
+       - fix fix_assignment_words to only look up the builtin corresponding
+         to the first word if one of the words in the list is marked as
+         W_ASSIGNMENT
+
+hashlib.c
+       - renamed hash_string to hash_bucket, which better reflects what it
+         does
+       - extracted the portion of hash_bucket that computes the hash out
+         into a new hash_string()
+       - made new body of hash_bucket into a macro HASH_BUCKET; function
+         just calls the macro
+       - calls to hash_bucket in this file now call HASH_BUCKET macro
+       - in add_hash_item, just add a new item at the front of the appropriate
+         bucket list instead of at the end
+
+hashcmd.h
+       - reduced FILENAME_HASH_BUCKETS to 53 from 107
+
+                                  2/19
+                                  ----
+hashlib.[ch]
+       - find_hash_item, remove_hash_item, add_hash_item all take a new
+         third `flags' argument
+       - add_hash_item doesn't call find_hash_item if HASH_NOSRCH passed in
+         flags arg
+       - find_hash_item will create a new hash table entry if HASH_CREATE is
+         passed in flags arg
+       - new function, hash_walk, takes a pointer to a function and a table
+         and calls the function for each item in the table.  If the function
+         returns < 0, the walk is terminated
+       - fixed flush_hash_table to set table->nentries to 0 after freeing
+         all entries
+       - BUCKET_CONTENTS now has a new `khash' member, what key hashes to;
+         set by HASH_BUCKET macro (which calls hash_string), assigned in
+         find_hash_item (HASH_CREATE) and add_hash_item
+       - find_hash_item and remove_hash_item check `khash' against the
+         hash of the string argument before calling strcmp
+
+{alias,hashlib,hashcmd,pcomplib,variables}.c
+       - changed all calls to {find,remove,add}_hash_item
+
+builtins/hash.def
+       - return immediately from print_hashed_commands if there are no
+         entries in the hash table (this eliminates need for `any_printed'
+         variable)
+       - change print_hashed_commands to use hash_walk
+
+alias.c
+       - short-circuit all_aliases and map_over_aliases if
+         HASH_ENTRIES(aliases) == 0
+       - simplify map_over_aliases by just allocating enough room in the
+         returned list for all entries in the aliases hash table, instead
+         of doing the check and xrealloc
+       - add_alias now calls add_hash_item with HASH_NOSRCH argument
+
+pcomplete.h
+       - sh_csprint_func_t is no more; use hash_wfunc instead
+
+pcomplib.c
+       - short-circuit print_all_compspecs if HASH_ENTRIES(prog_completes)
+         is 0
+       - print_all_compspecs now takes a `hash_wfunc *' argument
+       - print_all_compspecs now just calls hash_walk
+
+builtins/complete.def
+       - new function, print_compitem, takes a BUCKET_CONTENTS *, extracts
+         the right info, and calls print_one_completion
+
+variables.c
+       - short-circuit map_over_funcs if HASH_ENTRIES(shell_functions) == 0
+       - short-circuit flatten if the passed table has no entries
+       - bind_variable_internal takes a new fourth argument: `hflags',
+         to pass to hash table functions
+       - make_new_variable now passes HASH_NOSRCH flag to add_hash_item
+       - set_if_not now calls bind_variable_internal and passes
+         HASH_NOSRCH as flags argument
+       - bind_function now calls add_hash_item with HASH_NOSRCH argument
+       - fixed make_local_variable:  old_var == 0 && was_tmpvar can never
+         be true
+       - if we didn't find an old variable in make_local_variable, call
+         bind_variable_internal with HASH_NOSRCH argument
+       - fix push_temp_var to reset variable context to 0 if binding into
+         global_variables->table
+
+parse.y
+       - fix to parse_compound_assignment to avoid core dumps on empty
+         compound array assignments
+
+subst.c
+       - getifs() is now global so read_builtin can call it
+
+subst.h
+       - extern declaration for getifs()
+
+                                  2/20
+                                  ----
+hashlib.c
+       - changed hash_string to use a better hash function
+       - changed HASH_BUCKET to use masking rather than modulus to hash a
+         string to a bucket -- HASH TABLES MUST NOW BE SIZED BY POWERS
+         OF TWO
+
+hashlib.h
+       - DEFAULT_HASH_BUCKETS is now 64
+
+hashcmd.h
+       - FILENAME_HASH_BUCKETS is now 64
+
+pcomplib.c
+       - COMPLETE_HASH_BUCKETS is now 32
+
+variables.c
+       - TEMPENV_HASH_BUCKETS is now 4
+
+alias.c
+       - new define, ALIAS_HASH_BUCKETS, set to 16, used to size alias table
+
+hashlib.c
+       - removed initialize_hash_table; folded code into make_hash_table
+       - fixed copy_bucket_array to copy the `khash' member of an item
+       - renamed functions to be more systematic and easier for me:
+               make_hash_table -> hash_create
+               hash_table_nentries -> hash_size
+               copy_hash_table -> hash_copy
+               find_hash_item -> hash_search
+               remove_hash_item -> hash_remove
+               add_hash_item -> hash_insert
+               flush_hash_table -> hash_flush
+               dispose_hash_table -> hash_dispose
+               print_table_stats -> hash_pstats
+               get_hash_bucket -> hash_items
+       - changed hash_search to short-circuit if table->nentries == 0 and
+         HASH_CREATE has not been passed in the flags argument
+
+{alias,variables,hashcmd,pcomplib}.c
+       - renamed calls to all renamed functions from hashlib.c
+
+builtins/kill.def
+       - don't drop a leading `-' in a pid argument
+       - call kill_pid with an explicit third argument of 1 if the pid
+         argument to kill is < -1, rather than rely on the behavior of
+         kill(2)
+
+                                  2/21
+                                  ----
+subst.c
+       - quoted_strchr is no longer declared `inline'
+       - skip_double_quoted is no longer declared `inline'
+       - string_extract_double_quoted is no longer declared `inline'
+
+lib/readline/input.c
+       - rl_gather_tyi is now an `int' valued function; returns the number
+         of characters read (0 or 1) or -1 on error
+       - if rl_gather_tyi() returns -1 to rl_read_key(), set rl_done to 1
+         and return a newline; something is wrong with the input fd
+
+                                  2/25
+                                  ----
+variables.[ch]
+       - IFS is now a special variable
+       - new special var function, sv_ifs(), called when IFS is set or unset
+       - call setifs() when IFS is first set in initialize_shell_variables
+       - call setifs() from make_local_variable and assign_in_env if
+         appropriate
+       - if assign_in_env() is called with a var assignment like `VAR=',
+         make the value in the new SHELL_VAR created be "" like
+         do_assignment_internal does, since certain parts of the shell use
+         a NULL value as evidence that the variable is unset (though
+         attributes may have been assigned)
+       - if push_temp_var pushes something up to the global_variables table,
+         make sure that the context is set to 0
+       - new function dispose_temporary_env, called by both
+         dispose_used_env_vars and merge_temporary_env with different `free
+         func' function pointers; calls sv_ifs after disposing the temporary
+         environment
+       - push_exported_var now calls bind_variable_internal instead of
+         bind_variable
+       - pop_scope and pop_context now call sv_ifs
+
+subst.[ch]
+       - new global variables used to keep track of IFS state, to avoid
+         having to call find_variable("IFS") all the time:
+
+               ifs_var         the SHELL_VAR for IFS
+               ifs_value       ifs_var ? value_cell (ifs_var) : " \t\n"
+               ifs_cmap        bitmap of characters in ifs_value
+               ifs_firstc      first character in ifs_value
+
+       - new function setifs(), sets the aforementioned ifs variables each
+         time IFS is set or unset, and at nested scope exit
+       - instead of calling getifs() from inside subst.c, use ifs_value
+       - getifs() now just returns ifs_value
+       - use ifs_firstc in string_list_dollar_star()
+       - only call member() in issep() if separators is more than one char
+       - don't cache a bitmap every time expand_word_internal() is called;
+         use ifs_cmap instead
+       - new macro, isifs(c), checks whether C is in ifs_cmap
+
+builtins/read.def
+       - use issep() and isifs() macros instead of looking at $IFS directly
+
+syntax.h
+       - make sure macros that access sh_syntaxtab cast the argument to
+         `unsigned char' before array access
+       - new macros: issyntype(c, type) and notsyntype(c, type), check
+         sh_syntaxtab[c] for a particular flag value `type'
+
+                                  2/26
+                                  ----
+hashlib.h
+       - the `data' member of a `BUCKET_CONTENTS' is now a PTR_T
+
+{hashlib,alias,variables,hashcmd,pcomplib}.c
+       - removed some casts when assigning to and using `data' member of a
+         `BUCKET_CONTENTS'
+
+subst.c
+       - in split_at_delims, call make_word_list instead of allocating and
+         initializing a WORD_LIST * directly
+
+make_cmd.[ch]
+       - add_string_to_list is now just a macro that calls make_word_list
+       - make_simple_command now calls make_word_list instead of allocating
+         a WORD_LIST * directly
+
+                                  2/27
+                                  ----
+copy_cmd.c
+       - copy_word now calls make_bare_word to allocate the copy
+       - copy_word_list now calls make_word_list to allocate the copy
+
+shell.h
+       - include `ocache.h' for simple object caching
+       - call cmd_init() to initialize the WORD_DESC and WORD_LIST object
+         caches
+
+{make,dispose}_cmd.c
+       - allocate WORD_DESC * and WORD_LIST * vars from their respective
+         ocaches, and return them to the cache when disposing
+
+jobs.c
+       - renamed old `waiting_for_job' variable to `queue_sigchld', which
+         better reflects its intent:  sigchld_handler does not call waitchld
+         if `queue_sigchld' is non-zero, it simply increments the count of
+         waiting children
+       - cleanup_dead_jobs now just sets and clears queue_sigchld instead of
+         blocking and unblocking SIGCHLD; it calls waitchld at the end if
+         `sigchld' is non-zero, but that's not really necessary
+       - in setjstatus, only call xrealloc if `statsize' is less than the
+         number of processes passed -- no reason to do it if they're the
+         same
+
+                                  2/28
+                                  ----
+sig.[ch]
+       - reinitialize_signals is no more; initialize_signals takes an
+         argument saying whether or not we are reinitializing
+
+builtins/exec.def
+       - reinitialize_signals() -> initialize_signals(1)
+
+test.c
+       - fix filecomp() to work right when one file has a non-positive
+         timestamp and the other file does not exist
+
+doc/{bash.1,bashref.texi}
+       - document what happens for test's -nt and -ot operators when one
+         file operand exists and the other does not
+
+jobs.c
+       - if we haven't messed with SIGTTOU, just manipulate queue_sigchld
+         in notify_of_job_status instead of calling sigprocmask()
+       - list_one_job now calls pretty_print_job directly instead of going
+         through print_job
+       - pretty_print_job now must be called with SIGCHLD blocked or held
+         instead of blocking SIGCHLD itself
+       - changed start_job so that it doesn't call UNBLOCK_CHILD and then
+         immediately call BLOCK_CHILD again (explicitly or via last_pid()),
+         call find_last_pid instead of last_pid and then UNBLOCK_CHILD
+       - changed wait_for_job the same way
+       - find_last_pid now takes a second argument: block; uses BLOCK_CHILD
+         if `block' is 1, not otherwise.  Changed existing calls:
+               find_last_pid(j) -> find_last_pid(j, 0)
+               last_pid(j) -> find_last_pid(j, 1)
+         `last_pid()' is now gone
+       - rewrote wait_for_background_pids(); it was a little strange
+       
+copy_cmd.c
+       - copy_if_command: don't copy null false_case commands
+       - copy_simple_command: don't copy a null redirection list
+
+subst.c
+       - in get_word_from_string and list_string, just check for " \t\n"
+         directly rather than calling strcmp
+       - in get_word_from_string and strip_trailing_ifs_whitespace, use
+         isifs() instead of issep(), since they're never called with
+         separators != $IFS
+       - change issep() to call isifs if separators is longer than one
+         character, since it's never called with anything but "", " ",
+         or $IFS
+
+                                   3/1
+                                   ---
+sig.h
+       - enclose the BLOCK_SIGNAL macro in a do {...} while (0) loop, at it
+         should have been all along
+
+lib/readline/doc/rltech.texinfo
+       - document that readline defaults to stdin/stdout if rl_instream/
+         rl_outstream are NULL
+
+lib/readline/terminal.c
+       - if an application is using a custom redisplay function,
+         rl_resize_terminal just calls rl_forced_update_display to tell
+         (*rl_redisplay_func) to update the display, otherwise call
+         _rl_redisplay_after_sigwinch
+
+lib/readline/readline.c
+       - change readline_internal_setup() so the change to vi insertion mode
+         happens even if readline_echoing_p is 0
+       - don't print the prompt to rl_outstream in readline_internal_setup
+         if we're not echoing and the caller has defined a custom redisplay
+         function -- let the redisplay function deal with it
+
+configure.in
+       - new option: --enable-mem-scramble, controls memory scrambling on
+         free() (on by default; only affects use of bash malloc)
+
+config.h.in
+       - new option MEMSCRAMBLE, controlled by --enable-mem-scramble
+
+                                   3/5
+                                   ---
+parse.y
+       - added ksh-like behavior of [...] to read_token_word:  if a `[' is
+         seen in an assignment context and the previous characters in the
+         token form a valid identifier, parse the [...] with
+         parse_matched_pair to allow spaces (and newlines) in the subscript
+
+bashline.c
+       - new function bash_servicename_completion_function, for completing
+         service names from /etc/services
+
+bashline.h
+       - new extern declaration for bash_servicename_completion_function
+
+builtins/complete.def
+       - allow new `-s/-A service' option to complete and compgen builtins
+
+pcomplete.h
+       - new CA_SERVICE define, new ITEMLIST variable it_services
+
+pcomplete.c
+       - add callback to bash_servicename_completion_function to generate
+         list of matching service names for completion
+
+doc/bash.1,lib/readline/doc/rluser.texinfo
+       - documented new `-s/-A service' option to complete and compgen
+
+                                   3/6
+                                   ---
+builtins/read.def
+       - change hard-coded `0' to new variable `fd' (initially 0) in
+         preparation for adding `-u fd' option
+
+bashline.c
+       - bash_directory_completion_hook calls expand_prompt_string instead
+         of expand_string (it does the right thing).  This keeps expansion
+         errors from causing a longjmp, which shouldn't happen because of
+         completion
+       - command_subst_completion_function was augmented very slightly to
+         do filename completion on a non-command-word in a command
+         substitution
+       - command_subst_completion_function now skips over the lcd that
+         rl_completion_matches puts in matches[0] if there is more than
+         one possible completion
+
+                                   3/7
+                                   ---
+builtins/read.def
+       - only add the unwind_protect to free `rlbuf' if `edit' is non-zero,
+         since we won't be using readline otherwise
+
+lib/sh/zread.c
+       - renamed zread1 -> zreadintr
+
+redir.c
+       - small change to redirection_error() to make a slightly better
+         guess about the invalid file descriptor if the redirection op is
+         r_duplicating_input or r_duplicating_output
+
+include/stdc.h
+       - new macro, SH_VA_START, to encapsulate the difference between
+         stdarg va_start and varargs va_start
+
+{error,pcomplete,print_cmd}.c,builtins/common.c,lib/sh/snprintf.c
+       - use SH_VA_START
+
+                                   3/8
+                                   ---
+builtins/read.def
+       - support for the ksh-like `-u fd' option
+
+general.c
+       - new function sh_validfd(fd), returns 1 if fd is a valid open file
+         descriptor
+
+general.h
+       - extern decl for sh_validfd
+
+bashline.c
+       - don't call posix_readline_initialize() from initialize_readline();
+         sv_strict_posix() should already have taken care of it
+
+                                  3/11
+                                  ----
+{error,pcomplete,print_cmd}.c, builtins/common.c
+       - removed non-varargs versions of functions
+
+builtins/printf.def
+       - if the string argument to %q has non-printing characters, call
+         ansic_quote to quote it rather than sh_backslash_quote
+
+variables.h
+       - new attribute: att_trace (and corresponding trace_p() macro).
+         Functions with this attribute will inherit the DEBUG trap.
+         Currently ignored for variables
+
+builtins/declare.def
+       - new `-t' option to declare/typeset toggle the `att_trace' attribute
+
+builtins/setattr.def
+       - check for att_trace and output `-t' flag in show_var_attributes
+
+execute_cmd.c
+       - if a function is being traced (it has the `-t' attribute set),
+         don't turn off the DEBUG trap when it executes
+
+doc/{bash.1,bashref.texi}
+       - document the new `-t' option to declare/typeset
+
+                                  3/12
+                                  ----
+execute_cmd.c
+       - don't execute the debug trap in the `cm_simple:' case of
+         execute_command_internal; run it in execute_simple_command so we
+         get the line number information right when executing in a shell
+         function
+       - run a DEBUG trap before executing ((...)) arithmetic commands,
+         like ksh93
+       - run a DEBUG trap before executing [[...]] conditional commands,
+         like ksh93
+
+eval.c
+       - add a static forward declaration for alrm_catcher()
+
+general.c
+       - add static forward declarations for bash_special_tilde_expansions,
+         unquoted_tilde_word, initialize_group_array
+
+variables.h
+       - add extern declarations for sh_get_env_value, map_over_funcs,
+         local_exported_variables
+
+variables.c
+       - add static forward declarations for dispose_temporary_env,
+         make_func_export_array
+
+bashhist.c
+       - add static forward declaration for check_history_control
+
+configure.in
+       - add a call to AC_CHECK_DECLS for strcpy
+
+config.h.in
+       - add placeholder for HAVE_DECL_STRCPY define, set by configure
+
+general.h
+       - don't declare strcpy if HAVE_DECL_STRCPY is defined with a non-zero
+         value
+
+sig.h
+       - add prototype to typedef of SigHandler
+
+lib/readline/histlib.h
+       - removed extern declaration of strcpy()
+       - include string.h/strings.h directly in histlib.h instead of source
+         files
+
+lib/readline/{histexpand,histfile,history,histsearch}.c
+       - don't include string.h/strings.h now that histlib.h includes it
+
+lib/tilde/tilde.c
+       - removed extern declaration of strcpy(), rely on string.h/strings.h
+
+command.h
+       - four new redirection types: r_move_input, r_move_output,
+         r_move_input_word, r_move_output_word, for
+         [N]<&word- and [N]>&word- from ksh93
+
+print_cmd.c
+       - changes to print r_move_input[_word] and r_move_output[_word]
+
+copy_cmd.c
+       - changes to copy r_move_input[_word] and r_move_output[_word]
+
+dispose_cmd.c
+       - changes to dispose r_move_input_word and r_move_output_word
+
+make_cmd.c
+       - changes to make r_move_input[_word] and r_move_output[_word] from
+         r_duplicating_{input,output}_word, which is how the new redirs
+         are passed by the parser
+
+redir.c
+       - changes to make r_move_input[_word] and r_move_output[_word] do
+         the right thing when executed
+
+builtins/read.def
+       - print an error message and return failure immediately if zread/zreadc
+         return < 0
+
+doc/{bash.1,bashref.texi}
+       - documented new [n]<&word- and [n]>&word- redirections
+
+                                  3/13
+                                  ----
+lib/readline/isearch.c 
+       - enabled code to allow chars bound to rl_rubout to delete characters
+         from the incremental search string
+
+shell.c
+       - add `-l' invocation option to parse_shell_options; equivalent to
+         `--login'
+       - fixed set_login_shell to check first char of base pathname of argv0
+         for `-', like other shells
+       - move the check for make_login_shell after the call to
+         parse_shell_options because the `-l' option might set it
+
+doc/{bash.1,bashref.texi}
+       - documented new `-l' invocation option
+
+array.c
+       - new function, array_shift, shifts an array left by a specified
+         number of elements
+       - array_walk is now compiled in by default
+       - array_to_assignment_string now takes a second argument: int quoted.
+         If non-zero, the result is single-quoted before being returned
+       - quoted_array_assignment_string has been removed
+
+array.[ch]
+       - renamed most of the array functions so that all have an array_
+         prefix and are more systematically named
+       - array_slice now preserves the indicies from the original array
+       - change array_to_assign to use a static buffer for expanding the
+         array indices, instead of malloc/free
+
+{arrayfunc,subst,variables}.c, builtins/read.def
+       - changed calls to various array functions to use new names
+
+lib/sh/stringvec.c, externs.h
+       - renamed all of the functions to have a strvec_ prefix and to have
+         a more sensible name scheme
+       - strvec_search's arguments are now supplied in reverse order, so
+         the char **array is first, like the other functions
+       - new function, strvec_resize, xrealloc for strvecs
+
+{alias,array,bracecomp,braces,bashline,execute_cmd,findcmd,general,pathexp,
+pcomplete,variables}.c
+lib/sh/stringlist.c
+builtins/{bind,complete,exec,getopts,pushd,set}.def
+       - change calls to all functions from lib/sh/stringvec.c
+       - use strvec_resize where appropriate
+
+externs.h
+       - only declare dup2() if HAVE_DUP2 is undefined or DUP2_BROKEN is
+         defined
+
+lib/readline/{macro,readline,util}.c, lib/readline/rlprivate.h
+       - _rl_defining_kbd_macro is gone, use RL_ISSTATE(RL_STATE_MACRODEF)
+
+lib/readline/readline.h
+       - new struct readline_state, encapsulates most of readline's internal
+         state in case you need reentrancy or nested calls to readline()
+       - extern declarations for rl_save_state, rl_restore_state
+
+lib/readline/readline.c
+       - add (undocumented) int rl_save_state (struct readline_state *),
+         int rl_restore_state (struct readline_state *)
+
+                                  3/14
+                                  ----
+array.[ch]
+       - new function, array_rshift, shifts an array right by a specified
+         number of elements, optionally inserting a new element 0
+
+examples/bashdb/bashdb
+       - new single-file version of bash debugger, originally modified from
+         version in bash-2.04 by Gary Vaughan (the old debugger still
+         appears in examples/obashdb).  This version has a more gdb-like
+         command set
+
+examples/bashdb/bashdb.el
+       - new emacs bashdb debugger mode from Masatake YAMATO <jet@gyve.org>
+
+execute_cmd.c
+       - don't make $LINENO relative to function start unless the shell is
+         currently interactive -- this is what ksh93 does and what I
+         believe to be the intent of POSIX.2 (this required changing some
+         of the test checks because the output has changed)
+       - run the debug trap for each command in an arithmetic for expression,
+         like ksh93 does
+
+lib/readline/vi_mode.c
+       - redid rl_vi_subst (binding func for `s' and `S') in terms of
+         rl_vi_change_to:  `S' == `cc' and `s' == `c '.  This makes undo
+         work right
+
+                                  3/18
+                                  ----
+hashlib.c
+       - fixed hash_walk to return if the item function returns < 0, instead
+         of breaking out of the current hash chain
+
+array.c
+       - fixed array_walk to return if the item function returns < 0, like
+         hash_walk
+
+lib/sh/stringlist.c, externs.h
+       - new function: strlist_walk, takes a stringlist and a pointer to an
+         item func.  Like other _walk funcs, if item func returns < 0 the
+         walk is cancelled
+       - new function: strlist_flush, frees items in the contained list
+         with strvec_flush
+       - renamed functions to have a strlist_ prefix and be more systematic
+
+pcomplib.c,pcomplete.h
+       - removed redundant `progcomp_initialized' variable
+       - renamed functions to have `progcomp_' or `compspec_' prefixes
+         like the hash library
+
+{bashline,pcomplete}.c,builtins/complete.def
+       - fixed calls to stringlist functions to use new names
+       - fixed calls to functions in pcomplib.c to use new names
+
+pcomplete.c
+       - made the debugging code #ifdef DEBUG -- it should be mature enough
+
+builtins/hash.def,parse.y
+       - use REVERSE_LIST(x, t) instead of (t)reverse_list(x)
+
+list.c,{externs,general}.h
+       - renamed the list functions to have a list_ prefix, changed callers
+
+externs.h,{execute_cmd,stringlib,subst}.c,builtins/common.c,lib/sh/stringvec.c
+       - word_list_to_argv -> strvec_from_word_list
+       - argv_to_word_list -> strvec_to_word_list
+       - moved functions to lib/sh/stringvec.c
+
+lib/sh/stringvec.c
+       - changed name of second argument to strvec_from_word_list from `copy'
+         to `alloc' so the use of `copy' between strvec_from_word_list and
+         strvec_to_word_list isn't as confusing
+       - changed name and sense of second argument to
+         strvec_to_word_list from `copy' to `alloc' for the same reason --
+         now both functions agree on semantics of second argument
+
+lib/sh/stringlist.c
+       - ditto for strlist_from_word_list and strlist_to_word_list
+
+subst.c
+       - changed callers of strvec_to_word_list
+
+                                  3/19
+                                  ----
+builtins/hash.def
+       - added `-l' option to list table or individual targets in reusable
+         format
+       - added `-d' option to remove one or more names from the table of
+         hashed commands (provides `unhash' or `unalias -t' functionality)
+
+doc/{bash.1,bashref.texi}
+       - documented new `-l' and `-d' options to `hash'
+
+hashcmd.[ch]
+       - renamed functions to have a `phash_' prefix and follow new naming
+         convention
+       - phash_remove now returns an int:  1 if command not in hash table,
+         0 if filename removed OK
+
+{findcmd,variables}.c, builtins/{hash,type}.def
+       - changed callers to use new names from hashcmd.c
+
+builtins/common.[ch]
+       - new function, sh_notfound(s), prints standard `not found' message
+       - new function, sh_invalidid(s), prints standard `invalid identifier'
+         message
+       - new function, sh_restricted(s), prints standard `restricted' message
+         for restricted shells
+       - new function, sh_invalidnum(s), prints standard `invalid number'
+         message
+       - renamed bad_option to sh_invalidopt, changed to print
+         `invalid option' instead of `unknown option'
+       - new function, sh_invalidoptname, prints standard `invalid option
+         name' for long options
+       - new function, sh_badjob (s), prints standard `no such job' message
+       - new function, sh_invalidsig (s), prints standard `invalid signal
+         specification' message
+       - new function, sh_nojobs (s), prints standard `no job control' message
+       - new function, sh_needarg (s), prints standard `option requires an
+         argument' message
+       - new function, sh_neednumarg (s), prints standard `numeric
+         argument required' message
+       - new function, sh_badpid(s), prints standard `not a pid...' message
+       - new function, sh_erange (s, desc) prints standard `out of range'
+         message, optionally using `desc' to say what the argument is
+
+builtins/{alias,command,declare,exec,hash,type}.def
+       - call sh_notfound() instead of calling builtin_error directly
+
+builtins/{declare,getopts,read,set,setattr}.def
+       - call sh_invalidid() instead of calling builtin_error directly
+
+builtins/{cd,command,enable,exec,hash,source}.def
+       - call sh_restricted() instead of calling builtin_error directly
+
+builtins/{printf,read,ulimit}.def, builtins/common.c
+       - call sh_invalidnum instead of calling builtin_error directly
+
+builtins/{complete,declare,pushd,set}.def, builtins/bashgetopt.c
+       - call sh_invalidopt instead of bad_option or builtin_error directly
+
+builtins/{complete,set,shopt}.def
+       - call sh_invalidoptname instead of builtin_error directly
+
+builtins/{fg_bg,jobs,kill,wait}.def
+       - call sh_badjob instead of calling builtin_error directly
+
+builtins/common.c, builtins/{kill,signal}.def
+       - call sh_invalidsig instead of calling builtin_error directly
+
+builtins/{fg_bg,suspend,wait}.def
+       - call sh_nojobs instead of calling builtin_error directly
+
+builtins/{common,bashgetopt}.c, builtins/{hash,kill}.def
+       - call sh_neednumarg and sh_needarg where required
+
+builtins/{kill,wait}.def
+       - call sh_badpid where required
+
+builtins/{break,fc,history,pushd,shift,ulimit,umask}.def
+       - call sh_erange where appropriate
+
+builtins/printf.def
+       - new static function, printf_erange, prints standard out-of-range
+         warning message
+
+builtins/set.def
+       - changed so that calls to sh_invalidopt always include the leading
+         `+' or `-'
+
+builtins/shopt.def
+       - changed SHOPT_ERROR macro to shopt_error function
+
+builtins/bind.def
+       - regularized error messages to `bind: object: error string' like
+         other error messages
+
+builtins.h
+       - the `short_doc' member of a `struct builtin' is now of type
+         `const char *'
+       - the strings in `long_doc' array of a struct builtin are now const
+
+builtins/mkbuiltins.c
+       - changes for new `const' members of struct builtin
+
+                                  3/20
+                                  ----
+lib/readline/histfile.c
+       - use pointers instead of indexing into buffer when reading the
+         contents of the history file in read_history_range and
+         history_truncate_file
+
+                                  3/21
+                                  ----
+lib/readline/histfile.c
+       - new file, with code to mmap the history file for reading and
+         writing (depends on HAVE_MMAP, currently nothing checks for that)
+
+                                  3/25
+                                  ----
+error.[ch]
+       - new function, err_badarraysub(s), calls report_error with standard
+         `bad array subscript' message
+       - new function, err_unboundvar(s), calls report_error with standard
+         `unbound variable' message
+       - new function, err_readonly(s), calls report_error with standard
+         `readonly variable' message
+
+{arrayfunc,subst}.c
+       - call err_badarraysub where appropriate
+
+{expr,subst}.c
+       - call err_unboundvar where appropriate
+
+{arrayfunc,variables}.c
+       - call err_readonly where appropriate
+
+shell.c
+       - changed text of bad option error messages to be the same as that
+         printed for builtin errors
+
+builtins/common.c
+       - changed sh_invalidopt to print the invalid option before the rest
+         of the error message (required some tests to be modified)
+       - new function, sh_readonly, calls builtin_error with standard
+         `readonly variable' message
+
+variables.c,builtins/declare.def
+       - call sh_readonly where appropriate
+
+lib/sh/stringvec.c
+       - added strvec_remove (sv, s), removes S from SV and shuffles rest of
+         elements down 1
+
+lib/sh/stringlist.c
+       - added strlist_remove(sl, s), just calls strvec_remove on the
+         component list
+
+externs.h
+       - new extern declarations for strvec_remove and strlist_remove
+       - fixed extern declaration for strvec_search; the arguments were
+         reversed (unimportant, it's not compiled into the shell)
+
+subst.c
+       - change param_expand to call quote_escapes on values retrieved when
+         expanding the positional parameters
+       - change parameter_brace_expand_word to quote escapes on values
+         retrieved when expanding the positional parameters
+       - fix parameter_brace_substring to quote escape characters on unquoted
+         substrings extracted from variable values (needed to separate case
+         VT_VARIABLE from VT_ARRAYMEMBER for this, since, because
+         get_var_and_type calls array_value for VT_ARRAYMEMBER, we need to
+         skip over quoted characters in an already-appropriately-quoted
+         string to find the substring we want)
+       - fix parameter_brace_substring to quote escape characters in the
+         value returned by pos_params when expanding subsets of the
+         positional parameters and not within double quotes (in which case
+         pos_params() quotes the string for us)
+       - fix parameter_brace_substring to quote escape characters in the
+         value returned by array_subrange when expanding subsets of an
+         array and not within double quotes (in which case
+         array_subrange() quotes the string for us)
+       - new function, quoted_strlen(s), does strlen(s) while skipping over
+         characters quoted with CTLESC (#ifdef INCLUDE_UNUSED, since it's
+         not used yet)
+       - changed pos_params() so it always returns a list whose members are
+         quoted strings if (quoted&(Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) != 0
+
+arrayfunc.c
+       - fix array_value to consistently call quote_escapes, even when a
+         non-array variable is being subscripted with element 0, in which
+         case we return the variable value
+
+lib/sh/strtrans.c
+       - make the for_echo parameter to ansicstr a `flags' parameter that
+         has its old `for echo' meaning if flags&1 is non-zero (which is
+         consistent with the old code)
+       - Added code to the `flags' parameter to ansicstr so that if flags&2
+         is non-zero, CTLESC and CTLNUL are escaped with CTLESC in the
+         expanded string
+       - change ansiexpand() to call ansicstr with a `flags' parameter of 2
+
+                                  3/26
+                                  ----
+lib/readline/histfile.c
+       - when reading and writing the history file, use malloc instead of
+         xmalloc and handle failures gracefully, so the application doesn't
+         abort if the history file or history list is too big
+
+                                  3/27
+                                  ----
+arrayfunc.c
+       - changed array_value_internal to take an additional `int *'
+         parameter, in which is returned the type of array indexing
+         performed (array[@] vs. array or array[index])
+       - changed array_value and get_array_value to take a corresponding
+         extra parameter and pass it to array_value_internal
+       - changed array_value_internal to no longer return newly-allocated
+         memory or quote CTLESC and CTLNUL in the returned string if
+         `simple' array indexing (subscript not `@' or `*') is being
+         performed.  This makes it more like a variable lookup
+
+arrayfunc.h
+       - changed prototypes for array_value and get_array_value
+
+expr.c
+       - added new parameter to call to get_array_value in expr_streval
+       - don't need to free memory returned by get_array_value any more
+
+subst.c
+       - quote_escapes now works with multibyte characters
+       - dequote_string now works with multibyte characters
+       - dequote_escapes is now needed, so it's compiled in, and it
+         now works with multibyte characters
+       - remove_quoted_escapes now just calls dequote_escapes and copies the
+         result over the argument string
+       - remove_quoted_nulls now returns its char * argument, parallels
+         remove_quoted_escapes
+       - parameter_brace_expand_word now passes the new argument to
+         array_value and quotes CTLESC and CTLNUL in the result if it's a
+         `simple' array expansion by calling quote_escapes
+       - get_var_and_type now returns VT_ARRAYMEMBER for references like
+         ${array} where `array' is an array variable (just like ${array[0]}).
+         Documented (in comment) that a VT_VARIABLE return value means that
+         quote_escapes has been called at some point
+       - changed callers of get_var_and_type to no longer free value if
+         VT_ARRAYMEMBER is returned as type
+       - changed parameter_brace_substring and parameter_brace_patsub to
+         call dequote_escapes on the value from get_var_and_type if the
+         type is VT_VARIABLE, since the substring and pattern substitution
+         code doesn't understand CTLESC quoting
+       - parameter_brace_substring no longer needs to call quoted_substring
+         for the VT_ARRAYMEMBER case
+       - changed parameter_brace_patsub to call quote_escapes on the result
+         of pat_subst for the VT_VARIABLE and VT_ARRAYMEMBER cases, and to
+         quote the returned string in the VT_ARRAYVAR and VT_POSPARAMS cases
+         if the `MATCH_QUOTED' flag isn't set (if it is, the pattern
+         substitution functions perform any necessary quoting)
+       - quoted_substring is no longer used; it's now #ifdef INCLUDE_UNUSED
+
+lib/malloc/mstats.h
+       - new member in _malstats: u_bits32_t bytesreq, the total number of
+         bytes requested by the caller via calls to malloc() and realloc()
+
+lib/malloc/stats.c
+       - print bytesreq member in _print_malloc_stats
+       - don't print statistics for buckets for which nmal == 0 (no mallocs)
+
+lib/malloc/malloc.c
+       - modified internal_malloc, internal_realloc to keep running total of
+         number of bytes requested by calling application
+
+shell.c
+       - sh_exit is now compiled in; exit_shell calls sh_exit
+
+error.c
+       - changed fatal_error, report_error, parser_error to call sh_exit
+
+                                  3/28
+                                  ----
+subst.[ch]
+       - changed Q_NOQUOTE to Q_PATQUOTE; it makes the intent more clear
+
+subst.c
+       - moved code from parameter_brace_expand into a new function that
+         dispatches for pattern substitution: parameter_brace_remove_pattern
+       - changed structure of parameter_brace_remove_pattern to be like
+         parameter_brace_patsub and its ilk:  call get_var_and_type to
+         isolate the variable name, move the pattern isolation code out of
+         the various *_remove_pattern functions into
+         parameter_brace_remove_pattern and pass the results to the various
+         functions, use a switch on the return value from get_var_and_type
+         to decide which function to call, regularized the arguments to the
+         separate pattern removal functions
+       - parameter_brace_remove_pattern now properly quotes escape chars in
+         the returned value
+       - changed get_var_and_type to call dequote_escapes on the `value'
+         parameter for case VT_VARIABLE and return the result in *valp,
+         so the calling functions don't have to do it themselves; changed
+         callers appropriately
+       - fixed getpattern() where it broke posix compliance:  if you enclose
+         a pattern removal spec in double quotes, the outer double quotes
+         have no effect on the pattern (POSIX.1-200x 2.6.2).  This uncovered
+         a bug in the test suite (!)
+
+pathexp.c
+       - fixed a problem with quote_string_for_globbing where it would change
+         consecutive CTLESC chars all to \ instead of changing every other
+         quoted char
+
+                                  3/31
+                                  ----
+lib/malloc/{malloc,stats}.c
+       - moved declaration of _mstats to malloc.c so stats.o doesn't get
+         linked into the shell if the stats functions aren't called
+
+                                   4/2
+                                   ---
+lib/glob/smatch.c
+       - introduce `XCHAR' define, which is the type of arguments passed to
+         strcoll/strcmp/strlen and their wide-character equivalents, added
+         appropriate casts
+       - static arrays in single-byte version of rangecmp() are `char', not
+         `unsigned char', so compilers don't complain about calls to strcoll
+
+lib/glob/sm_loop.c
+       - casts for `XCHAR' and `XCHAR *' arguments to libc functions
+       - use prototype declaration for BRACKMATCH if `PROTOTYPES' is defined
+         to avoid problems with type promotion (unsigned char -> int)
+
+lib/glob/collsyms.h
+       - `name' member of struct _COLLSYM is now of type `XCHAR *', since
+         some compilers don't like `unsigned char *' initializers from
+         constant strings
+
+[bash-2.05b-alpha1 released]
+
+                                   4/3
+                                   ---
+builtins/{evalstring.c,common.h}
+       - new flag for parse_and_execute, SEVAL_NOFREE, means to not free
+         the argument string when finished
+
+lib/readline/text.c
+       - fixed a trivial typo in _rl_insert_char when reading multibyte
+         char sequences
+       - replace calls to ding() with rl_ding()
+
+include/chartypes.h
+       - remove SIGN_EXTEND_CHAR and TOASCII macros; they're unused
+
+make_cmd.c
+       - include dispose_cmd.h for extern function declarations
+
+lib/glob/glob.c
+       - include `shmbutil.h' and `xmalloc.h' for extern function declarations
+
+lib/glob/smatch.c
+       - include `xmalloc.h' for extern function declarations
+
+shell.c
+       - fix maybe_make_restricted to use its argument instead of global
+         `shell_name'
+
+version.c
+       - update copyright message to include this year
+
+lib/readline/display.c
+       - fixes from Jiro SEKIBA <jir@yamato.ibm.com> to fix autowrapping
+         when using multibyte characters
+
+lib/glob/sm_loop.c
+       - fixed a problem in BRACKMATCH where not enough memory was allocated
+         to hold a multibyte character when parsing POSIX.2 char class names
+
+support/config.{guess,sub}
+       - updated via patch from Paul Eggert with latest GNU additions
+
+variables.c
+       - var_lookup should use its `vcontext' argument instead of
+         unconditionally using `shell_variables'
+
+                                   4/4
+                                   ---
+builtins/bind.def,doc/{bash.1,bashref.texi}
+       - changed the usage summary and help text to make it clear that any
+         readline command that may appear in ~/.inputrc may be supplied as
+         one of the non-option arguments to `bind'
+
+builtins/mkbuiltins.c
+       - added support for `-H' option, which means to write long documentation
+         for each builtin to a separate file in the `helpfiles' directory
+
+builtins/Makefile.in
+       - new target `helpdoc', just creates long doc files in helpfiles
+         directory
+
+lib/sh/zcatfd.c
+       - new file, with zcatfd(int fd, int ofd, char *fn); dumps data from
+         FD to OFD
+
+Makefile.in,lib/sh/Makefile.in
+       - added zcatfd.c, zcatfd.o member of libsh.a
+
+builtins/evalstring.c
+       - changed cat_file to call zcatfd(fd, 1, fn)
+
+builtins/{shopt,colon}.def
+       - removed the $DOCNAME directive for `shopt', `true', and `false';
+         just use the names
+       - changed $DOCNAME for `:' to just be `colon' instead of
+         `colon_builtin'
+
+builtins/reserved.def
+       - added help entries for ((, [[, `for (('
+
+builtins/let.def
+       - add id++, id--, ++id, --id, ** to help text
+
+                                   4/8
+                                   ---
+builtins/bashgetopt.[ch]
+       - changed to allow options beginning with `+', enabled by a leading
+         `+' in the option string
+       - new variable, list_opttype, set to `-' or `+'
+
+builtins/{common.c,{builtin,eval,exit,fg_bg,let,printf,pushd,return,source,wait}.def
+       - changes to allow a `--' option for every builtin that accepts
+         operands but not options, as per posix.1-2001
+
+builtins/{declare,setattr}.def
+       - use internal_getopt for parsing options, now that it supports `+'
+
+builtins/set.def
+       - use internal_getopt for initial option parse, now that it supports
+         a leading `+'
+
+
+{configure,Makefile}.in, builtins/{Makefile.in,help.def,mkbuiltins.c}
+       - support for a new configure option, ``--enable-separate-helpfiles'',
+         moves the `long' help text to separate help files, installed by
+         default into ${datadir}/bash, one file per builtin.  Off by
+         default -- it saves 47K, but it's only 47K, and it's in the text
+         segment
+
+flags.c
+       - build internal_getopt() option string argument from flags array at
+         runtime in shell.c
+
+shell.c
+       - new variable to control writing malloc stats at exit:
+         malloc_trace_at_exit, 0 by default
+
+lib/malloc/malloc.c
+       - heavily updated:
+               o partial page allocated on first call to malloc to make
+                 subsequent sbrks page-aligned no longer wasted
+               o begin and end range guards are now the same value: the chunk
+                 requested
+               o coalescing code was changed to attempt to coalesce first two
+                 adjacent blocks on the free list; enabled by default
+               o blocks of size 32 are now candidates for larger block
+                 splitting, since 32 is the most popular size
+               o blocks of size 32 are now candidates for smaller block
+                 coalescing
+               o the IN_BUCKET check was changed to just make sure that the
+                 size isn't too big for the bucket, since the `busy block'
+                 checking code may increase the bucket by one or more,
+                 meaning that the old check would fail and cause a panic when
+                 a chunk allocated in such a way was freed
+               o bin sizes are now precomputed and looked up in an array
+                 rather than being computed at runtime
+               o moved the _mstats declaration here to avoid the stats code
+                 being linked in even when no stats functions were called
+                 (only matters if MALLOC_DEBUG is defined)
+               o malloc now keeps track of the address of the top of the heap
+                 and will return large chunks to the system with calls to
+                 sbrk with a negative argument when freeing the top chunk.
+                 Two thresholds:  LESSCORE_FRC means to unconditionally return
+                 memory to the system; LESSCORE_MIN means to return memory if
+                 there's at least one block already on the free list
+
+lib/malloc/mstats.h
+       - stats struct now keeps track of number of block coalesces by bin,
+         and the number of times memory was returned to the system by bin
+
+lib/malloc/stats.c
+       - trace_malloc_stats now takes a second argument: the name of the file
+         to write to.  The first `%p' in the template file name is replaced
+         by the pid
+
+                                   4/9
+                                   ---
+lib/malloc/imalloc.h
+       - added some macros derived from dlmalloc and glibc malloc to inline
+         memcpy and memset if the requested size is <= 32 bytes
+
+lib/malloc/malloc.c
+       - use MALLOC_MEMSET instead of memset in internal_{malloc,free}
+
+include/ocache.h
+       - use OC_MEMSET (variant of MALLOC_MEMSET) in ocache_free
+
+configure.in, config.h.in
+       - check for getservent(), define HAVE_GETSERVENT if found
+
+bashline.c
+       - punt immediately from bash_servicename_completion_function if
+         HAVE_GETSERVENT is not defined (cygwin seems to not define it)
+       - include "input.h" for extern save_token_state() and
+         restore_token_state() declarations
+       - change bash_execute_unix_command to call parse_and_execute with
+         SEVAL_NOHIST flag so the command doesn't get saved on the history
+         list
+       - change bash_execute_unix_command to save and restore the current
+         command line count and the token state (last_read_token, etc.).
+         Everything else is saved by either parse_and_execute directly or
+         the call it makes to push_stream().  The shell_input_line stuff
+         doesn't need to be saved and restored; it's not computed until
+         readline() returns
+
+                                  4/10
+                                  ----
+lib/glob/glob.[ch]
+       - glob_filename and glob_vector now take an additional `flags' arg
+       - define GX_MARKDIRS as possible flag value for glob_filename and
+         glob_vector
+
+lib/sh/snprintf.c
+       - fixed some bugs with handling of `g' and `G' formats
+       - make sure numtoa returns the fractional part correctly when passed 0
+       - implemented thousands grouping for `'' flag character
+
+lib/sh/rename.c
+       - a few changes to make it more bulletproof
+
+                                  4/11
+                                  ----
+lib/glob/glob.c
+       - added the couple of dozen lines of code to glob_dir_to_array to
+         finish implementing GX_MARKDIRS
+
+builtins/set.def
+       - changed unset builtin so that it no longer considers unsetting an
+         unset variable or function to be an error
+
+lib/readline/display.c
+       - fix to rl_redisplay for a problem which caused display to be messed
+         up when the last line of a multi-line prompt (possibly containing
+         invisible characters) was longer than the screen width
+
+                                  4/15
+                                  ----
+aclocal.m4
+       - use AC_DEFINE_UNQUOTED in BASH_SYS_DEFAULT_MAIL_DIR instead of
+         enumerating all of the possible values and using AC_DEFINE
+
+                                  4/16
+                                  ----
+Makefile.in, {builtins,support}/Makefile.in
+       - new variables, CFLAGS_FOR_BUILD and CPPFLAGS_FOR_BUILD, substituted
+         by `configure'
+       - changed CCFLAGS_FOR_BUILD to BASE_CCFLAGS, removing $(CPPFLAGS);
+         CCFLAGS and CCFLAGS_FOR_BUILD now include $(BASE_CCFLAGS) with
+         (possibly) different values for CPPFLAGS and CFLAGS 
+       - GCC_LINT_CFLAGS now includes $(BASE_CCFLAGS) and $(CPPFLAGS)
+         instead of CCFLAGS_FOR_BUILD
+       - new variable, LDFLAGS_FOR_BUILD, right now equivalent to LDFLAGS
+       - remove $(CPPFLAGS) from recipes for buildversion, mksignames, and
+         mksyntax
+
+configure.in
+       - compute and substitute CFLAGS_FOR_BUILD, CPPFLAGS_FOR_BUILD, and
+         LDFLAGS_FOR_BUILD
+       - changed qnx to use LOCAL_LDFLAGS and LOCAL_LIBS instead of putting
+         everything in LOCAL_LDFLAGS
+
+builtins/Makefile.in
+       - remove $(PROFILE_FLAGS) from recipe for building `mkbuiltins'
+       - use LDFLAGS_FOR_BUILD instead of LDFLAGS in recipe for building
+         `mkbuiltins'
+
+Makefile.in
+       - use $(CC_FOR_BUILD) and $(CCFLAGS_FOR_BUILD) to build auxiliary
+         test programs (printenv, recho, zecho)
+
+support/Makefile.in
+       - use CC_FOR_BUILD and CCFLAGS_FOR_BUILD in recipe for building
+         `man2html'
+
+lib/tilde/Makefile.in
+       - substitute PROFILE_FLAGS, use PROFILE_FLAGS in $(CCFLAGS)
+
+                                  4/25
+                                  ----
+Makefile.in, configure.in
+       - moved RELSTATUS to configure.in; configure substitutes it into
+         the generated Makefile
+
+lib/sh/snprintf.c
+       - fix wchars() to deal with systems where MB_CUR_MAX is not a
+         constant expression
+
+                                   5/2
+                                   ---
+lib/sh/shquote.c
+       - add `,' to list of chars that are backslash-quoted.  It doesn't
+         hurt normal usage and prevents filenames with commas from being
+         inappropriately split by brace expansion after using
+         complete-into-braces
+
+                                   5/6
+                                   ---
+lib/sh/xstrchr.c
+       - we only need the check of MB_CUR_MAX and the slow code for a
+         few encodings, and even then only for a subset of the charset
+
+arrayfunc.c
+       - some speedups for skipsubscript and multibyte chars from Bruno Haible
+
+locale.c
+       - changed set_lang to call setlocale(LC_ALL, ...) if LC_ALL doesn't
+         already have a value, but doesn't change any shell variables
+
+include/shmbutil.h
+       - major speedups from Bruno Haible, mostly concerned with reducing
+         the number of strlen(3) calls
+
+subst.c
+       - change callers of macros in shmbutil.h to add extra argument as
+         necessary
+       - skip_single_quoted and skip_double_quoted take another argument:
+         the length of the string; mostly useful when using multibyte chars
+       - many speedups from precomputing string lengths at function start
+       - fixed a small bug in de_backslash in the midst of rewriting for
+         better efficiency
+
+{braces,make_cmd,pathexp}.c
+       - change callers of macros in shmbutil.h to add extra argument as
+         necessary
+
+pathexp.c
+       - fix a one-too-far problem with multibyte chars in
+         unquoted_glob_pattern_p
+
+braces.c
+       - brace_gobbler takes a new argument, the length of the passed string
+       - expand_amble takes a new argument, the length of the passed string
+
+                                   5/7
+                                   ---
+subst.c
+       - modified remove_quoted_nulls to eliminate the memory allocation and
+         do the copy in place using the same strategy as de_backslash
+
+lib/readline/{rldefs.h,complete.c}
+       - new define RL_QF_OTHER_QUOTE, so _rl_find_completion_word can note
+         that it found a quoting character other than \'" that appears in
+         rl_completer_quote_characters
+
+                                   5/9
+                                   ---
+jobs.c
+       - save and restore old value of jobs_list_frozen when calling trap
+         handlers from set_job_status_and_cleanup to avoid seg faults when
+         running recursive trap handlers
+
+                                  5/10
+                                  ----
+builtins/common.h
+       - new #defines to use for value of changed_dollar_vars (provides
+         information about the caller who wants to blow away the old dollar
+         variables)
+
+builtins/common.c
+       - changed set_dollar_vars_changed to set changed_dollar_vars to one
+         of the ARGS_* values depending on the caller and environment
+
+builtins/source.def
+       - source restores the positional parameters unless the `set' builtin
+         was called to specify a new set while not executing a shell function
+
+                                  5/13
+                                  ----
+POSIX
+       - new file, was in CWRU/POSIX.NOTES
+
+doc/{Makefile.in,Makefile}
+       - changed `posix' rule to modify ../POSIX
+
+doc/mkposix
+       - write to `POSIX' by default
+
+lib/sh/strtrans.c
+       - when ansicstr is parsing a format string for `echo -e' (or the
+         equivalent xpg_echo option is enabled), obey the POSIX-2001/SUSv3
+         standard and accept 0-3 octal digits after a leading `0'
+
+doc/{bash.1,bashref.texi}
+       - updated `echo' description to note that up to three octal digits
+         are now accepted following `\0'
+
+                                  5/16
+                                  ----
+doc/Makefile.in
+       - remove the generated documentation on `make distclean' if the
+         build directory and source directory are not the same
+
+Makefile.in
+       - descend into `support' subdirectory on a `make clean' and
+         `make distclean'
+       - remove parser-built, y.tab[ch] on a `make distclean' if the build
+         directory and source directory are not the same
+
+support/Makefile.in
+       - support various `clean' targets and remove man2html.o and man2html
+
+{configure,Makefile}.in
+       - move values for DEBUG and MALLOC_DEBUG into configure.in; on by
+         default for development versions; off by default for releases
+         (off for profiling, too)
+
+                                  5/21
+                                  ----
+parse.y
+       - modified the grammar to allow a simple_list followed by yacc_EOF
+         to terminate a command.  This fixes problems with things like
+         a backslash-newline at the end of an `eval'd string
+       - change handle_eof_input_unit() to reset the token state before
+         calling prompt_again(), in case the prompt to be evaluated contains
+         a command substitution
+
+                                  5/23
+                                  ----
+lib/readline/vi_mode.c
+       - fix `r' command (rl_vi_change_char) when HANDLE_MULTIBYTE is defined
+         but MB_CUR_MAX == 1
+
+                                  5/24
+                                  ----
+lib/malloc/watch.c
+       - don't try to print `file' argument to _watch_warn if it's null
+
+lib/malloc/malloc.c
+       - changed guard checking code in internal_{malloc,free,realloc} to
+         access memory as (char *) and copy into a union instead of
+         casting and dereferencing a pointer to u_bits32_t, since that
+         results in unaligned accesses which will cause Sparcs to upchuck
+
+                                  5/30
+                                  ----
+[bash-2.05b-beta1 released]
+
+lib/readline/text.c
+       - fixed a problem with rl_transpose_chars on systems supporting
+         multibyte characters with a locale that doesn't have any multibyte
+         chars
+
+                                   6/4
+                                   ---
+expr.c
+       - fix a/=0 and a%=0 to throw evaluation errors rather than core dumps
+
+lib/readline/display.c
+       - fix core dump when line wrapping a multibyte character (line
+         accidentally dropped from the original patch)
+
+lib/readline/mbutil.c
+       - fix reversed return value from _rl_is_mbchar_matched; fixes problem
+         with backward-char-search
+
+                                  6/10
+                                  ----
+lib/sh/getenv.c
+       - fix getenv to not free value returned by find_tempenv_variable
+       - add setenv, putenv, unsetenv for completeness
+
+                                  6/12
+                                  ----
+shell.c
+       - change init_noninteractive to init expand_aliases to the value of
+         posixly_correct
+       - don't initialize expand_aliases to posixly_correct anywhere else.
+         This allows the -O expand_aliases invocation option to work correctly
+
+general.c
+       - fix move_to_high_fd to not try the dup2 unless the fd loop results
+         in an fd > 3; just return the passed file descriptor otherwise
+       - use HIGH_FD_MAX, defined in general.h, instead of hard-coded 256
+         as highest file descriptor to try
+
+subst.c
+       - in process_substitute, call move_to_high_fd with `maxfd' parameter
+         of -1 instead of 64, so move_to_high_fd will use its maximum
+
+                                  6/21
+                                  ----
+lib/malloc/malloc.c
+       - don't bother calling MALLOC_MEMSET if the requested size is 0
+
+builtins/setattr.def
+       - note in short doc that export and readonly can take assignment
+         statements as arguments
+
+error.c
+       - new function, error_prolog(), to capture common error message
+         prefix code (except for parser errors)
+
+                                  6/25
+                                  ----
+aclocal.m4
+       - add tests for standard-conforming declarations for putenv and
+         unsetenv in system header files
+
+{configure,config.h}.in
+       - call BASH_FUNC_STD_PUTENV and BASH_FUNC_STD_UNSETENV, define
+         HAVE_STD_GETENV and HAVE_STD_UNSETENV, respectively, if they
+         succeed
+
+lib/sh/getenv.c
+       - change putenv and unsetenv to take differing prototypes in
+         stdlib.h into account
+
+                                  6/27
+                                  ----
+[bash-2.05b-beta2 released]
+
+                                  6/28
+                                  ----
+builtins/common.c
+       - fix get_job_spec so that %N works when N is the size of the jobs
+         list (%8 means job 8, but the 7th member of the jobs array, so
+         it's OK if N == job_slots because the function returns N-1)
+
+                                   7/1
+                                   ---
+shell.c
+       - turn off line editing if $EMACS is set to `t'
+
+                                  7/10
+                                  ----
+builtins/set.def
+       - remove mention of `-i' from long help doc, since it has no effect
index b819c901cee478603440ba10be6d1e707dd1d983..5dcd3a89df7d4541d0af2785d4138ebdf1389bb7 100755 (executable)
@@ -1,4 +1,23 @@
 #! /bin/sh
+#
+# bison -- just call yacc
+#
+
+# Copyright (C) 1996-2002 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.
 
 if [ "$1" = '-y' ]; then
        shift
index 19ca6227f6501c7017a2929bd5c9d1e93e2e4013..3970ba19310970ea4700f3f8994742392bb21415 100644 (file)
@@ -2,6 +2,24 @@
  * If necessary, link with lib/sh/libsh.a
  */
 
+/* Copyright (C) 1998-2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 #include <stdio.h>
 #include <errno.h>
 
index 9014c2069d8020ad89ceabc9238dd03510277c32..69b626ede20760baeedab16ce25f05588f330ff7 100644 (file)
  * the -E flag to LOCAL_LDFLAGS.
  */
 
+/* Copyright (C) 1998-2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 #if !defined (__HPUX10_DLFCN_H__)
 
 #define __HPUX10_DLFCN_H__
index 8f4d18e5f8ab626dc10d447b9343d66b4d05f77f..aa4ab07414ce4b80529a4618c69cd9845edde5d8 100644 (file)
@@ -1,3 +1,23 @@
+/* open-files -- report files a process has open */
+
+/* Copyright (C) 1989-2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 #include <sys/types.h>
 #include <fcntl.h>
 #include <sys/file.h>
@@ -13,4 +33,3 @@ main()
        }
        exit(0);
 }
-
diff --git a/CWRU/misc/pid.c b/CWRU/misc/pid.c
deleted file mode 100644 (file)
index 458fde4..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <stdio.h>
-
-main()
-{
-       fprintf(stderr, "%d\n", getpid());
-       exit(0);
-}
index ea9f955c8d9e6552e2aa6f21b7b4cb352a815172..2c16935f817e597440d929fa987260340e2908db 100644 (file)
@@ -1,3 +1,23 @@
+/* sigs - print signal dispositions for a process */
+
+/* Copyright (C) 1990-2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 #include <signal.h>
 #include <stdio.h>
 
index f1ac55790b00306e7269f302357fa6fb94e8947a..2252a8573ae92350bfabefab8606652853b8e5d4 100644 (file)
@@ -1,8 +1,28 @@
 /*
  * sigstat - print out useful information about signal arguments
  *
+ * Chet Ramey
+ * chet@po.cwru.edu
  */
 
+/* Copyright (C) 1991-2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 #include <sys/types.h>
 #include <signal.h>
 #include <stdio.h>
diff --git a/INSTALL b/INSTALL
index 193f2b8645ac757694e4f6cf0cc1c66a0f2cbc95..bd0d41727c269b03fcf3a817b853c58f2868d8e0 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -210,7 +210,7 @@ the Bash `configure' recognizes.
 `--with-installed-readline[=PREFIX]'
      Define this to make Bash link with a locally-installed version of
      Readline rather than the version in `lib/readline'.  This works
-     only with Readline 4.2 and later versions.  If PREFIX is `yes' or
+     only with Readline 4.3 and later versions.  If PREFIX is `yes' or
      not supplied, `configure' uses the values of the make variables
      `includedir' and `libdir', which are subdirectories of `prefix' by
      default, to find the installed version of Readline if it is not in
@@ -236,7 +236,8 @@ and linked, rather than changing run-time features.
      Enable support for large files
      (http://www.sas.com/standards/large_file/x_open.20Mar96.html) if
      the operating system requires special compiler options to build
-     programs which can access large files.
+     programs which can access large files.  This is enabled by
+     default, if the operating system provides large file support.
 
 `--enable-profiling'
      This builds a Bash binary that produces profiling information to be
index 755bdd20b8ae430e7f498e1269a7f21bf6e56fd0..bfcac430b509f00a004ddd6ad1af93c865e1822d 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -11,6 +11,7 @@ cross-build   d
 doc    d
 examples       d
 examples/bashdb        d
+examples/obashdb       d
 examples/complete      d
 examples/functions d
 examples/scripts d
@@ -44,7 +45,9 @@ INSTALL               f
 MANIFEST       f
 NEWS           f
 NOTES          f
+POSIX          f
 README         f
+RBASH          f
 AUTHORS                f
 Y2K            f
 configure.in   f
@@ -206,21 +209,27 @@ include/chartypes.h       f
 include/filecntl.h     f
 include/maxpath.h      f
 include/memalloc.h     f
+include/ocache.h       f
 include/posixdir.h     f
 include/posixjmp.h     f
 include/posixstat.h    f
 include/posixtime.h    f
 include/posixwait.h    f
+include/shmbutil.h     f
 include/shtty.h                f
 include/stdc.h         f
 include/systimes.h     f
 include/typemax.h      f
 include/unionwait.h    f
 lib/glob/Makefile.in   f
+lib/glob/sm_loop.c     f
+lib/glob/smatch.c      f
 lib/glob/strmatch.c    f
 lib/glob/strmatch.h    f
 lib/glob/glob.c                f
 lib/glob/glob.h                f
+lib/glob/glob_loop.c   f
+lib/glob/xmbsrtowcs.c  f
 lib/glob/collsyms.h    f
 lib/glob/doc/Makefile  f
 lib/glob/doc/glob.texi f
@@ -231,11 +240,13 @@ lib/malloc/imalloc.h      f
 lib/malloc/mstats.h    f
 lib/malloc/shmalloc.h  f
 lib/malloc/table.h     f
+lib/malloc/watch.h     f
 lib/malloc/alloca.c    f
 lib/malloc/malloc.c    f
 lib/malloc/stats.c     f
 lib/malloc/table.c     f
 lib/malloc/trace.c     f
+lib/malloc/watch.c     f
 lib/malloc/xmalloc.c   f
 lib/malloc/xleaktrace  f       755
 lib/malloc/stub.c      f
@@ -269,10 +280,13 @@ lib/readline/bind.c       f
 lib/readline/display.c f
 lib/readline/signals.c f
 lib/readline/kill.c    f
+lib/readline/text.c    f
 lib/readline/undo.c    f
 lib/readline/macro.c   f
 lib/readline/input.c   f
 lib/readline/callback.c        f
+lib/readline/mbutil.c  f
+lib/readline/misc.c    f
 lib/readline/nls.c     f
 lib/readline/shell.c   f
 lib/readline/savestring.c      f
@@ -280,6 +294,7 @@ lib/readline/tilde.c        f
 lib/readline/tilde.h   f
 lib/readline/rldefs.h  f
 lib/readline/rlconf.h  f
+lib/readline/rlmbutil.h        f
 lib/readline/rlshell.h f
 lib/readline/rltty.h   f
 lib/readline/rltypedefs.h      f
@@ -313,18 +328,23 @@ lib/readline/examples/manexamp.c  f
 lib/readline/examples/histexamp.c      f
 lib/readline/examples/rltest.c f
 lib/readline/examples/rl.c     f
+lib/readline/examples/rlcat.c  f
 lib/readline/examples/Inputrc  f
 lib/sh/Makefile.in     f
 lib/sh/clktck.c                f
 lib/sh/clock.c         f
 lib/sh/fmtullong.c     f
 lib/sh/fmtulong.c      f
+lib/sh/fmtumax.c       f
 lib/sh/getcwd.c                f
 lib/sh/getenv.c                f
 lib/sh/inet_aton.c     f
 lib/sh/itos.c          f
 lib/sh/mailstat.c      f
 lib/sh/makepath.c      f
+lib/sh/memset.c                f
+lib/sh/mktime.c                f
+lib/sh/netconn.c       f
 lib/sh/netopen.c       f
 lib/sh/oslib.c         f
 lib/sh/pathcanon.c     f
@@ -337,6 +357,7 @@ lib/sh/snprintf.c   f
 lib/sh/spell.c         f
 lib/sh/strcasecmp.c    f
 lib/sh/strerror.c      f
+lib/sh/strftime.c      f
 lib/sh/strindex.c      f
 lib/sh/stringlist.c    f
 lib/sh/stringvec.c     f
@@ -353,6 +374,8 @@ lib/sh/times.c              f
 lib/sh/timeval.c       f
 lib/sh/tmpfile.c       f
 lib/sh/vprint.c                f
+lib/sh/xstrchr.c       f
+lib/sh/zcatfd.c                f
 lib/sh/zread.c         f
 lib/sh/zwrite.c                f
 lib/termcap/Makefile.in        f
@@ -385,14 +408,12 @@ lib/tilde/tilde.h f
 lib/tilde/shell.c      f
 CWRU/misc/open-files.c f
 CWRU/misc/sigs.c       f
-CWRU/misc/pid.c                f
 CWRU/misc/sigstat.c    f
 CWRU/misc/bison                f
 CWRU/misc/errlist.c    f
 CWRU/misc/hpux10-dlfcn.h       f
 CWRU/PLATFORMS         f
 CWRU/README            f
-CWRU/POSIX.NOTES       f
 CWRU/changelog         f
 CWRU/sh-redir-hack     f
 CWRU/mh-folder-comp    f
@@ -435,10 +456,13 @@ support/xenix-link.sh     f       755
 support/shobj-conf     f       755
 support/rlvers.sh      f       755
 examples/bashdb/PERMISSION     f
-examples/bashdb/README f
-examples/bashdb/bashdb f
-examples/bashdb/bashdb.fns     f
-examples/bashdb/bashdb.pre     f
+examples/bashdb/bashdb         f
+examples/bashdb/bashdb.el      f
+examples/obashdb/PERMISSION    f
+examples/obashdb/README        f
+examples/obashdb/bashdb        f
+examples/obashdb/bashdb.fns    f
+examples/obashdb/bashdb.pre    f
 examples/complete/complete-examples    f
 examples/complete/complete.ianmac      f
 examples/complete/complete2.ianmac     f
@@ -504,6 +528,7 @@ examples/functions/inetaddr f
 examples/functions/inpath      f
 examples/functions/isnum.bash  f
 examples/functions/isnum2      f
+examples/functions/isvalidip   f
 examples/functions/jdate.bash  f
 examples/functions/jj.bash     f
 examples/functions/keep                f
@@ -547,6 +572,7 @@ examples/scripts/precedence f
 examples/scripts/randomcard.bash       f
 examples/scripts/scrollbar     f
 examples/scripts/scrollbar2    f
+examples/scripts/self-repro    f
 examples/scripts/showperm.bash f
 examples/scripts/shprompt      f
 examples/scripts/spin.bash     f
@@ -639,17 +665,15 @@ tests/glob1.sub           f
 tests/glob.right       f
 tests/heredoc.tests    f
 tests/heredoc.right    f
+tests/herestr.tests    f
+tests/herestr.right    f
 tests/histexp.tests    f
 tests/histexp.right    f
 tests/history.tests    f
 tests/history.right    f
 tests/history.list     f
-tests/ifs-1.test       f
-tests/ifs-2.test       f
-tests/ifs-3.test       f
-tests/ifs-1.right      f
-tests/ifs-2.right      f
-tests/ifs-3.right      f
+tests/ifs.tests                f
+tests/ifs.right                f
 tests/input-line.sh    f
 tests/input-line.sub   f
 tests/input.right      f
@@ -669,6 +693,12 @@ tests/new-exp3.sub f
 tests/new-exp.right    f
 tests/nquote.tests     f
 tests/nquote.right     f
+tests/nquote1.tests    f
+tests/nquote1.right    f
+tests/nquote2.tests    f
+tests/nquote2.right    f
+tests/nquote3.tests    f
+tests/nquote3.right    f
 tests/posix2.tests     f
 tests/posix2.right     f
 tests/posixpat.tests   f
@@ -684,6 +714,7 @@ tests/read.right    f
 tests/read1.sub                f
 tests/read2.sub                f
 tests/read3.sub                f
+tests/read4.sub                f
 tests/redir.tests      f
 tests/redir.right      f
 tests/redir1.sub       f
@@ -693,6 +724,7 @@ tests/redir3.in1    f
 tests/redir3.in2       f
 tests/redir4.sub       f
 tests/redir4.in1       f
+tests/redir5.sub       f
 tests/rhs-exp.tests    f
 tests/rhs-exp.right    f
 tests/rsh.tests                f
@@ -718,15 +750,19 @@ tests/run-func            f
 tests/run-getopts      f
 tests/run-glob-test    f
 tests/run-heredoc      f
+tests/run-herestr      f
 tests/run-histexpand   f
 tests/run-history      f
-tests/run-ifs-tests    f
+tests/run-ifs          f
 tests/run-input-test   f
 tests/run-invert       f
 tests/run-jobs         f
 tests/run-more-exp     f
 tests/run-new-exp      f
 tests/run-nquote       f
+tests/run-nquote1      f
+tests/run-nquote2      f
+tests/run-nquote3      f
 tests/run-posix2       f
 tests/run-posixpat     f
 tests/run-precedence   f
@@ -764,6 +800,7 @@ tests/type.right    f
 tests/varenv.right     f
 tests/varenv.sh                f
 tests/varenv1.sub      f
+tests/varenv2.sub      f
 tests/version          f
 tests/version.mini     f
 tests/misc/dev-tcp.tests       f
@@ -794,6 +831,7 @@ examples/scripts.v2/newext  f
 examples/scripts.v2/nmv        f
 examples/scripts.v2/pages      f
 examples/scripts.v2/pf f
+examples/scripts.v2/ren                f
 examples/scripts.v2/rename     f
 examples/scripts.v2/repeat     f
 examples/scripts.v2/untar      f
index b4296462d9b2a9f07d9eb7a36f20652c727eb9e2..a3dcd7eefda06ea734db0f845a073c2aeccec11c 100644 (file)
@@ -1,6 +1,6 @@
-# Makefile for bash-2.05a, version 2.128
+# Makefile for bash-2.05b, version 2.142
 #
-# Copyright (C) 1996 Free Software Foundation, Inc.
+# Copyright (C) 1996-2002 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
@@ -27,6 +27,7 @@ bindir = @bindir@
 libdir = @libdir@
 infodir = @infodir@
 includedir = @includedir@
+datadir = @datadir@
 
 mandir = @mandir@
 manpfx = man
@@ -59,6 +60,7 @@ RANLIB = @RANLIB@
 
 INSTALL = @INSTALL@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALLMODE= -m 0755
 INSTALLMODE2 = -m 0555
@@ -86,7 +88,7 @@ VERSOBJ = bashversion.$(OBJEXT)
 Program = bash$(EXEEXT)
 Version = @BASHVERS@
 PatchLevel = `$(BUILD_DIR)/$(VERSPROG) -p`
-RELSTATUS = release
+RELSTATUS = @RELSTATUS@
 
 Machine = @host_cpu@
 OS = @host_os@
@@ -94,8 +96,8 @@ VENDOR = @host_vendor@
 MACHTYPE = @host@
 
 # comment out for release
-#DEBUG = -DDEBUG
-#MALLOC_DEBUG = -DMALLOC_DEBUG
+DEBUG = @DEBUG@
+MALLOC_DEBUG = @MALLOC_DEBUG@
 
 THIS_SH = $(BUILD_DIR)/$(Program)
 
@@ -103,26 +105,30 @@ THIS_SH = $(BUILD_DIR)/$(Program)
 # with gprof, or nothing (the default).
 PROFILE_FLAGS= @PROFILE_FLAGS@
 
-# The GNU coding standards don't recognize the possibility that
-# other information besides optimization and debugging might be
-# passed to cc.  A different name should have been used.
 CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
 CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
 LOCAL_CFLAGS = @LOCAL_CFLAGS@ ${DEBUG}
 DEFS = @DEFS@
 LOCAL_DEFS = @LOCAL_DEFS@
+
 LOCAL_LIBS = @LOCAL_LIBS@
 LIBS = $(BUILTINS_LIB) $(LIBRARIES) @LIBS@
-LDFLAGS = @LDFLAGS@ $(STATIC_LD) $(LOCAL_LDFLAGS) $(PROFILE_FLAGS) $(CFLAGS)
 STATIC_LD = @STATIC_LD@
 LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
 
 SYSTEM_FLAGS = -DPROGRAM='"$(Program)"' -DCONF_HOSTTYPE='"$(Machine)"' -DCONF_OSTYPE='"$(OS)"' -DCONF_MACHTYPE='"$(MACHTYPE)"' -DCONF_VENDOR='"$(VENDOR)"'
 
-CCFLAGS_FOR_BUILD = $(PROFILE_FLAGS) $(SYSTEM_FLAGS) $(LOCAL_DEFS) \
-         $(DEFS) $(LOCAL_CFLAGS) $(CPPFLAGS) $(INCLUDES)
+BASE_CCFLAGS = $(PROFILE_FLAGS) $(SYSTEM_FLAGS) $(LOCAL_DEFS) \
+         $(DEFS) $(LOCAL_CFLAGS) $(INCLUDES)
+
+CCFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(CFLAGS)
 
-CCFLAGS = $(CCFLAGS_FOR_BUILD) $(CFLAGS)
+CCFLAGS_FOR_BUILD = $(BASE_CCFLAGS) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD)
+
+LDFLAGS = @LDFLAGS@ $(STATIC_LD) $(LOCAL_LDFLAGS) $(PROFILE_FLAGS) $(CFLAGS)
+LDFLAGS_FOR_BUILD = $(LDFLAGS)
 
 INCLUDES = -I. @RL_INCLUDE@ -I$(srcdir) -I$(BASHINCDIR) -I$(LIBSRC)
 
@@ -130,7 +136,7 @@ GCC_LINT_FLAGS = -Wall -Wshadow -Wpointer-arith -Wcast-qual \
                 -Wcast-align -Wstrict-prototypes -Wconversion \
                 -Wmissing-prototypes -Wtraditional -Wredundant-decls -pedantic
 
-GCC_LINT_CFLAGS = $(CCFLAGS_FOR_BUILD) $(GCC_LINT_FLAGS)
+GCC_LINT_CFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(GCC_LINT_FLAGS)
 
 #
 # Support libraries
@@ -150,26 +156,30 @@ SH_LIBSRC = $(LIBSRC)/sh
 SH_LIBDIR = $(dot)/${LIBSUBDIR}/sh
 SH_ABSSRC = ${topdir}/${SH_LIBSRC}
 
-SHLIB_SOURCE = ${SH_LIBSRC}/clktck.c ${SH_LIBSRC}/getcwd.c \
-              ${SH_LIBSRC}/getenv.c ${SH_LIBSRC}/oslib.c \
-              ${SH_LIBSRC}/setlinebuf.c \
-              ${SH_LIBSRC}/strcasecmp.c ${SH_LIBSRC}/strerror.c \
-              ${SH_LIBSRC}/strtod.c ${SH_LIBSRC}/strtol.c \
-              ${SH_LIBSRC}/strtoul.c ${SH_LIBSRC}/vprint.c \
-              ${SH_LIBSRC}/itos.c ${SH_LIBSRC}/rename.c \
-              ${SH_LIBSRC}/zread.c ${SH_LIBSRC}/zwrite.c \
-              ${SH_LIBSRC}/shtty.c ${SH_LIBSRC}/inet_aton.c \
-              ${SH_LIBSRC}/netopen.c ${SH_LIBSRC}/strpbrk.c \
-              ${SH_LIBSRC}/timeval.c ${SH_LIBSRC}/clock.c \
-              ${SH_LIBSRC}/makepath.c ${SH_LIBSRC}/pathcanon.c \
-              ${SH_LIBSRC}/pathphys.c ${SH_LIBSRC}/stringlist.c \
-              ${SH_LIBSRC}/stringvec.c ${SH_LIBSRC}/tmpfile.c \
-              ${SH_LIBSRC}/spell.c ${SH_LIBSRC}/strtrans.c \
-              ${SH_LIBSRC}/strindex.c ${SH_LIBSRC}/shquote.c \
-              ${SH_LIBSRC}/snprintf.c ${SH_LIBSRC}/mailstat.c \
-              ${SH_LIBSRC}/fmtulong.c ${SH_LIBSRC}/fmtullong.c \
-              ${SH_LIBSRC}/strtoll.c ${SH_LIBSRC}/strtoull.c \
-              ${SH_LIBSRC}/strtoimax.c ${SH_LIBSRC}/strtoumax.c
+SHLIB_SOURCE = ${SH_LIBSRC}/clktck.c ${SH_LIBSRC}/getcwd.c \
+               ${SH_LIBSRC}/getenv.c ${SH_LIBSRC}/oslib.c \
+               ${SH_LIBSRC}/setlinebuf.c \
+               ${SH_LIBSRC}/strcasecmp.c ${SH_LIBSRC}/strerror.c \
+               ${SH_LIBSRC}/strtod.c ${SH_LIBSRC}/strtol.c \
+               ${SH_LIBSRC}/strtoul.c ${SH_LIBSRC}/vprint.c \
+               ${SH_LIBSRC}/itos.c ${SH_LIBSRC}/rename.c \
+               ${SH_LIBSRC}/zread.c ${SH_LIBSRC}/zwrite.c \
+               ${SH_LIBSRC}/shtty.c ${SH_LIBSRC}/inet_aton.c \
+               ${SH_LIBSRC}/netopen.c ${SH_LIBSRC}/strpbrk.c \
+               ${SH_LIBSRC}/timeval.c ${SH_LIBSRC}/clock.c \
+               ${SH_LIBSRC}/makepath.c ${SH_LIBSRC}/pathcanon.c \
+               ${SH_LIBSRC}/pathphys.c ${SH_LIBSRC}/stringlist.c \
+               ${SH_LIBSRC}/stringvec.c ${SH_LIBSRC}/tmpfile.c \
+               ${SH_LIBSRC}/spell.c ${SH_LIBSRC}/strtrans.c \
+               ${SH_LIBSRC}/strindex.c ${SH_LIBSRC}/shquote.c \
+               ${SH_LIBSRC}/snprintf.c ${SH_LIBSRC}/mailstat.c \
+               ${SH_LIBSRC}/fmtulong.c ${SH_LIBSRC}/fmtullong.c \
+               ${SH_LIBSRC}/strtoll.c ${SH_LIBSRC}/strtoull.c \
+               ${SH_LIBSRC}/strtoimax.c ${SH_LIBSRC}/strtoumax.c \
+               ${SH_LIBSRC}/fmtumax.c ${SH_LIBSRC}/netconn.c \
+               ${SH_LIBSRC}/mktime.c ${SH_LIBSRC}/strftime.c \
+               ${SH_LIBSRC}/memset.c ${SH_LIBSRC}/xstrchr.c \
+               ${SH_LIBSRC}/zcatfd.c
 
 SHLIB_LIB = -lsh
 SHLIB_LIBNAME = libsh.a
@@ -206,12 +216,12 @@ READLINE_SOURCE   = $(RL_LIBSRC)/rldefs.h $(RL_LIBSRC)/rlconf.h \
                  $(RL_LIBSRC)/rltty.c $(RL_LIBSRC)/complete.c \
                  $(RL_LIBSRC)/bind.c $(RL_LIBSRC)/isearch.c \
                  $(RL_LIBSRC)/display.c $(RL_LIBSRC)/signals.c \
-                 $(RL_LIBSRC)/util.c $(RL_LIBSRC)/kill.c \
+                 $(RL_LIBSRC)/util.c $(RL_LIBSRC)/kill.c $(RL_LIBSRC)/text.c \
                  $(RL_LIBSRC)/undo.c $(RL_LIBSRC)/macro.c \
                  $(RL_LIBSRC)/terminal.c $(RL_LIBSRC)/nls.c \
                  $(RL_LIBSRC)/input.c $(RL_LIBSRC)/xmalloc.c \
                  $(RL_LIBSRC)/shell.c $(RL_LIBSRC)/savestring.c \
-                 $(RL_LIBSRC)/compat.c \
+                 $(RL_LIBSRC)/misc.c $(RL_LIBSRC)/compat.c \
                  $(RL_LIBSRC)/histexpand.c $(RL_LIBSRC)/history.c \
                  $(RL_LIBSRC)/histsearch.c $(RL_LIBSRC)/histfile.c
 
@@ -271,8 +281,11 @@ GLOB_LDFLAGS = -L$(GLOB_LIBDIR)
 GLOB_DEP = $(GLOB_LIBRARY)
 
 GLOB_SOURCE = $(GLOB_LIBSRC)/glob.c $(GLOB_LIBSRC)/strmatch.c \
+             $(GLOB_LIBSRC)/smatch.c $(GLOB_LIBSRC)/xmbsrtowcs.c \
+             $(GLOB_LIBSRC)/glob_loop.c $(GLOB_LIBSRC)/sm_loop.c \
              $(GLOB_LIBSRC)/glob.h $(GLOB_LIBSRC)/strmatch.h
-GLOB_OBJ    = $(GLOB_LIBDIR)/glob.o $(GLOB_LIBDIR)/strmatch.o
+GLOB_OBJ    = $(GLOB_LIBDIR)/glob.o $(GLOB_LIBDIR)/strmatch.o \
+             $(GLOB_LIBDIR)/smatch.o $(GLOB_LIBDIR)/xmbsrtowcs.o
 
 # The source, object and documentation for the GNU Tilde library.
 TILDE_LIBSRC = $(LIBSRC)/tilde
@@ -299,7 +312,7 @@ ALLOC_ABSSRC = ${topdir}/$(ALLOC_LIBDIR)
 
 MALLOC_SRC = @MALLOC_SRC@
 MALLOC_OTHERSRC = ${ALLOC_LIBSRC}/trace.c ${ALLOC_LIBSRC}/stats.c \
-                 ${ALLOC_LIBSRC}/table.c
+                 ${ALLOC_LIBSRC}/table.c ${ALLOC_LIBSRC}/watch.c
 MALLOC_SOURCE = ${ALLOC_LIBSRC}/${MALLOC_SRC} ${MALLOC_OTHERSRC}
 MALLOC_CFLAGS = -DRCHECK -Dbotch=programming_error ${MALLOC_DEBUG}
 
@@ -309,7 +322,8 @@ MALLOC_LDFLAGS = @MALLOC_LDFLAGS@
 MALLOC_DEP = @MALLOC_DEP@
 
 ALLOC_HEADERS = $(ALLOC_LIBSRC)/getpagesize.h $(ALLOC_LIBSRC)/shmalloc.h \
-               $(ALLOC_LIBSRC)/imalloc.h $(ALLOC_LIBSRC)/mstats.h
+               $(ALLOC_LIBSRC)/imalloc.h $(ALLOC_LIBSRC)/mstats.h \
+               $(ALLOC_LIBSRC)/table.h $(ALLOC_LIBSRC)/watch.h
 
 $(MALLOC_LIBRARY):     ${MALLOC_SOURCE} ${ALLOC_HEADERS} config.h
                @(cd $(ALLOC_LIBDIR) && \
@@ -323,7 +337,8 @@ BASHINCFILES =       $(BASHINCDIR)/posixstat.h $(BASHINCDIR)/ansi_stdlib.h \
                 $(BASHINCDIR)/posixjmp.h $(BASHINCDIR)/posixwait.h \
                 $(BASHINCDIR)/posixtime.h $(BASHINCDIR)/systimes.h \
                 $(BASHINCDIR)/unionwait.h $(BASHINCDIR)/maxpath.h \
-                $(BASHINCDIR)/shtty.h $(BASHINCDIR)/typemax.h
+                $(BASHINCDIR)/shtty.h $(BASHINCDIR)/typemax.h \
+                $(BASHINCDIR)/ocache.h
 
 LIBRARIES = $(SHLIB_LIB) $(READLINE_LIB) $(HISTORY_LIB) $(TERMCAP_LIB) $(GLOB_LIB) \
            $(TILDE_LIB) $(MALLOC_LIB) $(LOCAL_LIBS)
@@ -436,7 +451,8 @@ TESTS_SUPPORT = recho$(EXEEXT) zecho$(EXEEXT) printenv$(EXEEXT)
 CREATED_SUPPORT = signames.h recho$(EXEEXT) zecho$(EXEEXT) printenv$(EXEEXT) \
                  tests/recho$(EXEEXT) tests/zecho$(EXEEXT) \
                  tests/printenv$(EXEEXT) mksignames$(EXEEXT) lsignames.h \
-                 mksyntax${EXEEXT} syntax.c $(VERSPROG) $(VERSOBJ)
+                 mksyntax${EXEEXT} syntax.c $(VERSPROG) $(VERSOBJ) \
+                 buildversion.o
 CREATED_CONFIGURE = config.h config.cache config.status config.log \
                    stamp-h
 CREATED_MAKEFILES = Makefile builtins/Makefile doc/Makefile \
@@ -486,8 +502,11 @@ version.h:  $(SOURCES) config.h Makefile
        $(SHELL) $(SUPPORT_SRC)mkversion.sh -b -S ${topdir} -s $(RELSTATUS) -d $(Version) -o newversion.h \
                && mv newversion.h version.h
 
-bashversion$(EXEEXT):  patchlevel.h conftypes.h version.h version.o $(SUPPORT_SRC)bashversion.c
-       $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) $(CPPFLAGS) -o $@ $(SUPPORT_SRC)bashversion.c version.o
+bashversion$(EXEEXT):  patchlevel.h conftypes.h version.h buildversion.o $(SUPPORT_SRC)bashversion.c
+       $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)bashversion.c buildversion.o
+
+buildversion.o: version.h conftypes.h patchlevel.h $(srcdir)/version.c
+       $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -c -o $@ $(srcdir)/version.c
 
 # old rules
 GRAM_H = parser-built
@@ -540,10 +559,10 @@ $(SHLIB_LIBRARY): config.h ${SHLIB_SOURCE}
                $(MAKE) $(MFLAGS) DEBUG=${DEBUG} ${SHLIB_LIBNAME}) || exit 1
 
 mksignames$(EXEEXT):   $(SUPPORT_SRC)mksignames.c
-       $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) $(CPPFLAGS) -o $@ $(SUPPORT_SRC)mksignames.c
+       $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)mksignames.c
 
 mksyntax$(EXEEXT):     ${srcdir}/mksyntax.c config.h syntax.h ${BASHINCDIR}/chartypes.h
-       ${CC_FOR_BUILD} ${CCFLAGS_FOR_BUILD} ${CPPFLAGS} -o $@ ${srcdir}/mksyntax.c
+       ${CC_FOR_BUILD} ${CCFLAGS_FOR_BUILD} -o $@ ${srcdir}/mksyntax.c
 
 # make a list of signals for the local system -- this is done when we're
 # *not* cross-compiling
@@ -628,11 +647,12 @@ installdirs:
 
 install:       .made installdirs
        $(INSTALL_PROGRAM) $(INSTALLMODE) $(Program) $(DESTDIR)$(bindir)/$(Program)
-       $(INSTALL_PROGRAM) $(INSTALLMODE2) bashbug $(DESTDIR)$(bindir)/bashbug
+       $(INSTALL_SCRIPT) $(INSTALLMODE2) bashbug $(DESTDIR)$(bindir)/bashbug
        -( cd $(DOCDIR) ; $(MAKE) $(MFLAGS) \
                man1dir=$(man1dir) man1ext=$(man1ext) \
                man3dir=$(man3dir) man3ext=$(man3ext) \
                infodir=$(infodir) htmldir=$(htmldir) DESTDIR=$(DESTDIR) $@ )
+       -( cd $(DEFDIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
 
 install-strip:
        $(MAKE) $(MFLAGS) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' \
@@ -646,7 +666,8 @@ uninstall:  .made
                man3dir=$(man3dir) man3ext=$(man3ext) \
                infodir=$(infodir) htmldir=$(htmldir) DESTDIR=$(DESTDIR) $@ )
 
-.PHONY: basic-clean clean realclean maintainer-clean distclean mostlyclean
+.PHONY: basic-clean clean realclean maintainer-clean distclean mostlyclean maybe-clean
+
 basic-clean:
        $(RM) $(OBJECTS) $(Program) bashbug
        $(RM) .build .made version.h
@@ -654,6 +675,7 @@ basic-clean:
 clean: basic-clean
        ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
        ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+       -( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
        -(cd $(RL_LIBDIR) && $(MAKE) $(MFLAGS) $@)
        -(cd $(HIST_LIBDIR) && test -f Makefile && $(MAKE) $(MFLAGS) $@)
        -(cd $(TERM_LIBDIR) && $(MAKE) $(MFLAGS) $@)
@@ -666,6 +688,7 @@ clean:      basic-clean
 mostlyclean: basic-clean
        ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
        ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+       -( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
        -(cd $(RL_LIBDIR) && $(MAKE) $(MFLAGS) $@)
        -(cd $(HIST_LIBDIR) && test -f Makefile && $(MAKE) $(MFLAGS) $@)
        -(cd $(TERM_LIBDIR) && $(MAKE) $(MFLAGS) $@)
@@ -674,9 +697,10 @@ mostlyclean: basic-clean
        -(cd $(ALLOC_LIBDIR) && $(MAKE) $(MFLAGS) $@)
        -(cd $(SH_LIBDIR) && $(MAKE) $(MFLAGS) $@)
 
-distclean:     basic-clean
+distclean:     basic-clean maybe-clean
        ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
        ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+       -( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
        -(cd $(RL_LIBDIR) && $(MAKE) $(MFLAGS) $@)
        -(cd $(HIST_LIBDIR) && test -f Makefile && $(MAKE) $(MFLAGS) $@)
        -(cd $(TERM_LIBDIR) && $(MAKE) $(MFLAGS) $@)
@@ -693,6 +717,7 @@ maintainer-clean:   basic-clean
        $(RM) y.tab.c y.tab.h parser-built tags TAGS
        ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
        ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+       ( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
        -(cd $(RL_LIBDIR) && $(MAKE) $(MFLAGS) $@)
        -(cd $(HIST_LIBDIR) && test -f Makefile && $(MAKE) $(MFLAGS) $@)
        -(cd $(TERM_LIBDIR) && $(MAKE) $(MFLAGS) $@)
@@ -703,14 +728,19 @@ maintainer-clean: basic-clean
        $(RM) $(CREATED_CONFIGURE) $(CREATED_MAKEFILES)
        $(RM) $(CREATED_SUPPORT) Makefile
 
+maybe-clean:
+       -if test "X$(topdir)" != "X$(BUILD_DIR)" ; then \
+               $(RM) parser-built y.tab.c y.tab.h ; \
+       fi
+
 recho$(EXEEXT):                $(SUPPORT_SRC)recho.c
-       @$(CC) $(CCFLAGS) -o $@ $(SUPPORT_SRC)recho.c
+       @$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)recho.c
 
 zecho$(EXEEXT):                $(SUPPORT_SRC)zecho.c
-       @$(CC) $(CCFLAGS) -o $@ $(SUPPORT_SRC)zecho.c
+       @$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)zecho.c
 
 printenv$(EXEEXT):     $(SUPPORT_SRC)printenv.c
-       @$(CC) $(CCFLAGS) -o $@ $(SUPPORT_SRC)printenv.c
+       @$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)printenv.c
 
 test tests check:      force $(Program) $(TESTS_SUPPORT)
        @-test -d tests || mkdir tests
@@ -766,6 +796,7 @@ dispose_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h comm
 dispose_cmd.o: error.h general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
 dispose_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
 dispose_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+dispose_cmd.o: ${BASHINCDIR}/ocache.h
 error.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h flags.h ${BASHINCDIR}/stdc.h error.h
 error.o: command.h general.h xmalloc.h externs.h input.h bashhist.h
 eval.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h trap.h flags.h ${DEFSRC}/common.h
@@ -810,7 +841,7 @@ general.o: ${BASHINCDIR}/chartypes.h
 hashcmd.o: config.h ${BASHINCDIR}/posixstat.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
 hashcmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
 hashcmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashcmd.h
-hashcmd.o: execute_cmd.h findcmd.h ${BASHINCDIR}/stdc.h
+hashcmd.o: execute_cmd.h findcmd.h ${BASHINCDIR}/stdc.h hashlib.h
 hashlib.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
 hashlib.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
 hashlib.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
@@ -838,7 +869,8 @@ mailcheck.o: execute_cmd.h mailcheck.h
 make_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h bashansi.h
 make_cmd.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h error.h flags.h make_cmd.h
 make_cmd.o: variables.h arrayfunc.h conftypes.h array.h hashlib.h subst.h input.h externs.h
-make_cmd.o: jobs.h quit.h siglist.h syntax.h
+make_cmd.o: jobs.h quit.h siglist.h syntax.h dispose_cmd.h
+make_cmd.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/ocache.h
 y.tab.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/memalloc.h
 y.tab.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
 y.tab.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
@@ -853,6 +885,7 @@ pathexp.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
 pathexp.o: make_cmd.h subst.h sig.h pathnames.h externs.h
 pathexp.o: pathexp.h flags.h 
 pathexp.o: $(GLOB_LIBSRC)/glob.h $(GLOB_LIBSRC)/strmatch.h
+pathexp.o: ${BASHINCDIR}/shmbutil.h
 print_cmd.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
 print_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
 print_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
@@ -894,6 +927,7 @@ subst.o: flags.h jobs.h siglist.h execute_cmd.h ${BASHINCDIR}/filecntl.h trap.h
 subst.o: mailcheck.h input.h $(DEFSRC)/getopt.h $(DEFSRC)/common.h
 subst.o: bashline.h bashhist.h ${GLOB_LIBSRC}/strmatch.h
 subst.o: ${BASHINCDIR}/chartypes.h
+subst.o: ${BASHINCDIR}/shmbutil.h
 test.o: bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
 test.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
 test.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
@@ -949,11 +983,13 @@ arrayfunc.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h
 arrayfunc.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
 arrayfunc.o: make_cmd.h subst.h sig.h pathnames.h externs.h
 arrayfunc.o: $(DEFSRC)/common.h
+arrayfunc.o: ${BASHINCDIR}/shmbutil.h
 braces.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
 braces.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
 braces.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
 braces.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
 braces.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+braces.o: ${BASHINCDIR}/shmbutil.h
 alias.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h command.h ${BASHINCDIR}/stdc.h
 alias.o: general.h xmalloc.h bashtypes.h externs.h alias.h
 alias.o: pcomplete.h
@@ -988,7 +1024,7 @@ bashline.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
 bashline.o: make_cmd.h subst.h sig.h pathnames.h externs.h
 bashline.o: builtins.h bashhist.h bashline.h execute_cmd.h findcmd.h pathexp.h
 bashline.o: $(DEFSRC)/common.h $(GLOB_LIBSRC)/glob.h alias.h
-bashline.o: pcomplete.h ${BASHINCDIR}/chartypes.h
+bashline.o: pcomplete.h ${BASHINCDIR}/chartypes.h input.h
 bracecomp.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
 bracecomp.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
 bracecomp.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
@@ -1074,7 +1110,7 @@ builtins/break.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h
 builtins/break.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
 builtins/break.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
 builtins/builtin.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
-builtins/builtin.o: quit.h $(DEFSRC)/common.h
+builtins/builtin.o: quit.h $(DEFSRC)/common.h $(DEFSRC)/bashgetopt.h
 builtins/builtin.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
 builtins/builtin.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
 builtins/cd.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
@@ -1088,6 +1124,7 @@ builtins/command.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/std
 builtins/declare.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/declare.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
 builtins/declare.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/declare.o: $(DEFSRC)/bashgetopt.h
 builtins/echo.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/echo.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
 builtins/echo.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
@@ -1114,7 +1151,7 @@ builtins/fc.o: flags.h unwind_prot.h variables.h arrayfunc.h conftypes.h shell.h
 builtins/fc.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h quit.h 
 builtins/fc.o: $(DEFSRC)/bashgetopt.h bashhist.h
 builtins/fc.o: ${BASHINCDIR}/chartypes.h
-builtins/fg_bg.o: bashtypes.h
+builtins/fg_bg.o: bashtypes.h $(DEFSRC)/bashgetopt.h
 builtins/fg_bg.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/fg_bg.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
 builtins/fg_bg.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
@@ -1180,7 +1217,7 @@ builtins/shopt.o: $(DEFSRC)/common.h $(DEFSRC)/bashgetopt.h
 builtins/source.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/source.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
 builtins/source.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
-builtins/source.o: findcmd.h
+builtins/source.o: findcmd.h $(DEFSRC)/bashgetopt.h
 builtins/suspend.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
 builtins/suspend.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
 builtins/suspend.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
diff --git a/NEWS b/NEWS
index 27fd87a575a0f9fee8cb5bb4e492170748f69567..b545eb60db027e7216de8be7fb2fbdfbdfb3c5dd 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,150 @@
+This is a terse description of the new features added to bash-2.05b since
+the release of bash-2.05a.  As always, the manual page (doc/bash.1) is
+the place to look for complete descriptions.
+
+1.  New Features in Bash
+
+a.  If set, TMOUT is the default timeout for the `read' builtin.
+
+b.  `type' has two new options:  `-f' suppresses shell function lookup, and
+    `-P' forces a $PATH search.
+
+c.  New code to handle multibyte characters.
+
+d.  `select' was changed to be more ksh-compatible, in that the menu is
+    reprinted each time through the loop only if REPLY is set to NULL.
+    The previous behavior is available as a compile-time option.
+
+e.  `complete -d' and `complete -o dirnames' now force a slash to be
+    appended to names which are symlinks to directories.
+
+f.  There is now a bindable edit-and-execute-command readline command,
+    like the vi-mode `v' command, bound to C-xC-e in emacs mode.
+
+g.  Added support for ksh93-like [:word:] character class in pattern matching.
+
+h.  The  $'...' quoting construct now expands \cX to Control-X.
+
+i.  A new \D{...} prompt expansion; passes the `...' to strftime and inserts
+    the result into the expanded prompt.
+
+j.  The shell now performs arithmetic in the largest integer size the
+    machine supports (intmax_t), instead of long.
+
+k.  If a numeric argument is supplied to one of the bash globbing completion
+    functions, a `*' is appended to the word before expansion is attempted.
+
+l.  The bash globbing completion functions now allow completions to be listed
+    with double tabs or if `show-all-if-ambiguous' is set.
+
+m.  New `-o nospace' option for `complete' and `compgen' builtins; suppresses
+    readline's appending a space to the completed word.
+
+n.  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).
+
+p.  There is a new configuration option `--enable-mem-scramble', controls
+    bash malloc behavior of writing garbage characters into memory at
+    allocation and free time.
+
+q.  The `complete' and `compgen' builtins now have a new `-s/-A service'
+    option to complete on names from /etc/services.
+
+r.  `read' has a new `-u fd' option to read from a specified file descriptor.
+
+s.  Fix the completion code so that expansion errors in a directory name
+    don't cause a longjmp back to the command loop.
+
+t.  Fixed word completion inside command substitution to work a little more
+    intuitively.
+
+u.  The `printf' %q format specifier now uses $'...' quoting to print the
+    argument if it contains non-printing characters.
+
+v.  The `declare' and `typeset' builtins have a new `-t' option.  When applied
+    to functions, it causes the DEBUG trap to be inherited by the named
+    function.  Currently has no effect on variables.
+
+w.  The DEBUG trap is now run *before* simple commands, ((...)) commands,
+    [[...]] conditional commands, and for ((...)) loops.
+
+x.  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.
+
+y.  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.  Code
+    from Gary Vaughan.
+
+z.  New [n]<&word- and [n]>&word- redirections from ksh93 -- move fds (dup
+    and close).
+
+aa. There is a new `-l' invocation option, equivalent to `--login'.
+
+bb. The `hash' builtin has a new `-l' option to list contents in a reusable
+    format, and a `-d' option to remove a name from the hash table.
+
+cc. There is now support for placing the long help text into separate files 
+    installed into ${datadir}/bash.  Not enabled by default; can be turned  
+    on with `--enable-separate-helpfiles' option to configure.
+    
+dd. All builtins that take operands accept a `--' pseudo-option, except
+    `echo'.
+
+ee. The `echo' builtin now accepts \0xxx (zero to three octal digits following
+    the `0') in addition to \xxx (one to three octal digits) for SUSv3/XPG6/
+    POSIX.1-2001 compliance.
+
+
+2.  New Features in Readline
+
+a.  Support for key `subsequences':  allows, e.g., ESC and ESC-a to both
+    be bound to readline functions.  Now the arrow keys may be used in vi
+    insert mode.
+
+b.  When listing completions, and the number of lines displayed is more than
+    the screen length, readline uses an internal pager to display the results.
+    This is controlled by the `page-completions' variable (default on).
+
+c.  New code to handle editing and displaying multibyte characters.
+
+d.  The behavior introduced in bash-2.05a of deciding whether or not to
+    append a slash to a completed name that is a symlink to a directory has
+    been made optional, controlled by the `mark-symlinked-directories'
+    variable (default is the 2.05a behavior).
+
+e.  The `insert-comment' command now acts as a toggle if given a numeric
+    argument:  if the first characters on the line don't specify a
+    comment, insert one; if they do, delete the comment text
+
+f.  New application-settable completion variable:
+    rl_completion_mark_symlink_dirs, allows an application's completion
+    function to temporarily override the user's preference for appending
+    slashes to names which are symlinks to directories.
+
+g.  New function available to application completion functions:
+    rl_completion_mode, to tell how the completion function was invoked
+    and decide which argument to supply to rl_complete_internal (to list
+    completions, etc.).
+
+h.  Readline now has an overwrite mode, toggled by the `overwrite-mode'
+    bindable command, which could be bound to `Insert'.
+
+i.  New application-settable completion variable:
+    rl_completion_suppress_append, inhibits appending of
+    rl_completion_append_character to completed words.
+
+j.  New key bindings when reading an incremental search string:  ^W yanks
+    the currently-matched word out of the current line into the search
+    string; ^Y yanks the rest of the current line into the search string,
+    DEL or ^H deletes characters from the search string.
+
+-------------------------------------------------------------------------------
 This is a terse description of the new features added to bash-2.05a since
 the release of bash-2.05.  As always, the manual page (doc/bash.1) is
 the place to look for complete descriptions.
diff --git a/NOTES b/NOTES
index 9e4eeafd9f384c780b14daa88426f26672e64860..31068d0eef56d60d823a37d03be203a7e9dca78b 100644 (file)
--- a/NOTES
+++ b/NOTES
@@ -30,11 +30,6 @@ Platform-Specific Configuration and Operation Notes
        leak caused by using the bash malloc because closedir(3) needs to read
        freed memory to find the file descriptor to close
 
-       If you are using GNU libc, especially on a linux system
-
-(Configuring --without-gnu-malloc will still result in lib/malloc/libmalloc.a
-being built and linked against, but there is only a stub file in the archive.)
-
 2.  Configure using shlicc2 on BSD/OS 2.1 and BSD/OS 3.x to use loadable
     builtins
 
@@ -234,7 +229,7 @@ being built and linked against, but there is only a stub file in the archive.)
 
     If you want to completely remove any dependence on /usr, perhaps
     to put a copy of bash in /sbin and have it available when /usr is
-    not mounted, force the build process to use the shared ld.so library
+    not mounted, force the build process to use the shared dl.so library
     in /etc/lib.
 
     For gcc, this would be something like
@@ -326,3 +321,6 @@ being built and linked against, but there is only a stub file in the archive.)
            want it).
 
        5. make; make install; enjoy
+
+15.  Configure with `CC=xlc' if you don't have gcc on AIX 4.2 and later
+     versions.  `xlc' running in `cc' mode has trouble compiling error.c.
similarity index 91%
rename from CWRU/POSIX.NOTES
rename to POSIX
index 7adf872723b800bb38a4ff1597c1c4b6f0089155..977f98914c1809b690636c94d65b51e22ef215bc 100644 (file)
+++ b/POSIX
@@ -6,6 +6,9 @@ Starting Bash with the `--posix' command-line option or executing `set
 to the POSIX 1003.2 standard by changing the behavior to match that
 specified by POSIX in areas where the Bash default differs.
 
+When invoked as `sh', Bash enters POSIX mode after reading the startup
+files.
+
 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
@@ -112,6 +115,14 @@ The following list is what's changed when `POSIX mode' is in effect:
  30. When the `set' builtin is invoked without options, it does not
      display shell function names and definitions.
 
+ 31. When the `set' builtin is invoked without options, it displays
+     variable values without quotes, unless they contain shell
+     metacharacters, even if the result contains nonprinting characters.
+
+ 32. When the `cd' builtin is invoked in LOGICAL mode, and the pathname
+     constructed from `$PWD' and the directory name supplied as an
+     argument does not refer to an existing directory, `cd' will fail
+     instead of falling back to PHYSICAL mode.
 
 There is other POSIX 1003.2 behavior that Bash does not implement.
 Specifically:
diff --git a/RBASH b/RBASH
new file mode 100644 (file)
index 0000000..c3667f5
--- /dev/null
+++ b/RBASH
@@ -0,0 +1,49 @@
+The Restricted Shell
+====================
+
+If Bash is started with the name `rbash', or the `--restricted' or `-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 `bash'
+with the exception that the following are disallowed or not performed:
+
+   * Changing directories with the `cd' builtin.
+
+   * Setting or unsetting the values of the `SHELL', `PATH', `ENV', or
+     `BASH_ENV' variables.
+
+   * Specifying command names containing slashes.
+
+   * Specifying a filename containing a slash as an argument to the `.'
+     builtin command.
+
+   * Specifying a filename containing a slash as an argument to the `-p'
+     option to the `hash' builtin command.
+
+   * Importing function definitions from the shell environment at
+     startup.
+
+   * Parsing the value of `SHELLOPTS' from the shell environment at
+     startup.
+
+   * Redirecting output using the `>', `>|', `<>', `>&', `&>', and `>>'
+     redirection operators.
+
+   * Using the `exec' builtin to replace the shell with another command.
+
+   * Adding or deleting builtin commands with the `-f' and `-d' options
+     to the `enable' builtin.
+
+   * Using the `enable' builtin command to enable disabled shell
+     builtins.
+
+   * Specifying the `-p' option to the `command' builtin.
+
+   * Turning off restricted mode with `set +r' or `set +o restricted'.
+
+These restrictions are enforced after any startup files are read.
+
+When a command that is found to be a shell script is executed (*note
+Shell Scripts::), `rbash' turns off any restrictions in the shell
+spawned to execute the script.
+
diff --git a/README b/README
index 92cf3c095b1e9ca960326e4d551c261e54af675e..9dff9ef2359d18e3c8a2098f36a1871c7ff59f27 100644 (file)
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
 Introduction
 ============
 
-This is GNU Bash, version 2.05a.  Bash is the GNU Project's Bourne
+This is GNU Bash, version 2.05b.  Bash is the GNU Project's Bourne
 Again SHell, a complete implementation of the POSIX.2 shell spec,
 but also with interactive command line editing, job control on
 architectures that support it, csh-like features such as history
@@ -67,9 +67,9 @@ built at the same time as bash.  If bash fails to build, try building
 bashbug directly with `make bashbug'.  If you cannot build `bashbug',
 please send mail to bug-bash@gnu.org with the following information:
 
-       * the version number and release status of Bash (e.g., 2.01-release)
-       * the machine and OS that it is running on (look at the file
-         `.made' in the bash build directory)
+       * the version number and release status of Bash (e.g., 2.05a-release)
+       * the machine and OS that it is running on (you may run
+         `bashversion -l' from the bash build directory for this information)
        * a list of the compilation flags or the contents of `config.h', if
          appropriate
        * a description of the bug
index 22fe7fe7dc7471d2380e0bfdc8a906963e8cc176..d1ad025fb0655546d53b41388d0e63f6d3eda212 100644 (file)
@@ -605,6 +605,66 @@ AC_DEFINE(CAN_REDEFINE_GETENV)
 fi
 ])
 
+# We should check for putenv before calling this
+AC_DEFUN(BASH_FUNC_STD_PUTENV,
+[
+AC_REQUIRE([AC_HEADER_STDC])
+AC_REQUIRE([AC_C_PROTOTYPES])
+AC_CACHE_CHECK([for standard-conformant putenv declaration], bash_cv_std_putenv,
+[AC_TRY_LINK([
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#ifndef __STDC__
+#  ifndef const
+#    define const
+#  endif
+#endif
+#ifdef PROTOTYPES
+extern int putenv (char *);
+#else
+extern int putenv ();
+#endif
+],
+[return (putenv == 0);],
+bash_cv_std_putenv=yes, bash_cv_std_putenv=no
+)])
+if test $bash_cv_std_putenv = yes; then
+AC_DEFINE(HAVE_STD_PUTENV)
+fi
+])
+
+# We should check for unsetenv before calling this
+AC_DEFUN(BASH_FUNC_STD_UNSETENV,
+[
+AC_REQUIRE([AC_HEADER_STDC])
+AC_REQUIRE([AC_C_PROTOTYPES])
+AC_CACHE_CHECK([for standard-conformant unsetenv declaration], bash_cv_std_unsetenv,
+[AC_TRY_LINK([
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#ifndef __STDC__
+#  ifndef const
+#    define const
+#  endif
+#endif
+#ifdef PROTOTYPES
+extern int unsetenv (const char *);
+#else
+extern int unsetenv ();
+#endif
+],
+[return (unsetenv == 0);],
+bash_cv_std_unsetenv=yes, bash_cv_std_unsetenv=no
+)])
+if test $bash_cv_std_unsetenv = yes; then
+AC_DEFINE(HAVE_STD_UNSETENV)
+fi
+])
+
 AC_DEFUN(BASH_FUNC_ULIMIT_MAXFDS,
 [AC_MSG_CHECKING(whether ulimit can substitute for getdtablesize)
 AC_CACHE_VAL(bash_cv_ulimit_maxfds,
@@ -922,7 +982,7 @@ _bash_needmsg=
 fi
 AC_CACHE_VAL(bash_cv_termcap_lib,
 [AC_CHECK_LIB(termcap, tgetent, bash_cv_termcap_lib=libtermcap,
-    [AC_CHECK_LIB(tinfo, tgetent, bash_cv_termcal_lib=libtinfo,
+    [AC_CHECK_LIB(tinfo, tgetent, bash_cv_termcap_lib=libtinfo,
         [AC_CHECK_LIB(curses, tgetent, bash_cv_termcap_lib=libcurses,
            [AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
                bash_cv_termcap_lib=gnutermcap)])])])])
@@ -1378,10 +1438,10 @@ AC_DEFUN(BASH_SYS_DEFAULT_MAIL_DIR,
 AC_CACHE_VAL(bash_cv_mail_dir,
 [if test -d /var/mail; then
    bash_cv_mail_dir=/var/mail
- elif test -d /usr/mail; then
-   bash_cv_mail_dir=/usr/mail
  elif test -d /var/spool/mail; then
    bash_cv_mail_dir=/var/spool/mail
+ elif test -d /usr/mail; then
+   bash_cv_mail_dir=/usr/mail
  elif test -d /usr/spool/mail; then
    bash_cv_mail_dir=/usr/spool/mail
  else
@@ -1389,17 +1449,7 @@ AC_CACHE_VAL(bash_cv_mail_dir,
  fi
 ])
 AC_MSG_RESULT($bash_cv_mail_dir)
-if test $bash_cv_mail_dir = "/var/mail"; then
-   AC_DEFINE(DEFAULT_MAIL_DIRECTORY, "/var/mail")
-elif test $bash_cv_mail_dir = "/usr/mail"; then
-   AC_DEFINE(DEFAULT_MAIL_DIRECTORY, "/usr/mail")
-elif test $bash_cv_mail_dir = "/var/spool/mail"; then
-   AC_DEFINE(DEFAULT_MAIL_DIRECTORY, "/var/spool/mail")
-elif test $bash_cv_mail_dir = "/usr/spool/mail"; then
-   AC_DEFINE(DEFAULT_MAIL_DIRECTORY, "/usr/spool/mail")
-else
-   AC_DEFINE(DEFAULT_MAIL_DIRECTORY, "unknown")
-fi
+AC_DEFINE_UNQUOTED(DEFAULT_MAIL_DIRECTORY, "$bash_cv_mail_dir")
 ])
 
 AC_DEFUN(BASH_HAVE_TIOCGWINSZ,
@@ -1593,6 +1643,42 @@ AC_DEFINE(UNUSABLE_RT_SIGNALS)
 fi
 ])
 
+dnl
+dnl check for availability of multibyte characters and functions
+dnl
+AC_DEFUN(BASH_CHECK_MULTIBYTE,
+[
+AC_CHECK_HEADERS(wctype.h)
+AC_CHECK_HEADERS(wchar.h)
+AC_CHECK_HEADERS(langinfo.h)
+
+AC_CHECK_FUNC(mbsrtowcs, AC_DEFINE(HAVE_MBSRTOWCS))
+AC_CHECK_FUNC(wcwidth, AC_DEFINE(HAVE_WCWIDTH))
+
+AC_CACHE_CHECK([for mbstate_t], bash_cv_have_mbstate_t,
+[AC_TRY_RUN([
+#include <wchar.h>
+int
+main ()
+{
+  mbstate_t ps;
+  return 0;
+}], bash_cv_have_mbstate_t=yes,  bash_cv_have_mbstate_t=no)])
+if test $bash_cv_have_mbstate_t = yes; then
+       AC_DEFINE(HAVE_MBSTATE_T)
+fi
+
+AC_CACHE_CHECK([for nl_langinfo and CODESET], bash_cv_langinfo_codeset,
+[AC_TRY_LINK(
+[#include <langinfo.h>],
+[char* cs = nl_langinfo(CODESET);],
+bash_cv_langinfo_codeset=yes, bash_cv_langinfo_codeset=no)])
+if test $bash_cv_langinfo_codeset = yes; then
+  AC_DEFINE(HAVE_LANGINFO_CODESET)
+fi
+
+])
+
 dnl need: prefix exec_prefix libdir includedir CC TERMCAP_LIB
 dnl require:
 dnl    AC_PROG_CC
@@ -1655,7 +1741,7 @@ RL_MINOR=0
 case "$ac_cv_rl_version" in
 2*|3*|4*|5*|6*|7*|8*|9*)
        RL_MAJOR=`echo $ac_cv_rl_version | sed 's:\..*$::'`
-       RL_MINOR=`echo $ac_cv_rl_version | sed -e 's:^.*\.::' -e 's:[a-zA-Z]*$::'`
+       RL_MINOR=`echo $ac_cv_rl_version | sed -e 's:^.*\.::' -e 's:[[a-zA-Z]]*$::'`
        ;;
 esac
 
diff --git a/alias.c b/alias.c
index 8af373b36da6714cb470787faa4ced4cee627e51..1aa9cb11b395c92b68c756e6cba8c28e2d8d419b 100644 (file)
--- a/alias.c
+++ b/alias.c
@@ -1,7 +1,7 @@
 /* alias.c -- Not a full alias, but just the kind that we use in the
    shell.  Csh style alias is somewhere else (`over there, in a box'). */
 
-/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -42,6 +42,8 @@
 #  include "pcomplete.h"
 #endif
 
+#define ALIAS_HASH_BUCKETS     16      /* must be power of two */
+
 typedef int sh_alias_map_func_t __P((alias_t *));
 
 static void free_alias_data __P((PTR_T));
@@ -66,7 +68,7 @@ void
 initialize_aliases ()
 {
   if (!aliases)
-    aliases = make_hash_table (0);
+    aliases = hash_create (ALIAS_HASH_BUCKETS);
 }
 
 /* Scan the list of aliases looking for one with NAME.  Return NULL
@@ -80,7 +82,7 @@ find_alias (name)
   if (aliases == 0)
     return ((alias_t *)NULL);
 
-  al = find_hash_item (name, aliases);
+  al = hash_search (name, aliases, 0);
   return (al ? (alias_t *)al->data : (alias_t *)NULL);
 }
 
@@ -120,6 +122,7 @@ add_alias (name, value)
     {
       free (temp->value);
       temp->value = savestring (value);
+      temp->flags &= ~AL_EXPANDNEXT;
       n = value[strlen (value) - 1];
       if (n == ' ' || n == '\t')
        temp->flags |= AL_EXPANDNEXT;
@@ -135,8 +138,8 @@ add_alias (name, value)
       if (n == ' ' || n == '\t')
        temp->flags |= AL_EXPANDNEXT;
 
-      elt = add_hash_item (savestring (name), aliases);
-      elt->data = (char *)temp;
+      elt = hash_insert (savestring (name), aliases, HASH_NOSRCH);
+      elt->data = temp;
 #if defined (PROGRAMMABLE_COMPLETION)
       set_itemlist_dirty (&it_aliases);
 #endif
@@ -168,7 +171,7 @@ remove_alias (name)
   if (aliases == 0)
     return (-1);
 
-  elt = remove_hash_item (name, aliases);
+  elt = hash_remove (name, aliases, 0);
   if (elt)
     {
       free_alias_data (elt->data);
@@ -189,8 +192,8 @@ delete_all_aliases ()
   if (aliases == 0)
     return;
 
-  flush_hash_table (aliases, free_alias_data);
-  dispose_hash_table (aliases);
+  hash_flush (aliases, free_alias_data);
+  hash_dispose (aliases);
   aliases = (HASH_TABLE *)NULL;
 #if defined (PROGRAMMABLE_COMPLETION)
   set_itemlist_dirty (&it_aliases);
@@ -206,30 +209,24 @@ map_over_aliases (function)
   register int i;
   register BUCKET_CONTENTS *tlist;
   alias_t *alias, **list;
-  int list_index, list_size;
+  int list_index;
 
-  list = (alias_t **)NULL;
-  for (i = list_index = list_size = 0; i < aliases->nbuckets; i++)
-    {
-      tlist = get_hash_bucket (i, aliases);
+  i = HASH_ENTRIES (aliases);
+  if (i == 0)
+    return ((alias_t **)NULL);
 
-      while (tlist)
+  list = (alias_t **)xmalloc ((i + 1) * sizeof (alias_t *));
+  for (i = list_index = 0; i < aliases->nbuckets; i++)
+    {
+      for (tlist = hash_items (i, aliases); tlist; tlist = tlist->next)
        {
          alias = (alias_t *)tlist->data;
 
          if (!function || (*function) (alias))
            {
-             if (list_index + 1 >= list_size)
-               {
-                 list_size += 20;
-                 list = (alias_t **)xrealloc (list,
-                                              list_size * sizeof (alias_t *));
-               }
-
              list[list_index++] = alias;
              list[list_index] = (alias_t *)NULL;
            }
-         tlist = tlist->next;
        }
     }
   return (list);
@@ -239,7 +236,7 @@ static void
 sort_aliases (array)
      alias_t **array;
 {
-  qsort (array, array_len ((char **)array), sizeof (alias_t *), (QSFUNC *)qsort_alias_compare);
+  qsort (array, strvec_len ((char **)array), sizeof (alias_t *), (QSFUNC *)qsort_alias_compare);
 }
 
 static int
@@ -260,7 +257,7 @@ all_aliases ()
 {
   alias_t **list;
 
-  if (!aliases)
+  if (aliases == 0 || HASH_ENTRIES (aliases) == 0)
     return ((alias_t **)NULL);
 
   list = map_over_aliases ((sh_alias_map_func_t *)NULL);
@@ -529,7 +526,7 @@ alias_expand (string)
       /* If there is a backslash-escaped character quoted in TOKEN,
         then we don't do alias expansion.  This should check for all
         other quoting characters, too. */
-      if (strchr (token, '\\'))
+      if (xstrchr (token, '\\'))
        expand_this_token = 0;
 
       /* If we should be expanding here, if we are expanding all words, or if
diff --git a/array.c b/array.c
index c1d862ed62cc37671a1cba081df11842486fbaa1..a73be55a8afe2c24084f8990b8a63ab5c5faf252 100644 (file)
--- a/array.c
+++ b/array.c
@@ -9,7 +9,7 @@
  * chet@ins.cwru.edu
  */
 
-/* Copyright (C) 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1997-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
                new->next = ae; \
        } while(0)
 
-/*
- * Allocate and return a new array element with index INDEX and value
- * VALUE.
- */
-ARRAY_ELEMENT *
-new_array_element(indx, value)
-arrayind_t     indx;
-char   *value;
-{
-       ARRAY_ELEMENT *r;
-
-       r = (ARRAY_ELEMENT *)xmalloc(sizeof(ARRAY_ELEMENT));
-       r->ind = indx;
-       r->value = value ? savestring(value) : (char *)NULL;
-       r->next = r->prev = (ARRAY_ELEMENT *) NULL;
-       return(r);
-}
-
-void
-destroy_array_element(ae)
-ARRAY_ELEMENT  *ae;
-{
-       FREE(ae->value);
-       free(ae);
-}
+static char *array_to_string_internal __P((ARRAY_ELEMENT *, ARRAY_ELEMENT *, char *, int));
 
 ARRAY *
-new_array()
+array_create()
 {
        ARRAY   *r;
        ARRAY_ELEMENT   *head;
 
        r =(ARRAY *)xmalloc(sizeof(ARRAY));
        r->type = array_indexed;
-       r->max_index = r->max_size = -1;
+       r->max_index = -1;
        r->num_elements = 0;
-       head = new_array_element(-1, (char *)NULL);     /* dummy head */
+       head = array_create_element(-1, (char *)NULL);  /* dummy head */
        head->prev = head->next = head;
        r->head = head;
        return(r);
 }
 
 void
-empty_array (a)
+array_flush (a)
 ARRAY  *a;
 {
        register ARRAY_ELEMENT *r, *r1;
@@ -105,27 +81,27 @@ ARRAY      *a;
                return;
        for (r = element_forw(a->head); r != a->head; ) {
                r1 = element_forw(r);
-               destroy_array_element(r);
+               array_dispose_element(r);
                r = r1;
        }
        a->head->next = a->head->prev = a->head;
-       a->max_index = a->max_size = -1;
-       a->num_elements = a->max_size = 0;
+       a->max_index = -1;
+       a->num_elements = 0;
 }
 
 void
-dispose_array(a)
+array_dispose(a)
 ARRAY  *a;
 {
        if (a == 0)
                return;
-       empty_array (a);
-       destroy_array_element(a->head);
+       array_flush (a);
+       array_dispose_element(a->head);
        free(a);
 }
 
 ARRAY *
-dup_array(a)
+array_copy(a)
 ARRAY  *a;
 {
        ARRAY   *a1;
@@ -133,13 +109,12 @@ ARRAY     *a;
 
        if (!a)
                return((ARRAY *) NULL);
-       a1 = new_array();
+       a1 = array_create();
        a1->type = a->type;
        a1->max_index = a->max_index;
        a1->num_elements = a->num_elements;
-       a1->max_size = a->max_size;
        for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae)) {
-               new = new_array_element(element_index(ae), element_value(ae));
+               new = array_create_element(element_index(ae), element_value(ae));
                ADD_BEFORE(a1->head, new);
        }
        return(a1);
@@ -151,41 +126,254 @@ ARRAY    *a;
  * S to E, inclusive.
  */
 ARRAY *
-dup_array_subrange(array, s, e)
+array_slice(array, s, e)
 ARRAY          *array;
 ARRAY_ELEMENT  *s, *e;
 {
        ARRAY   *a;
        ARRAY_ELEMENT *p, *n;
-       arrayind_t i;
+       int     i;
+       arrayind_t mi;
 
-       a = new_array ();
+       a = array_create ();
        a->type = array->type;
 
        for (p = s, i = 0; p != e; p = element_forw(p), i++) {
-               n = new_array_element (i, element_value(p));
+               n = array_create_element (element_index(p), element_value(p));
                ADD_BEFORE(a->head, n);
+               mi = element_index(ae);
        }
-       a->num_elements = a->max_index = i;
+       a->num_elements = i;
+       a->max_index = mi;
        return a;
 }
 #endif
 
+/*
+ * Walk the array, calling FUNC once for each element, with the array
+ * element as the argument.
+ */
+void
+array_walk(a, func)
+ARRAY  *a;
+sh_ae_map_func_t *func;
+{
+       register ARRAY_ELEMENT *ae;
+
+       if (a == 0 || array_empty(a))
+               return;
+       for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae))
+               if ((*func)(ae) < 0)
+                       return;
+}
+
+/*
+ * Shift the array A N elements to the left.  Delete the first N elements
+ * and subtract N from the indices of the remaining elements.  If FLAGS
+ * does not include AS_DISPOSE, this returns a singly-linked null-terminated
+ * list of elements so the caller can dispose of the chain.  If FLAGS
+ * includes AS_DISPOSE, this function disposes of the shifted-out elements
+ * and returns NULL.
+ */
+ARRAY_ELEMENT *
+array_shift(a, n, flags)
+ARRAY  *a;
+int    n, flags;
+{
+       register ARRAY_ELEMENT *ae, *ret;
+       register int i;
+
+       if (a == 0 || array_empty(a) || n <= 0)
+               return ((ARRAY_ELEMENT *)NULL);
+
+       for (i = 0, ret = ae = element_forw(a->head); ae != a->head && i < n; ae = element_forw(ae), i++)
+               ;
+       if (ae == a->head) {
+               /* Easy case; shifting out all of the elements */
+               if (flags & AS_DISPOSE) {
+                       array_flush (a);
+                       return ((ARRAY_ELEMENT *)NULL);
+               }
+               for (ae = ret; element_forw(ae) != a->head; ae = element_forw(ae))
+                       ;
+               element_forw(ae) = (ARRAY_ELEMENT *)NULL;
+               a->head->next = a->head->prev = a->head;
+               a->max_index = -1;
+               a->num_elements = 0;
+               return ret;
+       }
+       /*
+        * ae now points to the list of elements we want to retain.
+        * ret points to the list we want to either destroy or return.
+        */
+       ae->prev->next = (ARRAY_ELEMENT *)NULL;         /* null-terminate RET */
+
+       a->head->next = ae;             /* slice RET out of the array */
+       ae->prev = a->head;
+
+       for ( ; ae != a->head; ae = element_forw(ae))
+               element_index(ae) -= n; /* renumber retained indices */
+
+       a->num_elements -= n;           /* modify bookkeeping information */
+       a->max_index -= n;
+
+       if (flags & AS_DISPOSE) {
+               for (ae = ret; ae; ) {
+                       ret = element_forw(ae);
+                       array_dispose_element(ae);
+                       ae = ret;
+               }
+               return ((ARRAY_ELEMENT *)NULL);
+       }
+
+       return ret;
+}
+
+/*
+ * Shift array A right N indices.  If S is non-null, it becomes the value of
+ * the new element 0.  Returns the number of elements in the array after the
+ * shift.
+ */
+int
+array_rshift (a, n, s)
+ARRAY  *a;
+int    n;
+char   *s;
+{
+       register ARRAY_ELEMENT  *ae, *new;
+
+       if (a == 0)
+               return 0;
+       if (n <= 0)
+               return (a->num_elements);
+
+       ae = element_forw(a->head);
+       if (s) {
+               new = array_create_element(0, s);
+               ADD_BEFORE(ae, new);
+               a->num_elements++;
+       }
+
+       a->max_index += n;
+
+       /*
+        * Renumber all elements in the array except the one we just added.
+        */
+       for ( ; ae != a->head; ae = element_forw(ae))
+               element_index(ae) += n;
+
+       return (a->num_elements);
+}
+
+ARRAY  *
+array_quote(array)
+ARRAY  *array;
+{
+       ARRAY_ELEMENT   *a;
+       char    *t;
+
+       if (array == 0 || array->head == 0 || array_empty (array))
+               return (ARRAY *)NULL;
+       for (a = element_forw(array->head); a != array->head; a = element_forw(a)) {
+               t = quote_string (a->value);
+               FREE(a->value);
+               a->value = t;
+       }
+       return array;
+}
+
+char *
+array_subrange (a, start, end, quoted)
+ARRAY  *a;
+arrayind_t     start, end;
+int    quoted;
+{
+       ARRAY_ELEMENT   *h, *p;
+       arrayind_t      i;
+
+       p = array_head (a);
+       if (p == 0 || array_empty (a) || start > array_num_elements (a))
+               return ((char *)NULL);
+
+       for (i = 0, p = element_forw(p); p != a->head && i < start; i++, p = element_forw(p))
+               ;
+       if (p == a->head)
+               return ((char *)NULL);
+       for (h = p; p != a->head && i < end; i++, p = element_forw(p))
+               ;
+
+       return (array_to_string_internal (h, p, " ", quoted));
+}
+
+char *
+array_patsub (a, pat, rep, mflags)
+ARRAY  *a;
+char   *pat, *rep;
+int    mflags;
+{
+       ARRAY           *a2;
+       ARRAY_ELEMENT   *e;
+       char    *t;
+
+       if (array_head (a) == 0 || array_empty (a))
+               return ((char *)NULL);
+
+       a2 = array_copy (a);
+       for (e = element_forw(a2->head); e != a2->head; e = element_forw(e)) {
+               t = pat_subst(element_value(e), pat, rep, mflags);
+               FREE(element_value(e));
+               e->value = t;
+       }
+
+       if (mflags & MATCH_QUOTED)
+               array_quote (a2);
+       t = array_to_string (a2, " ", 0);
+       array_dispose (a2);
+
+       return t;
+}
+
+/*
+ * Allocate and return a new array element with index INDEX and value
+ * VALUE.
+ */
+ARRAY_ELEMENT *
+array_create_element(indx, value)
+arrayind_t     indx;
+char   *value;
+{
+       ARRAY_ELEMENT *r;
+
+       r = (ARRAY_ELEMENT *)xmalloc(sizeof(ARRAY_ELEMENT));
+       r->ind = indx;
+       r->value = value ? savestring(value) : (char *)NULL;
+       r->next = r->prev = (ARRAY_ELEMENT *) NULL;
+       return(r);
+}
+
 #ifdef INCLUDE_UNUSED
 ARRAY_ELEMENT *
-copy_array_element(ae)
+array_copy_element(ae)
 ARRAY_ELEMENT  *ae;
 {
-       return(ae ? new_array_element(element_index(ae), element_value(ae))
+       return(ae ? array_create_element(element_index(ae), element_value(ae))
                  : (ARRAY_ELEMENT *) NULL);
 }
 #endif
 
+void
+array_dispose_element(ae)
+ARRAY_ELEMENT  *ae;
+{
+       FREE(ae->value);
+       free(ae);
+}
+
 /*
  * Add a new element with index I and value V to array A (a[i] = v).
  */
 int
-array_add_element(a, i, v)
+array_insert(a, i, v)
 ARRAY  *a;
 arrayind_t     i;
 char   *v;
@@ -194,7 +382,7 @@ char        *v;
 
        if (!a)
                return(-1);
-       new = new_array_element(i, v);
+       new = array_create_element(i, v);
        if (i > array_max_index(a)) {
                /*
                 * Hook onto the end.  This also works for an empty array.
@@ -214,7 +402,7 @@ char        *v;
                        /*
                         * Replacing an existing element.
                         */
-                       destroy_array_element(new);
+                       array_dispose_element(new);
                        free(element_value(ae));
                        ae->value = savestring(v);
                        return(0);
@@ -232,7 +420,7 @@ char        *v;
  * caller can dispose of it.
  */
 ARRAY_ELEMENT *
-array_delete_element(a, i)
+array_remove(a, i)
 ARRAY  *a;
 arrayind_t     i;
 {
@@ -270,25 +458,68 @@ arrayind_t        i;
        return((char *) NULL);
 }
 
-#ifdef TEST_ARRAY
-/*
- * Walk the array, calling FUNC once for each element, with the array
- * element as the argument.
- */
-void
-array_walk(a, func)
+/* Convenience routines for the shell to translate to and from the form used
+   by the rest of the code. */
+WORD_LIST *
+array_to_word_list(a)
 ARRAY  *a;
-sh_ae_map_func_t *func;
 {
-       register ARRAY_ELEMENT *ae;
+       WORD_LIST       *list;
+       ARRAY_ELEMENT   *ae;
 
        if (a == 0 || array_empty(a))
-               return;
+               return((WORD_LIST *)NULL);
+       list = (WORD_LIST *)NULL;
        for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae))
-               (*func)(ae);
+               list = make_word_list (make_bare_word(element_value(ae)), list);
+       return (REVERSE_LIST(list, WORD_LIST *));
 }
-#endif
 
+ARRAY *
+array_from_word_list (list)
+WORD_LIST      *list;
+{
+       ARRAY   *a;
+
+       if (list == 0)
+               return((ARRAY *)NULL);
+       a = array_create();
+       return (array_assign_list (a, list));
+}
+
+ARRAY *
+array_assign_list (array, list)
+ARRAY  *array;
+WORD_LIST      *list;
+{
+       register WORD_LIST *l;
+       register arrayind_t i;
+
+       for (l = list, i = 0; l; l = l->next, i++)
+               array_insert(array, i, l->word->word);
+       return array;
+}
+
+char **
+array_to_argv (a)
+ARRAY  *a;
+{
+       char            **ret, *t;
+       int             i;
+       ARRAY_ELEMENT   *ae;
+
+       if (a == 0 || array_empty(a))
+               return ((char **)NULL);
+       ret = strvec_create (array_num_elements (a) + 1);
+       i = 0;
+       for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae)) {
+               t = element_value (ae);
+               ret[i++] = t ? savestring (t) : (char *)NULL;
+       }
+       ret[i] = (char *)NULL;
+       return (ret);
+}
+       
 /*
  * Return a string that is the concatenation of all the elements in A,
  * separated by SEP.
@@ -335,23 +566,12 @@ int       quoted;
 }
 
 char *
-array_to_string (a, sep, quoted)
+array_to_assign (a, quoted)
 ARRAY  *a;
-char   *sep;
 int    quoted;
 {
-       if (a == 0)
-               return((char *)NULL);
-       if (array_empty(a))
-               return(savestring(""));
-       return (array_to_string_internal (element_forw(a->head), a->head, sep, quoted));
-}
-
-char *
-array_to_assignment_string (a)
-ARRAY  *a;
-{
-       char    *result, *indstr, *valstr;
+       char    *result, *valstr, *is;
+       char    indstr[INT_STRLEN_BOUND(intmax_t) + 1];
        ARRAY_ELEMENT *ae;
        int     rsize, rlen, elen;
 
@@ -363,15 +583,15 @@ ARRAY     *a;
        rlen = 1;
 
        for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae)) {
-               indstr = itos (element_index(ae));
+               is = inttostr (element_index(ae), indstr, sizeof(indstr));
                valstr = element_value (ae) ? sh_double_quote (element_value(ae))
                                            : (char *)NULL;
                elen = STRLEN (indstr) + 8 + STRLEN (valstr);
                RESIZE_MALLOCED_BUFFER (result, rlen, (elen + 1), rsize, rsize);
 
                result[rlen++] = '[';
-               strcpy (result + rlen, indstr);
-               rlen += STRLEN (indstr);
+               strcpy (result + rlen, is);
+               rlen += STRLEN (is);
                result[rlen++] = ']';
                result[rlen++] = '=';
                if (valstr) {
@@ -382,52 +602,39 @@ ARRAY     *a;
                if (element_forw(ae) != a->head)
                  result[rlen++] = ' ';
 
-               FREE (indstr);
                FREE (valstr);
        }
        RESIZE_MALLOCED_BUFFER (result, rlen, 1, rsize, 8);
        result[rlen++] = ')';
        result[rlen] = '\0';
+       if (quoted) {
+               /* This is not as efficient as it could be... */
+               valstr = sh_single_quote (result);
+               free (result);
+               result = valstr;
+       }
        return(result);
 }
 
 char *
-quoted_array_assignment_string (a)
+array_to_string (a, sep, quoted)
 ARRAY  *a;
+char   *sep;
+int    quoted;
 {
-       char *vstr, *sv;
-
-       sv = array_to_assignment_string (a);
-       if (sv == 0)
-               return ((char *)NULL);
-
-       vstr = sh_single_quote (sv);
-       free (sv);
-       return (vstr);
-}
-
-#if 0
-/* Determine if s2 occurs in s1.  If so, return a pointer to the
-   match in s1.  The compare is case sensitive. */
-static char *
-sindex (s1, s2)
-register char *s1, *s2;
-{
-       register int i, l, len;
-
-       for (i = 0, l = strlen(s2), len = strlen(s1); (len - i) >= l; i++)
-               if (strncmp (s1 + i, s2, l) == 0)
-                       return (s1 + i);
-       return ((char *)NULL);
+       if (a == 0)
+               return((char *)NULL);
+       if (array_empty(a))
+               return(savestring(""));
+       return (array_to_string_internal (element_forw(a->head), a->head, sep, quoted));
 }
-#endif
 
 #if defined (INCLUDE_UNUSED) || defined (TEST_ARRAY)
 /*
  * Return an array consisting of elements in S, separated by SEP
  */
 ARRAY *
-string_to_array(s, sep)
+array_from_string(s, sep)
 char   *s, *sep;
 {
        ARRAY   *a;
@@ -438,147 +645,122 @@ char    *s, *sep;
        w = list_string (s, sep, 0);
        if (w == 0)
                return((ARRAY *)NULL);
-       a = word_list_to_array (w);
+       a = array_from_word_list (w);
        return (a);
 }
 #endif
 
-/* Convenience routines for the shell to translate to and from the form used
-   by the rest of the code. */
-WORD_LIST *
-array_to_word_list(a)
-ARRAY  *a;
-{
-       WORD_LIST       *list;
-       ARRAY_ELEMENT   *ae;
+#if defined (TEST_ARRAY)
+/*
+ * To make a running version, compile -DTEST_ARRAY and link with:
+ *     xmalloc.o syntax.o lib/malloc/libmalloc.a lib/sh/libsh.a
+ */
+int interrupt_immediately = 0;
 
-       if (a == 0 || array_empty(a))
-               return((WORD_LIST *)NULL);
-       list = (WORD_LIST *)NULL;
-       for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae))
-               list = make_word_list (make_bare_word(element_value(ae)), list);
-       return (REVERSE_LIST(list, WORD_LIST *));
+int
+signal_is_trapped(s)
+int    s;
+{
+       return 0;
 }
 
-char **
-array_to_argv (a)
-ARRAY  *a;
+void
+fatal_error(const char *s, ...)
 {
-       char            **ret, *t;
-       int             i;
-       ARRAY_ELEMENT   *ae;
+       fprintf(stderr, "array_test: fatal memory error\n");
+       abort();
+}
 
-       if (a == 0 || array_empty(a))
-               return ((char **)NULL);
-       ret = alloc_array (array_num_elements (a) + 1);
-       i = 0;
-       for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae)) {
-               t = element_value (ae);
-               ret[i++] = t ? savestring (t) : (char *)NULL;
-       }
-       ret[i] = (char *)NULL;
-       return (ret);
+void
+programming_error(const char *s, ...)
+{
+       fprintf(stderr, "array_test: fatal programming error\n");
+       abort();
 }
-       
-ARRAY *
-assign_word_list (array, list)
-ARRAY  *array;
-WORD_LIST      *list;
+
+WORD_DESC *
+make_bare_word (s)
+const char     *s;
 {
-       register WORD_LIST *l;
-       register arrayind_t i;
+       WORD_DESC *w;
 
-       for (l = list, i = 0; l; l = l->next, i++)
-               array_add_element(array, i, l->word->word);
-       return array;
+       w = (WORD_DESC *)xmalloc(sizeof(WORD_DESC));
+       w->word = s ? savestring(s) : savestring ("");
+       w->flags = 0;
+       return w;
 }
 
-ARRAY *
-word_list_to_array (list)
-WORD_LIST      *list;
+WORD_LIST *
+make_word_list(x, l)
+WORD_DESC      *x;
+WORD_LIST      *l;
 {
-       ARRAY   *a;
+       WORD_LIST *w;
 
-       if (list == 0)
-               return((ARRAY *)NULL);
-       a = new_array();
-       return (assign_word_list (a, list));
+       w = (WORD_LIST *)xmalloc(sizeof(WORD_LIST));
+       w->word = x;
+       w->next = l;
+       return w;
 }
 
-ARRAY  *
-array_quote(array)
-ARRAY  *array;
+WORD_LIST *
+list_string(s, t, i)
+char   *s, *t;
+int    i;
 {
-       ARRAY_ELEMENT   *a;
-       char    *t;
+       char    *r, *a;
+       WORD_LIST       *wl;
 
-       if (array == 0 || array->head == 0 || array_empty (array))
-               return (ARRAY *)NULL;
-       for (a = element_forw(array->head); a != array->head; a = element_forw(a)) {
-               t = quote_string (a->value);
-               FREE(a->value);
-               a->value = t;
+       if (s == 0)
+               return (WORD_LIST *)NULL;
+       r = savestring(s);
+       wl = (WORD_LIST *)NULL;
+       a = strtok(r, t);
+       while (a) {
+               wl = make_word_list (make_bare_word(a), wl);
+               a = strtok((char *)NULL, t);
        }
-       return array;
+       return (REVERSE_LIST (wl, WORD_LIST *));
 }
 
-char *
-array_subrange (a, start, end, quoted)
-ARRAY  *a;
-arrayind_t     start, end;
-int    quoted;
+GENERIC_LIST *
+list_reverse (list)
+GENERIC_LIST   *list;
 {
-       ARRAY_ELEMENT   *h, *p;
-       arrayind_t      i;
+       register GENERIC_LIST *next, *prev;
 
-       p = array_head (a);
-       if (p == 0 || array_empty (a) || start > array_num_elements (a))
-               return ((char *)NULL);
-
-       for (i = 0, p = element_forw(p); p != a->head && i < start; i++, p = element_forw(p))
-               ;
-       if (p == a->head)
-               return ((char *)NULL);
-       for (h = p; p != a->head && i < end; i++, p = element_forw(p))
-               ;
-
-       return (array_to_string_internal (h, p, " ", quoted));
+       for (prev = 0; list; ) {
+               next = list->next;
+               list->next = prev;
+               prev = list;
+               list = next;
+       }
+       return prev;
 }
 
 char *
-array_pat_subst (a, pat, rep, mflags)
-ARRAY  *a;
-char   *pat, *rep;
-int    mflags;
+pat_subst(s, t, u, i)
+char   *s, *t, *u;
+int    i;
 {
-       ARRAY           *a2;
-       ARRAY_ELEMENT   *e;
-       char    *t;
-
-       if (array_head (a) == 0 || array_empty (a))
-               return ((char *)NULL);
-
-       a2 = dup_array (a);
-       for (e = element_forw(a2->head); e != a2->head; e = element_forw(e)) {
-               t = pat_subst(element_value(e), pat, rep, mflags);
-               FREE(element_value(e));
-               e->value = t;
-       }
-
-       if (mflags & MATCH_QUOTED)
-               array_quote (a2);
-       t = array_to_string (a2, " ", 0);
-       dispose_array (a2);
-
-       return t;
+       return ((char *)NULL);
 }
 
+char *
+quote_string(s)
+char   *s;
+{
+       return savestring(s);
+}
 
-#if defined (TEST_ARRAY)
 print_element(ae)
 ARRAY_ELEMENT  *ae;
 {
-       printf("array[%ld] = %s\n", element_index(ae), element_value(ae));
+       char    lbuf[INT_STRLEN_BOUND (intmax_t) + 1];
+
+       printf("array[%s] = %s\n",
+               inttostr (element_index(ae), lbuf, sizeof (lbuf)),
+               element_value(ae));
 }
 
 print_array(a)
@@ -591,64 +773,90 @@ ARRAY     *a;
 main()
 {
        ARRAY   *a, *new_a, *copy_of_a;
-       ARRAY_ELEMENT   *ae;
+       ARRAY_ELEMENT   *ae, *aew;
        char    *s;
 
-       a = new_array();
-       array_add_element(a, 1, "one");
-       array_add_element(a, 7, "seven");
-       array_add_element(a, 4, "four");
-       array_add_element(a, 1029, "one thousand twenty-nine");
-       array_add_element(a, 12, "twelve");
-       array_add_element(a, 42, "forty-two");
+       a = array_create();
+       array_insert(a, 1, "one");
+       array_insert(a, 7, "seven");
+       array_insert(a, 4, "four");
+       array_insert(a, 1029, "one thousand twenty-nine");
+       array_insert(a, 12, "twelve");
+       array_insert(a, 42, "forty-two");
        print_array(a);
        s = array_to_string (a, " ", 0);
        printf("s = %s\n", s);
-       copy_of_a = string_to_array(s, " ");
+       copy_of_a = array_from_string(s, " ");
        printf("copy_of_a:");
        print_array(copy_of_a);
-       dispose_array(copy_of_a);
+       array_dispose(copy_of_a);
        printf("\n");
        free(s);
-       ae = array_delete_element(a, 4);
-       destroy_array_element(ae);
-       ae = array_delete_element(a, 1029);
-       destroy_array_element(ae);
-       array_add_element(a, 16, "sixteen");
+       ae = array_remove(a, 4);
+       array_dispose_element(ae);
+       ae = array_remove(a, 1029);
+       array_dispose_element(ae);
+       array_insert(a, 16, "sixteen");
        print_array(a);
        s = array_to_string (a, " ", 0);
        printf("s = %s\n", s);
-       copy_of_a = string_to_array(s, " ");
+       copy_of_a = array_from_string(s, " ");
        printf("copy_of_a:");
        print_array(copy_of_a);
-       dispose_array(copy_of_a);
+       array_dispose(copy_of_a);
        printf("\n");
        free(s);
-       array_add_element(a, 2, "two");
-       array_add_element(a, 1029, "new one thousand twenty-nine");
-       array_add_element(a, 0, "zero");
-       array_add_element(a, 134, "");
+       array_insert(a, 2, "two");
+       array_insert(a, 1029, "new one thousand twenty-nine");
+       array_insert(a, 0, "zero");
+       array_insert(a, 134, "");
        print_array(a);
        s = array_to_string (a, ":", 0);
        printf("s = %s\n", s);
-       copy_of_a = string_to_array(s, ":");
+       copy_of_a = array_from_string(s, ":");
        printf("copy_of_a:");
        print_array(copy_of_a);
-       dispose_array(copy_of_a);
+       array_dispose(copy_of_a);
        printf("\n");
        free(s);
-       new_a = copy_array(a);
+       new_a = array_copy(a);
        print_array(new_a);
        s = array_to_string (new_a, ":", 0);
        printf("s = %s\n", s);
-       copy_of_a = string_to_array(s, ":", 0);
+       copy_of_a = array_from_string(s, ":");
+       free(s);
        printf("copy_of_a:");
        print_array(copy_of_a);
-       dispose_array(copy_of_a);
-       printf("\n");
+       array_shift(copy_of_a, 2, AS_DISPOSE);
+       printf("copy_of_a shifted by two:");
+       print_array(copy_of_a);
+       ae = array_shift(copy_of_a, 2, 0);
+       printf("copy_of_a shifted by two:");
+       print_array(copy_of_a);
+       for ( ; ae; ) {
+               aew = element_forw(ae);
+               array_dispose_element(ae);
+               ae = aew;
+       }
+       array_rshift(copy_of_a, 1, (char *)0);
+       printf("copy_of_a rshift by 1:");
+       print_array(copy_of_a);
+       array_rshift(copy_of_a, 2, "new element zero");
+       printf("copy_of_a rshift again by 2 with new element zero:");
+       print_array(copy_of_a);
+       s = array_to_assign(copy_of_a, 0);
+       printf("copy_of_a=%s\n", s);
        free(s);
-       dispose_array(a);
-       dispose_array(new_a);
+       ae = array_shift(copy_of_a, array_num_elements(copy_of_a), 0);
+       for ( ; ae; ) {
+               aew = element_forw(ae);
+               array_dispose_element(ae);
+               ae = aew;
+       }
+       array_dispose(copy_of_a);
+       printf("\n");
+       array_dispose(a);
+       array_dispose(new_a);
 }
 
 #endif /* TEST_ARRAY */
diff --git a/array.h b/array.h
index b8f40ada0289b1fe98243fddee4facaddd9ed2c0..9c8e5fc54024793da9426ffcb1e198ab9393b236 100644 (file)
--- a/array.h
+++ b/array.h
 
 #include "stdc.h"
 
-typedef long   arrayind_t;
+typedef intmax_t       arrayind_t;
 
 enum atype {array_indexed, array_assoc};
 
 typedef struct array {
        enum atype      type;
-       arrayind_t      max_index, num_elements, max_size;
+       arrayind_t      max_index, num_elements;
        struct array_element *head;
 } ARRAY;
 
@@ -42,36 +42,43 @@ typedef struct array_element {
 
 typedef int sh_ae_map_func_t __P((ARRAY_ELEMENT *));
 
-char   *array_reference __P((ARRAY *, arrayind_t));
+/* Basic operations on entire arrays */
+extern ARRAY   *array_create __P((void));
+extern void    array_flush __P((ARRAY *));
+extern void    array_dispose __P((ARRAY *));
+extern ARRAY   *array_copy __P((ARRAY *));
+extern ARRAY   *array_slice __P((ARRAY *, ARRAY_ELEMENT *, ARRAY_ELEMENT *));
+extern void    array_walk __P((ARRAY   *, sh_ae_map_func_t *));
 
-extern int     array_add_element __P((ARRAY *, arrayind_t, char *));
-extern ARRAY_ELEMENT *array_delete_element __P((ARRAY *, arrayind_t));
+extern ARRAY_ELEMENT *array_shift __P((ARRAY *, int, int));
+extern int     array_rshift __P((ARRAY *, int, char *));
+extern ARRAY   *array_quote __P((ARRAY *));
 
-extern ARRAY_ELEMENT *new_array_element __P((arrayind_t, char *));
-extern void    destroy_array_element __P((ARRAY_ELEMENT *));
+extern char    *array_subrange __P((ARRAY *, arrayind_t, arrayind_t, int));
+extern char    *array_patsub __P((ARRAY *, char *, char *, int));
 
-extern ARRAY   *new_array __P((void));
-extern void    empty_array __P((ARRAY *));
-extern void    dispose_array __P((ARRAY *));
-extern ARRAY   *dup_array __P((ARRAY *));
-extern ARRAY   *dup_array_subrange __P((ARRAY *, ARRAY_ELEMENT *, ARRAY_ELEMENT *));
-extern ARRAY_ELEMENT *copy_array_element __P((ARRAY_ELEMENT *));
+/* Basic operations on array elements. */
+extern ARRAY_ELEMENT *array_create_element __P((arrayind_t, char *));
+extern ARRAY_ELEMENT *array_copy_element __P((ARRAY_ELEMENT *));
+extern void    array_dispose_element __P((ARRAY_ELEMENT *));
 
+extern int     array_insert __P((ARRAY *, arrayind_t, char *));
+extern ARRAY_ELEMENT *array_remove __P((ARRAY *, arrayind_t));
+extern char    *array_reference __P((ARRAY *, arrayind_t));
+
+/* Converting to and from arrays */
 extern WORD_LIST *array_to_word_list __P((ARRAY *));
-extern ARRAY *word_list_to_array __P((WORD_LIST *));
-extern ARRAY *assign_word_list __P((ARRAY *, WORD_LIST *));
+extern ARRAY *array_from_word_list __P((WORD_LIST *));
+extern ARRAY *array_assign_list __P((ARRAY *, WORD_LIST *));
 
 extern char **array_to_argv __P((ARRAY *));
 
-extern char *array_to_assignment_string __P((ARRAY *));
-extern char *quoted_array_assignment_string __P((ARRAY *));
+extern char *array_to_assign __P((ARRAY *, int));
 extern char *array_to_string __P((ARRAY *, char *, int));
-extern ARRAY *string_to_array __P((char *, char *));
-
-extern char *array_subrange __P((ARRAY *, arrayind_t, arrayind_t, int));
-extern char *array_pat_subst __P((ARRAY *, char *, char *, int));
+extern ARRAY *array_from_string __P((char *, char *));
 
-extern ARRAY *array_quote __P((ARRAY *));
+/* Flags for array_shift */
+#define AS_DISPOSE     0x01
 
 #define array_num_elements(a)  ((a)->num_elements)
 #define array_max_index(a)     ((a)->max_index)
index 4fe4f33390e232e76c1e8a62a0782c637f24d517..60e70d9255ecc7d1f8a6fd15f8ec84a80a5e8572 100644 (file)
@@ -1,6 +1,6 @@
 /* arrayfunc.c -- High-level array functions used by other parts of the shell. */
 
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 #include <stdio.h>
 
 #include "shell.h"
+
+#include "shmbutil.h"
+
 #include "builtins/common.h"
 
 extern char *this_command_name;
 extern int last_command_exit_value;
 
 static void quote_array_assignment_chars __P((WORD_LIST *));
-static char *array_value_internal __P((char *, int, int));
+static char *array_value_internal __P((char *, int, int, int *));
 
 /* **************************************************************** */
 /*                                                                 */
@@ -52,11 +55,15 @@ convert_var_to_array (var)
   ARRAY *array;
 
   oldval = value_cell (var);
-  array = new_array ();
-  array_add_element (array, 0, oldval);
+  array = array_create ();
+  array_insert (array, 0, oldval);
 
   FREE (value_cell (var));
-  var->value = (char *)array;
+  var_setarray (var, array);
+
+  /* these aren't valid anymore */
+  var->dynamic_value = (sh_var_value_func_t *)NULL;
+  var->assign_func = (sh_var_assign_func_t *)NULL;
 
   INVALIDATE_EXPORTSTR (var);
 
@@ -89,7 +96,7 @@ bind_array_variable (name, ind, value)
   else if (readonly_p (entry) || noassign_p (entry))
     {
       if (readonly_p (entry))
-       report_error ("%s: readonly variable", name);
+       err_readonly (name);
       return (entry);
     }
   else if (array_p (entry) == 0)
@@ -98,9 +105,9 @@ bind_array_variable (name, ind, value)
   /* ENTRY is an array variable, and ARRAY points to the value. */
   newval = make_variable_value (entry, value);
   if (entry->assign_func)
-    (*entry->assign_func) (entry, ind, newval);
+    (*entry->assign_func) (entry, newval, ind);
   else
-    array_add_element (array_cell (entry), ind, newval);
+    array_insert (array_cell (entry), ind, newval);
   FREE (newval);
 
   return (entry);
@@ -125,7 +132,7 @@ assign_array_element (name, value)
   if ((ALL_ELEMENT_SUB (sub[0]) && sub[1] == ']') || (sublen <= 1))
     {
       free (vname);
-      report_error ("%s: bad array subscript", name);
+      err_badarraysub (name);
       return ((SHELL_VAR *)NULL);
     }
 
@@ -133,7 +140,7 @@ assign_array_element (name, value)
   if (ind < 0)
     {
       free (vname);
-      report_error ("%s: bad array subscript", name);
+      err_badarraysub (name);
       return ((SHELL_VAR *)NULL);
     }
 
@@ -162,7 +169,7 @@ find_or_make_array_variable (name, check_flags)
   else if (check_flags && (readonly_p (var) || noassign_p (var)))
     {
       if (readonly_p (var))
-       report_error ("%s: readonly variable", name);
+       err_readonly (name);
       return ((SHELL_VAR *)NULL);
     }
   else if (array_p (var) == 0)
@@ -199,9 +206,9 @@ assign_array_var_from_word_list (var, list)
 
   for (a = array_cell (var), l = list, i = 0; l; l = l->next, i++)
     if (var->assign_func)
-      (*var->assign_func) (var, i, l->word->word);
+      (*var->assign_func) (var, l->word->word, i);
     else
-      array_add_element (a, i, l->word->word);
+      array_insert (a, i, l->word->word);
   return var;
 }
 
@@ -222,7 +229,7 @@ assign_array_var_from_string (var, value)
     return var;
 
   /* If this is called from declare_builtin, value[0] == '(' and
-     strchr(value, ')') != 0.  In this case, we need to extract
+     xstrchr(value, ')') != 0.  In this case, we need to extract
      the value from between the parens before going on. */
   if (*value == '(')   /*)*/
     {
@@ -259,7 +266,7 @@ assign_array_var_from_string (var, value)
   /* Now that we are ready to assign values to the array, kill the existing
      value. */
   if (a)
-    empty_array (a);
+    array_flush (a);
 
   for (last_ind = 0, list = nlist; list; list = list->next)
     {
@@ -274,9 +281,9 @@ assign_array_var_from_string (var, value)
            {
              nval = make_variable_value (var, w);
              if (var->assign_func)
-               (*var->assign_func) (var, last_ind, nval);
+               (*var->assign_func) (var, nval, last_ind);
              else
-               array_add_element (a, last_ind, nval);
+               array_insert (a, last_ind, nval);
              FREE (nval);
              last_ind++;
              continue;
@@ -284,7 +291,7 @@ assign_array_var_from_string (var, value)
 
          if (len == 1)
            {
-             report_error ("%s: bad array subscript", w);
+             err_badarraysub (w);
              continue;
            }
 
@@ -297,7 +304,7 @@ assign_array_var_from_string (var, value)
          ind = array_expand_index (w + 1, len);
          if (ind < 0)
            {
-             report_error ("%s: bad array subscript", w);
+             err_badarraysub (w);
              continue;
            }
          last_ind = ind;
@@ -313,9 +320,9 @@ assign_array_var_from_string (var, value)
        this_command_name = (char *)NULL;       /* no command name for errors */
       nval = make_variable_value (var, val);
       if (var->assign_func)
-       (*var->assign_func) (var, ind, nval);
+       (*var->assign_func) (var, nval, ind);
       else
-       array_add_element (a, ind, nval);
+       array_insert (a, ind, nval);
       FREE (nval);
       last_ind++;
     }
@@ -340,7 +347,7 @@ quote_array_assignment_chars (list)
       if (l->word == 0 || l->word->word == 0 || l->word->word[0] == '\0')
        continue;       /* should not happen, but just in case... */
       /* Don't bother if it doesn't look like [ind]=value */
-      if (l->word->word[0] != '[' || strchr (l->word->word, '=') == 0) /* ] */
+      if (l->word->word[0] != '[' || xstrchr (l->word->word, '=') == 0) /* ] */
        continue;
       s = nword = (char *)xmalloc (strlen (l->word->word) * 2 + 1);
       saw_eq = 0;
@@ -366,14 +373,56 @@ skipsubscript (s, i)
      int i;
 {
   int count, c;
+#if defined (HANDLE_MULTIBYTE)
+  mbstate_t state, state_bak;
+  size_t slength, mblength;
+  size_t mb_cur_max;
+#endif
 
-  for (count = 1; count && (c = s[++i]); )
+#if defined (HANDLE_MULTIBYTE)
+  memset (&state, '\0', sizeof (mbstate_t));
+  slength = strlen (s + i);
+  mb_cur_max = MB_CUR_MAX;
+#endif
+  
+  count = 1;
+  while (count)
     {
-      if (c == '[')
+      /* Advance one (possibly multibyte) character in S starting at I. */
+#if defined (HANDLE_MULTIBYTE)
+      if (mb_cur_max > 1)
+       {
+         state_bak = state;
+         mblength = mbrlen (s + i, slength, &state);
+
+         if (mblength == (size_t)-2 || mblength == (size_t)-1)
+           {
+             state = state_bak;
+             i++;
+             slength--;
+           }
+         else if (mblength == 0)
+           return i;
+         else
+           {
+             i += mblength;
+             slength -= mblength;
+           }
+       }
+      else
+#endif
+      ++i;
+
+      c = s[i];
+
+      if (c == 0)
+        break;
+      else if (c == '[')
        count++;
       else if (c == ']')
        count--;
     }
+
   return i;
 }
 
@@ -399,7 +448,7 @@ unbind_array_element (var, sub)
 
   if (ALL_ELEMENT_SUB (sub[0]) && sub[1] == 0)
     {
-      makunbound (var->name, shell_variables);
+      unbind_variable (var->name);
       return (0);
     }
   ind = array_expand_index (sub, len+1);
@@ -408,9 +457,9 @@ unbind_array_element (var, sub)
       builtin_error ("[%s]: bad array subscript", sub);
       return -1;
     }
-  ae = array_delete_element (array_cell (var), ind);
+  ae = array_remove (array_cell (var), ind);
   if (ae)
-    destroy_array_element (ae);
+    array_dispose_element (ae);
   return 0;
 }
 
@@ -423,10 +472,7 @@ print_array_assignment (var, quoted)
 {
   char *vstr;
 
-  if (quoted)
-    vstr = quoted_array_assignment_string (array_cell (var));
-  else
-    vstr = array_to_assignment_string (array_cell (var));
+  vstr = array_to_assign (array_cell (var), quoted);
 
   if (vstr == 0)
     printf ("%s=%s\n", var->name, quoted ? "'()'" : "()");
@@ -451,7 +497,7 @@ valid_array_reference (name)
   char *t;
   int r, len;
 
-  t = strchr (name, '[');      /* ] */
+  t = xstrchr (name, '[');     /* ] */
   if (t)
     {
       *t = '\0';
@@ -509,14 +555,14 @@ array_variable_name (s, subp, lenp)
   char *t, *ret;
   int ind, ni;
 
-  t = strchr (s, '[');
+  t = xstrchr (s, '[');
   if (t == 0)
     return ((char *)NULL);
   ind = t - s;
   ni = skipsubscript (s, ind);
   if (ni <= ind + 1 || s[ni] != ']')
     {
-      report_error ("%s: bad array subscript", s);
+      err_badarraysub (s);
       return ((char *)NULL);
     }
 
@@ -554,11 +600,13 @@ array_variable_part (s, subp, lenp)
 
 /* Return a string containing the elements in the array and subscript
    described by S.  If the subscript is * or @, obeys quoting rules akin
-   to the expansion of $* and $@ including double quoting. */
+   to the expansion of $* and $@ including double quoting.  If RTYPE
+   is non-null it gets 1 if the array reference is name[@] or name[*]
+   and 0 otherwise. */
 static char *
-array_value_internal (s, quoted, allow_all)
+array_value_internal (s, quoted, allow_all, rtype)
      char *s;
-     int quoted, allow_all;
+     int quoted, allow_all, *rtype;
 {
   int len;
   arrayind_t ind;
@@ -568,22 +616,27 @@ array_value_internal (s, quoted, allow_all)
 
   var = array_variable_part (s, &t, &len);
 
+  /* Expand the index, even if the variable doesn't exist, in case side
+     effects are needed, like ${w[i++]} where w is unset. */
+#if 0
   if (var == 0)
     return (char *)NULL;
+#endif
 
   /* [ */
   if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
     {
+      if (rtype)
+       *rtype = 1;
       if (allow_all == 0)
        {
-         report_error ("%s: bad array subscript", s);
+         err_badarraysub (s);
          return ((char *)NULL);
        }
+      else if (var == 0)
+       return ((char *)NULL);
       else if (array_p (var) == 0)
-       {
-         l = (WORD_LIST *)NULL;
-         l = add_string_to_list (value_cell (var), l);
-       }
+       l = add_string_to_list (value_cell (var), (WORD_LIST *)NULL);
       else
        {
          l = array_to_word_list (array_cell (var));
@@ -604,17 +657,26 @@ array_value_internal (s, quoted, allow_all)
     }
   else
     {
+      if (rtype)
+       *rtype = 0;
       ind = array_expand_index (t, len);
       if (ind < 0)
        {
-         report_error ("%s: bad array subscript", var->name);
+         if (var)
+           err_badarraysub (var->name);
+         else
+           {
+             t[-1] = '\0';
+             err_badarraysub (s);
+             t[-1] = '[';      /* ] */
+           }
          return ((char *)NULL);
        }
+      if (var == 0)
+       return ((char *)NULL);
       if (array_p (var) == 0)
-       return (ind == 0 ? savestring (value_cell (var)) : (char *)NULL);
+       return (ind == 0 ? value_cell (var) : (char *)NULL);
       retval = array_reference (array_cell (var), ind);
-      if (retval)
-       retval = quote_escapes (retval);
     }
 
   return retval;
@@ -623,11 +685,11 @@ array_value_internal (s, quoted, allow_all)
 /* Return a string containing the elements described by the array and
    subscript contained in S, obeying quoting for subscripts * and @. */
 char *
-array_value (s, quoted)
+array_value (s, quoted, rtype)
      char *s;
-     int quoted;
+     int quoted, *rtype;
 {
-  return (array_value_internal (s, quoted, 1));
+  return (array_value_internal (s, quoted, 1, rtype));
 }
 
 /* Return the value of the array indexing expression S as a single string.
@@ -635,11 +697,11 @@ array_value (s, quoted)
    by other parts of the shell such as the arithmetic expression evaluator
    in expr.c. */
 char *
-get_array_value (s, allow_all)
+get_array_value (s, allow_all, rtype)
      char *s;
-     int allow_all;
+     int allow_all, *rtype;
 {
-  return (array_value_internal (s, 0, allow_all));
+  return (array_value_internal (s, 0, allow_all, rtype));
 }
 
 #endif /* ARRAY_VARS */
index ba1e0c31d01823d0f5e91cd7999881f4e89030d7..7eae976fcfd833d592b44e991d6752ecc9b6cfde 100644 (file)
@@ -42,8 +42,8 @@ extern void print_array_assignment __P((SHELL_VAR *, int));
 
 extern arrayind_t array_expand_index __P((char *, int));
 extern int valid_array_reference __P((char *));
-extern char *array_value __P((char *, int));
-extern char *get_array_value __P((char *, int));
+extern char *array_value __P((char *, int, int *));
+extern char *get_array_value __P((char *, int, int *));
 
 extern char *array_variable_name __P((char *, char **, int *));
 extern SHELL_VAR *array_variable_part __P((char *, char **, int *));
index b89758aabc2f967518ce5d7ccd5e8086ba2756fa..809026687c686a9a741fe4a1734d63ff0e60b32d 100644 (file)
@@ -57,6 +57,8 @@ extern int errno;
 #endif
 
 static int histignore_item_func __P((struct ign *));
+static int check_history_control __P((char *));
+static void really_add_history __P((char *));
 
 static struct ignorevar histignore =
 {
@@ -87,8 +89,8 @@ int history_lines_in_file;
 int history_expansion_inhibited;
 #endif
 
-/* By default, every line is saved in the history individually.  I.e.,
-   if the user enters:
+/* With the old default, every line was saved in the history individually.
+   I.e., if the user enters:
        bash$ for i in a b c
        > do
        > echo $i
@@ -114,9 +116,16 @@ int history_expansion_inhibited;
        11  history
    The user can then recall the whole command all at once instead
    of just being able to recall one line at a time.
+
+   This is now enabled by default.
    */
 int command_oriented_history = 1;
 
+/* Set to 1 if the first line of a possibly-multi-line command was saved
+   in the history list.  Managed by maybe_add_history(), but global so
+   the history-manipluating builtins can see it. */
+int current_command_first_line_saved = 0;
+
 /* Non-zero means to store newlines in the history list when using
    command_oriented_history rather than trying to use semicolons. */
 int literal_history;
@@ -493,26 +502,61 @@ filter_comments (line)
 }
 #endif
 
-/* Add LINE to the history list depending on the value of HISTORY_CONTROL. */
-void
-maybe_add_history (line)
+/* Check LINE against what HISTCONTROL says to do.  Returns 1 if the line
+   should be saved; 0 if it should be discarded. */
+static int
+check_history_control (line)
      char *line;
 {
-  static int first_line_saved = 0;
   HIST_ENTRY *temp;
+  int r;
 
+  switch (history_control)
+    {
+    case 0:                    /* nothing */
+      return 1;
+    case 1:                    /* ignorespace */
+      return (*line != ' ');
+    case 3:                    /* ignoreboth */
+      if (*line == ' ')
+       return 0;
+      /* FALLTHROUGH if case == 3 (`ignoreboth') */
+    case 2:                    /* ignoredups */
+      using_history ();
+      temp = previous_history ();
+
+      r = (temp == 0 || STREQ (temp->line, line) == 0);
+
+      using_history ();
+      return r;
+    }
+
+  return 0;
+}
+
+/* Add LINE to the history list, handling possibly multi-line compound
+   commands.  We note whether or not we save the first line of each command
+   (which is usually the entire command and history entry), and don't add
+   the second and subsequent lines of a multi-line compound command if we
+   didn't save the first line.  We don't usually save shell comment lines in
+   compound commands in the history, because they could have the effect of
+   commenting out the rest of the command when the entire command is saved as
+   a single history entry (when COMMAND_ORIENTED_HISTORY is enabled).  If
+   LITERAL_HISTORY is set, we're saving lines in the history with embedded
+   newlines, so it's OK to save comment lines.  We also make sure to save
+   multiple-line quoted strings or other constructs. */
+void
+maybe_add_history (line)
+     char *line;
+{
   hist_last_line_added = 0;
 
   /* Don't use the value of history_control to affect the second
      and subsequent lines of a multi-line command (old code did
      this only when command_oriented_history is enabled). */
-#if 0
-  if (command_oriented_history && current_command_line_count > 1)
-#else
   if (current_command_line_count > 1)
-#endif
     {
-      if (first_line_saved &&
+      if (current_command_first_line_saved &&
          (literal_history || dstack.delimiter_depth != 0 || shell_comment (line) == 0))
        bash_add_history (line);
       return;
@@ -520,36 +564,29 @@ maybe_add_history (line)
 
   /* This is the first line of a (possible multi-line) command.  Note whether
      or not we should save the first line and remember it. */
-  first_line_saved = 0;
+  current_command_first_line_saved = check_add_history (line, 0);
+}
 
-  switch (history_control)
+/* Just check LINE against HISTCONTROL and HISTIGNORE and add it to the
+   history if it's OK.  Used by `history -s' as well as maybe_add_history().
+   Returns 1 if the line was saved in the history, 0 otherwise. */
+int
+check_add_history (line, force)
+     char *line;
+     int force;
+{
+  if (check_history_control (line) && history_should_ignore (line) == 0)
     {
-    case 0:
-      first_line_saved = 1;
-      break;
-    case 1:
-      if (*line != ' ')
-       first_line_saved = 1;
-      break;
-    case 3:
-      if (*line == ' ')
-       break;
-      /* FALLTHROUGH if case == 3 (`ignoreboth') */
-    case 2:
-      using_history ();
-      temp = previous_history ();
-
-      if (temp == 0 || STREQ (temp->line, line) == 0)
-       first_line_saved = 1;
-
-      using_history ();
-      break;
+      if (force)
+       {
+         really_add_history (line);
+         using_history ();
+       }
+      else
+       bash_add_history (line);
+      return 1;
     }
-
-  if (first_line_saved && history_should_ignore (line) == 0)
-    bash_add_history (line);
-  else
-    first_line_saved = 0;
+  return 0;
 }
 
 /* Add a line to the history list.
@@ -607,14 +644,20 @@ bash_add_history (line)
     }
 
   if (add_it)
-    {
-      hist_last_line_added = 1;
-      add_history (line);
-      history_lines_this_session++;
-    }
+    really_add_history (line);
+
   using_history ();
 }
 
+static void
+really_add_history (line)
+     char *line;
+{
+  hist_last_line_added = 1;
+  add_history (line);
+  history_lines_this_session++;
+}
+
 int
 history_number ()
 {
index e528416feef8af54616f852dbfbcee923173627a..f17e7e7fc798b8b42b8b86aeea9493756e35d380 100644 (file)
@@ -29,6 +29,7 @@ extern int history_lines_in_file;
 extern int history_expansion;
 extern int history_control;
 extern int command_oriented_history;
+extern int current_command_first_line_saved;
 extern int hist_last_line_added;
 
 #  if defined (BANG_HISTORY)
@@ -46,6 +47,7 @@ extern int maybe_save_shell_history __P((void));
 extern char *pre_process_line __P((char *, int, int));
 extern void maybe_add_history __P((char *));
 extern void bash_add_history __P((char *));
+extern int check_add_history __P((char *, int));
 extern int history_number __P((void));
 
 extern void setup_history_ignore __P((char *));
index 6cfb1b063d64d894024463652b8193f9fb5ff47a..8874314b94566def1400d2cddd1ef38bcfba0879 100644 (file)
@@ -1,6 +1,6 @@
 /* bashline.c -- Bash's interface to the readline library. */
 
-/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 #  include <grp.h>
 #endif
 
+#if defined (HAVE_NETDB_H)
+#  include <netdb.h>
+#endif
+
 #include <stdio.h>
 #include "chartypes.h"
 #include "bashansi.h"
 #include "shell.h"
+#include "input.h"
 #include "builtins.h"
 #include "bashhist.h"
 #include "bashline.h"
 #  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
+
 #if defined (BRACE_COMPLETION)
 extern int bash_brace_completion __P((int, int));
 #endif /* BRACE_COMPLETION */
@@ -170,13 +183,16 @@ 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));
 #endif
+static int emacs_edit_and_execute_command __P((int, int));
 
 /* Non-zero once initalize_readline () has been called. */
 int bash_readline_initialized = 0;
@@ -213,7 +229,7 @@ posix_readline_initialize (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);
+  rl_bind_key_in_map (CTRL ('I'), on_or_off ? rl_insert : rl_complete, vi_insertion_keymap);
 #endif
 }
 
@@ -275,6 +291,7 @@ initialize_readline ()
 
   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);
@@ -291,6 +308,7 @@ initialize_readline ()
   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
@@ -341,6 +359,7 @@ initialize_readline ()
   rl_bind_key_in_map ('!', bash_complete_command, emacs_meta_keymap);
   rl_bind_key_in_map ('!', bash_possible_command_completions, emacs_ctlx_keymap);
 
+  rl_bind_key_in_map ('g', bash_glob_complete_word, emacs_meta_keymap);
   rl_bind_key_in_map ('*', bash_glob_expand_word, emacs_ctlx_keymap);
   rl_bind_key_in_map ('g', bash_glob_list_expansions, emacs_ctlx_keymap);
 
@@ -358,6 +377,8 @@ initialize_readline ()
   /* 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_in_map (CTRL ('E'), emacs_edit_and_execute_command, emacs_ctlx_keymap);
 #if defined (VI_MODE)
   rl_bind_key_in_map ('v', vi_edit_and_execute_command, vi_movement_keymap);
 #  if defined (ALIAS)
@@ -378,8 +399,14 @@ initialize_readline ()
   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;
 }
@@ -491,13 +518,10 @@ static void
 add_host_name (name)
      char *name;
 {
-  size_t size;
-
   if (hostname_list_length + 2 > hostname_list_size)
     {
       hostname_list_size = (hostname_list_size + 32) - (hostname_list_size % 32);
-      size = hostname_list_size * sizeof (char *);
-      hostname_list = (char **)xrealloc (hostname_list, size);
+      hostname_list = strvec_resize (hostname_list, hostname_list_size);
     }
 
   hostname_list[hostname_list_length++] = savestring (name);
@@ -613,7 +637,7 @@ hostnames_matching (text)
      what is desired. */
   if (*text == '\0')
     {
-      result = alloc_array (1 + hostname_list_length);
+      result = strvec_create (1 + hostname_list_length);
       for (i = 0; i < hostname_list_length; i++)
        result[i] = hostname_list[i];
       result[i] = (char *)NULL;
@@ -632,7 +656,7 @@ hostnames_matching (text)
       if (nmatch >= (rsize - 1))
        {
          rsize = (rsize + 16) - (rsize % 16);
-         result = (char **)xrealloc (result, rsize * sizeof (char *));
+         result = strvec_resize (result, rsize);
        }
 
       result[nmatch++] = hostname_list[i];
@@ -680,16 +704,17 @@ operate_and_get_next (count, c)
   return 0;
 }
 
-#if defined (VI_MODE)
 /* 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 VI_EDIT_COMMAND                "fc -e ${VISUAL:-${EDITOR:-vi}}"
+#define EMACS_EDIT_COMMAND     "fc -e ${VISUAL:-${EDITOR:-emacs}}"
 
 static int
-vi_edit_and_execute_command (count, c)
-     int count, c;
+edit_and_execute_command (count, c, editing_mode, edit_command)
+     int count, c, editing_mode;
+     char *edit_command;
 {
   char *command;
   int r, cclc, rrs;
@@ -702,8 +727,8 @@ vi_edit_and_execute_command (count, c)
 
   if (rl_explicit_arg)
     {
-      command = (char *)xmalloc (strlen (VI_EDIT_COMMAND) + 8);
-      sprintf (command, "%s %d", VI_EDIT_COMMAND, count);
+      command = (char *)xmalloc (strlen (edit_command) + 8);
+      sprintf (command, "%s %d", edit_command, count);
     }
   else
     {
@@ -716,9 +741,13 @@ vi_edit_and_execute_command (count, c)
       bash_add_history ("");
       history_lines_this_session++;
       using_history ();
-      command = savestring (VI_EDIT_COMMAND);
+      command = savestring (edit_command);
     }
-  r = parse_and_execute (command, "v", SEVAL_NOHIST);
+
+  /* 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. */
+  r = parse_and_execute (command, (editing_mode == VI_EDITING_MODE) ? "v" : "C-xC-e", SEVAL_NOHIST);
 
   current_command_line_count = cclc;
 
@@ -734,8 +763,23 @@ vi_edit_and_execute_command (count, c)
 
   return r;
 }
+
+#if defined (VI_MODE)
+static int
+vi_edit_and_execute_command (count, c)
+     int count, c;
+{
+  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)
@@ -927,7 +971,7 @@ attempt_shell_completion (text, start, end)
 #if defined (PROGRAMMABLE_COMPLETION)
   /* Attempt programmable completion. */
   if (!matches && in_command_position == 0 && prog_completion_enabled &&
-      (num_progcomps () > 0) && current_prompt_string == ps1_prompt)
+      (progcomp_size () > 0) && current_prompt_string == ps1_prompt)
     {
       int s, e, foundcs;
       char *n;
@@ -955,6 +999,9 @@ attempt_shell_completion (text, start, end)
             sure that readline knows it. */
          if (foundcs & COPT_FILENAMES)
            rl_filename_completion_desired = 1;
+         /* If the user doesn't want a space appended, tell readline. */
+         if (foundcs & COPT_NOSPACE)
+           rl_completion_suppress_append = 1;
          /* Turn what the programmable completion code returns into what
             readline wants.  I should have made compute_lcd_of_matches
             external... */
@@ -977,7 +1024,7 @@ attempt_shell_completion (text, start, end)
 
   /* If the word starts in `~', and there is no slash in the word, then
      try completing this word as a username. */
-  if (!matches && *text == '~' && !strchr (text, '/'))
+  if (!matches && *text == '~' && !xstrchr (text, '/'))
     matches = rl_completion_matches (text, rl_username_completion_function);
 
   /* Another one.  Why not?  If the word starts in '@', then look through
@@ -1005,6 +1052,25 @@ attempt_shell_completion (text, start, end)
             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 && *matches[0] != '/')
+           /* Turn off rl_filename_completion_desired so readline doesn't
+              append a slash if there is a directory with the same name
+              in the current directory, or other filename-specific things.
+              If the name begins with a slash, we're either completing a
+              full pathname or a directory pathname, and readline won't be
+              looking in the current directory anyway, so there's no
+              conflict. */
+           rl_filename_completion_desired = 0;
+         else if (matches[0] && matches[1] && STREQ (matches[0], matches[1]) && *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 off
+              rl_filename_completion_desired 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_filename_completion_desired = 0;
        }
     }
 
@@ -1015,9 +1081,9 @@ attempt_shell_completion (text, start, end)
       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])
+      if (matches && matches[1] && rl_completion_type == TAB)
        {
-         free_array (matches);
+         strvec_dispose (matches);
          matches = (char **)0;
        }
     }
@@ -1064,7 +1130,7 @@ command_word_completion_function (hint_text, state)
          /* 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);
+           hint = bash_tilde_expand (hint_text, 0);
          else
            hint = savestring (hint_text);
          hint_len = strlen (hint);
@@ -1195,7 +1261,7 @@ command_word_completion_function (hint_text, state)
        {
          char *t;
 
-         t = bash_tilde_expand (current_path);
+         t = bash_tilde_expand (current_path, 0);
          free (current_path);
          current_path = t;
        }
@@ -1203,8 +1269,7 @@ command_word_completion_function (hint_text, state)
       if (filename_hint)
        free (filename_hint);
 
-      filename_hint = (char *)xmalloc (2 + strlen (current_path) + hint_len);
-      sprintf (filename_hint, "%s/%s", current_path, hint);
+      filename_hint = sh_makepath (current_path, hint, 0);
 
       free (current_path);
     }
@@ -1304,8 +1369,31 @@ command_subst_completion_function (text, state)
       filename_text = savestring (text);
       if (matches)
        free (matches);
-      matches = rl_completion_matches (filename_text, command_word_completion_function);
-      cmd_index = 0;
+
+      /*
+       * 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 (!matches || !matches[cmd_index])
@@ -1359,7 +1447,7 @@ variable_completion_function (text, state)
 
       namelen = strlen (varname);
       if (varlist)
-       free_array (varlist);
+       strvec_dispose (varlist);
 
       varlist = all_variables_matching_prefix (varname);
       varlist_index = 0;
@@ -1432,6 +1520,67 @@ hostname_completion_function (text, state)
   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; aentry = *alist; 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;
@@ -1516,7 +1665,7 @@ maybe_make_readline_line (new_line)
 
       rl_add_undo (UNDO_BEGIN, 0, 0, 0);
       rl_delete_text (0, rl_point);
-      rl_point = rl_end = 0;
+      rl_point = rl_end = rl_mark = 0;
       rl_insert_text (new_line);
       rl_add_undo (UNDO_END, 0, 0, 0);
     }
@@ -1777,9 +1926,9 @@ _ignore_completion_names (names, name_func)
      filenames.  The pointers are copied back to NAMES when done. */
   for (nidx = 1; names[nidx]; nidx++)
     ;
-  newnames = alloc_array (nidx + 1);
+  newnames = strvec_create (nidx + 1);
 #ifdef NO_FORCE_FIGNORE
-  oldnames = alloc_array (nidx - 1);
+  oldnames = strvec_create (nidx - 1);
   oidx = 0;
 #endif
 
@@ -1887,7 +2036,7 @@ test_for_directory (name)
   struct stat finfo;
   char *fn;
 
-  fn = bash_tilde_expand (name);
+  fn = bash_tilde_expand (name, 0);
   if (stat (fn, &finfo) != 0)
     {
       free (fn);
@@ -1935,13 +2084,13 @@ bash_directory_completion_hook (dirname)
   local_dirname = *dirname;
 
 #if 0
-  should_expand_dirname = strchr (local_dirname, '$') || strchr (local_dirname, '`');
+  should_expand_dirname = xstrchr (local_dirname, '$') || xstrchr (local_dirname, '`');
 #else
-  if (strchr (local_dirname, '$'))
+  if (xstrchr (local_dirname, '$'))
     should_expand_dirname = 1;
   else
     {
-      t = strchr (local_dirname, '`');
+      t = xstrchr (local_dirname, '`');
       if (t && unclosed_pair (local_dirname, strlen (local_dirname), "`") == 0)
        should_expand_dirname = 1;
     }
@@ -1950,7 +2099,7 @@ bash_directory_completion_hook (dirname)
   if (should_expand_dirname)  
     {
       new_dirname = savestring (local_dirname);
-      wl = expand_string (new_dirname, 0);
+      wl = expand_prompt_string (new_dirname, 0);      /* does the right thing */
       if (wl)
        {
          *dirname = string_list (wl);
@@ -2016,11 +2165,7 @@ build_history_completion_array ()
   /* First, clear out the current dynamic history completion list. */
   if (harry_size)
     {
-      for (i = 0; history_completion_array[i]; i++)
-       free (history_completion_array[i]);
-
-      free (history_completion_array);
-
+      strvec_dispose (history_completion_array);
       history_completion_array = (char **)NULL;
       harry_size = 0;
       harry_len = 0;
@@ -2040,11 +2185,7 @@ build_history_completion_array ()
          for (j = 0; tokens && tokens[j]; j++)
            {
              if (harry_len + 2 > harry_size)
-               {
-                 harry_size += 10;
-                 history_completion_array = (char **)xrealloc
-                   (history_completion_array, harry_size * sizeof (char *));
-               }
+               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;
@@ -2053,7 +2194,7 @@ build_history_completion_array ()
        }
 
       /* Sort the complete list of tokens. */
-      qsort (history_completion_array, harry_len, sizeof (char *), (QSFUNC *)qsort_string_compare);
+      qsort (history_completion_array, harry_len, sizeof (char *), (QSFUNC *)strvec_strcmp);
     }
 }
 
@@ -2097,6 +2238,7 @@ dynamic_complete_history (count, key)
   rl_completion_entry_function = history_completion_generator;
   rl_attempted_completion_function = (rl_completion_func_t *)NULL;
 
+  /* XXX - use rl_completion_mode here? */
   if (rl_last_func == dynamic_complete_history)
     r = rl_complete_internal ('?');
   else
@@ -2112,7 +2254,7 @@ static int
 bash_complete_username (ignore, ignore2)
      int ignore, ignore2;
 {
-  return bash_complete_username_internal (TAB);
+  return bash_complete_username_internal (rl_completion_mode (bash_complete_username));
 }
 
 static int
@@ -2133,7 +2275,7 @@ static int
 bash_complete_filename (ignore, ignore2)
      int ignore, ignore2;
 {
-  return bash_complete_filename_internal (TAB);
+  return bash_complete_filename_internal (rl_completion_mode (bash_complete_filename));
 }
 
 static int
@@ -2176,7 +2318,7 @@ static int
 bash_complete_hostname (ignore, ignore2)
      int ignore, ignore2;
 {
-  return bash_complete_hostname_internal (TAB);
+  return bash_complete_hostname_internal (rl_completion_mode (bash_complete_hostname));
 }
 
 static int
@@ -2190,7 +2332,7 @@ static int
 bash_complete_variable (ignore, ignore2)
      int ignore, ignore2;
 {
-  return bash_complete_variable_internal (TAB);
+  return bash_complete_variable_internal (rl_completion_mode (bash_complete_variable));
 }
 
 static int
@@ -2204,7 +2346,7 @@ static int
 bash_complete_command (ignore, ignore2)
      int ignore, ignore2;
 {
-  return bash_complete_command_internal (TAB);
+  return bash_complete_command_internal (rl_completion_mode (bash_complete_command));
 }
 
 static int
@@ -2235,6 +2377,9 @@ bash_complete_command_internal (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;
@@ -2242,14 +2387,30 @@ glob_complete_word (text, state)
 {
   static char **matches = (char **)NULL;
   static int ind;
+  int glen;
   char *ret;
 
   if (state == 0)
     {
       rl_filename_completion_desired = 1;
-      if (matches)
-       free (matches);
-      matches = shell_glob_filename (text);
+      FREE (matches);
+      if (globorig != globtext)
+       FREE (globorig);
+      FREE (globtext);
+
+      if (rl_explicit_arg)
+       {
+         globorig = savestring (text);
+         glen = strlen (text);
+         globtext = (char *)xmalloc (glen + 2);
+         strcpy (globtext, text);
+         globtext[glen] = '*';
+         globtext[glen+1] = '\0';
+       }
+      else
+        globtext = globorig = savestring (text);
+
+      matches = shell_glob_filename (globtext);
       if (GLOB_FAILED (matches))
        matches = (char **)NULL;
       ind = 0;
@@ -2267,6 +2428,37 @@ bash_glob_completion_internal (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;
+
+  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;
@@ -2372,7 +2564,7 @@ quote_word_break_chars (text)
        }
       /* OK, we have an unquoted character.  Check its presence in
         rl_completer_word_break_characters. */
-      if (strchr (rl_completer_word_break_characters, *s))
+      if (xstrchr (rl_completer_word_break_characters, *s))
        *r++ = '\\';
       *r++ = *s;
     }
@@ -2384,7 +2576,8 @@ quote_word_break_chars (text)
    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. */
+   quote_word_break_chars on the result.  This returns newly-allocated
+   memory. */
 static char *
 bash_quote_filename (s, rtype, qcp)
      char *s;
@@ -2405,7 +2598,7 @@ bash_quote_filename (s, rtype, qcp)
 
   mtext = s;
   if (mtext[0] == '~' && rtype == SINGLE_MATCH)
-    mtext = bash_tilde_expand (s);
+    mtext = bash_tilde_expand (s, 0);
 
   cs = completion_quoting_style;
   /* Might need to modify the default completion style based on *qcp,
@@ -2414,7 +2607,7 @@ bash_quote_filename (s, rtype, qcp)
      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 && strchr (mtext, '\n'))
+  if (*qcp == '\0' && cs == COMPLETE_BSQUOTE && xstrchr (mtext, '\n'))
     cs = COMPLETE_SQUOTE;
   else if (*qcp == '"')
     cs = COMPLETE_DQUOTE;
@@ -2422,11 +2615,11 @@ bash_quote_filename (s, rtype, qcp)
     cs = COMPLETE_SQUOTE;
 #if defined (BANG_HISTORY)
   else if (*qcp == '\0' && history_expansion && cs == COMPLETE_DQUOTE &&
-          history_expansion_inhibited == 0 && strchr (mtext, '!'))
+          history_expansion_inhibited == 0 && xstrchr (mtext, '!'))
     cs = COMPLETE_BSQUOTE;
 
   if (*qcp == '"' && history_expansion && cs == COMPLETE_DQUOTE &&
-       history_expansion_inhibited == 0 && strchr (mtext, '!'))
+       history_expansion_inhibited == 0 && xstrchr (mtext, '!'))
     {
       cs = COMPLETE_BSQUOTE;
       *qcp = '\0';
@@ -2483,6 +2676,8 @@ bash_execute_unix_command (count, key)
   Keymap xkmap;                /* unix command executing keymap */
   register int i;
   char *cmd;
+  int old_line_count;
+  int *ts;
 
   /* First, we need to find the right command to execute.  This is tricky,
      because we might have already indirected into another keymap. */
@@ -2518,8 +2713,14 @@ bash_execute_unix_command (count, key)
 
   rl_crlf ();  /* move to a new line */
 
+  old_line_count = current_command_line_count;
+  ts = save_token_state ();
+
   cmd = savestring (cmd);
-  parse_and_execute (cmd, "bash_execute_unix_command", 0);
+  parse_and_execute (cmd, "bash_execute_unix_command", SEVAL_NOHIST);
+
+  current_command_line_count = old_line_count;
+  restore_token_state (ts);
 
   /* and restore the readline buffer and display after command execution. */
   rl_forced_update_display ();
index c4861577645b6fdbf6aaeb9a837be26e494c2777..32d3b0982bdf291bc7a1fc945005a8a056d705e1 100644 (file)
@@ -36,6 +36,7 @@ extern int bind_keyseq_to_unix_command __P((char *));
 /* Used by programmable completion code. */
 extern char *command_word_completion_function __P((const char *, int));
 extern char *bash_groupname_completion_function __P((const char *, int));
+extern char *bash_servicename_completion_function __P((const char *, int));
 
 extern char **get_hostname_list __P((void));
 extern void clear_hostname_list __P((void));
index c3739485bcb195d5f16b96be817e45ff9b7b83d6..7409247c095e4b1f85167feeec98b2e19b8777af 100644 (file)
@@ -1,4 +1,4 @@
-/* bashtypes.h -- <sys/types.h> with special handling for crays. */
+/* bashtypes.h -- Bash system types. */
 
 /* Copyright (C) 1993 Free Software Foundation, Inc.
 
@@ -31,4 +31,8 @@
 #  undef word
 #endif
 
+#if defined (HAVE_INTTYPES_H)
+#  include <inttypes.h>
+#endif
+
 #endif /* _BASHTYPES_H_ */
index 323b7945e15b201056a23e1213852db4f5914137..34fc91e8d03e5881b3d71359194a3a9f78e6e4c1 100644 (file)
@@ -152,7 +152,7 @@ hack_braces_completion (names)
   register int i;
   char *temp;
 
-  temp = really_munge_braces (names, 1, array_len (names), 0);
+  temp = really_munge_braces (names, 1, strvec_len (names), 0);
 
   for (i = 0; names[i]; ++i)
     {
index 1d8509d87b809bf833002443f80e89d5e8827205..4f5b0f0f3b59e9fa2e48d59cf8c3d6aa45a9ec24 100644 (file)
--- a/braces.c
+++ b/braces.c
@@ -1,6 +1,6 @@
 /* braces.c -- code for doing word expansion in curly braces. */
 
-/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -38,6 +38,8 @@
 #endif /* SHELL */
 
 #include "general.h"
+#include "shmbutil.h"
+
 #define brace_whitespace(c) (!(c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
 
 /* Basic idea:
@@ -53,8 +55,8 @@
 int brace_arg_separator = ',';
 
 #if defined (__P)
-static int brace_gobbler __P((char *, int *, int));
-static char **expand_amble __P((char *));
+static int brace_gobbler __P((char *, size_t, int *, int));
+static char **expand_amble __P((char *, size_t));
 static char **array_concat __P((char **, char **));
 #else
 static int brace_gobbler ();
@@ -68,13 +70,18 @@ brace_expand (text)
      char *text;
 {
   register int start;
+  size_t tlen;
   char *preamble, *postamble, *amble;
+  size_t alen;
   char **tack, **result;
   int i, j, c;
 
+  DECLARE_MBSTATE;
+
   /* Find the text of the preamble. */
+  tlen = strlen (text);
   i = 0;
-  c = brace_gobbler (text, &i, '{');
+  c = brace_gobbler (text, tlen, &i, '{');
 
   preamble = (char *)xmalloc (i + 1);
   strncpy (preamble, text, i);
@@ -91,7 +98,7 @@ brace_expand (text)
 
   /* Find the amble.  This is the stuff inside this set of braces. */
   start = ++i;
-  c = brace_gobbler (text, &i, '}');
+  c = brace_gobbler (text, tlen, &i, '}');
 
   /* What if there isn't a matching close brace? */
   if (c == 0)
@@ -99,20 +106,23 @@ brace_expand (text)
 #if defined (NOTDEF)
       /* Well, if we found an unquoted BRACE_ARG_SEPARATOR between START
         and I, then this should be an error.  Otherwise, it isn't. */
-      for (j = start; j < i; j++)
+      j = start;
+      while (j < i)
        {
          if (text[j] == '\\')
            {
              j++;
+             ADVANCE_CHAR (text, tlen, j);
              continue;
            }
 
          if (text[j] == brace_arg_separator)
            {
-             free_array (result);
+             strvec_dispose (result);
              report_error ("missing `}'");
              throw_to_top_level ();
            }
+         ADVANCE_CHAR (text, tlen, j);
        }
 #endif
       free (preamble);         /* Same as result[0]; see initialization. */
@@ -122,24 +132,33 @@ brace_expand (text)
 
 #if defined (SHELL)
   amble = substring (text, start, i);
+  alen = i - start;
 #else
   amble = (char *)xmalloc (1 + (i - start));
   strncpy (amble, &text[start], (i - start));
-  amble[i - start] = '\0';
+  alen = i - start;
+  amble[alen] = '\0';
 #endif
 
 #if defined (SHELL)
+  INITIALIZE_MBSTATE;
+
   /* If the amble does not contain an unquoted BRACE_ARG_SEPARATOR, then
      just return without doing any expansion.  */
-  for (j = 0; amble[j]; j++)
+  j = 0;
+  while (amble[j])
     {
       if (amble[j] == '\\')
        {
          j++;
+         ADVANCE_CHAR (amble, alen, j);
          continue;
        }
+
       if (amble[j] == brace_arg_separator)
        break;
+
+      ADVANCE_CHAR (amble, alen, j);
     }
 
   if (!amble[j])
@@ -153,14 +172,14 @@ brace_expand (text)
 
   postamble = &text[i + 1];
 
-  tack = expand_amble (amble);
+  tack = expand_amble (amble, alen);
   result = array_concat (result, tack);
   free (amble);
-  free_array (tack);
+  strvec_dispose (tack);
 
   tack = brace_expand (postamble);
   result = array_concat (result, tack);
-  free_array (tack);
+  strvec_dispose (tack);
 
   return (result);
 }
@@ -170,18 +189,23 @@ brace_expand (text)
    expand each slot which needs it, until there are no more slots which
    need it. */
 static char **
-expand_amble (text)
+expand_amble (text, tlen)
      char *text;
+     size_t tlen;
 {
   char **result, **partial;
   char *tem;
   int start, i, c;
 
+  DECLARE_MBSTATE;
+
   result = (char **)NULL;
 
-  for (start = 0, i = 0, c = 1; c; start = ++i)
+  start = i = 0;
+  c = 1;
+  while (c)
     {
-      c = brace_gobbler (text, &i, brace_arg_separator);
+      c = brace_gobbler (text, tlen, &i, brace_arg_separator);
 #if defined (SHELL)
       tem = substring (text, start, i);
 #else
@@ -196,11 +220,11 @@ expand_amble (text)
        result = partial;
       else
        {
-         register int lr = array_len (result);
-         register int lp = array_len (partial);
+         register int lr = strvec_len (result);
+         register int lp = strvec_len (partial);
          register int j;
 
-         result = (char **)xrealloc (result, (1 + lp + lr) * sizeof (char *));
+         result = strvec_resize (result, lp + lr + 1);
 
          for (j = 0; j < lp; j++)
            result[lr + j] = partial[j];
@@ -209,6 +233,8 @@ expand_amble (text)
          free (partial);
        }
       free (tem);
+      ADVANCE_CHAR (text, tlen, i);
+      start = i;
     }
   return (result);
 }
@@ -218,8 +244,9 @@ expand_amble (text)
    quoting.  Return the character that caused us to stop searching;
    this is either the same as SATISFY, or 0. */
 static int
-brace_gobbler (text, indx, satisfy)
+brace_gobbler (text, tlen, indx, satisfy)
      char *text;
+     size_t tlen;
      int *indx;
      int satisfy;
 {
@@ -228,14 +255,17 @@ brace_gobbler (text, indx, satisfy)
   int si;
   char *t;
 #endif
+  DECLARE_MBSTATE;
 
   level = quoted = pass_next = 0;
 
-  for (i = *indx; c = text[i]; i++)
+  i = *indx;
+  while (c = text[i])
     {
       if (pass_next)
        {
          pass_next = 0;
+         ADVANCE_CHAR (text, tlen, i);
          continue;
        }
 
@@ -244,6 +274,7 @@ brace_gobbler (text, indx, satisfy)
       if (c == '\\' && (quoted == 0 || quoted == '"' || quoted == '`'))
        {
          pass_next = 1;
+         i++;
          continue;
        }
 
@@ -251,12 +282,14 @@ brace_gobbler (text, indx, satisfy)
        {
          if (c == quoted)
            quoted = 0;
+         ADVANCE_CHAR (text, tlen, i);
          continue;
        }
 
       if (c == '"' || c == '\'' || c == '`')
        {
          quoted = c;
+         i++;
          continue;
        }
 
@@ -268,6 +301,7 @@ brace_gobbler (text, indx, satisfy)
          t = extract_command_subst (text, &si);
          i = si;
          free (t);
+         i++;
          continue;
        }
 #endif
@@ -280,7 +314,10 @@ brace_gobbler (text, indx, satisfy)
          if (c == '{' &&
              ((!i || brace_whitespace (text[i - 1])) &&
               (brace_whitespace (text[i + 1]) || text[i + 1] == '}')))
-           continue;
+           {
+             i++;
+             continue;
+           }
 #if defined (SHELL)
          /* If this is being compiled as part of bash, ignore the `{'
             in a `${}' construct */
@@ -293,6 +330,8 @@ brace_gobbler (text, indx, satisfy)
        level++;
       else if (c == '}' && level)
        level--;
+
+      ADVANCE_CHAR (text, tlen, i);
     }
 
   *indx = i;
@@ -312,13 +351,13 @@ array_concat (arr1, arr2)
   register char **result;
 
   if (arr1 == 0)
-    return (copy_array (arr2));
+    return (strvec_copy (arr2));
 
   if (arr2 == 0)
-    return (copy_array (arr1));
+    return (strvec_copy (arr1));
 
-  len1 = array_len (arr1);
-  len2 = array_len (arr2);
+  len1 = strvec_len (arr1);
+  len2 = strvec_len (arr2);
 
   result = (char **)xmalloc ((1 + (len1 * len2)) * sizeof (char *));
 
index e97fa04bb99282f36f6933e4abe80a1fc1235e78..53fb5274efc998c2a74350cd6dc770107acf50d3 100644 (file)
 /* The thing that we build the array of builtins out of. */
 struct builtin {
   char *name;                  /* The name that the user types. */
-  sh_builtin_func_t *function;         /* The address of the invoked function. */
+  sh_builtin_func_t *function; /* The address of the invoked function. */
   int flags;                   /* One of the #defines above. */
-  char **long_doc;             /* NULL terminated array of strings. */
-  char *short_doc;             /* Short version of documenation. */
+  char * const *long_doc;      /* NULL terminated array of strings. */
+  const char *short_doc;       /* Short version of documenation. */
   char *handle;                        /* for future use */
 };
 
index 837b53ee7e9798c57813b53511d19faa8a2c2bd6..53ae75ac06dfc22accdee2793aca7e079e5728b5 100644 (file)
@@ -28,32 +28,52 @@ CP = cp
 
 EXEEXT = @EXEEXT@
 
+prefix = @prefix@
+
 srcdir = @srcdir@
 VPATH = .:@srcdir@
 topdir = @top_srcdir@
 includedir = @includedir@
+datadir = @datadir@
+
+# Support an alternate destination root directory for package building
+DESTDIR =
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
 BUILD_DIR = @BUILD_DIR@
 
 PROFILE_FLAGS = @PROFILE_FLAGS@
 CFLAGS = @CFLAGS@
-LOCAL_CFLAGS = @LOCAL_CFLAGS@ ${DEBUG}
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
 CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+LOCAL_CFLAGS = @LOCAL_CFLAGS@ ${DEBUG}
 DEFS = @DEFS@
 LOCAL_DEFS = @LOCAL_DEFS@
+
+LIBS = @LIBS@
 LDFLAGS = @LDFLAGS@ $(LOCAL_LDFLAGS) $(CFLAGS)
+LDFLAGS_FOR_BUILD = $(LDFLAGS)
 LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
-LIBS = @LIBS@
+#LIBS_FOR_BUILD = @LIBS_FOR_BUILD@
+LIBS_FOR_BUILD = $(LIBS)
 
 BASHINCDIR = ${topdir}/include
 
 RL_INCLUDEDIR = @RL_INCLUDEDIR@
 
+HELPDIR = @HELPDIR@
+MKDIRS = ${topdir}/support/mkdirs
+
 INCLUDES = -I. -I.. @RL_INCLUDE@ -I$(topdir) -I$(BASHINCDIR) -I$(topdir)/lib -I$(srcdir)
 
-CCFLAGS_FOR_BUILD = ${PROFILE_FLAGS} $(DEFS) $(LOCAL_DEFS) $(SYSTEM_FLAGS) \
-       $(CPPFLAGS) ${INCLUDES} $(LOCAL_CFLAGS)
+BASE_CCFLAGS = ${PROFILE_FLAGS} $(DEFS) $(LOCAL_DEFS) $(SYSTEM_FLAGS) \
+        ${INCLUDES} $(LOCAL_CFLAGS)
 
-CCFLAGS = $(CCFLAGS_FOR_BUILD) $(CFLAGS)
+CCFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(CFLAGS)
+
+CCFLAGS_FOR_BUILD = $(BASE_CCFLAGS) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD)
 
 GCC_LINT_FLAGS = -Wall -Wshadow -Wpointer-arith -Wcast-qual \
                 -Wcast-align -Wstrict-prototypes -Wconversion \
@@ -61,6 +81,7 @@ GCC_LINT_FLAGS = -Wall -Wshadow -Wpointer-arith -Wcast-qual \
 
 MKBUILTINS = mkbuiltins$(EXEEXT)
 DIRECTDEFINE = -D $(srcdir)
+HELPDIRDEFINE = @HELPDIRDEFINE@
 
 # xxx this is bad style
 RL_LIBSRC = $(topdir)/lib/readline
@@ -124,7 +145,7 @@ builtext.h builtins.c: $(MKBUILTINS) $(DEFSRC)
        @-if test -f builtins.c; then mv -f builtins.c old-builtins.c; fi
        @-if test -f builtext.h; then mv -f builtext.h old-builtext.h; fi
        ./$(MKBUILTINS) -externfile builtext.h -structfile builtins.c \
-           -noproduction $(DIRECTDEFINE) $(DEFSRC)
+           -noproduction $(DIRECTDEFINE) $(HELPDIRDEFINE) $(DEFSRC)
        @-if cmp -s old-builtext.h builtext.h 2>/dev/null; then \
                mv old-builtext.h builtext.h; \
         else \
@@ -136,13 +157,28 @@ builtext.h builtins.c: $(MKBUILTINS) $(DEFSRC)
                $(RM) old-builtins.c; \
         fi
 
+helpdoc:       $(MKBUILTINS) $(DEFSRC)
+       ./$(MKBUILTINS) ${HELPDIRDEFINE} -noproduction $(DIRECTDEFINE) $(DEFSRC)
+
+install-help:
+       @-if test -n "${HELPDIR}" && test -d helpfiles ; then \
+               test -d ${HELPDIR} || ${SHELL} ${MKDIRS} $(DESTDIR)$(HELPDIR) ;\
+               ( cd helpfiles ; \
+                 for f in *; do \
+                       echo installing $$f; \
+                       ${INSTALL_DATA} $$f $(DESTDIR)$(HELPDIR); \
+                 done; ) ; \
+       fi
+
+install:       @HELPINSTALL@
+
 mkbuiltins.o: ../config.h
 mkbuiltins.o: mkbuiltins.c
        $(RM) $@
        $(CC_FOR_BUILD) -c $(CCFLAGS_FOR_BUILD) $<
 
 mkbuiltins$(EXEEXT): mkbuiltins.o
-       $(CC_FOR_BUILD) $(PROFILE_FLAGS) $(LDFLAGS) -o $(MKBUILTINS) mkbuiltins.o $(LIBS)
+       $(CC_FOR_BUILD) $(LDFLAGS_FOR_BUILD) -o $(MKBUILTINS) mkbuiltins.o $(LIBS_FOR_BUILD)
 
 # rules for deficient makes, like SunOS
 mkbuiltins.o: mkbuiltins.c
@@ -163,13 +199,12 @@ psize.aux:        psize.c
 
 documentation: builtins.texi
 
-$(OFILES):     $(MKBUILTINS) ../config.h
-
 builtins.texi: $(MKBUILTINS)
        ./$(MKBUILTINS) -documentonly $(DEFSRC)
 
 clean:
        $(RM) $(OFILES) $(CREATED_FILES) $(MKBUILTINS) mkbuiltins.o libbuiltins.a
+       -test -d helpfiles && $(RM) -r helpfiles
 
 mostlyclean: 
        $(RM) $(OFILES) libbuiltins.a
@@ -177,6 +212,8 @@ mostlyclean:
 distclean maintainer-clean: clean
        $(RM) Makefile
 
+$(OFILES):     $(MKBUILTINS) ../config.h
+
 alias.o: alias.def
 bind.o: bind.def
 break.o: break.def
@@ -293,6 +330,7 @@ builtin.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/e
 builtin.o: $(topdir)/quit.h $(srcdir)/common.h $(BASHINCDIR)/maxpath.h
 builtin.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
 builtin.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h 
+builtin.o: $(srcdir)/bashgetopt.h
 cd.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
 cd.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/quit.h $(topdir)/dispose_cmd.h
 cd.o: $(topdir)/make_cmd.h $(topdir)/subst.h $(topdir)/externs.h
@@ -308,7 +346,7 @@ declare.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
 declare.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
 declare.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
 declare.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-declare.o: $(topdir)/arrayfunc.h
+declare.o: $(topdir)/arrayfunc.h $(srcdir)/bashgetopt.h
 echo.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
 echo.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/subst.h $(topdir)/externs.h
 echo.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
@@ -351,7 +389,7 @@ fc.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
 fc.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/shell.h $(topdir)/syntax.h
 fc.o: $(topdir)/flags.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
 fc.o: $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h $(BASHINCDIR)/chartypes.h
-fg_bg.o: $(topdir)/bashtypes.h
+fg_bg.o: $(topdir)/bashtypes.h $(srcdir)/bashgetopt.h
 fg_bg.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
 fg_bg.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
 fg_bg.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
@@ -373,7 +411,7 @@ help.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
 help.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
 help.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
 help.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-help.o: ${srcdir}/common.h ../version.h
+help.o: ${srcdir}/common.h
 history.o: $(topdir)/bashtypes.h
 history.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
 history.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
@@ -449,6 +487,7 @@ source.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/fi
 source.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
 source.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
 source.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
+source.o: $(srcdir)/bashgetopt.h
 suspend.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
 suspend.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
 suspend.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
index e279d4d17ecd2e8f121dfffc3e766c23f76e675f..f51df94858a3a5e6894d4883b1ea33438e5e675d 100644 (file)
@@ -1,7 +1,7 @@
 This file is alias.def, from which is created alias.c
 It implements the builtins "alias" and "unalias" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -120,7 +120,7 @@ alias_builtin (list)
            print_alias (t);
          else
            {
-             builtin_error ("`%s' not found", name);
+             sh_notfound (name);
              any_failed++;
            }
        }
@@ -180,7 +180,7 @@ unalias_builtin (list)
        remove_alias (alias->name);
       else
        {
-         builtin_error ("`%s': not an alias", list->word->word);
+         sh_notfound (list->word->word);
          aflag++;
        }
 
index a0b14c0ae61a85c4f6d1c7c6983073cd26f70f42..4c8d907a9cf27ee8b0b19ba1d21c56d9d0cfb198 100644 (file)
@@ -1,6 +1,6 @@
 /* bashgetopt.c -- `getopt' for use by the builtins. */
 
-/* Copyright (C) 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -31,12 +31,14 @@ Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
 #include "../shell.h"
 #include "common.h"
 
-#define ERR(S, C)      builtin_error("%s%c", (S), (C))
-
+#define ISOPT(s)       (((*(s) == '-') || (plus && *(s) == '+')) && (s)[1])
+#define NOTOPT(s)      (((*(s) != '-') && (!plus || *(s) != '+')) || (s)[1] == '\0')
+                       
 static int     sp;
 
 char    *list_optarg;
 int    list_optopt;
+int    list_opttype;
 
 static WORD_LIST *lhead = (WORD_LIST *)NULL;
 WORD_LIST      *lcurrent = (WORD_LIST *)NULL;
@@ -50,12 +52,11 @@ char                *opts;
        register int c;
        register char *cp;
        int     plus;   /* nonzero means to handle +option */
+       static char errstr[3] = { '-', '\0', '\0' };
 
-       if (*opts == '+') {
-               plus = 1;
+       plus = *opts == '+';
+       if (plus)
                opts++;
-       } else
-               plus = 0;
 
        if (list == 0) {
                list_optarg = (char *)NULL;
@@ -71,8 +72,7 @@ char          *opts;
        }
 
        if (sp == 1) {
-               if (lcurrent == 0 ||
-                   (lcurrent->word->word[0] != '-' || lcurrent->word->word[1] == '\0')) {
+               if (lcurrent == 0 || NOTOPT(lcurrent->word->word)) {
                        lhead = (WORD_LIST *)NULL;
                        loptend = lcurrent;
                        return(-1);
@@ -83,12 +83,14 @@ char                *opts;
                        loptend = lcurrent->next;
                        return(-1);
                }
+               errstr[0] = list_opttype = lcurrent->word->word[0];
        }
 
        list_optopt = c = lcurrent->word->word[sp];
 
        if (c == ':' || (cp = strchr(opts, c)) == NULL) {
-               ERR("illegal option: -", c);
+               errstr[1] = c;
+               sh_invalidopt (errstr);         
                if (lcurrent->word->word[++sp] == '\0') {
                        lcurrent = lcurrent->next;
                        sp = 1;
@@ -108,7 +110,11 @@ char               *opts;
                        lcurrent = lcurrent->next;
                /* If the specifier is `;', don't set optarg if the next
                   argument looks like another option. */
+#if 0
                } else if (lcurrent->next && (*cp == ':' || lcurrent->next->word->word[0] != '-')) {
+#else
+               } else if (lcurrent->next && (*cp == ':' || NOTOPT(lcurrent->next->word->word))) {
+#endif
                        lcurrent = lcurrent->next;
                        list_optarg = lcurrent->word->word;
                        lcurrent = lcurrent->next;
@@ -116,14 +122,15 @@ char              *opts;
                        list_optarg = (char *)NULL;
                        lcurrent = lcurrent->next;
                } else {        /* lcurrent->next == NULL */
-                       ERR("option requires an argument: -", c);
+                       errstr[1] = c;
+                       sh_needarg (errstr);
                        sp = 1;
                        list_optarg = (char *)NULL;
                        return('?');
                }
                sp = 1;
        } else if (*cp == '#') {
-               /* optional numeric argument */
+               /* option requires a numeric argument */
                if (lcurrent->word->word[sp+1]) {
                        if (DIGIT(lcurrent->word->word[sp+1])) {
                                list_optarg = lcurrent->word->word + sp + 1;
@@ -131,12 +138,17 @@ char              *opts;
                        } else
                                list_optarg = (char *)NULL;
                } else {
-                       if (lcurrent->next && legal_number(lcurrent->next->word->word, (long *)0)) {
+                       if (lcurrent->next && legal_number(lcurrent->next->word->word, (intmax_t *)0)) {
                                lcurrent = lcurrent->next;
                                list_optarg = lcurrent->word->word;
                                lcurrent = lcurrent->next;
-                       } else
+                       } else {
+                               errstr[1] = c;
+                               sh_neednumarg (errstr);
+                               sp = 1;
                                list_optarg = (char *)NULL;
+                               return ('?');
+                       }
                }
 
        } else {
@@ -161,16 +173,3 @@ reset_internal_getopt ()
        lhead = lcurrent = loptend = (WORD_LIST *)NULL;
        sp = 1;
 }
-
-#ifdef INCLUDE_UNUSED
-void
-report_bad_option ()
-{
-       char s[3];
-
-       s[0] = '-';
-       s[1] = list_optopt;
-       s[2] = '\0';
-       bad_option (s);
-}
-#endif
index 93cf590beeb69b26f8a13e7f9453ca8a612af297..835797c150df7671760d85321891471f786841f5 100644 (file)
 extern char *list_optarg;
 
 extern int list_optopt;
+extern int list_opttype;
 
 extern WORD_LIST *lcurrent;
 extern WORD_LIST *loptend;
 
 extern int internal_getopt __P((WORD_LIST *, char *));
 extern void reset_internal_getopt __P((void));
-extern void report_bad_option __P((void));
 
 #endif /* !__BASH_GETOPT_H */
index 40c8c9f8942b2abb6de70c0c1b84a5ce618c18f3..ddf561991a406c9597f294d5831617b75cb2ef18 100644 (file)
@@ -1,7 +1,7 @@
 This file is bind.def, from which is created bind.c.
 It implements the builtin "bind" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -26,11 +26,12 @@ $PRODUCES bind.c
 $BUILTIN bind
 $DEPENDS_ON READLINE
 $FUNCTION bind_builtin
-$SHORT_DOC bind [-lpvsPVS] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-x keyseq:shell-command] [keyseq:readline-function]
-Bind a key sequence to a Readline function, or to a macro.  The
-syntax is equivalent to that found in ~/.inputrc, but must be
-passed as a single argument: bind '"\C-x\C-r": re-read-init-file'.
-Arguments we accept:
+$SHORT_DOC bind [-lpvsPVS] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-x keyseq:shell-command] [keyseq:readline-function or readline-command]
+Bind a key sequence to a Readline function or a macro, or set
+a Readline variable.  The non-option argument syntax is equivalent
+to that found in ~/.inputrc, but must be passed as a single argument:
+bind '"\C-x\C-r": re-read-init-file'.
+bind accepts the following options:
   -m  keymap         Use `keymap' as the keymap for the duration of this
                      command.  Acceptable keymap names are emacs,
                      emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,
@@ -40,8 +41,8 @@ Arguments we accept:
   -p                 List functions and bindings in a form that can be
                      reused as input.
   -r  keyseq         Remove the binding for KEYSEQ.
-  -x  keyseq:shell-command     Cause SHELL-COMMAND to be executed when KEYSEQ
-                               is entered.
+  -x  keyseq:shell-command     Cause SHELL-COMMAND to be executed when
+                               KEYSEQ is entered.
   -f  filename       Read key bindings from FILENAME.
   -q  function-name  Query about which keys invoke the named function.
   -u  function-name  Unbind all keys which are bound to the named function.
@@ -49,8 +50,8 @@ Arguments we accept:
   -v                 List variable names and values in a form that can
                      be reused as input.
   -S                 List key sequences that invoke macros and their values
-  -s                 List key sequences that invoke macros and their values in
-                     a form that can be reused as input.
+  -s                 List key sequences that invoke macros and their values
+                     in a form that can be reused as input.
 $END
 
 #if defined (READLINE)
@@ -227,7 +228,7 @@ bind_builtin (list)
     {
       if (rl_read_init_file (initfile) != 0)
        {
-         builtin_error ("cannot read %s: %s", initfile, strerror (errno));
+         builtin_error ("%s: cannot read: %s", initfile, strerror (errno));
          BIND_RETURN (EXECUTION_FAILURE);
        }
     }
@@ -242,7 +243,7 @@ bind_builtin (list)
     {
       if (rl_set_key (remove_seq, (rl_command_func_t *)NULL, rl_get_keymap ()) != 0)
        {
-         builtin_error ("cannot unbind %s", remove_seq);
+         builtin_error ("`%s': cannot unbind", remove_seq);
          BIND_RETURN (EXECUTION_FAILURE);
        }
     }
@@ -277,7 +278,7 @@ query_bindings (name)
   function = rl_named_function (name);
   if (function == 0)
     {
-      builtin_error ("unknown function name `%s'", name);
+      builtin_error ("`%s': unknown function name", name);
       return EXECUTION_FAILURE;
     }
 
@@ -294,7 +295,7 @@ query_bindings (name)
     printf ("\"%s\"%s", keyseqs[j], keyseqs[j + 1] ? ", " : ".\n");
   if (keyseqs[j])
     printf ("...\n");
-  free_array (keyseqs);
+  strvec_dispose (keyseqs);
   return EXECUTION_SUCCESS;
 }
 
@@ -307,7 +308,7 @@ unbind_command (name)
   function = rl_named_function (name);
   if (function == 0)
     {
-      builtin_error ("unknown function name `%s'", name);
+      builtin_error ("`%s': unknown function name", name);
       return EXECUTION_FAILURE;
     }
 
index e90a32b5b9372c60c5a940f48defa8e3075956cc..1025414526802653eed8612d79231e04c345f8fb 100644 (file)
@@ -1,7 +1,7 @@
 This file is break.def, from which is created break.c.
 It implements the builtins "break" and "continue" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -59,7 +59,7 @@ int
 break_builtin (list)
      WORD_LIST *list;
 {
-  long newbreak;
+  intmax_t newbreak;
 
   if (check_loop_level () == 0)
     return (EXECUTION_SUCCESS);
@@ -68,7 +68,7 @@ break_builtin (list)
 
   if (newbreak <= 0)
     {
-      builtin_error ("loop count must be > 0");
+      sh_erange (list->word->word, "loop count");
       breaking = loop_level;
       return (EXECUTION_FAILURE);
     }
@@ -94,7 +94,7 @@ int
 continue_builtin (list)
      WORD_LIST *list;
 {
-  long newcont;
+  intmax_t newcont;
 
   if (check_loop_level () == 0)
     return (EXECUTION_SUCCESS);
@@ -103,7 +103,7 @@ continue_builtin (list)
 
   if (newcont <= 0)
     {
-      builtin_error ("loop count must be > 0");
+      sh_erange (list->word->word, "loop count");
       breaking = loop_level;
       return (EXECUTION_FAILURE);
     }
index f3de5d6736507a2d139fd37629d2f8305ac1149e..8571f372a7fd64a9e847a77fda8a26232b4912ec 100644 (file)
@@ -1,7 +1,7 @@
 This file is builtin.def, from which is created builtin.c.
 It implements the builtin "builtin" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -39,6 +39,7 @@ $END
 
 #include "../shell.h"
 #include "common.h"
+#include "bashgetopt.h"
 
 extern char *this_command_name;
 
@@ -51,10 +52,14 @@ builtin_builtin (list)
   sh_builtin_func_t *function;
   register char *command;
 
-  if (!list)
+  if (no_options (list))
+    return (EX_USAGE);
+  list = loptend;      /* skip over possible `--' */
+
+  if (list == 0)
     return (EXECUTION_SUCCESS);
 
-  command = (list->word->word);
+  command = list->word->word;
 #if defined (DISABLED_BUILTINS)
   function = builtin_address (command);
 #else /* !DISABLED_BUILTINS */
index 77e8f82155a84f3c956df74db49edc5bc9ea6149..1c58c7c1602ca286fc9ed7799feacfb1935450f5 100644 (file)
@@ -69,7 +69,7 @@ int cdable_vars;
 
 $BUILTIN cd
 $FUNCTION cd_builtin
-$SHORT_DOC cd [-PL] [dir]
+$SHORT_DOC cd [-L|-P] [dir]
 Change the current directory to DIR.  The variable $HOME is the
 default DIR.  The variable CDPATH defines the search path for
 the directory containing DIR.  Alternative directory names in CDPATH
@@ -118,6 +118,19 @@ bindpwd (no_symlinks)
   return (EXECUTION_SUCCESS);
 }
 
+/* Call get_working_directory to reset the value of
+   the_current_working_directory () */
+static char *
+resetpwd ()
+{
+  char *tdir;
+      
+  FREE (the_current_working_directory);
+  the_current_working_directory = (char *)NULL;
+  tdir = get_working_directory ("cd");
+  return (tdir);
+}
+
 #define LCD_DOVARS     0x001
 #define LCD_DOSPELL    0x002
 #define LCD_PRINTPATH  0x004
@@ -137,7 +150,7 @@ cd_builtin (list)
 #if defined (RESTRICTED_SHELL)
   if (restricted)
     {
-      builtin_error ("restricted");
+      sh_restricted ((char *)NULL);
       return (EXECUTION_FAILURE);
     }
 #endif /* RESTRICTED_SHELL */
@@ -350,7 +363,7 @@ change_to_directory (newdir, nolinks)
      int nolinks;
 {
   char *t, *tdir;
-  int err;
+  int err, canon_failed;
 
   tdir = (char *)NULL;
 
@@ -370,20 +383,38 @@ change_to_directory (newdir, nolinks)
 
   /* Use the canonicalized version of NEWDIR, or, if canonicalization
      failed, use the non-canonical form. */
+  canon_failed = 0;
   if (tdir && *tdir)
     free (t);
   else
     {
       FREE (tdir);
       tdir = t;
+      canon_failed = 1;
+    }
+
+  /* In POSIX mode, if we're resolving symlinks logically and sh_canonpath
+     returns NULL (because it checks the path, it will return NULL if the
+     resolved path doesn't exist), fail immediately. */
+  if (posixly_correct && nolinks == 0 && canon_failed)
+    {
+      errno = ENOENT;
+      return (0);
     }
 
   /* If the chdir succeeds, update the_current_working_directory. */
   if (chdir (nolinks ? newdir : tdir) == 0)
     {
-      FREE (the_current_working_directory);
-      the_current_working_directory = tdir;
-      
+      /* If canonicalization failed, but the chdir succeeded, reset the
+        shell's idea of the_current_working_directory. */
+      if (canon_failed)
+       resetpwd ();
+      else
+       {
+         FREE (the_current_working_directory);
+         the_current_working_directory = tdir;
+       }
+
       return (1);
     }
 
@@ -400,9 +431,7 @@ change_to_directory (newdir, nolinks)
      verbatim. If we succeed, reinitialize the_current_working_directory. */
   if (chdir (newdir) == 0)
     {
-      FREE (the_current_working_directory);
-      the_current_working_directory = (char *)NULL;
-      tdir = get_working_directory ("cd");
+      tdir = resetpwd ();
       FREE (tdir);
 
       return (1);
index e00428d5ad10bcf92bfc2aac88a6d83063b16cf7..a7cdc12506c971de55d7aae2b27d645fb00b6656 100644 (file)
@@ -1,7 +1,7 @@
 This file is colon.def, from which is created colon.c.
 It implements the builtin ":" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -22,21 +22,19 @@ Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
 $PRODUCES colon.c
 
 $BUILTIN :
-$DOCNAME colon_builtin
+$DOCNAME colon
 $FUNCTION colon_builtin
 $SHORT_DOC :
 No effect; the command does nothing.  A zero exit code is returned.
 $END
 
 $BUILTIN true
-$DOCNAME true_builtin
 $FUNCTION colon_builtin
 $SHORT_DOC true
 Return a successful result.
 $END
 
 $BUILTIN false
-$DOCNAME false_builtin
 $FUNCTION false_builtin
 $SHORT_DOC false
 Return an unsuccessful result.
index 28515be40741a69d5f44134c6961a2a67e99446f..dcbbec148149c2784de00757372dae7a9683934f 100644 (file)
@@ -1,7 +1,7 @@
 This file is command.def, from which is created command.c.
 It implements the builtin "command" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -78,10 +78,10 @@ command_builtin (list)
          use_standard_path = 1;
          break;
        case 'V':
-         verbose = 2;
+         verbose = CDESC_SHORTDESC;    /* look in common.h for constants */
          break;
        case 'v':
-         verbose = 4;
+         verbose = CDESC_REUSABLE;     /* ditto */
          break;
        default:
          builtin_usage ();
@@ -99,10 +99,10 @@ command_builtin (list)
 
       for (any_found = 0; list; list = list->next)
        {
-         found = describe_command (list->word->word, verbose, 0);
+         found = describe_command (list->word->word, verbose);
 
          if (found == 0)
-           builtin_error ("%s: not found", list->word->word);
+           sh_notfound (list->word->word);
 
          any_found += found;
        }
@@ -112,7 +112,7 @@ command_builtin (list)
 #if defined (RESTRICTED_SHELL)
   if (use_standard_path && restricted)
     {
-      builtin_error ("restricted: cannot use -p");
+      sh_restricted ("-p");
       return (EXECUTION_FAILURE);
     }
 #endif
index 19a76ea60102719cf947d84cc38b3c300e7bcfa1..b818600294dc08b71780754924086724da703db7 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -36,9 +36,7 @@
 #if defined (PREFER_STDARG)
 #  include <stdarg.h>
 #else
-#  if defined (PREFER_VARARGS)
-#    include <varargs.h>
-#  endif
+#  include <varargs.h>
 #endif
 
 #include "../bashansi.h"
@@ -64,8 +62,7 @@
 extern int errno;   
 #endif /* !errno */
 
-extern int no_symbolic_links;
-extern int indirection_level, startup_state, subshell_environment;
+extern int indirection_level, subshell_environment;
 extern int line_number;
 extern int last_command_exit_value;
 extern int running_trap;
@@ -86,7 +83,6 @@ sh_builtin_func_t *this_shell_builtin = (sh_builtin_func_t *)NULL;
 /* This is a lot like report_error (), but it is for shell builtins
    instead of shell control structures, and it won't ever exit the
    shell. */
-#if defined (USE_VARARGS)
 void
 #if defined (PREFER_STDARG)
 builtin_error (const char *format, ...)
@@ -102,32 +98,18 @@ builtin_error (format, va_alist)
   name = get_name_for_error ();
   fprintf (stderr, "%s: ", name);
 
+  if (interactive_shell == 0)
+    fprintf (stderr, "line %d: ", executing_line_number ());
+
   if (this_command_name && *this_command_name)
     fprintf (stderr, "%s: ", this_command_name);
 
-#if defined (PREFER_STDARG)
-  va_start (args, format);
-#else
-  va_start (args);
-#endif
+  SH_VA_START (args, format);
 
   vfprintf (stderr, format, args);
   va_end (args);
   fprintf (stderr, "\n");
 }
-#else /* !USE_VARARGS */
-void
-builtin_error (format, arg1, arg2, arg3, arg4, arg5)
-     char *format, *arg1, *arg2, *arg3, *arg4, *arg5;
-{
-  if (this_command_name && *this_command_name)
-    fprintf (stderr, "%s: ", this_command_name);
-
-  fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
-  fprintf (stderr, "\n");
-  fflush (stderr);
-}
-#endif /* !USE_VARARGS */
 
 /* Print a usage summary for the currently-executing builtin command. */
 void
@@ -152,15 +134,6 @@ no_args (list)
     }
 }
 
-/* Function called when one of the builtin commands detects a bad
-   option. */
-void
-bad_option (s)
-     char *s;
-{
-  builtin_error ("unknown option: %s", s);
-}
-
 /* Check that no options were given to the currently-executing builtin,
    and return 0 if there were options. */
 int
@@ -176,6 +149,119 @@ no_options (list)
   return (0);
 }
 
+void
+sh_needarg (s)
+     char *s;
+{
+  builtin_error ("%s: option requires an argument", s);
+}
+
+void
+sh_neednumarg (s)
+     char *s;
+{
+  builtin_error ("%s: numeric argument required", s);
+}
+
+void
+sh_notfound (s)
+     char *s;
+{
+  builtin_error ("%s: not found", s);
+}
+
+/* Function called when one of the builtin commands detects an invalid
+   option. */
+void
+sh_invalidopt (s)
+     char *s;
+{
+  builtin_error ("%s: invalid option", s);
+}
+
+void
+sh_invalidoptname (s)
+     char *s;
+{
+  builtin_error ("%s: invalid option name", s);
+}
+
+void
+sh_invalidid (s)
+     char *s;
+{
+  builtin_error ("`%s': not a valid identifier", s);
+}
+
+void
+sh_invalidnum (s)
+     char *s;
+{
+  builtin_error ("%s: invalid number", s);
+}
+
+void
+sh_invalidsig (s)
+     char *s;
+{
+  builtin_error ("%s: invalid signal specification", s);
+}
+
+void
+sh_badpid (s)
+     char *s;
+{
+  builtin_error ("`%s': not a pid or valid job spec", s);
+}
+
+void
+sh_readonly (s)
+     const char *s;
+{
+  builtin_error ("%s: readonly variable", s);
+}
+
+void
+sh_erange (s, desc)
+     char *s, *desc;
+{
+  if (s)
+    builtin_error ("%s: %s out of range", s, desc ? desc : "argument");
+  else
+    builtin_error ("%s out of range", desc ? desc : "argument");
+}
+
+#if defined (JOB_CONTROL)
+void
+sh_badjob (s)
+     char *s;
+{
+  builtin_error ("%s: no such job", s);
+}
+
+void
+sh_nojobs (s)
+     char *s;
+{
+  if (s)
+    builtin_error ("%s: no job control");
+  else
+    builtin_error ("no job control");
+}
+#endif
+
+#if defined (RESTRICTED_SHELL)
+void
+sh_restricted (s)
+     char *s;
+{
+  if (s)
+    builtin_error ("%s: restricted", s);
+  else
+    builtin_error ("restricted");
+}
+#endif
+
 /* **************************************************************** */
 /*                                                                 */
 /*          Shell positional parameter manipulation                */
@@ -192,7 +278,7 @@ make_builtin_argv (list, ip)
 {
   char **argv;
 
-  argv = word_list_to_argv (list, 0, 1, ip);
+  argv = strvec_from_word_list (list, 0, 1, ip);
   argv[0] = this_command_name;
   return argv;
 }
@@ -235,67 +321,6 @@ remember_args (list, destructive)
     set_dollar_vars_changed ();
 }
 
-/* **************************************************************** */
-/*                                                                 */
-/*              Pushing and Popping variable contexts              */
-/*                                                                 */
-/* **************************************************************** */
-
-static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
-static int dollar_arg_stack_slots;
-static int dollar_arg_stack_index;
-
-void
-push_context ()
-{
-  push_dollar_vars ();
-  variable_context++;
-}
-
-void
-pop_context ()
-{
-  pop_dollar_vars ();
-  kill_all_local_variables ();
-  variable_context--;
-}
-
-/* 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;
-}
-
-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;
-}
-
 static int changed_dollar_vars;
 
 /* Have the dollar variables been reset to new values since we last
@@ -315,7 +340,12 @@ set_dollar_vars_unchanged ()
 void
 set_dollar_vars_changed ()
 {
-  changed_dollar_vars = 1;
+  if (variable_context)
+    changed_dollar_vars |= ARGS_FUNC;
+  else if (this_shell_builtin == set_builtin)
+    changed_dollar_vars |= ARGS_SETBLTIN;
+  else
+    changed_dollar_vars |= ARGS_INVOC;
 }
 
 /* **************************************************************** */
@@ -330,21 +360,24 @@ set_dollar_vars_changed ()
    follow.  If FATAL is true, call throw_to_top_level, which exits the
    shell; if not, call jump_to_top_level (DISCARD), which aborts the
    current command. */
-long
+intmax_t
 get_numeric_arg (list, fatal)
      WORD_LIST *list;
      int fatal;
 {
-  long count = 1;
+  intmax_t count = 1;
+
+  if (list && list->word && ISOPTION (list->word->word, '-'))
+    list = list->next;
 
   if (list)
     {
       register char *arg;
 
       arg = list->word->word;
-      if (!arg || (legal_number (arg, &count) == 0))
+      if (arg == 0 || (legal_number (arg, &count) == 0))
        {
-         builtin_error ("bad non-numeric arg `%s'", list->word->word);
+         sh_neednumarg (list->word->word);
          if (fatal)
            throw_to_top_level ();
          else
@@ -362,13 +395,19 @@ get_exitstat (list)
      WORD_LIST *list;
 {
   int status;
-  long sval;
+  intmax_t sval;
   char *arg;
 
+  if (list && list->word && ISOPTION (list->word->word, '-'))
+    list = list->next;
+
+  if (list == 0)
+    return (last_command_exit_value);      
+
   arg = list->word->word;
   if (arg == 0 || legal_number (arg, &sval) == 0)
     {
-      builtin_error ("bad non-numeric arg `%s'", list->word->word);
+      sh_neednumarg (list->word->word ? list->word->word : "`'");
       return 255;
     }
   no_args (list->next);
@@ -460,13 +499,65 @@ set_working_directory (name)
 /* **************************************************************** */
 
 #if defined (JOB_CONTROL)
+int
+get_job_by_name (name, flags)
+     const char *name;
+     int flags;
+{
+  register int i, wl, cl, match, job;
+  register PROCESS *p;
+
+  job = NO_JOB;
+  wl = strlen (name);
+  for (i = job_slots - 1; i >= 0; i--)
+    {
+      if (jobs[i] == 0 || ((flags & JM_STOPPED) && JOBSTATE(i) != JSTOPPED))
+        continue;
+
+      p = jobs[i]->pipe;
+      do
+        {
+         if (flags & JM_EXACT)
+           {
+             cl = strlen (p->command);
+             match = STREQN (p->command, name, cl);
+           }
+         else if (flags & JM_SUBSTRING)
+           match = strindex (p->command, name) != (char *)0;
+         else
+           match = STREQN (p->command, name, wl);
+
+         if (match == 0)
+           {
+             p = p->next;
+             continue;
+           }
+         else if (flags & JM_FIRSTMATCH)
+           return i;           /* return first match */
+         else if (job != NO_JOB)
+           {
+             if (this_shell_builtin)
+               builtin_error ("%s: ambiguous job spec", name);
+             else
+               report_error ("%s: ambiguous job spec", name);
+             return (DUP_JOB);
+           }
+         else
+           job = i;
+        }
+      while (p != jobs[i]->pipe);
+    }
+
+  return (job);
+}
+
 /* Return the job spec found in LIST. */
 int
 get_job_spec (list)
      WORD_LIST *list;
 {
   register char *word;
-  int job, substring_search;
+  int job, jflags;
 
   if (list == 0)
     return (current_job);
@@ -482,10 +573,14 @@ get_job_spec (list)
   if (DIGIT (*word) && all_digits (word))
     {
       job = atoi (word);
+#if 0
       return (job >= job_slots ? NO_JOB : job - 1);
+#else
+      return (job > job_slots ? NO_JOB : job - 1);
+#endif
     }
 
-  substring_search = 0;
+  jflags = 0;
   switch (*word)
     {
     case 0:
@@ -497,43 +592,12 @@ get_job_spec (list)
       return (previous_job);
 
     case '?':                  /* Substring search requested. */
-      substring_search++;
+      jflags |= JM_SUBSTRING;
       word++;
       /* FALLTHROUGH */
 
     default:
-      {
-       register int i, wl;
-
-       job = NO_JOB;
-       wl = strlen (word);
-       for (i = 0; i < job_slots; i++)
-         {
-           if (jobs[i])
-             {
-               register PROCESS *p;
-               p = jobs[i]->pipe;
-               do
-                 {
-                   if ((substring_search && strindex (p->command, word)) ||
-                       (STREQN (p->command, word, wl)))
-                     {
-                       if (job != NO_JOB)
-                         {
-                           builtin_error ("ambigious job spec: %s", word);
-                           return (DUP_JOB);
-                         }
-                       else
-                         job = i;
-                     }
-
-                   p = p->next;
-                 }
-               while (p != jobs[i]->pipe);
-             }
-         }
-       return (job);
-      }
+      return get_job_by_name (word, jflags);
     }
 }
 #endif /* JOB_CONTROL */
@@ -546,7 +610,8 @@ display_signal_list (list, forcecols)
   register int i, column;
   char *name;
   int result;
-  long signum;
+  int signum;
+  intmax_t lsignum;
 
   result = EXECUTION_SUCCESS;
   if (!list)
@@ -581,20 +646,21 @@ display_signal_list (list, forcecols)
   /* List individual signal names or numbers. */
   while (list)
     {
-      if (legal_number (list->word->word, &signum))
+      if (legal_number (list->word->word, &lsignum))
        {
          /* This is specified by Posix.2 so that exit statuses can be
             mapped into signal numbers. */
-         if (signum > 128)
-           signum -= 128;
-         if (signum < 0 || signum >= NSIG)
+         if (lsignum > 128)
+           lsignum -= 128;
+         if (lsignum < 0 || lsignum >= NSIG)
            {
-             builtin_error ("bad signal number: %s", list->word->word);
+             sh_invalidsig (list->word->word);
              result = EXECUTION_FAILURE;
              list = list->next;
              continue;
            }
 
+         signum = lsignum;
          name = signal_name (signum);
          if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
            {
@@ -614,12 +680,12 @@ display_signal_list (list, forcecols)
          signum = decode_signal (list->word->word);
          if (signum == NO_SIG)
            {
-             builtin_error ("%s: not a signal specification", list->word->word);
+             sh_invalidsig (list->word->word);
              result = EXECUTION_FAILURE;
              list = list->next;
              continue;
            }
-         printf ("%ld\n", signum);
+         printf ("%d\n", signum);
        }
       list = list->next;
     }
index dbebeda0ff7c9fa101b6b4424ac7f803e5e4fbe3..a971bcda247d14719696ecacb6f7d0fd788a079a 100644 (file)
@@ -1,6 +1,6 @@
 /* common.h -- extern declarations for functions defined in common.c. */
 
-/* Copyright (C) 1993 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 #define ISOPTION(s, c) (s[0] == '-' && !s[2] && s[1] == c)
 
 /* Flag values for parse_and_execute () */
-#define SEVAL_NONINT   0x01
-#define SEVAL_INTERACT 0x02
-#define SEVAL_NOHIST   0x04
+#define SEVAL_NONINT   0x001
+#define SEVAL_INTERACT 0x002
+#define SEVAL_NOHIST   0x004
+#define SEVAL_NOFREE   0x008
+
+/* Flags for describe_command, shared between type.def and command.def */
+#define CDESC_ALL              0x001   /* type -a */
+#define CDESC_SHORTDESC                0x002   /* command -V */
+#define CDESC_REUSABLE         0x004   /* command -v */
+#define CDESC_TYPE             0x008   /* type -t */
+#define CDESC_PATH_ONLY                0x010   /* type -p */
+#define CDESC_FORCE_PATH       0x020   /* type -ap or type -P */
+#define CDESC_NOFUNCS          0x040   /* type -f */
+
+/* Flags for get_job_by_name */
+#define JM_PREFIX              0x01    /* prefix of job name */
+#define JM_SUBSTRING           0x02    /* substring of job name */
+#define JM_EXACT               0x04    /* match job name exactly */
+#define JM_STOPPED             0x08    /* match stopped jobs only */
+#define JM_FIRSTMATCH          0x10    /* return first matching job */
+
+/* Flags for remember_args and value of changed_dollar_vars */
+#define ARGS_NONE              0x0
+#define ARGS_INVOC             0x01
+#define ARGS_FUNC              0x02
+#define ARGS_SETBLTIN          0x04
 
 /* Functions from common.c */
 extern void builtin_error __P((const char *, ...))  __attribute__((__format__ (printf, 1, 2)));
 extern void builtin_usage __P((void));
 extern void no_args __P((WORD_LIST *));
-extern void bad_option __P((char *));
 extern int no_options __P((WORD_LIST *));
 
+/* common error message functions */
+extern void sh_needarg __P((char *));
+extern void sh_neednumarg __P((char *));
+extern void sh_notfound __P((char *));
+extern void sh_invalidopt __P((char *));
+extern void sh_invalidoptname __P((char *));
+extern void sh_invalidid __P((char *));
+extern void sh_invalidnum __P((char *));
+extern void sh_invalidsig __P((char *));
+extern void sh_erange __P((char *, char *));
+extern void sh_badpid __P((char *));
+extern void sh_badjob __P((char *));
+extern void sh_readonly __P((const char *));
+extern void sh_nojobs __P((char *));
+extern void sh_restricted __P((char *));
+
 extern char **make_builtin_argv __P((WORD_LIST *, int *));
 extern void remember_args __P((WORD_LIST *, int));
 
-extern void push_context __P((void));
-extern void pop_context __P((void));
-extern void push_dollar_vars __P((void));
-extern void pop_dollar_vars __P((void));
-extern void dispose_saved_dollar_vars __P((void));
 extern int dollar_vars_changed __P((void));
 extern void set_dollar_vars_unchanged __P((void));
 extern void set_dollar_vars_changed __P((void));
 
-extern long get_numeric_arg __P((WORD_LIST *, int));
+extern intmax_t get_numeric_arg __P((WORD_LIST *, int));
 extern int get_exitstat __P((WORD_LIST *));
 extern int read_octal __P((char *));
 
@@ -59,6 +92,7 @@ extern char *get_working_directory __P((char *));
 extern void set_working_directory __P((char *));
 
 #if defined (JOB_CONTROL)
+extern int get_job_by_name __P((const char *, int));
 extern int get_job_spec __P((WORD_LIST *));
 #endif
 extern int display_signal_list __P((WORD_LIST *, int));
@@ -96,7 +130,7 @@ extern int shopt_listopt __P((char *, int));
 extern int set_login_shell __P((int));
 
 /* Functions from type.def */
-extern int describe_command __P((char *, int, int));
+extern int describe_command __P((char *, int));
 
 /* Functions from setattr.def */
 extern int set_or_show_attributes __P((WORD_LIST *, int, int));
@@ -106,8 +140,8 @@ extern void set_var_attribute __P((char *, int, int));
 
 /* Functions from pushd.def */
 extern char *get_dirstack_from_string __P((char *));
-extern char *get_dirstack_element __P((long, int));
-extern void set_dirstack_element __P((long, int, char *));
+extern char *get_dirstack_element __P((intmax_t, int));
+extern void set_dirstack_element __P((intmax_t, int, char *));
 extern WORD_LIST *get_directory_stack __P((void));
 
 /* Functions from evalstring.c */
index 732ba03682af24f7751cf3003d52be119542f8aa..f39162048ffce730946d2900a676824c857c4c62 100644 (file)
@@ -1,7 +1,7 @@
 This file is complete.def, from which is created complete.c.
 It implements the builtins "complete" and "compgen" in Bash.
 
-Copyright (C) 1999 Free Software Foundation, Inc.
+Copyright (C) 1999-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -24,7 +24,7 @@ $PRODUCES complete.c
 $BUILTIN complete
 $DEPENDS_ON PROGRAMMABLE_COMPLETION
 $FUNCTION complete_builtin
-$SHORT_DOC complete [-abcdefgjkvu] [-pr] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [name ...]
+$SHORT_DOC complete [-abcdefgjksuv] [-pr] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [name ...]
 For each NAME, specify how arguments are to be completed.
 If the -p option is supplied, or if no options are supplied, existing
 completion specifications are printed in a way that allows them to be
@@ -62,11 +62,12 @@ static int build_actions __P((WORD_LIST *, int *, int *, unsigned long *, unsign
 
 static int remove_cmd_completions __P((WORD_LIST *));
 
-static void print_one_completion __P((char *, COMPSPEC *));
+static int print_one_completion __P((char *, COMPSPEC *));
+static int print_compitem __P((BUCKET_CONTENTS *));
 static void print_all_completions __P((void));
 static int print_cmd_completions __P((WORD_LIST *));
 
-static char *Aarg, *Garg, *Warg, *Parg, *Sarg, *Xarg, *Farg, *Carg;
+static char *Garg, *Warg, *Parg, *Sarg, *Xarg, *Farg, *Carg;
 
 static struct _compacts {
   char *actname;
@@ -90,6 +91,7 @@ static struct _compacts {
   { "job",       CA_JOB,       'j' },
   { "keyword",   CA_KEYWORD,   'k' },
   { "running",   CA_RUNNING,    0 },
+  { "service",   CA_SERVICE,   's' },
   { "setopt",    CA_SETOPT,     0 },
   { "shopt",     CA_SHOPT,      0 },
   { "signal",    CA_SIGNAL,     0 },
@@ -99,6 +101,7 @@ static struct _compacts {
   { (char *)NULL, 0, 0 },
 };
 
+/* This should be a STRING_INT_ALIST */
 static struct _compopt {
   char *optname;
   int optflag;
@@ -106,6 +109,7 @@ static struct _compopt {
   { "default", COPT_DEFAULT },
   { "dirnames", COPT_DIRNAMES },
   { "filenames",COPT_FILENAMES},
+  { "nospace", COPT_NOSPACE },
   { (char *)NULL, 0 },
 };
 
@@ -160,7 +164,7 @@ build_actions (list, pp, rp, actp, optp)
   opt_given = 0;
 
   reset_internal_getopt ();
-  while ((opt = internal_getopt (list, "abcdefgjko:pruvA:G:W:P:S:X:F:C:")) != -1)
+  while ((opt = internal_getopt (list, "abcdefgjko:prsuvA:G:W:P:S:X:F:C:")) != -1)
     {
       opt_given = 1;
       switch (opt)
@@ -173,7 +177,7 @@ build_actions (list, pp, rp, actp, optp)
            }
          else
            {
-             builtin_error ("illegal option: -r");
+             sh_invalidopt ("-r");
              builtin_usage ();
              return (EX_USAGE);
            }
@@ -186,7 +190,7 @@ build_actions (list, pp, rp, actp, optp)
            }
          else
            {
-             builtin_error ("illegal option: -p");
+             sh_invalidopt ("-p");
              builtin_usage ();
              return (EX_USAGE);
            }
@@ -218,6 +222,9 @@ build_actions (list, pp, rp, actp, optp)
        case 'k':
          acts |= CA_KEYWORD;
          break;
+       case 's':
+         acts |= CA_SERVICE;
+         break;
        case 'u':
          acts |= CA_USER;
          break;
@@ -228,7 +235,7 @@ build_actions (list, pp, rp, actp, optp)
          ind = find_compopt (list_optarg);
          if (ind < 0)
            {
-             builtin_error ("%s: invalid option name", list_optarg);
+             sh_invalidoptname (list_optarg);
              return (EX_USAGE);
            }
          copts |= compopts[ind].optflag;
@@ -282,7 +289,6 @@ complete_builtin (list)
 {
   int opt_given, pflag, rflag, rval;
   unsigned long acts, copts;
-  char *cmd;
   COMPSPEC *cs;
 
   if (list == 0)
@@ -293,7 +299,7 @@ complete_builtin (list)
 
   opt_given = pflag = rflag = 0;
   acts = copts = (unsigned long)0L;
-  Aarg = Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
+  Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
   cs = (COMPSPEC *)NULL;
 
   /* Build the actions from the arguments.  Also sets the [A-Z]arg variables
@@ -321,7 +327,7 @@ complete_builtin (list)
     {
       if (list == 0)
        {
-         clear_progcomps ();
+         progcomp_flush ();
          return (EXECUTION_SUCCESS);
        }
       return (remove_cmd_completions (list));
@@ -335,7 +341,7 @@ complete_builtin (list)
 
   /* If we get here, we need to build a compspec and add it for each
      remaining argument. */
-  cs = alloc_compspec ();
+  cs = compspec_create ();
   cs->actions = acts;
   cs->options = copts;
 
@@ -350,8 +356,7 @@ complete_builtin (list)
   for (rval = EXECUTION_SUCCESS ; list; list = list->next)
     {
       /* Add CS as the compspec for the specified commands. */
-      cmd = list->word->word;
-      if (add_progcomp (cmd, cs) == 0)
+      if (progcomp_insert (list->word->word, cs) == 0)
        rval = EXECUTION_FAILURE;
     }
 
@@ -367,7 +372,7 @@ remove_cmd_completions (list)
 
   for (ret = EXECUTION_SUCCESS, l = list; l; l = l->next)
     {
-      if (remove_progcomp (l->word->word) == 0)
+      if (progcomp_remove (l->word->word) == 0)
        {
          builtin_error ("%s: no completion specification", l->word->word);
          ret = EXECUTION_FAILURE;
@@ -410,7 +415,7 @@ remove_cmd_completions (list)
       printf ("-o %s ", f); \
   } while (0)
 
-static void
+static int
 print_one_completion (cmd, cs)
      char *cmd;
      COMPSPEC *cs;
@@ -426,6 +431,7 @@ print_one_completion (cmd, cs)
   PRINTCOMPOPT (COPT_DEFAULT, "default");
   PRINTCOMPOPT (COPT_DIRNAMES, "dirnames");
   PRINTCOMPOPT (COPT_FILENAMES, "filenames");
+  PRINTCOMPOPT (COPT_NOSPACE, "nospace");
 
   acts = cs->actions;
 
@@ -437,8 +443,9 @@ print_one_completion (cmd, cs)
   PRINTOPT (CA_EXPORT, "-e");
   PRINTOPT (CA_FILE, "-f");
   PRINTOPT (CA_GROUP, "-g");
-  PRINTOPT (CA_KEYWORD, "-k");
   PRINTOPT (CA_JOB, "-j");
+  PRINTOPT (CA_KEYWORD, "-k");
+  PRINTOPT (CA_SERVICE, "-s");
   PRINTOPT (CA_USER, "-u");
   PRINTOPT (CA_VARIABLE, "-v");
 
@@ -470,12 +477,27 @@ print_one_completion (cmd, cs)
   PRINTARG (cs->command, "-C");
 
   printf ("%s\n", cmd);
+
+  return (0);
+}
+
+static int
+print_compitem (item)
+     BUCKET_CONTENTS *item;
+{
+  COMPSPEC *cs;
+  char *cmd;
+
+  cmd = item->key;
+  cs = (COMPSPEC *)item->data;
+
+  return (print_one_completion (cmd, cs));
 }
 
 static void
 print_all_completions ()
 {
-  print_all_compspecs (print_one_completion);
+  progcomp_walk (print_compitem);
 }
 
 static int
@@ -488,7 +510,7 @@ print_cmd_completions (list)
 
   for (ret = EXECUTION_SUCCESS, l = list; l; l = l->next)
     {
-      cs = find_compspec (l->word->word);
+      cs = progcomp_search (l->word->word);
       if (cs)
        print_one_completion (l->word->word, cs);
       else
@@ -503,7 +525,7 @@ print_cmd_completions (list)
 $BUILTIN compgen
 $DEPENDS_ON PROGRAMMABLE_COMPLETION
 $FUNCTION compgen_builtin
-$SHORT_DOC compgen [-abcdefgjkvu] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [word]
+$SHORT_DOC compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-P prefix] [-S suffix] [-X filterpat] [-F function] [-C command] [word]
 Display the possible completions depending on the options.  Intended
 to be used from within a shell function generating possible completions.
 If the optional WORD argument is supplied, matches against WORD are
@@ -524,7 +546,7 @@ compgen_builtin (list)
     return (EXECUTION_SUCCESS);
 
   acts = copts = (unsigned long)0L;
-  Aarg = Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
+  Garg = Warg = Parg = Sarg = Xarg = Farg = Carg = (char *)NULL;
   cs = (COMPSPEC *)NULL;
 
   /* Build the actions from the arguments.  Also sets the [A-Z]arg variables
@@ -545,7 +567,7 @@ compgen_builtin (list)
     internal_warning ("compgen: -C option may not work as you expect");
 
   /* If we get here, we need to build a compspec and evaluate it. */
-  cs = alloc_compspec ();
+  cs = compspec_create ();
   cs->actions = acts;
   cs->options = copts;
   cs->refcount = 1;
@@ -569,7 +591,7 @@ compgen_builtin (list)
 
       matches = rl_completion_matches (word, rl_filename_completion_function);
       sl = completions_to_stringlist (matches);
-      free_array (matches);
+      strvec_dispose (matches);
     }
 
   if (sl)
@@ -577,11 +599,11 @@ compgen_builtin (list)
       if (sl->list && sl->list_len)
        {
          rval = EXECUTION_SUCCESS;
-         print_stringlist (sl, (char *)NULL);
+         strlist_print (sl, (char *)NULL);
        }
-      free_stringlist (sl);
+      strlist_dispose (sl);
     }
 
-  free_compspec (cs);
+  compspec_dispose (cs);
   return (rval);
 }
index 98f1cb1eebba2700176201f63e962dcbfb1cef23..75b154f8fce65416a0c6029214a210eb470d8bb3 100644 (file)
@@ -1,7 +1,7 @@
 This file is declare.def, from which is created declare.c.
 It implements the builtins "declare" and "local" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -23,7 +23,7 @@ $PRODUCES declare.c
 
 $BUILTIN declare
 $FUNCTION declare_builtin
-$SHORT_DOC declare [-afFrxi] [-p] name[=value] ...
+$SHORT_DOC declare [-afFirtx] [-p] name[=value] ...
 Declare variables and/or give them attributes.  If no NAMEs are
 given, then display the values of variables instead.  The -p option
 will display the attributes and values of each NAME.
@@ -33,9 +33,10 @@ The flags are:
   -a   to make NAMEs arrays (if supported)
   -f   to select from among function names only
   -F   to display function names without definitions
+  -i   to make NAMEs have the `integer' attribute
   -r   to make NAMEs readonly
+  -t   to make NAMEs have the `trace' attribute
   -x   to make NAMEs export
-  -i   to make NAMEs have the `integer' attribute set
 
 Variables with the integer attribute have arithmetic evaluation (see
 `let') done when the variable is assigned to.
@@ -50,7 +51,7 @@ $END
 
 $BUILTIN typeset
 $FUNCTION declare_builtin
-$SHORT_DOC typeset [-afFrxi] [-p] name[=value] ...
+$SHORT_DOC typeset [-afFirtx] [-p] name[=value] ...
 Obsolete.  See `declare'.
 $END
 
@@ -70,6 +71,7 @@ $END
 #include "../shell.h"
 #include "common.h"
 #include "builtext.h"
+#include "bashgetopt.h"
 
 extern int array_needs_making;
 
@@ -103,66 +105,70 @@ local_builtin (list)
     }
 }
 
+#if defined (ARRAY_VARS)
+#  define DECLARE_OPTS "+afiprtxF"
+#else
+#  define DECLARE_OPTS "+fiprtxF"
+#endif
+
 /* The workhorse function. */
 static int
 declare_internal (list, local_var)
      register WORD_LIST *list;
      int local_var;
 {
-  int flags_on, flags_off, *flags, any_failed, assign_error, pflag, nodefs;
+  int flags_on, flags_off, *flags, any_failed, assign_error, pflag, nodefs, opt;
   char *t, *subscript_start;
   SHELL_VAR *var;
 
   flags_on = flags_off = any_failed = assign_error = pflag = nodefs = 0;
-  while (list)
+  reset_internal_getopt ();
+  while ((opt = internal_getopt (list, DECLARE_OPTS)) != EOF)
     {
-      t = list->word->word;
-      if (t[0] == '-' && t[1] == '-' && t[2] == '\0')
-       {
-         list = list->next;
-         break;
-       }
-
-      if (*t != '+' && *t != '-')
-       break;
+      flags = list_opttype == '+' ? &flags_off : &flags_on;
 
-      flags = (*t++ == '+') ? &flags_off : &flags_on;
-
-      while (*t)
+      switch (opt)
        {
-         if (*t == 'p' && local_var == 0)
-           pflag++, t++;
-         else if (*t == 'F')
-           {
-             nodefs++;
-             *flags |= att_function; t++;
-           }
-         else if (*t == 'f')
-           *flags |= att_function, t++;
-         else if (*t == 'x')
-           *flags |= att_exported, t++, array_needs_making = 1;
-         else if (*t == 'r')
-           *flags |= att_readonly, t++;
-         else if (*t == 'i')
-           *flags |= att_integer, t++;
+       case 'a':
 #if defined (ARRAY_VARS)
-         else if (*t == 'a')
-           *flags |= att_array, t++;
+         *flags |= att_array;
 #endif
-         else
-           {
-             builtin_error ("unknown option: `-%c'", *t);
-             builtin_usage ();
-             return (EX_USAGE);
-           }
+         break;
+       case 'p':
+         if (local_var == 0)
+           pflag++;
+         break;
+        case 'F':
+         nodefs++;
+         *flags |= att_function;
+         break;
+       case 'f':
+         *flags |= att_function;
+         break;
+       case 'i':
+         *flags |= att_integer;
+         break;
+       case 'r':
+         *flags |= att_readonly;
+         break;
+       case 't':
+         *flags |= att_trace;
+         break;
+       case 'x':
+         *flags |= att_exported;
+         array_needs_making = 1;
+         break;
+       default:
+         builtin_usage ();
+         return (EX_USAGE);
        }
-
-      list = list->next;
     }
 
+  list = loptend;
+
   /* If there are no more arguments left, then we just want to show
      some variables. */
-  if (list == 0)       /* declare -[afFirx] */
+  if (list == 0)       /* declare -[afFirtx] */
     {
       /* Show local variables defined at this context level if this is
         the `local' builtin. */
@@ -171,7 +177,7 @@ declare_internal (list, local_var)
          register SHELL_VAR **vlist;
          register int i;
 
-         vlist = map_over (variable_in_context, shell_variables);
+         vlist = all_local_variables ();
 
          if (vlist)
            {
@@ -193,14 +199,14 @@ declare_internal (list, local_var)
       return (EXECUTION_SUCCESS);
     }
 
-  if (pflag)   /* declare -p [-afFirx] name [name...] */
+  if (pflag)   /* declare -p [-afFirtx] name [name...] */
     {
       for (any_failed = 0; list; list = list->next)
        {
          pflag = show_name_attributes (list->word->word, nodefs);
          if (pflag)
            {
-             builtin_error ("%s: not found", list->word->word);
+             sh_notfound (list->word->word);
              any_failed++;
            }
        }
@@ -244,7 +250,7 @@ declare_internal (list, local_var)
        
       if (legal_identifier (name) == 0)
        {
-         builtin_error ("`%s': not a valid identifier", name);
+         sh_invalidid (name);
          assign_error++;
          NEXT_VARIABLE ();
        }
@@ -253,7 +259,10 @@ declare_internal (list, local_var)
         inside of a function.  This means we should make local variables,
         not global ones. */
 
-      if (variable_context)
+      /* XXX - this has consequences when we're making a local copy of a
+              variable that was in the temporary environment.  Watch out
+              for this. */
+      if (variable_context && ((flags_on & att_function) == 0))
        {
 #if defined (ARRAY_VARS)
          if ((flags_on & att_array) || making_array_special)
@@ -267,6 +276,8 @@ declare_internal (list, local_var)
              NEXT_VARIABLE ();
            }
        }
+      else
+       var = (SHELL_VAR *)NULL;
 
       /* If we are declaring a function, then complain about it in some way.
         We don't let people make functions by saying `typeset -f foo=bar'. */
@@ -315,7 +326,9 @@ declare_internal (list, local_var)
        }
       else             /* declare -[airx] name [name...] */
        {
-         var = find_variable (name);
+         /* Non-null if we just created or fetched a local variable. */
+         if (var == 0)
+           var = find_variable (name);
 
          if (var == 0)
            {
@@ -330,7 +343,7 @@ declare_internal (list, local_var)
          /* Cannot use declare +r to turn off readonly attribute. */ 
          if (readonly_p (var) && (flags_off & att_readonly))
            {
-             builtin_error ("%s: readonly variable", name);
+             sh_readonly (name);
              any_failed++;
              NEXT_VARIABLE ();
            }
@@ -340,7 +353,7 @@ declare_internal (list, local_var)
          if ((readonly_p (var) || noassign_p (var)) && offset)
            {
              if (readonly_p (var))
-               builtin_error ("%s: readonly variable", name);
+               sh_readonly (name);
              assign_error++;
              NEXT_VARIABLE ();
            }
@@ -394,12 +407,27 @@ declare_internal (list, local_var)
             `var=value declare -x var', make sure it is treated identically
             to `var=value export var'.  Do the same for `declare -r' and
             `readonly'.  Preserve the attributes, except for att_tempvar. */
+         /* XXX -- should this create a variable in the global scope, or
+            modify the local variable flags?  ksh93 has it modify the
+            global scope.
+            Need to handle case like in set_var_attribute where a temporary
+            variable is in the same table as the function local vars. */
          if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
            {
              SHELL_VAR *tv;
-             tv = bind_variable (var->name, var->value ? var->value : "");
-             tv->attributes = var->attributes & ~att_tempvar;
-             dispose_variable (var);
+             char *tvalue;
+
+             tv = find_tempenv_variable (var->name);
+             if (tv)
+               {
+                 tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
+                 tv = bind_variable (var->name, tvalue);
+                 tv->attributes |= var->attributes & ~att_tempvar;
+                 if (tv->context > 0)
+                   VSETATTR (tv, att_propagate);
+                 free (tvalue);
+               }
+             VSETATTR (var, att_propagate);
            }
        }
 
index e1015b33fbd8756ea683552209d90a2b9321eae6..07e9f247bf9431889e39505740e08eb8fa0f535c 100644 (file)
@@ -1,7 +1,7 @@
 This file is echo.def, from which is created echo.c.
 It implements the builtin "echo" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
index 50b4dc7a37b80ddf68f2e9a64ef319855738db03..7496d42792171087e2a956efa1bf589eda0dfd13 100644 (file)
@@ -1,7 +1,7 @@
 This file is enable.def, from which is created enable.c.
 It implements the builtin "enable" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -146,7 +146,7 @@ enable_builtin (list)
   /* Restricted shells cannot load new builtins. */
   if (restricted && (flags & (FFLAG|DFLAG)))
     {
-      builtin_error ("restricted");
+      sh_restricted ((char *)NULL);
       return (EXECUTION_FAILURE);
     }
 #endif
@@ -246,6 +246,13 @@ enable_shell_command (name, disable_p)
 
   if (disable_p)
     b->flags &= ~BUILTIN_ENABLED;
+#if defined (RESTRICTED_SHELL)
+  else if (restricted && ((b->flags & BUILTIN_ENABLED) == 0))
+    {
+      sh_restricted ((char *)NULL);
+      return (EXECUTION_FAILURE);
+    }
+#endif
   else
     b->flags |= BUILTIN_ENABLED;
 
@@ -453,7 +460,7 @@ dyn_unload_builtin (name)
      using it drops to zero. */
   if (ref == 1 && local_dlclose (handle) != 0)
     {
-      builtin_error ("cannot delete %s: %s", name, dlerror ());
+      builtin_error ("%s: cannot delete: %s", name, dlerror ());
       return (EXECUTION_FAILURE);
     }
 
index db48e1297eea4d993dd3bcd64dd4d4b7810f6f26..500e8c7304875fff022d6976440ba24c44d262dc 100644 (file)
@@ -1,7 +1,7 @@
 This file is eval.def, from which is created eval.c.
 It implements the builtin "eval" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -46,6 +46,7 @@ eval_builtin (list)
 {
   if (no_options (list))
     return (EX_USAGE);
+  list = loptend;      /* skip over possible `--' */
 
   /* Note that parse_and_execute () frees the string it is passed. */
   return (list ? parse_and_execute (string_list (list), "eval", SEVAL_NOHIST) : EXECUTION_SUCCESS);
index f3342215dde39e35aeb37a73131e38edd6a8b190..0675753ec8b597d43d95b39985f84e116dd07ed9 100644 (file)
@@ -216,7 +216,7 @@ maybe_execute_file (fname, force_noninteractive)
   char *filename;
   int result, flags;
 
-  filename = bash_tilde_expand (fname);
+  filename = bash_tilde_expand (fname, 0);
   flags = FEVAL_ENOENTOK;
   if (force_noninteractive)
     flags |= FEVAL_NONINT;
index b164e744ed10c20c8d13e30961b0e6156774a174..860a3de868a7b4536183c39e82e710670e121405 100644 (file)
@@ -83,6 +83,7 @@ parse_and_execute_cleanup ()
        (flags & SEVAL_NONINT) -> interactive = 0;
        (flags & SEVAL_INTERACT) -> interactive = 1;
        (flags & SEVAL_NOHIST) -> call bash_history_disable ()
+       (flags & SEVAL_NOFREE) -> don't free STRING when finished
 */
 
 int
@@ -123,7 +124,7 @@ parse_and_execute (string, from_file, flags)
     }
   
   add_unwind_protect (pop_stream, (char *)NULL);
-  if (orig_string)
+  if (orig_string && ((flags & SEVAL_NOFREE) == 0))
     add_unwind_protect (xfree, orig_string);
   end_unwind_frame ();
 
@@ -320,23 +321,7 @@ cat_file (r)
       return -1;
     }
 
-  rval = 0;
-  while (1)
-    {
-      nr = zread (fd, lbuf, sizeof(lbuf));
-      if (nr == 0)
-       break;
-      else if (nr < 0)
-       {
-         rval = -1;
-         break;
-       }
-      if (zwrite (1, lbuf, nr) < 0)
-       {
-         rval = -1;
-         break;
-       }
-    }
+  rval = zcatfd (fd, 1, fn);
 
   free (fn);
   close (fd);
index c7137e373d8f1bc44095773e3007a0f36d9b98d8..a6881b88c79092ed755fb4c9cde3f6833abbdf83 100644 (file)
@@ -1,7 +1,7 @@
 This file is exec.def, from which is created exec.c.
 It implements the builtin "exec" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -127,19 +127,19 @@ exec_builtin (list)
 #if defined (RESTRICTED_SHELL)
   if (restricted)
     {
-      builtin_error ("restricted");
+      sh_restricted ((char *)NULL);
       return (EXECUTION_FAILURE);
     }
 #endif /* RESTRICTED_SHELL */
 
-  args = word_list_to_argv (list, 1, 0, (int *)NULL);
+  args = strvec_from_word_list (list, 1, 0, (int *)NULL);
 
   /* A command with a slash anywhere in its name is not looked up in $PATH. */
   command = absolute_program (args[0]) ? args[0] : search_for_command (args[0]);
 
   if (command == 0)
     {
-      builtin_error ("%s: not found", args[0]);
+      sh_notfound (args[0]);
       exit_value = EX_NOTFOUND;        /* As per Posix.2, 3.14.6 */
       goto failed_exec;
     }
@@ -215,10 +215,10 @@ failed_exec:
     exit_shell (exit_value);
 
   if (args)
-    free_array (args);
+    strvec_dispose (args);
 
   initialize_traps ();
-  reinitialize_signals ();
+  initialize_signals (1);
 
 #if defined (JOB_CONTROL)
   restart_job_control ();
index 54b6760d38c2d93d1bae885f97616f036afeaac5..bf1d9205ca64da18bad568c7404a2155ba8b0073 100644 (file)
@@ -1,7 +1,7 @@
 This file is exit.def, from which is created exit.c.
 It implements the builtins "exit", and "logout" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -119,7 +119,8 @@ exit_or_logout (list)
 
   /* Get return value if present.  This means that you can type
      `logout 5' to a shell, and it returns 5. */
-  exit_value = list ? get_exitstat (list) : last_command_exit_value;
+
+  exit_value = get_exitstat (list);
 
   /* Run our `~/.bash_logout' file if it exists, and this is a login shell. */
   if (login_shell && sourced_logout++ == 0 && subshell_environment == 0)
index af9957968b26a7a555a4b56737db0ff138576770..c300066f77b258be8b5a97a1c79e4fe122e2dcf0 100644 (file)
@@ -1,7 +1,7 @@
 This file is fc.def, from which is created fc.c.
 It implements the builtin "fc" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -239,8 +239,7 @@ fc_builtin (list)
       /* If we have a list of substitutions to do, then reverse it
         to get the replacements in the proper order. */
 
-      if (rlist && rlist->next)
-       rlist = (REPL *)reverse_list ((GENERIC_LIST *) rlist);
+      rlist = REVERSE_LIST (rlist, REPL *);
 
       hlist = history_list ();
 
@@ -313,10 +312,9 @@ fc_builtin (list)
     }
 
   /* We print error messages for line specifications out of range. */
-  if ((histbeg < 0) || (histend < 0) ||
-      (histbeg > last_hist) || (histend > last_hist))
+  if ((histbeg < 0) || (histend < 0))
     {
-      builtin_error ("history specification out of range");
+      sh_erange ((char *)NULL, "history specification");
       return (EXECUTION_FAILURE);
     }
 
@@ -410,7 +408,7 @@ fc_number (list)
   s = list->word->word;
   if (*s == '-')
     s++;
-  return (legal_number (s, (long *)NULL));
+  return (legal_number (s, (intmax_t *)NULL));
 }
 
 /* Return an absolute index into HLIST which corresponds to COMMAND.  If
@@ -457,19 +455,20 @@ fc_gethnum (command, hlist)
       n = atoi (s);
       n *= sign;
 
-      /* Anything specified greater than the last history element that we
-        deal with is an error. */
-      if (n > i + history_base)
-       return (-1);
-
       /* If the value is negative or zero, then it is an offset from
         the current history item. */
       if (n < 0)
-       return (i + n + 1);
+       {
+         n += i + 1;
+         return (n < 0 ? 0 : n);
+       }
       else if (n == 0)
        return (i);
       else
-       return (n - history_base);
+       {
+         n -= history_base;
+         return (i < n ? i : n);
+       }
     }
 
   clen = strlen (command);
index 9d379e8453f78960dcd38d0bea513b5d97d23fce..c16d894d3a4e580875568b943a7463f4a8f25834 100644 (file)
@@ -1,7 +1,7 @@
 This file is fg_bg.def, from which is created fg_bg.c.
 It implements the builtins "bg" and "fg" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -42,6 +42,7 @@ $END
 #include "../shell.h"
 #include "../jobs.h"
 #include "common.h"
+#include "bashgetopt.h"
 
 #if defined (JOB_CONTROL)
 extern char *this_command_name;
@@ -58,12 +59,13 @@ fg_builtin (list)
 
   if (job_control == 0)
     {
-      builtin_error ("no job control");
+      sh_nojobs ((char *)NULL);
       return (EXECUTION_FAILURE);
     }
 
   if (no_options (list))
     return (EX_USAGE);
+  list = loptend;
 
   /* If the last arg on the line is '&', then start this job in the
      background.  Else, fg the job. */
@@ -92,12 +94,13 @@ bg_builtin (list)
 {
   if (job_control == 0)
     {
-      builtin_error ("no job control");
+      sh_nojobs ((char *)NULL);
       return (EXECUTION_FAILURE);
     }
 
   if (no_options (list))
     return (EX_USAGE);
+  list = loptend;
 
   return (fg_bg (list, 0));
 }
@@ -117,7 +120,7 @@ fg_bg (list, foreground)
   if (job < 0 || job >= job_slots || jobs[job] == 0)
     {
       if (job != DUP_JOB)
-       builtin_error ("%s: no such job", list ? list->word->word : "current");
+       sh_badjob (list ? list->word->word : "current");
 
       goto failure;
     }
index 6ea34018136538a2f90b76d68f317684fd4c1144..60c6188af17e0b7bae834ce43661cd1832a2001f 100644 (file)
@@ -75,7 +75,7 @@ int sh_opterr = 1;
 
 int sh_optopt = '?';
 
-/* Set to 1 when we see an illegal option; public so getopts can reset it. */
+/* Set to 1 when we see an invalid option; public so getopts can reset it. */
 int sh_badopt = 0;
 
 /* Scan elements of ARGV (whose length is ARGC) for option characters
@@ -135,15 +135,6 @@ sh_getopt (argc, argv, optstring)
       nextchar = (char *)NULL;
     }
 
-  /* Do the increment of `sh_optind' we deferred because the last option
-     was illegal.  */
-  if (sh_badopt && (nextchar == 0 || *nextchar == '\0'))
-    {
-      sh_badopt = 0;
-      sh_optind++;
-      nextchar = (char *)NULL;
-    }
-
   if (nextchar == 0 || *nextchar == '\0')
     {
       /* If we have done all the ARGV-elements, stop the scan. */
@@ -179,8 +170,13 @@ sh_getopt (argc, argv, optstring)
 
   sh_optopt = c;
 
-  /* If the option is illegal, return an error, but defer updating sh_optind
-     until the next call so $OPTIND is correct. */
+  /* Increment `sh_optind' when we start to process its last character.  */
+  if (nextchar == 0 || *nextchar == '\0')
+    {
+      sh_optind++;
+      nextchar = (char *)NULL;
+    }
+
   if (sh_badopt = (temp == NULL || c == ':'))
     {
       if (sh_opterr)
@@ -189,13 +185,6 @@ sh_getopt (argc, argv, optstring)
       return '?';
     }
 
-  /* Increment `sh_optind' when we start to process its last character.  */
-  if (nextchar == 0 || *nextchar == '\0')
-    {
-      sh_optind++;
-      nextchar = (char *)NULL;
-    }
-
   if (temp[1] == ':')
     {
       if (nextchar && *nextchar)
index 0e881d24f3f2573776ed4690940c5fa02ac8b261..a2a82ff45e20bd9e3b30938ac03fa3b507d7727d 100644 (file)
@@ -1,7 +1,7 @@
 This file is getopts.def, from which is created getopts.c.
 It implements the builtin "getopts" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -39,11 +39,11 @@ getopts places that argument into the shell variable OPTARG.
 
 getopts reports errors in one of two ways.  If the first character
 of OPTSTRING is a colon, getopts uses silent error reporting.  In
-this mode, no error messages are printed.  If an illegal option is
+this mode, no error messages are printed.  If an invalid option is
 seen, getopts places the option character found into OPTARG.  If a
 required argument is not found, getopts places a ':' into NAME and
 sets OPTARG to the option character found.  If getopts is not in
-silent mode, and an illegal option is seen, getopts places '?' into
+silent mode, and an invalid option is seen, getopts places '?' into
 NAME and unsets OPTARG.  If a required option is not found, a '?'
 is placed in NAME, OPTARG is unset, and a diagnostic message is
 printed.
@@ -75,11 +75,14 @@ $END
 #include "getopt.h"
 
 #define G_EOF          -1
-#define G_ILLEGAL_OPT  -2
+#define G_INVALID_OPT  -2
 #define G_ARG_MISSING  -3
 
 extern char *this_command_name;
 
+static int getopts_bind_variable __P((char *, char *));
+static int dogetopts __P((int, char **));
+
 /* getopts_reset is magic code for when OPTIND is reset.  N is the
    value that has just been assigned to OPTIND. */
 void
@@ -103,7 +106,7 @@ getopts_bind_variable (name, value)
     }
   else
     {
-      builtin_error ("`%s': not a valid identifier", name);
+      sh_invalidid (name);
       return (EXECUTION_FAILURE);
     }
 }
@@ -112,9 +115,9 @@ getopts_bind_variable (name, value)
    (identical to that of ksh-88).  The special handling is enabled if
    the first character of the option string is a colon; this handling
    disables diagnostic messages concerning missing option arguments
-   and illegal option characters.  The handling is as follows.
+   and invalid option characters.  The handling is as follows.
 
-   ILLEGAL OPTIONS:
+   INVALID OPTIONS:
         name -> "?"
         if (special_error) then
                 OPTARG = option character found
@@ -193,7 +196,7 @@ dogetopts (argc, argv)
        ;
       for (words = rest_of_args; words; words = words->next, i++)
        ;
-      v = alloc_array (i + 1);
+      v = strvec_create (i + 1);
       for (i = 0; i < 10 && dollar_vars[i]; i++)
        v[i] = dollar_vars[i];
       for (words = rest_of_args; words; words = words->next, i++)
@@ -207,7 +210,8 @@ dogetopts (argc, argv)
   if (special_error)
     sh_opterr = old_opterr;
 
-  /* Set the OPTIND variable in any case, to handle "--" skipping. */
+  /* Set the OPTIND variable in any case, to handle "--" skipping.  It's
+     highly unlikely that 14 digits will be too few. */
   if (sh_optind < 10)
     {
       numval[14] = sh_optind + '0';
@@ -228,13 +232,13 @@ dogetopts (argc, argv)
 
   /* If an error occurred, decide which one it is and set the return
      code appropriately.  In all cases, the option character in error
-     is in OPTOPT.  If an illegal option was encountered, OPTARG is
+     is in OPTOPT.  If an invalid option was encountered, OPTARG is
      NULL.  If a required option argument was missing, OPTARG points
      to a NULL string (that is, sh_optarg[0] == 0). */
   if (ret == '?')
     {
       if (sh_optarg == NULL)
-       ret = G_ILLEGAL_OPT;
+       ret = G_INVALID_OPT;
       else if (sh_optarg[0] == '\0')
        ret = G_ARG_MISSING;
     }
@@ -245,9 +249,9 @@ dogetopts (argc, argv)
       return (EXECUTION_FAILURE);
     }
 
-  if (ret == G_ILLEGAL_OPT)
+  if (ret == G_INVALID_OPT)
     {
-      /* Illegal option encountered. */
+      /* Invalid option encountered. */
       ret = getopts_bind_variable (name, "?");
 
       if (special_error)
@@ -257,7 +261,7 @@ dogetopts (argc, argv)
          bind_variable ("OPTARG", strval);
        }
       else
-       makunbound ("OPTARG", shell_variables);
+       unbind_variable ("OPTARG");
 
       return (ret);
     }
@@ -276,7 +280,7 @@ dogetopts (argc, argv)
       else
        {
          ret = getopts_bind_variable (name, "?");
-         makunbound ("OPTARG", shell_variables);
+         unbind_variable ("OPTARG");
        }
       return (ret);
     }                  
index 35d50864eb9407252b1e1f6a6098c7664ebd994c..6e0e347637c56a26c21c597d356c6b8347481e60 100644 (file)
@@ -1,7 +1,7 @@
 This file is hash.def, from which is created hash.c.
 It implements the builtin "hash" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -23,15 +23,17 @@ $PRODUCES hash.c
 
 $BUILTIN hash
 $FUNCTION hash_builtin
-$SHORT_DOC hash [-r] [-p pathname] [-t] [name ...]
+$SHORT_DOC hash [-lr] [-p pathname] [-dt] [name ...]
 For each NAME, the full pathname of the command is determined and
 remembered.  If the -p option is supplied, PATHNAME is used as the
 full pathname of NAME, and no path search is performed.  The -r
-option causes the shell to forget all remembered locations.
+option causes the shell to forget all remembered locations.  The -d
+option causes the shell to forget the remembered location of each NAME.
 If the -t option is supplied the full pathname to which each NAME
 corresponds is printed.  If multiple NAME arguments are supplied with
--t, the NAME is printed before the hashed full pathname.  If no arguments
-are given, information about remembered commands is displayed.
+-t, the NAME is printed before the hashed full pathname.  The -l option
+causes output to be displayed in a format that may be reused as input.
+If no arguments are given, information about remembered commands is displayed.
 $END
 
 #include <config.h>
@@ -60,8 +62,10 @@ extern int dot_found_in_search;
 extern char *this_command_name;
 
 static int add_hashed_command __P((char *, int));
-static int print_hashed_commands __P((void));
-static int list_hashed_filename_targets __P((WORD_LIST *));
+static int print_hash_info __P((BUCKET_CONTENTS *));
+static int print_portable_hash_info __P((BUCKET_CONTENTS *));
+static int print_hashed_commands __P((int));
+static int list_hashed_filename_targets __P((WORD_LIST *, int));
 
 /* Print statistics on the current state of hashed commands.  If LIST is
    not empty, then rehash (or hash in the first place) the specified
@@ -70,7 +74,7 @@ int
 hash_builtin (list)
      WORD_LIST *list;
 {
-  int expunge_hash_table, list_targets, opt;
+  int expunge_hash_table, list_targets, list_portably, delete, opt;
   char *w, *pathname;
 
   if (hashing_enabled == 0)
@@ -79,19 +83,25 @@ hash_builtin (list)
       return (EXECUTION_FAILURE);
     }
 
-  expunge_hash_table = list_targets = 0;
+  expunge_hash_table = list_targets = list_portably = delete = 0;
   pathname = (char *)NULL;
   reset_internal_getopt ();
-  while ((opt = internal_getopt (list, "rp:t")) != -1)
+  while ((opt = internal_getopt (list, "dlp:rt")) != -1)
     {
       switch (opt)
        {
-       case 'r':
-         expunge_hash_table = 1;
+       case 'd':
+         delete = 1;
+         break;
+       case 'l':
+         list_portably = 1;
          break;
        case 'p':
          pathname = list_optarg;
          break;
+       case 'r':
+         expunge_hash_table = 1;
+         break;
        case 't':
          list_targets = 1;
          break;
@@ -105,40 +115,38 @@ hash_builtin (list)
   /* hash -t requires at least one argument. */
   if (list == 0 && list_targets)
     {
-      builtin_error("-t: argument required");
+      sh_needarg ("-t");
       return (EXECUTION_FAILURE);
     }
 
-  /* We want hash -r to be silent, but hash -- to print hashing info.  That
-     is the reason for the test of expunge_hash_table. */
+  /* We want hash -r to be silent, but hash -- to print hashing info, so
+     we test expunge_hash_table. */
   if (list == 0 && expunge_hash_table == 0)
     {
-      if (print_hashed_commands () == 0)
+      if (print_hashed_commands (list_portably) == 0)
        printf ("%s: hash table empty\n", this_command_name);
 
       return (EXECUTION_SUCCESS);
     }
 
   if (expunge_hash_table)
-    flush_hashed_filenames ();
+    phash_flush ();
 
   /* If someone runs `hash -r -t xyz' he will be disappointed. */
   if (list_targets)
-    {
-      return (list_hashed_filename_targets (list));
-    }
+    return (list_hashed_filename_targets (list, list_portably));
       
 #if defined (RESTRICTED_SHELL)
   if (restricted && pathname && strchr (pathname, '/'))
     {
-      builtin_error ("%s: restricted", pathname);
+      sh_restricted (pathname);
       return (EXECUTION_FAILURE);
     }
 #endif
 
   for (opt = EXECUTION_SUCCESS; list; list = list->next)
     {
-      /* Add or rehash the specified commands. */
+      /* Add, remove or rehash the specified commands. */
       w = list->word->word;
       if (pathname)
        {
@@ -152,10 +160,15 @@ hash_builtin (list)
              opt = EXECUTION_FAILURE;
            }
          else
-           remember_filename (w, pathname, 0, 0);
+           phash_insert (w, pathname, 0, 0);
        }
       else if (absolute_program (w))
        continue;
+      else if (delete && phash_remove (w))
+       {
+         sh_notfound (w);
+         opt = EXECUTION_FAILURE;
+       }
       else if (add_hashed_command (w, 0))
        opt = EXECUTION_FAILURE;
     }
@@ -177,51 +190,52 @@ add_hashed_command (w, quiet)
     {
       full_path = find_user_command (w);
       if (full_path && executable_file (full_path))
-       remember_filename (w, full_path, dot_found_in_search, 0);
+       phash_insert (w, full_path, dot_found_in_search, 0);
       else
        {
          if (quiet == 0)
-           builtin_error ("%s: not found", w);
+           sh_notfound (w);
          rv++;
        }
-      if (full_path)
-       free (full_path);
+      FREE (full_path);
     }
   return (rv);
 }
 
 /* Print information about current hashed info. */
 static int
-print_hashed_commands ()
+print_hash_info (item)
+     BUCKET_CONTENTS *item;
 {
-  BUCKET_CONTENTS *item_list;
-  int bucket, any_printed;
-
-  if (hashed_filenames == 0)
-    return (0);
-
-  for (bucket = any_printed = 0; bucket < hashed_filenames->nbuckets; bucket++)
-    {
-      item_list = get_hash_bucket (bucket, hashed_filenames);
-      if (item_list == 0)
-       continue;
+  printf ("%4d\t%s\n", item->times_found, pathdata(item)->path);
+  return 0;
+}
 
-      if (any_printed == 0)
-       {
-         printf ("hits\tcommand\n");
-         any_printed++;
-       }
+static int
+print_portable_hash_info (item)
+     BUCKET_CONTENTS *item;
+{
+  printf ("builtin hash -p %s %s\n", pathdata(item)->path, item->key);
+  return 0;
+}
 
-      for ( ; item_list; item_list = item_list->next)
-       printf ("%4d\t%s\n", item_list->times_found, pathdata(item_list)->path);
+static int
+print_hashed_commands (fmt)
+     int fmt;
+{
+  if (hashed_filenames == 0 || HASH_ENTRIES (hashed_filenames) == 0)
+    return (0);
 
-    }
-  return (any_printed);
+  if (fmt == 0)
+    printf ("hits\tcommand\n");
+  hash_walk (hashed_filenames, fmt ? print_portable_hash_info : print_hash_info);
+  return (1);
 }
 
 static int
-list_hashed_filename_targets (list)
+list_hashed_filename_targets (list, fmt)
      WORD_LIST *list;
+     int fmt;
 {
   int all_found, multiple;
   char *target;
@@ -232,16 +246,21 @@ list_hashed_filename_targets (list)
 
   for (l = list; l; l = l->next)
     {
-      target = find_hashed_filename (l->word->word);
+      target = phash_search (l->word->word);
       if (target == 0)
        {
          all_found = 0;
-         builtin_error ("%s: not found", l->word->word);
+         sh_notfound (l->word->word);
          continue;
        }
-      if (multiple)
-        printf ("%s\t", l->word->word);
-      printf ("%s\n", target);
+      if (fmt)
+       printf ("builtin hash -p %s %s\n", target, l->word->word);
+      else
+       {
+         if (multiple)
+           printf ("%s\t", l->word->word);
+         printf ("%s\n", target);
+       }
     }
 
   return (all_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
index 22181b1e78566be2e6359c1f098fd1c2789f82dd..234307b79eb49c8bcaa46934c811f8b41ad3731f 100644 (file)
@@ -1,7 +1,7 @@
 This file is help.def, from which is created help.c.
 It implements the builtin "help" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -44,6 +44,10 @@ $END
 #  include <unistd.h>
 #endif
 
+#include <errno.h>
+
+#include <filecntl.h>
+
 #include "../shell.h"
 #include "../builtins.h"
 #include "../pathexp.h"
@@ -53,7 +57,12 @@ $END
 #include <glob/strmatch.h>
 #include <glob/glob.h>
 
-static  void show_builtin_command_help __P((void));
+#ifndef errno
+extern int errno;
+#endif
+
+static void show_builtin_command_help __P((void));
+static void show_longdoc __P((int));
 
 /* Print out a list of the known functions in the shell, and what they do.
    If LIST is supplied, print out the list which matches for each pattern
@@ -62,7 +71,7 @@ int
 help_builtin (list)
      WORD_LIST *list;
 {
-  register int i, j;
+  register int i;
   char *pattern, *name;
   int plen, match_found, sflag;
 
@@ -112,8 +121,7 @@ help_builtin (list)
              printf ("%s: %s\n", name, shell_builtins[i].short_doc);
 
              if (sflag == 0)
-               for (j = 0; shell_builtins[i].long_doc[j]; j++)
-                 printf ("    %s\n", shell_builtins[i].long_doc[j]);
+               show_longdoc (i);
 
              match_found++;
            }
@@ -122,7 +130,7 @@ help_builtin (list)
 
   if (match_found == 0)
     {
-      builtin_error ("no help topics match `%s'.  Try `help help'.", pattern);
+      builtin_error ("no help topics match `%s'.  Try `help help' or `man -k %s' or `info %s'.", pattern, pattern, pattern);
       return (EXECUTION_FAILURE);
     }
 
@@ -130,6 +138,35 @@ help_builtin (list)
   return (EXECUTION_SUCCESS);
 }
 
+/* By convention, enforced by mkbuiltins.c, if separate help files are being
+   used, the long_doc array contains one string -- the full pathname of the
+   help file for this builtin.  */
+static void
+show_longdoc (i)
+     int i;
+{
+  register int j;
+  char * const *doc;
+  int fd;
+
+  doc = shell_builtins[i].long_doc;
+
+  if (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL)
+    {
+      fd = open (doc[0], O_RDONLY);
+      if (fd == -1)
+       {
+         builtin_error ("%s: cannot open: %s", doc[0], strerror (errno));
+         return;
+       }
+      zcatfd (fd, 1, doc[0]);
+      close (fd);
+    }
+  else
+    for (j = 0; doc[j]; j++)
+      printf ("    %s\n", doc[j]);
+}
+
 static void
 show_builtin_command_help ()
 {
@@ -140,6 +177,7 @@ show_builtin_command_help ()
 "These shell commands are defined internally.  Type `help' to see this list.\n\
 Type `help name' to find out more about the function `name'.\n\
 Use `info bash' to find out more about the shell in general.\n\
+Use `man -k' or `info' to find out more about commands not in this list.\n\
 \n\
 A star (*) next to a name means that the command is disabled.\n\
 \n");
index df416ae515f925c56f62c4dfe11dcbafb474a11d..7311705d34d31bbe926e99a0e10f7abc57c545a2 100644 (file)
@@ -1,7 +1,7 @@
 This file is history.def, from which is created history.c.
 It implements the builtin "history" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -70,6 +70,8 @@ $END
 extern int errno;
 #endif
 
+extern int current_command_line_count;
+
 static void display_history __P((WORD_LIST *));
 static int delete_histent __P((int));
 static int delete_last_history __P((void));
@@ -89,9 +91,9 @@ int
 history_builtin (list)
      WORD_LIST *list;
 {
-  int flags, opt, result;
+  int flags, opt, result, old_history_lines;
   char *filename, *delete_arg;
-  long delete_offset;
+  intmax_t delete_offset;
 
   flags = 0;
   reset_internal_getopt ();
@@ -168,7 +170,7 @@ history_builtin (list)
          || (delete_offset < history_base)
          || (delete_offset > (history_base + history_length)))
        {
-         builtin_error ("%s: not a valid history position", delete_arg);
+         sh_erange (delete_arg, "history position");
          return (EXECUTION_FAILURE);
        }
       opt = delete_offset;
@@ -197,10 +199,12 @@ history_builtin (list)
   else if (flags & NFLAG)      /* Read `new' history from file. */
     {
       /* Read all of the lines in the file that we haven't already read. */
+      old_history_lines = history_lines_in_file;
       using_history ();
       result = read_history_range (filename, history_lines_in_file, -1);
       using_history ();
       history_lines_in_file = where_history ();
+      history_lines_this_session += history_lines_in_file - old_history_lines;
     }
 
   return (result ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
@@ -215,7 +219,7 @@ display_history (list)
      WORD_LIST *list;
 {
   register int i;
-  long limit;
+  intmax_t limit;
   HIST_ENTRY **hlist;
 
   if (list)
@@ -297,10 +301,28 @@ push_history (list)
 {
   char *s;
 
+  /* Delete the last history entry if it was a single entry added to the
+     history list (generally the `history -s' itself), or if `history -s'
+     is being used in a compound command and the compound command was
+     added to the history as a single element (command-oriented history).
+     If you don't want history -s to remove the compound command from the
+     history, change #if 0 to #if 1 below. */
+#if 0
   if (hist_last_line_added && delete_last_history () == 0)
-    return;
+#else
+  if ((hist_last_line_added || (current_command_line_count > 0 && current_command_first_line_saved && command_oriented_history))
+      && delete_last_history () == 0)
+#endif
+      return;
+
   s = string_list (list);
-  maybe_add_history (s);       /* Obeys HISTCONTROL setting. */
+  /* Call check_add_history with FORCE set to 1 to skip the check against
+     current_command_line_count.  If history -s is used in a compound
+     command, the above code will delete the compound command's history
+     entry and this call will add the line to the history as a separate
+     entry.  Without FORCE=1, if current_command_line_count were > 1, the
+     line would be appended to the entry before the just-deleted entry. */
+  check_add_history (s, 1);    /* obeys HISTCONTROL, HISTIGNORE */
   free (s);
 }
 
index ff068f8319d41cb94d755a779c8ece39ae01e248..094c4b949a89126eebce89701526bc44c41c4a19 100644 (file)
@@ -1,7 +1,7 @@
 This file is inlib.def, from which is created inlib.c.
 It implements the Apollo-specific builtin "inlib" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -51,7 +51,7 @@ inlib_builtin (list)
 
   if (!list)
     {
-      builtin_error ("usage: inlib pathname [pathname...]");
+      builtin_usage ();
       return (EX_USAGE);
     }
 
@@ -64,7 +64,7 @@ inlib_builtin (list)
 
       if (status.all != status_$ok)
        {
-         builtin_error ("inlib failed for %s", list->word->word);
+         builtin_error ("%s: inlib failed", list->word->word);
          return_value = EXECUTION_FAILURE;
        }
 
index f8a2b0081eda9e8101781d14680f5394c41d3e9c..54f50ca32dd6c41a374403b18ed31c51dc7cffd1 100644 (file)
@@ -1,7 +1,7 @@
 This file is jobs.def, from which is created jobs.c.
 It implements the builtins "jobs" and "disown" in Bash.
 
-Copyright (C) 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -98,7 +98,7 @@ jobs_builtin (list)
        case 'x':
          if (form != JLIST_STANDARD)
            {
-             builtin_error ("Other options not allowed with `-x'");
+             builtin_error ("no other options allowed with `-x'");
              return (EXECUTION_FAILURE);
            }
          execute++;
@@ -145,7 +145,7 @@ jobs_builtin (list)
 
       if ((job == NO_JOB) || !jobs || !jobs[job])
        {
-         builtin_error ("no such job %s", list->word->word);
+         sh_badjob (list->word->word);
          any_failed++;
        }
       else if (job != DUP_JOB)
@@ -219,7 +219,7 @@ disown_builtin (list)
 {
   int opt, job, retval, nohup_only, running_jobs, all_jobs;
   sigset_t set, oset;
-  long pid_value;
+  intmax_t pid_value;
 
   nohup_only = running_jobs = all_jobs = 0;
   reset_internal_getopt ();
@@ -263,7 +263,7 @@ disown_builtin (list)
 
       if (job == NO_JOB || jobs == 0 || job < 0 || job >= job_slots || jobs[job] == 0)
        {
-         builtin_error ("%s: no such job", list ? list->word->word : "current");
+         sh_badjob (list ? list->word->word : "current");
          retval = EXECUTION_FAILURE;
        }
       else if (nohup_only)
index d7aba5b6d2fe374632ee56e5ecf9829a559583c0..96b34fcb4acb225f27e00c5c84bb56f95c3d8483 100644 (file)
@@ -1,7 +1,7 @@
 This file is kill.def, from which is created kill.c.
 It implements the builtin "kill" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -73,10 +73,10 @@ int
 kill_builtin (list)
      WORD_LIST *list;
 {
-  int signal, any_succeeded, listing, saw_signal;
+  int sig, any_succeeded, listing, saw_signal;
   char *sigspec, *word;
   pid_t pid;
-  long pid_value;
+  intmax_t pid_value;
 
   if (list == 0)
     {
@@ -85,7 +85,7 @@ kill_builtin (list)
     }
 
   any_succeeded = listing = saw_signal = 0;
-  signal = SIGTERM;
+  sig = SIGTERM;
   sigspec = "TERM";
 
   /* Process options. */
@@ -105,14 +105,14 @@ kill_builtin (list)
            {
              sigspec = list->word->word;
              if (sigspec[0] == '0' && sigspec[1] == '\0')
-               signal = 0;
+               sig = 0;
              else
-               signal = decode_signal (sigspec);
+               sig = decode_signal (sigspec);
              list = list->next;
            }
          else
            {
-             builtin_error ("%s requires an argument", word);
+             sh_needarg (word);
              return (EXECUTION_FAILURE);
            }
        }
@@ -132,7 +132,7 @@ kill_builtin (list)
       else if ((*word == '-') && !saw_signal)
        {
          sigspec = word + 1;
-         signal = decode_signal (sigspec);
+         sig = decode_signal (sigspec);
          saw_signal++;
          list = list->next;
        }
@@ -144,9 +144,9 @@ kill_builtin (list)
     return (display_signal_list (list, 0));
 
   /* OK, we are killing processes. */
-  if (signal == NO_SIG)
+  if (sig == NO_SIG)
     {
-      builtin_error ("bad signal spec `%s'", sigspec);
+      sh_invalidsig (sigspec);
       return (EXECUTION_FAILURE);
     }
 
@@ -163,12 +163,12 @@ kill_builtin (list)
       if (*word == '-')
        word++;
 
-      if (*word && legal_number (word, &pid_value) && (pid_value == (pid_t)pid_value))
+      /* Use the entire argument in case of minus sign presence. */
+      if (*word && legal_number (list->word->word, &pid_value) && (pid_value == (pid_t)pid_value))
        {
-         /* Use the entire argument in case of minus sign presence. */
          pid = (pid_t) pid_value;
 
-         if (kill_pid (pid, signal, 0) < 0)
+         if ((pid < -1 ? kill_pid (-pid, sig, 1) : kill_pid (pid, sig, 0)) < 0)
            goto signal_error;
          else
            any_succeeded++;
@@ -190,7 +190,7 @@ kill_builtin (list)
          if (job < 0 || job >= job_slots || !jobs[job])
            {
              if (job != DUP_JOB)
-               builtin_error ("%s: no such job", list->word->word);
+               sh_badjob (list->word->word);
              UNBLOCK_CHILD (oset);
              CONTINUE_OR_FAIL;
            }
@@ -203,11 +203,11 @@ kill_builtin (list)
 
          UNBLOCK_CHILD (oset);
 
-         if (kill_pid (pid, signal, 1) < 0)
+         if (kill_pid (pid, sig, 1) < 0)
            {
            signal_error:
              if (errno == EINVAL)
-               builtin_error ("Invalid signal %d", signal);
+               sh_invalidsig (sigspec);
              else
                builtin_error ("(%ld) - %s", (long)pid, strerror (errno));
              CONTINUE_OR_FAIL;
@@ -217,7 +217,7 @@ kill_builtin (list)
        }
       else
        {
-         builtin_error ("`%s': not a pid or valid job spec", list->word->word);
+         sh_badpid (list->word->word);
          CONTINUE_OR_FAIL;
        }
     continue_killing:
index 1d8c25e404050239c3df5fec1c5e360194cf4ad6..7c9341ed48758136feb360c50fad15dfedf205c8 100644 (file)
@@ -1,7 +1,7 @@
 This file is let.def, from which is created let.c.
 It implements the builtin "let" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -24,13 +24,16 @@ $FUNCTION let_builtin
 $PRODUCES let.c
 $SHORT_DOC let arg [arg ...]
 Each ARG is an arithmetic expression to be evaluated.  Evaluation
-is done in long integers with no check for overflow, though division
-by 0 is trapped and flagged as an error.  The following list of
-operators is grouped into levels of equal-precedence operators.
+is done in fixed-width integers with no check for overflow, though
+division by 0 is trapped and flagged as an error.  The following
+list of operators is grouped into levels of equal-precedence operators.
 The levels are listed in order of decreasing precedence.
 
+       id++, id--      variable post-increment, post-decrement
+       ++id, --id      variable pre-increment, pre-decrement
        -, +            unary minus, plus
        !, ~            logical and bitwise negation
+       **              exponentiation
        *, /, %         multiplication, division, remainder
        +, -            addition, subtraction
        <<, >>          left and right bitwise shifts
@@ -48,7 +51,7 @@ The levels are listed in order of decreasing precedence.
        &=, ^=, |=      assignment
 
 Shell variables are allowed as operands.  The name of the variable
-is replaced by its value (coerced to a long integer) within
+is replaced by its value (coerced to a fixed-width integer) within
 an expression.  The variable need not have its integer attribute
 turned on to be used in an expression.
 
@@ -77,9 +80,13 @@ int
 let_builtin (list)
      WORD_LIST *list;
 {
-  long ret;
+  intmax_t ret;
   int expok;
 
+  /* Skip over leading `--' argument. */
+  if (list && list->word && ISOPTION (list->word->word, '-'))
+    list = list->next;
+
   if (list == 0)
     {
       builtin_error ("expression expected");
@@ -102,7 +109,8 @@ exp_builtin (list)
      WORD_LIST *list;
 {
   char *exp;
-  int ret, expok;
+  intmax_t ret;
+  int expok;
 
   if (list == 0)
     {
index 753286621bd3a1abdfc60392e0e7e9543518d968..c911f86e2a8fd7c6750f336da53699ddcc6629b1 100644 (file)
@@ -1,7 +1,7 @@
 /* mkbuiltins.c - Create builtins.c, builtext.h, and builtdoc.c from
    a single source file called builtins.def. */
 
-/* Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -38,11 +38,16 @@ Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
 
 #include "../bashansi.h"
 #include <stdio.h>
+#include <errno.h>
 
 #include "stdc.h"
 
 #define DOCFILE "builtins.texi"
 
+#ifndef errno
+extern int errno;
+#endif
+
 static char *xmalloc (), *xrealloc ();
 
 #if !defined (__STDC__) && !defined (strcpy)
@@ -66,9 +71,13 @@ int only_documentation = 0;
 /* Non-zero means to not do any productions. */
 int inhibit_production = 0;
 
-#if !defined (OLDCODE)
-int no_long_document = 0;
-#endif /* !OLDCODE */
+/* Non-zero means to produce separate help files for each builtin, named by
+   the builtin name, in `./helpfiles'. */
+int separate_helpfiles = 0;
+
+/* The name of a directory into which the separate external help files will
+   eventually be installed. */
+char *helpfile_directory;
 
 /* The name of a directory to precede the filename when reporting
    errors. */
@@ -149,11 +158,16 @@ void write_documentation ();
 void write_longdocs ();
 void write_builtins ();
 
+int write_helpfiles ();
+
 void free_defs ();
 void add_documentation ();
 
 void must_be_building ();
 void remove_trailing_whitespace ();
+
+#define document_name(b)       ((b)->docname ? (b)->docname : (b)->name)
+
 \f
 /* For each file mentioned on the command line, process it and
    write the information to STRUCTFILE and EXTERNFILE, while
@@ -204,10 +218,11 @@ main (argc, argv)
          only_documentation = 1;
          documentation_file = fopen (documentation_filename, "w");
        }
-#if !defined (OLDCODE)
-      else if (strcmp (arg, "-nodocument") == 0)
-       no_long_document = 1;
-#endif /* !OLDCODE */  
+      else if (strcmp (arg, "-H") == 0)
+        {
+         separate_helpfiles = 1;
+         helpfile_directory = argv[arg_index++];
+        }
       else
        {
          fprintf (stderr, "%s: Unknown flag %s.\n", argv[0], arg);
@@ -278,6 +293,11 @@ main (argc, argv)
        fclose (externfile);
     }
 
+  if (separate_helpfiles)
+    {
+      write_helpfiles (saved_builtins);
+    }
+
   if (documentation_file)
     {
       fprintf (documentation_file, "@end ftable\n");
@@ -1036,8 +1056,9 @@ save_builtin (builtin)
 }
 
 /* Flags that mean something to write_documentation (). */
-#define STRING_ARRAY 1
-#define TEXINFO 2
+#define STRING_ARRAY   1
+#define TEXINFO                2
+#define PLAINTEXT      4
 
 char *structfile_header[] = {
   "/* builtins.c -- the built in shell commands. */",
@@ -1045,7 +1066,7 @@ char *structfile_header[] = {
   "/* This file is manufactured by ./mkbuiltins, and should not be",
   "   edited by hand.  See the source to mkbuiltins for details. */",
   "",
-  "/* Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.",
+  "/* Copyright (C) 1987-2002 Free Software Foundation, Inc.",
   "",
   "   This file is part of GNU Bash, the Bourne Again SHell.",
   "",
@@ -1165,8 +1186,8 @@ write_builtins (defs, structfile, externfile)
                    fprintf (externfile, "extern int %s __P((WORD_LIST *));\n",
                             builtin->function);
 
-                 fprintf (externfile, "extern char *%s_doc[];\n",
-                          builtin->docname ? builtin->docname : builtin->name);
+                 fprintf (externfile, "extern char * const %s_doc[];\n",
+                          document_name (builtin));
                }
 
              /* Write the structure definition. */
@@ -1183,17 +1204,19 @@ write_builtins (defs, structfile, externfile)
                    "BUILTIN_ENABLED | STATIC_BUILTIN",
                    (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
                    (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
-                   builtin->docname ? builtin->docname : builtin->name);
+                   document_name (builtin));
 
                  fprintf
                    (structfile, "     \"%s\", (char *)NULL },\n",
                     builtin->shortdoc ? builtin->shortdoc : builtin->name);
 
-                 /* Save away this builtin for later writing of the
-                    long documentation strings. */
-                 save_builtin (builtin);
                }
 
+             if (structfile || separate_helpfiles)
+               /* Save away this builtin for later writing of the
+                  long documentation strings. */
+               save_builtin (builtin);
+
              /* Write out the matching #endif, if neccessary. */
              if (builtin->dependencies)
                {
@@ -1223,6 +1246,8 @@ write_longdocs (stream, builtins)
 {
   register int i;
   register BUILTIN_DESC *builtin;
+  char *dname;
+  char *sarray[2];
 
   for (i = 0; i < builtins->sindex; i++)
     {
@@ -1232,9 +1257,20 @@ write_longdocs (stream, builtins)
        write_ifdefs (stream, builtin->dependencies->array);
 
       /* Write the long documentation strings. */
-      fprintf (stream, "char *%s_doc[] =",
-              builtin->docname ? builtin->docname : builtin->name);
-      write_documentation (stream, builtin->longdoc->array, 0, STRING_ARRAY);
+      dname = document_name (builtin);
+      fprintf (stream, "char * const %s_doc[] =", dname);
+
+      if (separate_helpfiles)
+       {
+         int l = strlen (helpfile_directory) + strlen (dname) + 1;
+         sarray[0] = (char *)xmalloc (l + 1);
+         sprintf (sarray[0], "%s/%s", helpfile_directory, dname);
+         sarray[1] = (char *)NULL;
+         write_documentation (stream, sarray, 0, STRING_ARRAY);
+         free (sarray[0]);
+       }
+      else
+       write_documentation (stream, builtin->longdoc->array, 0, STRING_ARRAY);
 
       if (builtin->dependencies)
        write_endifs (stream, builtin->dependencies->array);
@@ -1321,12 +1357,6 @@ write_documentation (stream, documentation, indentation, flags)
   if (string_array)
     fprintf (stream, " {\n#if defined (HELP_BUILTIN)\n");
 
-#if !defined (OLDCODE)
-  /* XXX -- clean me up; for experiment only */
-  if (no_long_document)
-    goto end_of_document;
-#endif /* !OLDCODE */
-
   for (i = 0, texinfo = (flags & TEXINFO); line = documentation[i]; i++)
     {
       /* Allow #ifdef's to be written out verbatim. */
@@ -1384,14 +1414,52 @@ write_documentation (stream, documentation, indentation, flags)
        fprintf (stream, "%s\n", line);
     }
 
-#if !defined (OLDCODE)
-end_of_document:
-#endif /* !OLDCODE */
-
   if (string_array)
     fprintf (stream, "#endif /* HELP_BUILTIN */\n  (char *)NULL\n};\n");
 }
 
+int
+write_helpfiles (builtins)
+     ARRAY *builtins;
+{
+  char *helpfile, *bname;
+  FILE *helpfp;
+  int i, hdlen;
+  BUILTIN_DESC *builtin;       
+
+  i = mkdir ("helpfiles", 0777);
+  if (i < 0 && errno != EEXIST)
+    {
+      fprintf (stderr, "write_helpfiles: helpfiles: cannot create directory\n");
+      return -1;
+    }
+
+  hdlen = strlen ("helpfiles/");
+  for (i = 0; i < builtins->sindex; i++)
+    {
+      builtin = (BUILTIN_DESC *)builtins->array[i];
+
+      bname = document_name (builtin);
+      helpfile = (char *)xmalloc (hdlen + strlen (bname) + 1);
+      sprintf (helpfile, "helpfiles/%s", bname);
+
+      helpfp = fopen (helpfile, "w");
+      if (helpfp == 0)
+       {
+         fprintf (stderr, "write_helpfiles: cannot open %s\n", helpfile);
+         free (helpfile);
+         continue;
+       }
+
+      write_documentation (helpfp, builtin->longdoc->array, 4, PLAINTEXT);
+
+      fflush (helpfp);
+      fclose (helpfp);
+      free (helpfile);
+    }
+  return 0;
+}      
+               
 static int
 _find_in_table (name, name_table)
      char *name, *name_table[];
index bcf625c79fe689aea1c4f0601f9cd0a71bb726f9..8821ecb245a65cdd9114efca046cb29758c17f06 100644 (file)
@@ -1,7 +1,7 @@
 This file is printf.def, from which is created printf.c.
 It implements the builtin "printf" in Bash.
 
-Copyright (C) 1997 Free Software Foundation, Inc.
+Copyright (C) 1997-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -56,18 +56,17 @@ $END
 
 #include "../bashansi.h"
 
-#define NEED_STRTOIMAX_DECL
-
 #include "../shell.h"
 #include "stdc.h"
 #include "bashgetopt.h"
 #include "common.h"
 
-/* This should use the ISO C constant format strings; I'll do that later. */
-#if SIZEOF_LONG < SIZEOF_LONG_LONG
-#  define INTMAX_CONV  "ll"
-#else
-#  define INTMAX_CONV  "l"
+#if !defined (PRIdMAX)
+#  if HAVE_LONG_LONG
+#    define PRIdMAX    "lld"
+#  else
+#    define PRIdMAX    "ld"
+#  endif
 #endif
 
 #if !defined (errno)
@@ -104,25 +103,28 @@ extern int errno;
 #define SKIP1 "#'-+ 0"
 #define LENMODS "hjlLtz"
 
+static void printf_erange __P((char *));
 static void printstr __P((char *, char *, int, int, int));
 static int tescape __P((char *, int, char *, int *));
 static char *bexpand __P((char *, int, int *, int *));
-static char *mklong __P((char *, char *));
+static char *mklong __P((char *, char *, size_t));
 static int getchr __P((void));
 static char *getstr __P((void));
 static int  getint __P((void));
-static long getlong __P((void));
-static unsigned long getulong __P((void));
-#if defined (HAVE_LONG_LONG)
-static long long getllong __P((void));
-static unsigned long long getullong __P((void));
-#endif
 static intmax_t getintmax __P((void));
 static uintmax_t getuintmax __P((void));
-static double getdouble __P((void));
+
 #if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD
-static long double getldouble __P((void));
+typedef long double floatmax_t;
+#  define FLOATMAX_CONV        "L"
+#  define strtofltmax  strtold
+#else
+typedef double floatmax_t;
+#  define FLOATMAX_CONV        ""
+#  define strtofltmax  strtod
 #endif
+static floatmax_t getfloatmax __P((void));
+
 static int asciicode __P((void));
 
 static WORD_LIST *garglist;
@@ -138,18 +140,15 @@ printf_builtin (list)
 {
   int ch, fieldwidth, precision;
   int have_fieldwidth, have_precision;
-  long tw;
+  intmax_t tw;
   char convch, thisch, nextch, *format, *modstart, *fmt, *start;
 
   conversion_error = 0;
   retval = EXECUTION_SUCCESS;
-  reset_internal_getopt ();
-  if (internal_getopt (list, "") != -1)
-    {
-      builtin_usage();
-      return (EX_USAGE);
-    }
-  list = loptend;
+
+  if (no_options (list))
+    return (EX_USAGE);
+  list = loptend;      /* skip over possible `--' */
 
   if (list == 0)
     {
@@ -288,7 +287,7 @@ printf_builtin (list)
                      bind_var_to_int (var, tw);
                    else
                      {
-                       builtin_error ("%s: invalid variable name", var);
+                       sh_invalidid (var);
                        PRETURN (EXECUTION_FAILURE);
                      }
                  }
@@ -322,7 +321,10 @@ printf_builtin (list)
                char *p, *xp;
 
                p = getstr ();
-               xp = sh_backslash_quote (p);
+               if (ansic_shouldquote (p))
+                 xp = ansic_quote (p, 0, (int *)0);
+               else
+                 xp = sh_backslash_quote (p);
                if (xp)
                  {
                    /* Use printstr to get fieldwidth and precision right. */
@@ -336,32 +338,23 @@ printf_builtin (list)
            case 'i':
              {
                char *f;
-#if defined (HAVE_LONG_LONG)
-               if (thisch == 'l' && nextch == 'l')
-                 {
-                   long long p;
+               long p;
+               intmax_t pp;
 
-                   p = getllong ();
-                   f = mklong (start, "ll");
-                   PF(f, p);
-                 }
-               else
-#endif
-               if (thisch == 'j')
+               p = pp = getintmax ();
+               if (p != pp)
                  {
-                   intmax_t p;
-
-                   p = getintmax ();
-                   f = mklong (start, INTMAX_CONV);
-                   PF(f, p);
+                   f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
+                   PF (f, pp);
                  }
                else
                  {
-                   long p;
-
-                   p = getlong ();
-                   f = mklong (start, "l");
-                   PF(f, p);
+                   /* Optimize the common case where the integer fits
+                      in "long".  This also works around some long
+                      long and/or intmax_t library bugs in the common
+                      case, e.g. glibc 2.2 x86.  */
+                   f = mklong (start, "l", 1);
+                   PF (f, p);
                  }
                break;
              }
@@ -372,31 +365,18 @@ printf_builtin (list)
            case 'X':
              {
                char *f;
-#if defined (HAVE_LONG_LONG)
-               if (thisch == 'l' && nextch == 'l')
-                 {
-                   unsigned long long p;
+               unsigned long p;
+               uintmax_t pp;
 
-                   p = getullong ();
-                   f = mklong (start, "ll");
-                   PF(f, p);
-                 }
-               else
-#endif
-               if (thisch == 'j')
+               p = pp = getuintmax ();
+               if (p != pp)
                  {
-                   uintmax_t p;
-
-                   p = getuintmax ();
-                   f = mklong (start, INTMAX_CONV);
-                   PF(f, p);
+                   f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
+                   PF (f, pp);
                  }
                else
                  {
-                   unsigned long p;
-
-                   p = getulong ();
-                   f = mklong (start, "l");
+                   f = mklong (start, "l", 1);
                    PF (f, p);
                  }
                break;
@@ -414,24 +394,11 @@ printf_builtin (list)
 #endif
              {
                char *f;
-#if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD
-               if (thisch == 'L')
-                 {
-                   long double p;
-
-                   p = getldouble ();
-                   f = mklong (start, "L");
-                   PF (f, p);
-                 }
-               else
-#endif
-                 {
-                   double p;
+               floatmax_t p;
 
-                   p = getdouble ();
-                   f = mklong (start, "");
-                   PF (f, p);
-                 }
+               p = getfloatmax ();
+               f = mklong (start, FLOATMAX_CONV, sizeof(FLOATMAX_CONV) - 1);
+               PF (f, p);
                break;
              }
 
@@ -454,6 +421,13 @@ printf_builtin (list)
   PRETURN (retval);
 }
 
+static void
+printf_erange (s)
+     char *s;
+{
+  builtin_error ("warning: %s: %s", s, strerror(ERANGE));
+}
+
 /* We duplicate a lot of what printf(3) does here. */
 static void
 printstr (fmt, string, len, fieldwidth, precision)
@@ -605,16 +579,11 @@ tescape (estart, trans_squote, cp, sawc)
       /* %b octal constants are `\0' followed by one, two, or three
         octal digits... */
       case '0':
-       for (temp = 3, evalue = 0; ISOCTAL (*p) && temp--; p++)
-         evalue = (evalue * 8) + OCTVALUE (*p);
-       *cp = evalue & 0xFF;
-       break;
-
       /* but, as an extension, the other echo-like octal escape
         sequences are supported as well. */
       case '1': case '2': case '3': case '4':
       case '5': case '6': case '7':
-       for (temp = 2, evalue = c - '0'; ISOCTAL (*p) && temp--; p++)
+       for (temp = 2+(c=='0'), evalue = c - '0'; ISOCTAL (*p) && temp--; p++)
          evalue = (evalue * 8) + OCTVALUE (*p);
        *cp = evalue & 0xFF;
        break;
@@ -706,14 +675,14 @@ bexpand (string, len, sawc, lenp)
 }
 
 static char *
-mklong (str, modifiers)
+mklong (str, modifiers, mlen)
      char *str;
      char *modifiers;
+     size_t mlen;
 {
-  size_t len, slen, mlen;
+  size_t len, slen;
 
   slen = strlen (str);
-  mlen = strlen (modifiers);
   len = slen + mlen + 1;
 
   if (len > conv_bufsize)
@@ -759,152 +728,24 @@ getstr ()
 static int
 getint ()
 {
-  long ret;
+  intmax_t ret;
 
-  ret = getlong ();
+  ret = getintmax ();
 
   if (ret > INT_MAX)
     {
-      builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
+      printf_erange (garglist->word->word);
       ret = INT_MAX;
     }
   else if (ret < INT_MIN)
     {
-      builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
+      printf_erange (garglist->word->word);
       ret = INT_MIN;
     }
 
   return ((int)ret);
 }
 
-static long
-getlong ()
-{
-  long ret;
-  char *ep;
-
-  if (garglist == 0)
-    return (0);
-
-  if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
-    return asciicode ();
-
-  errno = 0;
-  ret = strtol (garglist->word->word, &ep, 0);
-
-  if (*ep)
-    {
-      builtin_error ("%s: invalid number", garglist->word->word);
-      /* POSIX.2 says ``...a diagnostic message shall be written to standard
-        error, and the utility shall not exit with a zero exit status, but
-        shall continue processing any remaining operands and shall write the
-         value accumulated at the time the error was detected to standard
-        output.''  Yecch. */
-      ret = 0;
-      conversion_error = 1;
-    }
-  else if (errno == ERANGE)
-    builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
-
-  garglist = garglist->next;
-  return (ret);
-}
-
-static unsigned long
-getulong ()
-{
-  unsigned long ret;
-  char *ep;
-
-  if (garglist == 0)
-    return (0);
-
-  if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
-    return asciicode ();
-
-  errno = 0;
-  ret = strtoul (garglist->word->word, &ep, 0);
-  
-  if (*ep)
-    {
-      builtin_error ("%s: invalid number", garglist->word->word);
-      /* Same thing about POSIX.2 conversion error requirements as getlong(). */
-      ret = 0;
-      conversion_error = 1;
-    }
-  else if (errno == ERANGE)
-    builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
-
-  garglist = garglist->next;
-  return (ret);
-}
-
-#if defined (HAVE_LONG_LONG)
-
-static long long
-getllong ()
-{
-  long long ret;
-  char *ep;
-
-  if (garglist == 0)
-    return (0);
-
-  if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
-    return asciicode ();
-
-  errno = 0;
-  ret = strtoll (garglist->word->word, &ep, 0);
-
-  if (*ep)
-    {
-      builtin_error ("%s: invalid number", garglist->word->word);
-      /* POSIX.2 says ``...a diagnostic message shall be written to standard
-        error, and the utility shall not exit with a zero exit status, but
-        shall continue processing any remaining operands and shall write the
-         value accumulated at the time the error was detected to standard
-        output.''  Yecch. */
-      ret = 0;
-      conversion_error = 1;
-    }
-  else if (errno == ERANGE)
-    builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
-
-  garglist = garglist->next;
-  return (ret);
-}
-
-static unsigned long long
-getullong ()
-{
-  unsigned long long ret;
-  char *ep;
-
-  if (garglist == 0)
-    return (0);
-
-  if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
-    return asciicode ();
-
-  errno = 0;
-  ret = strtoull (garglist->word->word, &ep, 0);
-  
-  if (*ep)
-    {
-      builtin_error ("%s: invalid number", garglist->word->word);
-      /* Same thing about POSIX.2 conversion error requirements as getlong(). */
-      ret = 0;
-      conversion_error = 1;
-    }
-  else if (errno == ERANGE)
-    builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
-
-  garglist = garglist->next;
-  return (ret);
-}
-
-#endif /* HAVE_LONG_LONG */
-
 static intmax_t
 getintmax ()
 {
@@ -922,7 +763,7 @@ getintmax ()
 
   if (*ep)
     {
-      builtin_error ("%s: invalid number", garglist->word->word);
+      sh_invalidnum (garglist->word->word);
       /* POSIX.2 says ``...a diagnostic message shall be written to standard
         error, and the utility shall not exit with a zero exit status, but
         shall continue processing any remaining operands and shall write the
@@ -932,7 +773,7 @@ getintmax ()
       conversion_error = 1;
     }
   else if (errno == ERANGE)
-    builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
+    printf_erange (garglist->word->word);
 
   garglist = garglist->next;
   return (ret);
@@ -955,22 +796,22 @@ getuintmax ()
   
   if (*ep)
     {
-      builtin_error ("%s: invalid number", garglist->word->word);
-      /* Same thing about POSIX.2 conversion error requirements as getlong(). */
+      sh_invalidnum (garglist->word->word);
+      /* Same POSIX.2 conversion error requirements as getintmax(). */
       ret = 0;
       conversion_error = 1;
     }
   else if (errno == ERANGE)
-    builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
+    printf_erange (garglist->word->word);
 
   garglist = garglist->next;
   return (ret);
 }
 
-static double
-getdouble ()
+static floatmax_t
+getfloatmax ()
 {
-  double ret;
+  floatmax_t ret;
   char *ep;
 
   if (garglist == 0)
@@ -980,52 +821,21 @@ getdouble ()
     return asciicode ();
 
   errno = 0;
-  ret = strtod (garglist->word->word, &ep);
-
-  if (*ep)
-    {
-      builtin_error ("%s: invalid number", garglist->word->word);
-      /* Same thing about POSIX.2 conversion error requirements. */
-      ret = 0;
-      conversion_error = 1;
-    }
-  else if (errno == ERANGE)
-    builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
-
-  garglist = garglist->next;
-  return (ret);
-}
-
-#if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD
-static long double
-getldouble ()
-{
-  long double ret;
-  char *ep;
-
-  if (garglist == 0)
-    return (0);
-
-  if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
-    return (asciicode ());
-
-  errno = 0;
-  ret = strtold (garglist->word->word, &ep);
+  ret = strtofltmax (garglist->word->word, &ep);
 
   if (*ep)
     {
-      builtin_error ("%s: invalid number", garglist->word->word);
+      sh_invalidnum (garglist->word->word);
       /* Same thing about POSIX.2 conversion error requirements. */
       ret = 0;
       conversion_error = 1;
     }
   else if (errno == ERANGE)
-    builtin_error ("warning: %s: %s", garglist->word->word, strerror(ERANGE));
+    printf_erange (garglist->word->word);
 
   garglist = garglist->next;
   return (ret);
 }
-#endif /* HAVE_LONG_DOUBLE && HAVE_DECL_STRTOLD */
 
 /* NO check is needed for garglist here. */
 static int
index f47b2941ac909291db123824c248758e4037d8ad..2bb72ffa4dcd5a9ba021b5406f31d03d32bf1a8f 100644 (file)
@@ -1,7 +1,7 @@
 This file is pushd.def, from which is created pushd.c.  It implements the
 builtins "pushd", "popd", and "dirs" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -125,8 +125,6 @@ $END
 extern int errno;
 #endif /* !errno */
 
-static char *m_badarg = "%s: bad argument";
-
 /* The list of remembered directories. */
 static char **pushd_directory_list = (char **)NULL;
 
@@ -141,7 +139,7 @@ static void clear_directory_stack __P((void));
 static int cd_to_string __P((char *));
 static int change_to_temp __P((char *));
 static void add_dirstack_element __P((char *));
-static int get_dirstack_index __P((long, int, int *));
+static int get_dirstack_index __P((intmax_t, int, int *));
 
 #define NOCD           0x01
 #define ROTATE         0x02
@@ -154,9 +152,12 @@ pushd_builtin (list)
 {
   char *temp, *current_directory, *top;
   int j, flags;
-  long num;
+  intmax_t num;
   char direction;
 
+  if (list && list->word && ISOPTION (list->word->word, '-'))
+    list = list->next;
+
   /* If there is no argument list then switch current and
      top of list. */
   if (list == 0)
@@ -197,7 +198,7 @@ pushd_builtin (list)
        {
          if (legal_number (list->word->word + 1, &num) == 0)
            {
-             builtin_error (m_badarg, list->word->word);
+             sh_invalidnum (list->word->word);
              builtin_usage ();
              return (EXECUTION_FAILURE);
            }
@@ -214,7 +215,7 @@ pushd_builtin (list)
        }
       else if (*list->word->word == '-')
        {
-         bad_option (list->word->word);
+         sh_invalidopt (list->word->word);
          builtin_usage ();
          return (EXECUTION_FAILURE);
        }
@@ -287,7 +288,7 @@ popd_builtin (list)
      WORD_LIST *list;
 {
   register int i;
-  long which;
+  intmax_t which;
   int flags;
   char direction;
   char *which_word;
@@ -308,7 +309,7 @@ popd_builtin (list)
        {
          if (legal_number (list->word->word + 1, &which) == 0)
            {
-             builtin_error (m_badarg, list->word->word);
+             sh_invalidnum (list->word->word);
              builtin_usage ();
              return (EXECUTION_FAILURE);
            }
@@ -316,7 +317,7 @@ popd_builtin (list)
        }
       else if (*list->word->word == '-')
        {
-         bad_option (list->word->word);
+         sh_invalidopt (list->word->word);
          builtin_usage ();
          return (EXECUTION_FAILURE);
        }
@@ -364,7 +365,7 @@ dirs_builtin (list)
      WORD_LIST *list;
 {
   int flags, desired_index, index_flag, vflag;
-  long i;
+  intmax_t i;
   char *temp, *w;
 
   for (flags = vflag = index_flag = 0, desired_index = -1, w = ""; list; list = list->next)
@@ -395,7 +396,7 @@ dirs_builtin (list)
          int sign;
          if (legal_number (w = list->word->word + 1, &i) == 0)
            {
-             builtin_error (m_badarg, list->word->word);
+             sh_invalidnum (list->word->word);
              builtin_usage ();
              return (EXECUTION_FAILURE);
            }
@@ -404,7 +405,7 @@ dirs_builtin (list)
        }
       else
        {
-         bad_option (list->word->word);
+         sh_invalidopt (list->word->word);
          builtin_usage ();
          return (EXECUTION_FAILURE);
        }
@@ -475,10 +476,8 @@ pushd_error (offset, arg)
 {
   if (offset == 0)
     builtin_error ("directory stack empty");
-  else if (arg)
-    builtin_error ("%s: bad directory stack index", arg);
   else
-    builtin_error ("bad directory stack index");
+    sh_erange (arg, "directory stack index");
 }
 
 static void
@@ -525,19 +524,14 @@ static void
 add_dirstack_element (dir)
      char *dir;
 {
-  int j;
-
   if (directory_list_offset == directory_list_size)
-    {
-      j = (directory_list_size += 10) * sizeof (char *);
-      pushd_directory_list = (char **)xrealloc (pushd_directory_list, j);
-    }
+    pushd_directory_list = strvec_resize (pushd_directory_list, directory_list_size += 10);
   pushd_directory_list[directory_list_offset++] = dir;
 }
 
 static int
 get_dirstack_index (ind, sign, indexp)
-     long ind;
+     intmax_t ind;
      int sign, *indexp;
 {
   if (indexp)
@@ -565,7 +559,7 @@ get_dirstack_from_string (string)
      char *string;
 {
   int ind, sign, index_flag;
-  long i;
+  intmax_t i;
 
   sign = 1;
   if (*string == '-' || *string == '+')
@@ -589,7 +583,7 @@ get_dirstack_from_string (string)
 #ifdef INCLUDE_UNUSED
 char *
 get_dirstack_element (ind, sign)
-     long ind;
+     intmax_t ind;
      int sign;
 {
   int i;
@@ -602,7 +596,7 @@ get_dirstack_element (ind, sign)
 
 void
 set_dirstack_element (ind, sign, value)
-     long ind;
+     intmax_t ind;
      int  sign;
      char *value;
 {
index a9d4a406b55f58f8f76632a82ded4f04176cafc0..46a0407bf8860919e33f000d7b91714a23f61177 100644 (file)
@@ -1,7 +1,7 @@
 This file is read.def, from which is created read.c.
 It implements the builtin "read" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -23,25 +23,28 @@ $PRODUCES read.c
 
 $BUILTIN read
 $FUNCTION read_builtin
-$SHORT_DOC read [-ers] [-t timeout] [-p prompt] [-a array] [-n nchars] [-d delim] [name ...]
-One line is read from the standard input, and the first word is
-assigned to the first NAME, the second word to the second NAME, and so
-on, with leftover words assigned to the last NAME.  Only the characters
-found in $IFS are recognized as word delimiters.  If no NAMEs are supplied,
-the line read is stored in the REPLY variable.  If the -r option is given,
-this signifies `raw' input, and backslash escaping is disabled.  The
--d option causes read to continue until the first character of DELIM is
-read, rather than newline.  If the `-p' option is supplied, the string
-PROMPT is output without a trailing newline before attempting to read.
-If -a is supplied, the words read are assigned to sequential indices of
-ARRAY, starting at zero.  If -e is supplied and the shell is interactive,
-readline is used to obtain the line.  If -n is supplied with a non-zero
-NCHARS argument, read returns after NCHARS characters have been read.
-The -s option causes input coming from a terminal to not be echoed.
+$SHORT_DOC read [-ers] [-u fd] [-t timeout] [-p prompt] [-a array] [-n nchars] [-d delim] [name ...]
+One line is read from the standard input, or from file descriptor FD if the
+-u option is supplied, and the first word is assigned to the first NAME,
+the second word to the second NAME, and so on, with leftover words assigned
+to the last NAME.  Only the characters found in $IFS are recognized as word
+delimiters.  If no NAMEs are supplied, the line read is stored in the REPLY
+variable.  If the -r option is given, this signifies `raw' input, and
+backslash escaping is disabled.  The -d option causes read to continue
+until the first character of DELIM is read, rather than newline.  If the -p
+option is supplied, the string PROMPT is output without a trailing newline
+before attempting to read.  If -a is supplied, the words read are assigned
+to sequential indices of ARRAY, starting at zero.  If -e is supplied and
+the shell is interactive, readline is used to obtain the line.  If -n is
+supplied with a non-zero NCHARS argument, read returns after NCHARS
+characters have been read.  The -s option causes input coming from a
+terminal to not be echoed.
 
 The -t option causes read to time out and return failure if a complete line
-of input is not read within TIMEOUT seconds.  The return code is zero,
-unless end-of-file is encountered or read times out.
+of input is not read within TIMEOUT seconds.  If the TMOUT variable is set,
+its value is the default timeout.  The return code is zero, unless end-of-file
+is encountered, read times out, or an invalid file descriptor is supplied as
+the argument to -u.
 $END
 
 #include <config.h>
@@ -78,8 +81,6 @@ $END
 extern int errno;
 #endif
 
-#define issep(c)       (strchr (ifs_chars, (c)))
-
 extern int interrupt_immediately;
 
 #if defined (READLINE)
@@ -123,9 +124,9 @@ read_builtin (list)
   register char *varname;
   int size, i, pass_next, saw_escape, eof, opt, retval, code;
   int input_is_tty, input_is_pipe, unbuffered_read;
-  int raw, edit, nchars, silent, have_timeout;
+  int raw, edit, nchars, silent, have_timeout, fd;
   unsigned int tmout;
-  long timeoutval, ncharsval;
+  intmax_t intval;
   char c;
   char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
   char *e, *t, *t1;
@@ -162,6 +163,7 @@ read_builtin (list)
   raw = edit = 0;      /* Not reading raw input by default. */
   silent = 0;
   arrayname = prompt = (char *)NULL;
+  fd = 0;              /* file descriptor to read from */
 
 #if defined (READLINE)
   rlbuf = (char *)0;
@@ -173,7 +175,7 @@ read_builtin (list)
   delim = '\n';                /* read until newline */
 
   reset_internal_getopt ();
-  while ((opt = internal_getopt (list, "erp:a:d:t:n:s")) != -1)
+  while ((opt = internal_getopt (list, "ersa:d:n:p:t:u:")) != -1)
     {
       switch (opt)
        {
@@ -197,8 +199,8 @@ read_builtin (list)
          break;
 #endif
        case 't':
-         code = legal_number (list_optarg, &timeoutval);
-         if (code == 0 || timeoutval < 0 || timeoutval != (unsigned int)timeoutval)
+         code = legal_number (list_optarg, &intval);
+         if (code == 0 || intval < 0 || intval != (unsigned int)intval)
            {
              builtin_error ("%s: invalid timeout specification", list_optarg);
              return (EXECUTION_FAILURE);
@@ -206,18 +208,33 @@ read_builtin (list)
          else
            {
              have_timeout = 1;
-             tmout = timeoutval;
+             tmout = intval;
            }
          break;
        case 'n':
-         code = legal_number (list_optarg, &ncharsval);
-         if (code == 0 || ncharsval < 0 || ncharsval != (int)ncharsval)
+         code = legal_number (list_optarg, &intval);
+         if (code == 0 || intval < 0 || intval != (int)intval)
            {
-             builtin_error ("%s: invalid number specification", list_optarg);
+             sh_invalidnum (list_optarg);
              return (EXECUTION_FAILURE);
            }
          else
-           nchars = ncharsval;
+           nchars = intval;
+         break;
+       case 'u':
+         code = legal_number (list_optarg, &intval);
+         if (code == 0 || intval < 0 || intval != (int)intval)
+           {
+             builtin_error ("%s: invalid file descriptor specification", list_optarg);
+             return (EXECUTION_FAILURE);
+           }
+         else
+           fd = intval;
+         if (sh_validfd (fd) == 0)
+           {
+             builtin_error ("%d: invalid file descriptor: %s", fd, strerror (errno));
+             return (EXECUTION_FAILURE);
+           }
          break;
        case 'd':
          delim = *list_optarg;
@@ -229,24 +246,32 @@ read_builtin (list)
     }
   list = loptend;
 
-  /* `read -t 0 var' returns failure immediately. */
+  /* `read -t 0 var' returns failure immediately.  XXX - should it test
+     whether input is available with select/FIONREAD, and fail if those
+     are unavailable? */
   if (have_timeout && tmout == 0)
     return (EXECUTION_FAILURE);
 
   /* IF IFS is unset, we use the default of " \t\n". */
-  var = find_variable ("IFS");
-  ifs_chars = var ? value_cell (var) : " \t\n";
-  if (ifs_chars == 0)          /* XXX */
-    ifs_chars = "";            /* XXX */
+  ifs_chars = getifs ();
+  if (ifs_chars == 0)          /* XXX - shouldn't happen */
+    ifs_chars = "";
 
-  input_string = (char *)xmalloc (size = 128);
+  input_string = (char *)xmalloc (size = 112); /* XXX was 128 */
+
+  /* $TMOUT, if set, is the default timeout for read. */
+  if (have_timeout == 0 && (e = get_string_value ("TMOUT")))
+    {
+      code = legal_number (e, &intval);
+      if (code == 0 || intval < 0 || intval != (unsigned int)intval)
+       tmout = 0;
+      else
+       tmout = intval;
+    }
 
   begin_unwind_frame ("read_builtin");
-#if defined (READLINE)
-  add_unwind_protect (xfree, rlbuf);
-#endif
 
-  input_is_tty = isatty (0);
+  input_is_tty = isatty (fd);
   if (input_is_tty == 0)
 #ifndef __CYGWIN__
     input_is_pipe = (lseek (0, 0L, SEEK_CUR) < 0) && (errno == ESPIPE);
@@ -262,6 +287,11 @@ read_builtin (list)
       edit = silent = 0;
     }
 
+#if defined (READLINE)
+  if (edit)
+    add_unwind_protect (xfree, rlbuf);
+#endif
+
   if (prompt && edit == 0)
     {
       fprintf (stderr, "%s", prompt);
@@ -275,7 +305,7 @@ read_builtin (list)
     {
       /* Turn off the timeout if stdin is a regular file (e.g. from
         input redirection). */
-      if ((fstat (0, &tsb) < 0) || S_ISREG (tsb.st_mode))
+      if ((fstat (fd, &tsb) < 0) || S_ISREG (tsb.st_mode))
        tmout = 0;
     }
 
@@ -341,7 +371,7 @@ read_builtin (list)
   setmode (0, O_TEXT);
 #endif
 
-  for (eof = 0;;)
+  for (eof = retval = 0;;)
     {
 #if defined (READLINE)
       if (edit)
@@ -368,9 +398,9 @@ read_builtin (list)
 #endif
 
       if (unbuffered_read)
-       retval = zread (0, &c, 1);
+       retval = zread (fd, &c, 1);
       else
-       retval = zreadc (0, &c);
+       retval = zreadc (fd, &c);
 
       if (retval <= 0)
        {
@@ -425,6 +455,14 @@ read_builtin (list)
     }
   input_string[i] = '\0';
 
+#if 1
+  if (retval < 0)
+    {
+      builtin_error ("read error: %d: %s", fd, strerror (errno));
+      return (EXECUTION_FAILURE);
+    }
+#endif
+
   if (tmout > 0)
     reset_alarm ();
 
@@ -447,7 +485,7 @@ read_builtin (list)
     ttrestore ();
 
   if (unbuffered_read == 0)
-    zsyncfd (0);
+    zsyncfd (fd);
 
   interrupt_immediately--;
   discard_unwind_frame ("read_builtin");
@@ -462,7 +500,7 @@ read_builtin (list)
       var = find_or_make_array_variable (arrayname, 1);
       if (var == 0)
        return EXECUTION_FAILURE;       /* readonly or noassign */
-      empty_array (array_cell (var));
+      array_flush (array_cell (var));
 
       alist = list_string (input_string, ifs_chars, 0);
       if (alist)
@@ -487,7 +525,7 @@ read_builtin (list)
     {
 #if 0
       orig_input_string = input_string;
-      for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && issep(*t); t++)
+      for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++)
        ;
       input_string = t;
       input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
@@ -513,7 +551,7 @@ read_builtin (list)
 
   /* Remove IFS white space at the beginning of the input string.  If
      $IFS is null, no field splitting is performed. */
-  for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && issep(*t); t++)
+  for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++)
     ;
   input_string = t;
 
@@ -526,7 +564,7 @@ read_builtin (list)
       if (legal_identifier (varname) == 0)
 #endif
        {
-         builtin_error ("`%s': not a valid identifier", varname);
+         sh_invalidid (varname);
          xfree (orig_input_string);
          return (EXECUTION_FAILURE);
        }
@@ -574,7 +612,7 @@ read_builtin (list)
   if (legal_identifier (list->word->word) == 0)
 #endif
     {
-      builtin_error ("`%s': not a valid identifier", list->word->word);
+      sh_invalidid (list->word->word);
       xfree (orig_input_string);
       return (EXECUTION_FAILURE);
     }
@@ -615,6 +653,8 @@ bind_read_variable (name, value)
 }
 
 #if defined (READLINE)
+static rl_completion_func_t *old_attempted_completion_function;
+
 static char *
 edit_line (p)
      char *p;
@@ -624,7 +664,10 @@ edit_line (p)
 
   if (!bash_readline_initialized)
     initialize_readline ();
+  old_attempted_completion_function = rl_attempted_completion_function;
+  rl_attempted_completion_function = (rl_completion_func_t *)NULL;
   ret = readline (p);
+  rl_attempted_completion_function = old_attempted_completion_function;
   if (ret == 0)
     return ret;
   len = strlen (ret);
index 28979008292b8c8d84696daa2eec80fb9b661f24..0f293d3974d2d854adac3156f446ea5c28d4085d 100644 (file)
@@ -2,7 +2,7 @@ This file is reserved.def, in which the shell reserved words are defined.
 It has no direct C file production, but defines builtins for the Bash
 builtin help command.
 
-Copyright (C) 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -28,6 +28,19 @@ assumed.  For each element in WORDS, NAME is set to that element, and
 the COMMANDS are executed.
 $END
 
+$BUILTIN for ((
+$DOCNAME arith_for
+$SHORT_DOC for (( exp1; exp2; exp3 )); do COMMANDS; done
+Equivalent to
+       (( EXP1 ))
+       while (( EXP2 )); do
+               COMMANDS
+               (( EXP3 ))
+       done
+EXP1, EXP2, and EXP3 are arithmetic expressions.  If any expression is
+omitted, it behaves as if it evaluates to 1.
+$END
+
 $BUILTIN select
 $SHORT_DOC select NAME [in WORDS ... ;] do COMMANDS; done
 The WORDS are expanded, generating a list of words.  The
@@ -40,7 +53,7 @@ to that word.  If the line is empty, WORDS and the prompt are
 redisplayed.  If EOF is read, the command completes.  Any other
 value read causes NAME to be set to null.  The line read is saved
 in the variable REPLY.  COMMANDS are executed after each selection
-until a break or return command is executed.
+until a break command is executed.
 $END
 
 $BUILTIN time
@@ -103,6 +116,31 @@ WORD, then the job whose name begins with WORD is used.  Following the
 job specification with a `&' places the job in the background.
 $END
 
+$BUILTIN (( ... ))
+$DOCNAME arith
+$SHORT_DOC (( expression ))
+The EXPRESSION is evaluated according to the rules for arithmetic
+evaluation.  Equivalent to "let EXPRESSION".
+$END
+
+$BUILTIN [[ ... ]]
+$DOCNAME conditional
+$SHORT_DOC [[ expression ]]
+Returns a status of 0 or 1 depending on the evaluation of the conditional
+expression EXPRESSION.  Expressions are composed of the same primaries used
+by the `test' builtin, and may be combined using the following operators
+
+       ( EXPRESSION )  Returns the value of EXPRESSION
+       ! EXPRESSION    True if EXPRESSION is false; else false
+       EXPR1 && EXPR2  True if both EXPR1 and EXPR2 are true; else false
+       EXPR1 || EXPR2  True if either EXPR1 or EXPR2 is true; else false
+
+When the `==' and `!=' operators are used, the string to the right of the
+operator is used as a pattern and pattern matching is performed.  The
+&& and || operators do not evaluate EXPR2 if EXPR1 is sufficient to
+determine the expression's value.
+$END
+
 $BUILTIN variables
 $DOCNAME variable_help
 $SHORT_DOC variables - Some variable names and meanings
index 529e04cd93693a7d23797e923af5995fa1a5c83d..84a90a338615ea1da8fc0988562c2cea943bc61b 100644 (file)
@@ -1,7 +1,7 @@
 This file is return.def, from which is created return.c.
 It implements the builtin "return" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -52,7 +52,7 @@ int
 return_builtin (list)
      WORD_LIST *list;
 {
-  return_catch_value = list ? get_exitstat (list) : last_command_exit_value;
+  return_catch_value = get_exitstat (list);
 
   if (return_catch_flag)
     longjmp (return_catch, 1);
index 8f9601714230e354d931caea979757d2913cb244..10aaf5ff2cc4fb6fd02c96bd0e565ea799501355 100644 (file)
@@ -1,7 +1,7 @@
 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.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -49,7 +49,7 @@ $PRODUCES set.c
 #  include "../bashhist.h"
 #endif
 
-extern int noclobber, posixly_correct, ignoreeof, eof_encountered_limit;
+extern int posixly_correct, ignoreeof, eof_encountered_limit;
 #if defined (HISTORY)
 extern int dont_save_function_defs;
 #endif
@@ -65,8 +65,6 @@ $SHORT_DOC set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
     -e  Exit immediately if a command exits with a non-zero status.
     -f  Disable file name generation (globbing).
     -h  Remember the location of commands as they are looked up.
-    -i  Force the shell to be an "interactive" one.  Interactive shells
-        always read `~/.bashrc' on startup.
     -k  All assignment arguments are placed in the environment for a
         command, not just those that precede the command name.
     -m  Job control is enabled.
@@ -135,6 +133,9 @@ parameters and are assigned, in order, to $1, $2, .. $n.  If no
 ARGs are given, all shell variables are printed.
 $END
 
+typedef int setopt_set_func_t __P((int, char *));
+typedef int setopt_get_func_t __P((char *));
+
 static void print_minus_o_option __P((char *, int, int));
 static void print_all_shell_variables __P((void));
 
@@ -153,70 +154,66 @@ static int bash_set_history __P((int, char *));
 static char *on = "on";
 static char *off = "off";
 
-/* An a-list used to match long options for set -o to the corresponding
-   option letter. */
+/* A struct used to match long options for set -o to the corresponding
+   option letter or internal variable.  The functions can be called to
+   dynamically generate values. */
 struct {
   char *name;
   int letter;
+  int *variable;
+  setopt_set_func_t *set_func;
+  setopt_get_func_t *get_func;
 } o_options[] = {
-  { "allexport",  'a' },
+  { "allexport",  'a', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
 #if defined (BRACE_EXPANSION)
-  { "braceexpand",'B' },
+  { "braceexpand",'B', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
 #endif
-  { "errexit",   'e' },
-  { "hashall",    'h' },
+#if defined (READLINE)
+  { "emacs",     '\0', (int *)NULL, set_edit_mode, get_edit_mode },
+#endif
+  { "errexit",   'e', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "hashall",    'h', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
 #if defined (BANG_HISTORY)
-  { "histexpand", 'H' },
+  { "histexpand", 'H', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
 #endif /* BANG_HISTORY */
-  { "keyword",    'k' },
-  { "monitor",   'm' },
-  { "noclobber",  'C' },
-  { "noexec",    'n' },
-  { "noglob",    'f' },
-#if defined (JOB_CONTROL)
-  { "notify",    'b' },
-#endif /* JOB_CONTROL */
-  { "nounset",   'u' },
-  { "onecmd",    't' },
-  { "physical",   'P' },
-  { "privileged", 'p' },
-  { "verbose",   'v' },
-  { "xtrace",    'x' },
-  {(char *)NULL, 0 },
-};
-
-typedef int setopt_set_func_t __P((int, char *));
-typedef int setopt_get_func_t __P((char *));
-
-struct {
-  char *name;
-  int *variable;
-  setopt_set_func_t *set_func;
-  setopt_get_func_t *get_func;
-} binary_o_options[] = {
 #if defined (HISTORY)
-  { "history", &remember_on_history, bash_set_history, (setopt_get_func_t *)NULL },
+  { "history",   '\0', &remember_on_history, bash_set_history, (setopt_get_func_t *)NULL },
 #endif
-  { "ignoreeof", &ignoreeof, set_ignoreeof, (setopt_get_func_t *)NULL },
-  { "interactive-comments", &interactive_comments, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+  { "ignoreeof", '\0', &ignoreeof, set_ignoreeof, (setopt_get_func_t *)NULL },
+  { "interactive-comments", '\0', &interactive_comments, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+  { "keyword",    'k', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "monitor",   'm', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "noclobber",  'C', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "noexec",    'n', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "noglob",    'f', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
 #if defined (HISTORY)
-  { "nolog", &dont_save_function_defs, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+  { "nolog",     '\0', &dont_save_function_defs, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
 #endif
-  { "posix", &posixly_correct, set_posix_mode, (setopt_get_func_t *)NULL },
+#if defined (JOB_CONTROL)
+  { "notify",    'b', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+#endif /* JOB_CONTROL */
+  { "nounset",   'u', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "onecmd",    't', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+  { "physical",   'P', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "posix",     '\0', &posixly_correct, set_posix_mode, (setopt_get_func_t *)NULL },
+  { "privileged", 'p', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "verbose",   'v', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
 #if defined (READLINE)
-  { "emacs", (int *)NULL, set_edit_mode, get_edit_mode },
-  { "vi", (int *)NULL, set_edit_mode, get_edit_mode },
+  { "vi",        '\0', (int *)NULL, set_edit_mode, get_edit_mode },
 #endif
-  { (char *)NULL, (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }
+  { "xtrace",    'x', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  {(char *)NULL, 0 , (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
 };
 
+#define N_O_OPTIONS    (sizeof (o_options) / sizeof (o_options[0]))
+
 #define GET_BINARY_O_OPTION_VALUE(i, name) \
-  ((binary_o_options[i].get_func) ? (*binary_o_options[i].get_func) (name) \
-                                 : (*binary_o_options[i].variable))
+  ((o_options[i].get_func) ? (*o_options[i].get_func) (name) \
+                          : (*o_options[i].variable))
 
 #define SET_BINARY_O_OPTION_VALUE(i, onoff, name) \
-  ((binary_o_options[i].set_func) ? (*binary_o_options[i].set_func) (onoff, name) \
-                                 : (*binary_o_options[i].variable = (onoff == FLAG_ON)))
+  ((o_options[i].set_func) ? (*o_options[i].set_func) (onoff, name) \
+                          : (*o_options[i].variable = (onoff == FLAG_ON)))
 
 int
 minus_o_option_value (name)
@@ -229,15 +226,15 @@ minus_o_option_value (name)
     {
       if (STREQ (name, o_options[i].name))
        {
-         on_or_off = find_flag (o_options[i].letter);
-         return ((on_or_off == FLAG_UNKNOWN) ? -1 : *on_or_off);
+         if (o_options[i].letter)
+           {
+             on_or_off = find_flag (o_options[i].letter);
+             return ((on_or_off == FLAG_UNKNOWN) ? -1 : *on_or_off);
+           }
+         else
+           return (GET_BINARY_O_OPTION_VALUE (i, name));
        }
     }
-  for (i = 0; binary_o_options[i].name; i++)
-    {
-      if (STREQ (name, binary_o_options[i].name))
-       return (GET_BINARY_O_OPTION_VALUE (i, name));
-    }
 
   return (-1);
 }
@@ -262,19 +259,23 @@ list_minus_o_opts (mode, reusable)
   register int i;
   int *on_or_off, value;
 
-  for (value = i = 0; o_options[i].name; i++)
-    {
-      on_or_off = find_flag (o_options[i].letter);
-      if (on_or_off == FLAG_UNKNOWN)
-       on_or_off = &value;
-      if (mode == -1 || mode == *on_or_off)
-       print_minus_o_option (o_options[i].name, *on_or_off, reusable);
-    }
-  for (i = 0; binary_o_options[i].name; i++)
+  for (i = 0; o_options[i].name; i++)
     {
-      value = GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name);
-      if (mode == -1 || mode == value)
-       print_minus_o_option (binary_o_options[i].name, value, reusable);
+      if (o_options[i].letter)
+       {
+         value = 0;
+         on_or_off = find_flag (o_options[i].letter);
+         if (on_or_off == FLAG_UNKNOWN)
+           on_or_off = &value;
+         if (mode == -1 || mode == *on_or_off)
+           print_minus_o_option (o_options[i].name, *on_or_off, reusable);
+       }
+      else
+       {
+         value = GET_BINARY_O_OPTION_VALUE (i, o_options[i].name);
+         if (mode == -1 || mode == value)
+           print_minus_o_option (o_options[i].name, value, reusable);
+       }
     }
 }
 
@@ -282,16 +283,12 @@ char **
 get_minus_o_opts ()
 {
   char **ret;
-  int n, i, ind;
-
-  n = (sizeof (o_options) / sizeof (o_options[0])) +
-      (sizeof (binary_o_options) / sizeof (binary_o_options[0]));
-  ret = alloc_array (n + 1);
-  for (i = ind = 0; o_options[i].name; i++)
-    ret[ind++] = o_options[i].name;
-  for (i = 0; binary_o_options[i].name; i++)
-    ret[ind++] = binary_o_options[i].name;
-  ret[ind] = (char *)NULL;
+  int i;
+
+  ret = strvec_create (N_O_OPTIONS + 1);
+  for (i = 0; o_options[i].name; i++)
+    ret[i] = o_options[i].name;
+  ret[i] = (char *)NULL;
   return ret;
 }
 
@@ -386,37 +383,33 @@ set_minus_o_option (on_or_off, option_name)
      int on_or_off;
      char *option_name;
 {
-  int option_char;
   register int i;
 
-  for (i = 0; binary_o_options[i].name; i++)
-    {
-      if (STREQ (option_name, binary_o_options[i].name))
-       {
-         SET_BINARY_O_OPTION_VALUE (i, on_or_off, option_name);
-         return (EXECUTION_SUCCESS);
-       }
-    }
-
-  for (i = 0, option_char = -1; o_options[i].name; 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 (o_options[i].letter == 0)
+           {
+             SET_BINARY_O_OPTION_VALUE (i, on_or_off, option_name);
+             return (EXECUTION_SUCCESS);
+           }
+         else
+           {
+             if (change_flag (o_options[i].letter, on_or_off) == FLAG_ERROR)
+               {
+                 sh_invalidoptname (option_name);
+                 return (EXECUTION_FAILURE);
+               }
+             else
+               return (EXECUTION_SUCCESS);
+           }
+
        }
     }
-  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);
+
+  sh_invalidoptname (option_name);
+  return (EXECUTION_FAILURE);
 }
 
 static void
@@ -448,38 +441,41 @@ void
 set_shellopts ()
 {
   char *value;
+  char tflag[N_O_OPTIONS];
   int vsize, i, vptr, *ip, exported;
   SHELL_VAR *v;
 
   for (vsize = i = 0; o_options[i].name; i++)
     {
-      ip = find_flag (o_options[i].letter);
-      if (ip && *ip)
-       vsize += strlen (o_options[i].name) + 1;
+      tflag[i] = 0;
+      if (o_options[i].letter)
+       {
+         ip = find_flag (o_options[i].letter);
+         if (ip && *ip)
+           {
+             vsize += strlen (o_options[i].name) + 1;
+             tflag[i] = 1;
+           }
+       }
+      else if (GET_BINARY_O_OPTION_VALUE (i, o_options[i].name))
+       {
+         vsize += strlen (o_options[i].name) + 1;
+         tflag[i] = 1;
+       }
     }
-  for (i = 0; binary_o_options[i].name; i++)
-    if (GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name))
-      vsize += strlen (binary_o_options[i].name) + 1;
 
   value = (char *)xmalloc (vsize + 1);
 
   for (i = vptr = 0; o_options[i].name; i++)
     {
-      ip = find_flag (o_options[i].letter);
-      if (ip && *ip)
+      if (tflag[i])
        {
          strcpy (value + vptr, o_options[i].name);
          vptr += strlen (o_options[i].name);
          value[vptr++] = ':';
        }
     }
-  for (i = 0; binary_o_options[i].name; i++)
-    if (GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name))
-      {
-       strcpy (value + vptr, binary_o_options[i].name);
-       vptr += strlen (binary_o_options[i].name);
-       value[vptr++] = ':';
-      }
+
   if (vptr)
     vptr--;                    /* cut off trailing colon */
   value[vptr] = '\0';
@@ -571,6 +567,7 @@ set_builtin (list)
   int on_or_off, flag_name, force_assignment, opts_changed;
   WORD_LIST *l;
   register char *arg;
+  char s[3];
 
   if (list == 0)
     {
@@ -579,34 +576,19 @@ set_builtin (list)
     }
 
   /* Check validity of flag arguments. */
-  if (*list->word->word == '-' || *list->word->word == '+')
+  reset_internal_getopt ();
+  while ((flag_name = internal_getopt (list, optflags)) != -1)
     {
-      for (l = list; l && (arg = l->word->word); l = l->next)
+      switch (flag_name)
        {
-         char c;
-
-         if (arg[0] != '-' && arg[0] != '+')
+         case '?':
+           builtin_usage ();
+           return (list_optopt == '?' ? EXECUTION_SUCCESS : EX_USAGE);
+         default:
            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);
-               }
-           }
        }
     }
-
+    
   /* Do the set command.  While the list consists of words starting with
      '-' or '+' treat them as flags, otherwise, start assigning them to
      $1 ... $n. */
@@ -678,11 +660,10 @@ set_builtin (list)
                }
              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);
+                 s[0] = on_or_off;
+                 s[1] = flag_name;
+                 s[2] = '\0';
+                 sh_invalidopt (s);
                  builtin_usage ();
                  set_shellopts ();
                  return (EXECUTION_FAILURE);
@@ -777,7 +758,7 @@ unset_builtin (list)
         mode when unsetting a function. */
       if (((unset_function && posixly_correct) || !unset_function) && legal_identifier (name) == 0)
        {
-         builtin_error ("`%s': not a valid identifier", name);
+         sh_invalidid (name);
          NEXT_VARIABLE ();
        }
 
@@ -807,22 +788,27 @@ unset_builtin (list)
              NEXT_VARIABLE ();
            }
          else
-           tem = unbind_array_element (var, t);
+           {
+             tem = unbind_array_element (var, t);
+             if (tem == -1)
+               any_failed++;
+           }
        }
       else
 #endif /* ARRAY_VARS */
-      tem = makunbound (name, unset_function ? shell_functions : shell_variables);
+      tem = unset_function ? unbind_func (name) : unbind_variable (name);
 
       /* 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);
+       tem = unbind_func (name);
+
+      /* SUSv3, POSIX.1-2001 say:  ``Unsetting a variable or function that
+        was not previously set shall not be considered an error.'' */
 
-      if (tem == -1)
-       any_failed++;
-      else if (!unset_function)
+      if (unset_function == 0)
        stupidly_hack_special_variables (name);
 
       list = list->next;
index dad11fdfe1c97fa821bad73857011a87febe9aad..8465e7d3f70ccae8175539b82e6c54ef05a301e1 100644 (file)
@@ -1,7 +1,7 @@
 This file is setattr.def, from which is created setattr.c.
 It implements the builtins "export" and "readonly", in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -43,7 +43,7 @@ extern char *this_command_name;
 extern sh_builtin_func_t *this_shell_builtin;
 
 #ifdef ARRAY_VARS
-extern int declare_builtin ();
+extern int declare_builtin __P((WORD_LIST *));
 #endif
 
 #define READONLY_OR_EXPORT \
@@ -51,7 +51,7 @@ extern int declare_builtin ();
 
 $BUILTIN export
 $FUNCTION export_builtin
-$SHORT_DOC export [-nf] [name ...] or export -p
+$SHORT_DOC export [-nf] [name[=value] ...] or export -p
 NAMEs are marked for automatic export to the environment of
 subsequently executed commands.  If the -f option is given,
 the NAMEs refer to functions.  If no NAMEs are given, or if `-p'
@@ -75,7 +75,7 @@ export_builtin (list)
 
 $BUILTIN readonly
 $FUNCTION readonly_builtin
-$SHORT_DOC readonly [-anf] [name ...] or readonly -p
+$SHORT_DOC readonly [-anf] [name[=value] ...] or readonly -p
 The given NAMEs are marked readonly and the values of these NAMEs may
 not be changed by subsequent assignment.  If the -f option is given,
 then functions corresponding to the NAMEs are so marked.  If no
@@ -95,6 +95,12 @@ readonly_builtin (list)
   return (set_or_show_attributes (list, att_readonly, 0));
 }
 
+#if defined (ARRAY_VARS)
+#  define ATTROPTS     "afnp"
+#else
+#  define ATTROPTS     "fnp"
+#endif
+
 /* For each variable name in LIST, make that variable have the specified
    ATTRIBUTE.  An arg of `-n' says to remove the attribute from the the
    remaining names in LIST. */
@@ -114,7 +120,7 @@ set_or_show_attributes (list, attribute, nodefs)
   undo = functions_only = arrays_only = any_failed = assign_error = 0;
   /* Read arguments from the front of the list. */
   reset_internal_getopt ();
-  while ((opt = internal_getopt (list, "anfp")) != -1)
+  while ((opt = internal_getopt (list, ATTROPTS)) != -1)
     {
       switch (opt)
        {
@@ -174,7 +180,7 @@ set_or_show_attributes (list, attribute, nodefs)
 
          if (legal_identifier (name) == 0)
            {
-             builtin_error ("`%s': not a valid identifier", name);
+             sh_invalidid (name);
              if (assign)
                assign_error++;
              else
@@ -248,11 +254,7 @@ set_or_show_attributes (list, attribute, nodefs)
              if (arrays_only && array_p (var) == 0)
                continue;
 #endif
-#if 0
-             if ((var->attributes & attribute) && invisible_p (var) == 0)
-#else
              if ((var->attributes & attribute))
-#endif
                show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
            }
          free (variable_list);
@@ -275,7 +277,7 @@ show_var_attributes (var, pattr, nodefs)
      SHELL_VAR *var;
      int pattr, nodefs;
 {
-  char flags[6], *x;
+  char flags[8], *x;
   int i;
 
   i = 0;
@@ -297,6 +299,9 @@ show_var_attributes (var, pattr, nodefs)
       if (readonly_p (var))
        flags[i++] = 'r';
 
+      if (trace_p (var))
+       flags[i++] = 't';
+
       if (exported_p (var))
        flags[i++] = 'x';
     }
@@ -313,6 +318,17 @@ show_var_attributes (var, pattr, nodefs)
 
   flags[i] = '\0';
 
+  /* If we're printing functions with definitions, print the function def
+     first, then the attributes, instead of printing output that can't be
+     reused as input to recreate the current state. */
+  if (function_p (var) && nodefs == 0 && (pattr == 0 || posixly_correct == 0))
+    {
+      printf ("%s\n", named_function_string (var->name, function_cell (var), 1));
+      nodefs++;
+      if (pattr == 0 && i == 1 && flags[0] == 'f')
+       return 0;               /* don't print `declare -f name' */
+    }
+
   if (pattr == 0 || posixly_correct == 0)
     printf ("declare -%s ", i ? flags : "-");
   else if (i)
@@ -325,7 +341,7 @@ show_var_attributes (var, pattr, nodefs)
     print_array_assignment (var, 1);
   else
 #endif
-  /* force `readline' and `export' to not print out function definitions
+  /* force `readonly' and `export' to not print out function definitions
      when in POSIX mode. */
   if (nodefs || (function_p (var) && pattr != 0 && posixly_correct))
     printf ("%s\n", var->name);
@@ -335,7 +351,7 @@ show_var_attributes (var, pattr, nodefs)
     printf ("%s\n", var->name);
   else
     {
-      x = sh_double_quote (value_cell (var) ? value_cell (var) : "");
+      x = sh_double_quote (var_isset (var) ? value_cell (var) : "");
       printf ("%s=%s\n", var->name, x);
       free (x);
     }
@@ -349,15 +365,11 @@ show_name_attributes (name, nodefs)
 {
   SHELL_VAR *var;
 
-  var = find_tempenv_variable (name);
-  if (var == 0)
-    var = find_variable (name);
+  var = find_variable_internal (name, 1);
 
   if (var && invisible_p (var) == 0)
     {
       show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
-      if (tempvar_p (var))
-       dispose_variable (var);
       return (0);
     }
   else
@@ -370,23 +382,39 @@ set_var_attribute (name, attribute, undo)
      int attribute, undo;
 {
   SHELL_VAR *var, *tv;
+  char *tvalue;
 
   if (undo)
     var = find_variable (name);
   else
     {
-      if (tv = find_tempenv_variable (name))
+      tv = find_tempenv_variable (name);
+      /* XXX -- need to handle case where tv is a temp variable in a
+        function-scope context, since function_env has been merged into
+        the local variables table. */
+      if (tv && tempvar_p (tv))
        {
-         var = bind_variable (tv->name, tv->value ? tv->value : "");
-         dispose_variable (tv);
+         tvalue = var_isset (tv) ? savestring (value_cell (tv)) : savestring ("");
+
+         var = bind_variable (tv->name, tvalue);
+         var->attributes |= tv->attributes & ~att_tempvar;
+         VSETATTR (tv, att_propagate);
+         if (var->context != 0)
+           VSETATTR (var, att_propagate);
+         SETVARATTR (tv, attribute, undo);     /* XXX */
+
+         free (tvalue);
        }
       else
-       var = find_variable (name);
-
-      if (var == 0)
        {
-         var = bind_variable (name, (char *)NULL);
-         VSETATTR (var, att_invisible);
+         var = find_variable_internal (name, 0);
+         if (var == 0)
+           {
+             var = bind_variable (name, (char *)NULL);
+             VSETATTR (var, att_invisible);
+           }
+         else if (var->context != 0)
+           VSETATTR (var, att_propagate);
        }
     }
 
index 6db7c7f68d40ea7ebd7b8b4b59d7a91c2f3d73a2..dbff0622197dd1c970133578effc7d126414570d 100644 (file)
@@ -1,7 +1,7 @@
 This file is shift.def, from which is created shift.c.
 It implements the builtin "shift" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -52,7 +52,7 @@ int
 shift_builtin (list)
      WORD_LIST *list;
 {
-  long times;
+  intmax_t times;
   register int count;
   WORD_LIST *temp;
 
@@ -62,13 +62,13 @@ shift_builtin (list)
     return (EXECUTION_SUCCESS);
   else if (times < 0)
     {
-      builtin_error ("shift count must be >= 0");
+      sh_erange (list->word->word, "shift count");
       return (EXECUTION_FAILURE);
     }
   else if (times > number_of_args ())
     {
       if (print_shift_error)
-       builtin_error ("shift count must be <= $#");
+       sh_erange (list->word->word, "shift count");
       return (EXECUTION_FAILURE);
     }
 
index 8de2aadb78f76625f09c54bc3e0ce502e2ff5d1d..ae15330dd3835204a3eb207c4765c5b9c11fc4c5 100644 (file)
@@ -1,7 +1,7 @@
 This file is shopt.def, from which is created shopt.c.
 It implements the Bash `shopt' builtin.
 
-Copyright (C) 1994 Free Software Foundation, Inc.
+Copyright (C) 1994-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -22,7 +22,6 @@ Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
 $PRODUCES shopt.c
 
 $BUILTIN shopt
-$DOCNAME shopt_builtin
 $FUNCTION shopt_builtin
 $SHORT_DOC shopt [-pqsu] [-o long-option] optname [optname...]
 Toggle the values of variables controlling optional behavior.
@@ -59,7 +58,7 @@ $END
 extern int allow_null_glob_expansion, glob_dot_filenames;
 extern int cdable_vars, mail_warning, source_uses_path;
 extern int no_exit_on_failed_exec, print_shift_error;
-extern int check_hashed_filenames, promptvars, interactive_comments;
+extern int check_hashed_filenames, promptvars;
 extern int cdspelling, expand_aliases;
 extern int check_window_size;
 extern int glob_ignore_case;
@@ -86,10 +85,11 @@ extern int prog_completion_enabled;
 #endif
 
 #if defined (RESTRICTED_SHELL)
-extern int restricted_shell;
 extern char *shell_name;
 #endif
 
+static void shopt_error __P((char *));
+
 static int set_interactive_comments __P((int));
 
 #if defined (RESTRICTED_SHELL)
@@ -268,7 +268,12 @@ find_shopt (name)
   return -1;
 }
 
-#define SHOPT_ERROR(str)       builtin_error ("%s: unknown shell option name", str)
+static void
+shopt_error (s)
+     char *s;
+{
+  builtin_error ("%s: invalid shell option name", s);
+}
 
 static int
 toggle_shopts (mode, list, quiet)
@@ -284,7 +289,7 @@ toggle_shopts (mode, list, quiet)
       ind = find_shopt (l->word->word);
       if (ind < 0)
        {
-         SHOPT_ERROR (l->word->word);
+         shopt_error (l->word->word);
          rval = EXECUTION_FAILURE;
        }
       else
@@ -334,7 +339,7 @@ list_shopts (list, flags)
       i = find_shopt (l->word->word);
       if (i < 0)
        {
-         SHOPT_ERROR (l->word->word);
+         shopt_error (l->word->word);
          rval = EXECUTION_FAILURE;
          continue;
        }
@@ -383,7 +388,7 @@ list_shopt_o_options (list, flags)
       val = minus_o_option_value (l->word->word);
       if (val == -1)
        {
-         builtin_error ("%s: unknown option name", l->word->word);
+         sh_invalidoptname (l->word->word);
          rval = EXECUTION_FAILURE;
          continue;
        }
@@ -470,7 +475,7 @@ get_shopt_options ()
   int n, i;
 
   n = sizeof (shopt_vars) / sizeof (shopt_vars[0]);
-  ret = alloc_array (n + 1);
+  ret = strvec_create (n + 1);
   for (i = 0; shopt_vars[i].name; i++)
     ret[i] = savestring (shopt_vars[i].name);
   ret[i] = (char *)NULL;
@@ -509,7 +514,7 @@ shopt_listopt (name, reusable)
   i = find_shopt (name);
   if (i < 0)
     {
-      SHOPT_ERROR (name);
+      shopt_error (name);
       return (EXECUTION_FAILURE);
     }
 
index f9086f8164a6ebed2674ccd488a55f943b5c319e..ffb23f07f10a36dde93ceacf1db34651499626ef 100644 (file)
@@ -1,7 +1,7 @@
 This file is source.def, from which is created source.c.
 It implements the builtins "." and  "source" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -55,6 +55,7 @@ $END
 #include "../shell.h"
 #include "../findcmd.h"
 #include "common.h"
+#include "bashgetopt.h"
 
 #if !defined (errno)
 extern int errno;
@@ -80,13 +81,11 @@ int source_searches_cwd = 1;
 static void
 maybe_pop_dollar_vars ()
 {
-  if (variable_context == 0 && dollar_vars_changed ())
-    {
-      dispose_saved_dollar_vars ();
-      set_dollar_vars_unchanged ();
-    }
+  if (variable_context == 0 && (dollar_vars_changed () & ARGS_SETBLTIN))
+    dispose_saved_dollar_vars ();
   else
     pop_dollar_vars ();
+  set_dollar_vars_unchanged ();
 }
 
 /* Read and execute commands from the file passed as argument.  Guess what.
@@ -100,6 +99,10 @@ source_builtin (list)
   int result;
   char *filename;
 
+  if (no_options (list))
+    return (EX_USAGE);
+  list = loptend;
+
   if (list == 0)
     {
       builtin_error ("filename argument required");
@@ -107,13 +110,10 @@ source_builtin (list)
       return (EX_USAGE);
     }
 
-  if (no_options (list))
-    return (EX_USAGE);
-
 #if defined (RESTRICTED_SHELL)
   if (restricted && strchr (list->word->word, '/'))
     {
-      builtin_error ("%s: restricted", list->word->word);
+      sh_restricted (list->word->word);
       return (EXECUTION_FAILURE);
     }
 #endif
index c1dc6d142c5f83cd70d6af103bb839cf4ccf8da6..43391c0d784fd3d362e44c88d474c53b2075562f 100644 (file)
@@ -1,7 +1,7 @@
 This file is suspend.def, from which is created suspend.c.
 It implements the builtin "suspend" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -89,7 +89,7 @@ suspend_builtin (list)
 
   if (job_control == 0)
     {
-      builtin_error ("cannot suspend a shell without job control");
+      sh_nojobs ("cannot suspend");
       return (EXECUTION_FAILURE);
     }
 
index d3288764471e7095557d51f23c0b5997e9b3179b..e51d00b7a4bb15e3362193273d49d4836ecf1fa5 100644 (file)
@@ -1,7 +1,7 @@
 This file is test.def, from which is created test.c.
 It implements the builtin "test" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -24,7 +24,7 @@ $PRODUCES test.c
 $BUILTIN test
 $FUNCTION test_builtin
 $SHORT_DOC test [expr]
-Exits with a status of 0 (trueness) or 1 (falseness) depending on
+Exits with a status of 0 (true) or 1 (false) depending on
 the evaluation of EXPR.  Expressions may be unary or binary.  Unary
 expressions are often used to examine the status of a file.  There
 are string operators as well, and numeric comparison operators.
index 4dba72489652be0708c6dc9d0678ca9ea4fea10f..22304fc2f92c00c4a25fcf3469dad27063640410 100644 (file)
@@ -1,7 +1,7 @@
 This file is times.def, from which is created times.c.
 It implements the builtin "times" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -61,6 +61,11 @@ times_builtin (list)
 #if defined (HAVE_GETRUSAGE) && defined (HAVE_TIMEVAL) && defined (RUSAGE_SELF)
   struct rusage self, kids;
 
+  USE_VAR(list);
+
+  if (no_options (list))
+    return (EX_USAGE);
+
   getrusage (RUSAGE_SELF, &self);
   getrusage (RUSAGE_CHILDREN, &kids);  /* terminated child processes */
 
@@ -79,6 +84,11 @@ times_builtin (list)
      `struct tms' with values of type clock_t. */
   struct tms t;
 
+  USE_VAR(list);
+
+  if (no_options (list))
+    return (EX_USAGE);
+
   times (&t);
 
   print_clock_t (stdout, t.tms_utime);
@@ -89,8 +99,15 @@ times_builtin (list)
   putchar (' ');
   print_clock_t (stdout, t.tms_cstime);
   putchar ('\n');
+
 #  else /* !HAVE_TIMES */
+
+  USE_VAR(list);
+
+  if (no_options (list))
+    return (EX_USAGE);
   printf ("0.00 0.00\n0.00 0.00\n");
+
 #  endif /* HAVE_TIMES */
 #endif /* !HAVE_TIMES */
 
index 933bd25a421cd7af77c71431ecc535ecb0af0ee6..af9e6d6c1b535644024bee4af25192758ce535c6 100644 (file)
@@ -1,7 +1,7 @@
 This file is trap.def, from which is created trap.c.
 It implements the builtin "trap" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -137,8 +137,7 @@ trap_builtin (list)
 
          if (sig == NO_SIG)
            {
-             builtin_error ("%s: not a signal specification",
-                            list->word->word);
+             sh_invalidsig (list->word->word);
              result = EXECUTION_FAILURE;
            }
          else
@@ -239,8 +238,8 @@ display_traps (list)
       i = decode_signal (list->word->word);
       if (i == NO_SIG)
        {
+         sh_invalidsig (list->word->word);
          result = EXECUTION_FAILURE;
-         builtin_error ("%s: not a signal specification", list->word->word);
        }
       else
        showtrap (i);
index 9510a0e6f079530fe7c39d48d27621703c34d9cf..2d9d2a56b54bd4cdba89f8121351f3c9bb5715ef 100644 (file)
@@ -1,7 +1,7 @@
 This file is type.def, from which is created type.c.
 It implements the builtin "type" in Bash.
 
-Copyright (C) 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -23,7 +23,7 @@ $PRODUCES type.c
 
 $BUILTIN type
 $FUNCTION type_builtin
-$SHORT_DOC type [-apt] name [name ...]
+$SHORT_DOC type [-afptP] name [name ...]
 For each NAME, indicate how it would be interpreted if used as a
 command name.
 
@@ -37,8 +37,14 @@ file that would be executed, or nothing if `type -t NAME' would not
 return `file'.
 
 If the -a flag is used, `type' displays all of the places that contain
-an executable named `file'.  This includes aliases and functions, if
-and only if the -p flag is not also used.
+an executable named `file'.  This includes aliases, builtins, and
+functions, if and only if the -p flag is not also used.
+
+The -f flag suppresses shell function lookup.
+
+The -P flag forces a PATH search for each NAME, even if it is an alias,
+builtin, or function, and returns the name of the disk file that would
+be executed.
 $END
 
 #include <config.h>
@@ -82,6 +88,12 @@ extern char *this_command_name;
        -a              Returns all occurrences of words, whether they
                        be a filename in the path, alias, function,
                        or builtin.
+
+       -f              Suppress shell function lookup, like `command'.
+
+       -P              Force a path search even in the presence of other
+                       definitions.
+
    Order of evaluation:
        alias
        keyword
@@ -94,72 +106,62 @@ int
 type_builtin (list)
      WORD_LIST *list;
 {
-  int path_only, type_only, all, verbose;
-  int successful_finds, opt;
-  WORD_LIST *prev, *this;
+  int dflags, successful_finds, opt;
+  WORD_LIST *this;
 
   if (list == 0)
     return (EXECUTION_SUCCESS);
 
-  path_only = type_only = all = 0;
+  dflags = CDESC_SHORTDESC;    /* default */
   successful_finds = 0;
 
   /* Handle the obsolescent `-type', `-path', and `-all' by prescanning
-     the arguments and removing those options from the list before calling
-     internal_getopt.  Recognize `--type', `--path', and `--all' also.
-     THIS SHOULD REALLY GO AWAY. */
-  for (this = list; this && this->word->word[0] == '-'; )
+     the arguments and converting those options to the form that
+     internal_getopt recognizes. Converts `--type', `--path', and `--all'
+     also. THIS SHOULD REALLY GO AWAY. */
+  for (this = list; this && this->word->word[0] == '-'; this = this->next)
     {
       char *flag = &(this->word->word[1]);
 
       if (STREQ (flag, "type") || STREQ (flag, "-type"))
        {
-         type_only = 1;
-         path_only = 0;
+         this->word->word[1] = 't';
+         this->word->word[2] = '\0';
        }
       else if (STREQ (flag, "path") || STREQ (flag, "-path"))
        {
-         path_only = 1;
-         type_only = 0;
+         this->word->word[1] = 'p';
+         this->word->word[2] = '\0';
        }
       else if (STREQ (flag, "all") || STREQ (flag, "-all"))
-       all = 1;
-      else
-       {
-         prev = this;
-         this = this->next;
-         continue;
-       }
-
-      /* We found a long option; remove it from the argument list.  Don't
-        free it if it's the head of the argument list, though -- the
-        argument list will be freed by the caller. */
-      if (this == list)
-       this = list = list->next;
-      else
        {
-         prev->next = this->next;
-         this->next = (WORD_LIST *)NULL;
-         dispose_words (this);
-         this = prev->next;
+         this->word->word[1] = 'a';
+         this->word->word[2] = '\0';
        }
     }
 
   reset_internal_getopt ();
-  while ((opt = internal_getopt (list, "apt")) != -1)
+  while ((opt = internal_getopt (list, "afptP")) != -1)
     {
       switch (opt)
        {
-       case 't':
-         type_only = 1;
-         path_only = 0;
+       case 'a':
+         dflags |= CDESC_ALL;
+         break;
+       case 'f':
+         dflags |= CDESC_NOFUNCS;
          break;
        case 'p':
-         path_only = 1;
-         type_only = 0;
+         dflags |= CDESC_PATH_ONLY;
+         dflags &= ~(CDESC_TYPE|CDESC_SHORTDESC);
          break;
-       case 'a':
-         all = 1;
+       case 't':
+         dflags |= CDESC_TYPE;
+         dflags &= ~(CDESC_PATH_ONLY|CDESC_SHORTDESC);
+         break;
+       case 'P':       /* shorthand for type -ap */
+         dflags |= (CDESC_PATH_ONLY|CDESC_FORCE_PATH);
+         dflags &= ~(CDESC_TYPE|CDESC_SHORTDESC);
          break;
        default:
          builtin_usage ();
@@ -168,23 +170,14 @@ type_builtin (list)
     }
   list = loptend;
 
-  if (type_only)
-    verbose = 1;
-  else if (path_only == 0)
-    verbose = 2;
-  else if (path_only)
-    verbose = 3;
-  else
-    verbose = 0;
-
   while (list)
     {
       int found;
 
-      found = describe_command (list->word->word, verbose, all);
+      found = describe_command (list->word->word, dflags);
 
-      if (!found && !path_only && !type_only)
-       builtin_error ("%s: not found", list->word->word);
+      if (!found && (dflags & (CDESC_PATH_ONLY|CDESC_TYPE)) == 0)
+       sh_notfound (list->word->word);
 
       successful_finds += found;
       list = list->next;
@@ -196,43 +189,45 @@ type_builtin (list)
 }
 
 /*
- * Describe COMMAND as required by the type builtin.
+ * Describe COMMAND as required by the type and command builtins.
  *
- * If VERBOSE == 0, don't print anything
- * If VERBOSE == 1, print short description as for `type -t'
- * If VERBOSE == 2, print long description as for `type' and `command -V'
- * If VERBOSE == 3, print path name only for disk files
- * If VERBOSE == 4, print string used to invoke COMMAND, for `command -v'
+ * Behavior is controlled by DFLAGS.  Flag values are
+ *     CDESC_ALL       print all descriptions of a command
+ *     CDESC_SHORTDESC print the description for type and command -V
+ *     CDESC_REUSABLE  print in a format that may be reused as input
+ *     CDESC_TYPE      print the type for type -t
+ *     CDESC_PATH_ONLY print the path for type -p
+ *     CDESC_FORCE_PATH        force a path search for type -P
+ *     CDESC_NOFUNCS   skip function lookup for type -f
  *
- * ALL says whether or not to look for all occurrences of COMMAND, or
+ * CDESC_ALL says whether or not to look for all occurrences of COMMAND, or
  * return after finding it once.
  */
 int
-describe_command (command, verbose, all)
+describe_command (command, dflags)
      char *command;
-     int verbose, all;
+     int dflags;
 {
-  int found, i, found_file, f;
+  int found, i, found_file, f, all;
   char *full_path, *x;
   SHELL_VAR *func;
 #if defined (ALIAS)
   alias_t *alias;
 #endif
 
+  all = (dflags & CDESC_ALL) != 0;
   found = found_file = 0;
   full_path = (char *)NULL;
 
 #if defined (ALIAS)
   /* Command is an alias? */
-  alias = find_alias (command);
-
-  if (alias)
+  if (((dflags & CDESC_FORCE_PATH) == 0) && (alias = find_alias (command)))
     {
-      if (verbose == 1)
+      if (dflags & CDESC_TYPE)
        puts ("alias");
-      else if (verbose == 2)
+      else if (dflags & CDESC_SHORTDESC)
        printf ("%s is aliased to `%s'\n", command, alias->value);
-      else if (verbose == 4)
+      else if (dflags & CDESC_REUSABLE)
        {
          x = sh_single_quote (alias->value);
          printf ("alias %s=%s\n", command, x);
@@ -247,14 +242,13 @@ describe_command (command, verbose, all)
 #endif /* ALIAS */
 
   /* Command is a shell reserved word? */
-  i = find_reserved_word (command);
-  if (i >= 0)
+  if (((dflags & CDESC_FORCE_PATH) == 0) && (i = find_reserved_word (command)) >= 0)
     {
-      if (verbose == 1)
+      if (dflags & CDESC_TYPE)
        puts ("keyword");
-      else if (verbose == 2)
+      else if (dflags & CDESC_SHORTDESC)
        printf ("%s is a shell keyword\n", command);
-      else if (verbose == 4)
+      else if (dflags & CDESC_REUSABLE)
        printf ("%s\n", command);
 
       found = 1;
@@ -264,13 +258,11 @@ describe_command (command, verbose, all)
     }
 
   /* Command is a function? */
-  func = find_function (command);
-
-  if (func)
+  if (((dflags & (CDESC_FORCE_PATH|CDESC_NOFUNCS)) == 0) && (func = find_function (command)))
     {
-      if (verbose == 1)
+      if (dflags & CDESC_TYPE)
        puts ("function");
-      else if (verbose == 2)
+      else if (dflags & CDESC_SHORTDESC)
        {
 #define PRETTY_PRINT_FUNC 1
          char *result;
@@ -285,7 +277,7 @@ describe_command (command, verbose, all)
          printf ("%s\n", result);
 #undef PRETTY_PRINT_FUNC
        }
-      else if (verbose == 4)
+      else if (dflags & CDESC_REUSABLE)
        printf ("%s\n", command);
 
       found = 1;
@@ -295,13 +287,13 @@ describe_command (command, verbose, all)
     }
 
   /* Command is a builtin? */
-  if (find_shell_builtin (command))
+  if (((dflags & CDESC_FORCE_PATH) == 0) && find_shell_builtin (command))
     {
-      if (verbose == 1)
+      if (dflags & CDESC_TYPE)
        puts ("builtin");
-      else if (verbose == 2)
+      else if (dflags & CDESC_SHORTDESC)
        printf ("%s is a shell builtin\n", command);
-      else if (verbose == 4)
+      else if (dflags & CDESC_REUSABLE)
        printf ("%s\n", command);
 
       found = 1;
@@ -318,11 +310,11 @@ describe_command (command, verbose, all)
       f = file_status (command);
       if (f & FS_EXECABLE)
        {
-         if (verbose == 1)
+         if (dflags & CDESC_TYPE)
            puts ("file");
-         else if (verbose == 2)
+         else if (dflags & CDESC_SHORTDESC)
            printf ("%s is %s\n", command, command);
-         else if (verbose == 3 || verbose == 4)
+         else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
            printf ("%s\n", command);
 
          /* There's no use looking in the hash table or in $PATH,
@@ -334,15 +326,15 @@ describe_command (command, verbose, all)
 
   /* If the user isn't doing "-a", then we might care about
      whether the file is present in our hash table. */
-  if (all == 0)
+  if (all == 0 || (dflags & CDESC_FORCE_PATH))
     {
-      if ((full_path = find_hashed_filename (command)) != (char *)NULL)
+      if (full_path = phash_search (command))
        {
-         if (verbose == 1)
+         if (dflags & CDESC_TYPE)
            puts ("file");
-         else if (verbose == 2)
+         else if (dflags & CDESC_SHORTDESC)
            printf ("%s is hashed (%s)\n", command, full_path);
-         else if (verbose == 3 || verbose == 4)
+         else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
            printf ("%s\n", full_path);
 
          free (full_path);
@@ -376,18 +368,18 @@ describe_command (command, verbose, all)
              if (all == 0)
                break;
            }
-         else if (verbose >= 2)
+         else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY|CDESC_SHORTDESC))
            full_path = sh_makepath ((char *)NULL, full_path, MP_DOCWD);
        }
 
       found_file++;
       found = 1;
 
-      if (verbose == 1)
+      if (dflags & CDESC_TYPE)
        puts ("file");
-      else if (verbose == 2)
+      else if (dflags & CDESC_SHORTDESC)
        printf ("%s is %s\n", command, full_path);
-      else if (verbose == 3 || verbose == 4)
+      else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
        printf ("%s\n", full_path);
 
       free (full_path);
index a830fb58666e3141c4c8361b48899304bc5c7d34..3e147b4f26b25c7bd532b111fc4198b15d29d600 100644 (file)
@@ -1,7 +1,7 @@
 This file is ulimit.def, from which is created ulimit.c.
 It implements the builtin "ulimit" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -327,7 +327,7 @@ ulimit_builtin (list)
         {
           if (STREQ (list->word->word, "unlimited") == 0)
             {
-              builtin_error ("invalid limit argument: %s", list->word->word);
+              builtin_error ("%s: invalid limit argument", list->word->word);
               return (EXECUTION_FAILURE);
             }
           return (set_all_limits (mode == 0 ? LIMIT_SOFT|LIMIT_HARD : mode, RLIM_INFINITY));
@@ -353,7 +353,7 @@ ulimit_builtin (list)
       limind = _findlim (cmdlist[c].cmd);
       if (limind == -1)
        {
-         builtin_error ("bad command: `%c'", cmdlist[c].cmd);
+         builtin_error ("`%c': bad command", cmdlist[c].cmd);
          return (EX_USAGE);
        }
     }
@@ -382,8 +382,8 @@ ulimit_internal (cmd, cmdarg, mode, multiple)
   opt = get_limit (limind, &soft_limit, &hard_limit);
   if (opt < 0)
     {
-      builtin_error ("cannot get %s limit: %s", limits[limind].description,
-                                               strerror (errno));
+      builtin_error ("%s: cannot get limit: %s", limits[limind].description,
+                                                strerror (errno));
       return (EXECUTION_FAILURE);
     }
 
@@ -408,20 +408,20 @@ ulimit_internal (cmd, cmdarg, mode, multiple)
 
       if ((real_limit / block_factor) != limit)
        {
-         builtin_error ("limit out of range: %s", cmdarg);
+         sh_erange (cmdarg, "limit");
          return (EXECUTION_FAILURE);
        }
     }
   else
     {
-      builtin_error ("bad non-numeric arg `%s'", cmdarg);
+      sh_invalidnum (cmdarg);
       return (EXECUTION_FAILURE);
     }
 
   if (set_limit (limind, real_limit, mode) < 0)
     {
-      builtin_error ("cannot modify %s limit: %s", limits[limind].description,
-                                                  strerror (errno));
+      builtin_error ("%s: cannot modify limit: %s", limits[limind].description,
+                                                   strerror (errno));
       return (EXECUTION_FAILURE);
     }
 
@@ -618,23 +618,19 @@ static int
 getmaxuprc (valuep)
      RLIMTYPE *valuep;
 {
-#  if defined (HAVE_SYSCONF) && defined (_SC_CHILD_MAX)
   long maxchild;
-  maxchild = sysconf (_SC_CHILD_MAX);
+
+  maxchild = getmaxchild ();
   if (maxchild < 0)
-    return -1;
+    {
+      errno = EINVAL;
+      return -1;
+    }
   else
-    *valuep = (RLIMTYPE) maxchild;
-  return 0;
-#  else /* !HAVE_SYSCONF || !_SC_CHILD_MAX */
-#    if defined (MAXUPRC)
-  *valuep = (RLIMTYPE) MAXUPRC;
-  return 0;
-#    else /* MAXUPRC */
-  errno = EINVAL;
-  return -1;
-#    endif /* !MAXUPRC */
-#  endif /* !HAVE_SYSCONF || !_SC_CHILD_MAX */
+    {
+      *valuep = (RLIMTYPE) maxchild;
+      return 0;
+    }
 }
 
 static void
@@ -650,7 +646,8 @@ print_all_limits (mode)
   for (i = 0; limits[i].option > 0; i++)
     {
       if (get_limit (i, &softlim, &hardlim) < 0)
-       builtin_error ("cannot get %s limit: %s", limits[i].description, strerror (errno));
+       builtin_error ("%s: cannot get limit: %s", limits[i].description,
+                                                  strerror (errno));
       else
        printone (i, (mode & LIMIT_SOFT) ? softlim : hardlim, 1);
     }
@@ -716,8 +713,8 @@ set_all_limits (mode, newlim)
   for (retval = i = 0; limits[i].option > 0; i++)
     if (set_limit (i, newlim, mode) < 0)
       {
-       builtin_error ("cannot modify %s limit: %s", limits[i].description,
-                                                    strerror (errno));
+       builtin_error ("%s: cannot modify limit: %s", limits[i].description,
+                                                     strerror (errno));
        retval = 1;
       }
   return retval;
index 4d62184a71a0f6e61efd9203edd073bc96083b1c..19a0ac0d692d17e72f881fcc967b7188d49f9fdf 100644 (file)
@@ -1,7 +1,7 @@
 This file is umask.def, from which is created umask.c.
 It implements the builtin "umask" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -107,8 +107,7 @@ umask_builtin (list)
             is lousy. */
          if (umask_value == -1)
            {
-             builtin_error ("`%s' is not an octal number from 000 to 777",
-                               list->word->word);
+             sh_erange (list->word->word, "octal number");
              return (EXECUTION_FAILURE);
            }
        }
@@ -222,7 +221,7 @@ parse_symbolic_mode (mode, initial_bits)
        case '=':
          break;
        default:
-         builtin_error ("bad symbolic mode operator: %c", op);
+         builtin_error ("`%c': invalid symbolic mode operator", op);
          return (-1);
        }
 
@@ -275,7 +274,7 @@ parse_symbolic_mode (mode, initial_bits)
        }
       else
        {
-         builtin_error ("bad character in symbolic mode: %c", *s);
+         builtin_error ("`%c': invalid symbolic mode character", *s);
          return (-1);
        }
     }
index f34da8d4e119b04a08cf7eefb3a10e0a4b38809d..23c8b19f6b5d07a432d421776080555c88561155 100644 (file)
@@ -1,7 +1,7 @@
 This file is wait.def, from which is created wait.c.
 It implements the builtin "wait" in Bash.
 
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -60,6 +60,7 @@ $END
 #include "bashgetopt.h"
 
 extern int interrupt_immediately;
+extern int wait_signal_received;
 
 procenv_t wait_intr_buf;
 
@@ -87,8 +88,7 @@ wait_builtin (list)
 
   if (no_options (list))
     return (EX_USAGE);
-  if (list != loptend)
-    list = loptend;
+  list = loptend;
 
   old_interrupt_immediately = interrupt_immediately;
   interrupt_immediately++;
@@ -104,7 +104,7 @@ wait_builtin (list)
   code = setjmp (wait_intr_buf);
   if (code)
     {
-      status = 128 + SIGINT;
+      status = 128 + wait_signal_received;
       WAIT_RETURN (status);
     }
 
@@ -124,7 +124,7 @@ wait_builtin (list)
     {
       pid_t pid;
       char *w;
-      long pid_value;
+      intmax_t pid_value;
 
       w = list->word->word;
       if (DIGIT (*w))
@@ -136,7 +136,7 @@ wait_builtin (list)
            }
          else
            {
-             builtin_error ("`%s' is not a pid or valid job spec", w);
+             sh_badpid (w);
              WAIT_RETURN (EXECUTION_FAILURE);
            }
        }
@@ -153,7 +153,7 @@ wait_builtin (list)
          if (job < 0 || job >= job_slots || !jobs[job])
            {
              if (job != DUP_JOB)
-               builtin_error ("%s: no such job", list->word->word);
+               sh_badjob (list->word->word);
              UNBLOCK_CHILD (oset);
              status = 127;     /* As per Posix.2, section 4.70.2 */
              list = list->next;
@@ -167,13 +167,13 @@ wait_builtin (list)
       else if (job_control == 0 && *w == '%')
        {
          /* can't use jobspecs as arguments if job control is not active. */
-         builtin_error ("job control not enabled");
+         sh_nojobs ((char *)NULL);
          status = EXECUTION_FAILURE;
        }
 #endif /* JOB_CONTROL */
       else
        {
-         builtin_error ("`%s' is not a pid or valid job spec", w);
+         sh_badpid (w);
          status = EXECUTION_FAILURE;
        }
       list = list->next;
index a0697abe6aba62ea0c617d61fcf6d1dcf0e6272e..e72b3eedcfa99d972e2c45dabf38a37e0c5c59b1 100644 (file)
--- a/command.h
+++ b/command.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_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_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
 };
 
 /* Redirection errors. */
@@ -55,6 +56,11 @@ enum r_instruction {
        ri == r_appending_to || \
        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,
@@ -68,6 +74,7 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
 #define W_NOSPLIT      0x10    /* Do not perform word splitting on this word. */
 #define W_NOGLOB       0x20    /* Do not perform globbing on this word. */
 #define W_NOSPLIT2     0x40    /* Don't split word except for $@ expansion. */
+#define W_TILDEEXP     0x80    /* Tilde expand this assignment word */
 
 /* Possible values for subshell_environment */
 #define SUBSHELL_ASYNC 0x01    /* subshell caused by `command &' */
index cf10140c678dfbddecf5aa37ee062e6e35bd9192..76732998ec8a3f304b4cbcee2df13d768ff65bf3 100644 (file)
@@ -1,6 +1,24 @@
 /* config-bot.h */
 /* modify settings or make new ones based on what autoconf tells us. */
 
+/* Copyright (C) 1989-2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 #if !defined (HAVE_VPRINTF) && defined (HAVE_DOPRNT)
 #  define USE_VFPRINTF_EMULATION
 #  define HAVE_VPRINTF
 #  undef PPROMPT
 #  define PPROMPT "$ "
 #endif
+
+/************************************************/
+/* check multibyte capability for I18N code    */
+/************************************************/
+
+/* For platforms which support the ISO C amendement 1 functionality we
+   support user defined character classes.  */
+/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
+#if defined (HAVE_WCTYPE_H) && defined (HAVE_WCHAR_H)
+#  include <wchar.h>
+#  include <wctype.h>
+#  if defined (HAVE_MBSRTOWCS) /* system is supposed to support XPG5 */
+#    define HANDLE_MULTIBYTE      1
+#  endif
+#endif
+
+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
+#if HANDLE_MULTIBYTE && !defined (HAVE_MBSTATE_T)
+#  define wcsrtombs(dest, src, len, ps) (wcsrtombs) (dest, src, len, 0)
+#  define mbsrtowcs(dest, src, len, ps) (mbsrtowcs) (dest, src, len, 0)
+#  define wcrtomb(s, wc, ps) (wcrtomb) (s, wc, 0)
+#  define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
+#  define mbrlen(s, n, ps) (mbrlen) (s, n, 0)
+#  define mbstate_t int
+#endif
+
+/* Make sure MB_LEN_MAX is at least 16 (some systems define
+   MB_LEN_MAX as 1) */
+#ifdef HANDLE_MULTIBYTE
+#  include <limits.h>
+#  if defined(MB_LEN_MAX) && (MB_LEN_MAX < 16)
+#    undef MB_LEN_MAX
+#  endif
+#  if !defined (MB_LEN_MAX)
+#    define MB_LEN_MAX 16
+#  endif
+#endif
+
+/************************************************/
+/* end of multibyte capability checks for I18N */
+/************************************************/
index 3b0ac06054cfefc51666acfd7c5d34da74aa7feb..b2bcffab58959934d25189c8cbb8091334600470 100644 (file)
@@ -3,6 +3,24 @@
 /* This contains various user-settable options not under the control of
    autoconf. */
 
+/* Copyright (C) 2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 /* Define CONTINUE_AFTER_KILL_ERROR if you want the kill command to
    continue processing arguments after one of them fails.  This is
    what POSIX.2 specifies. */
 #define PPROMPT "\\s-\\v\\$ "
 #define SPROMPT "> "
 
+/* Undefine this if you don't want the ksh-compatible behavior of reprinting
+   the select menu after a valid choice is made only if REPLY is set to NULL
+   in the body of the select command.  The menu is always reprinted if the
+   reply to the select query is an empty line. */
+#define KSH_COMPATIBLE_SELECT
+
 /* System-wide .bashrc file for interactive shells. */
 /* #define SYS_BASHRC "/etc/bash.bashrc" */
 
index 580217abfc2c61fb2df1ffeff83d1bd9f9f72266..ff28c0d15497ffe1b4d98ac997aa6838da3ead47 100644 (file)
@@ -1,6 +1,6 @@
 /* config.h -- Configuration file for bash. */
 
-/* Copyright (C) 1987-2001 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
    and the complete builtin. */
 #undef PROGRAMMABLE_COMPLETION
 
+/* Define MEMSCRAMBLE if you want the bash malloc and free to scramble
+   memory contents on malloc() and free(). */
+#undef MEMSCRAMBLE
+
 /* Define AFS if you are using Transarc's AFS. */
 #undef AFS
 
 /* Define if using the bash version of malloc in lib/malloc/malloc.c */
 #undef USING_BASH_MALLOC
 
+#undef DISABLE_MALLOC_WRAPPERS
+
 /* Define if using alloca.c.  */
 #undef C_ALLOCA
 
 
 #undef HAVE_TIMEVAL
 
+#undef HAVE_TZNAME
+
 
 /* Characteristics of some of the system structures. */
 
 
 #undef STRUCT_WINSIZE_IN_SYS_IOCTL
 
+#undef TM_IN_SYS_TIME
+
 #undef STRUCT_WINSIZE_IN_TERMIOS
 
 #undef SPEED_T_IN_SYS_TYPES
 
 #undef HAVE_STRUCT_STAT_ST_BLOCKS
 
+#undef HAVE_STRUCT_TM_TM_ZONE
+#undef HAVE_TM_ZONE
+
 /* Characteristics of definitions in the system header files. */
 
 #undef HAVE_GETPW_DECLS
 
 #undef HAVE_LIBC_FNM_EXTMATCH
 
+
 #undef HAVE_DECL_CONFSTR
 
-#undef HAVE_DECL_STRTOLD
+#undef HAVE_DECL_PRINTF
 
 #undef HAVE_DECL_SBRK
 
-#undef HAVE_DECL_PRINTF
+#undef HAVE_DECL_STRCPY
 
 #undef HAVE_DECL_STRSIGNAL
 
+#undef HAVE_DECL_STRTOLD
+
+
+#undef HAVE_MBSTATE_T
+
 /* These are checked with BASH_CHECK_DECL */
 
 #undef HAVE_DECL_STRTOIMAX
 
 #undef CAN_REDEFINE_GETENV
 
+#undef HAVE_STD_PUTENV
+
+#undef HAVE_STD_UNSETENV
+
 #undef HAVE_PRINTF_A_FORMAT
 
+/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+#undef HAVE_LANGINFO_CODESET
+
 /* Characteristics of properties exported by the kernel. */
 
 /* Define if the kernel can exec files beginning with #! */
 /* Define if you have the getservbyname function.  */
 #undef HAVE_GETSERVBYNAME
 
+/* Define if you have the getservent function.  */
+#undef HAVE_GETSERVENT
+
 /* Define if you have the gettext function. */
 #undef HAVE_GETTEXT
 
 /* Define if you have the isgraph function.  */
 #undef HAVE_ISGRAPH
 
+/* Define if you have the isint function in libc */
+#undef HAVE_ISINF_IN_LIBC
+
 /* Define if you have the isprint function.  */
 #undef HAVE_ISPRINT
 
 /* Define if you have the lstat function. */
 #undef HAVE_LSTAT
 
+/* Define if you have the mbsrtowcs function. */
+#undef HAVE_MBSRTOWCS
+
 /* Define if you have the memmove function.  */
 #undef HAVE_MEMMOVE
 
+/* Define if you have the memset function.  */
+#undef HAVE_MEMSET
+
 /* Define if you have the mkfifo function.  */
 #undef HAVE_MKFIFO
 
 /* Define if you have the strerror function.  */
 #undef HAVE_STRERROR
 
+/* Define if you have the strftime function. */
+#undef HAVE_STRFTIME
+
 /* Define if you have the strpbrk function. */
 #undef HAVE_STRPBRK
 
 /* Define if you have the uname function. */
 #undef HAVE_UNAME
 
+/* Define if you have the unsetenv function.  */
+#undef HAVE_UNSETENV
+
 /* Define if you have the vasprintf function.  */
 #undef HAVE_VASPRINTF
 
 /* Define if you have the wait3 function.  */
 #undef HAVE_WAIT3
 
+/* Define if you have the wcwidth function.  */
+#undef HAVE_WCWIDTH
+
 /* Presence of certain system include files. */
 
 /* Define if you have the <arpa/inet.h> header file. */
 /* Define if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
+/* Define if you have the <langinfo.h> header file.  */
+#undef HAVE_LANGINFO_H
+
 /* Define if you have the <libintl.h> header file. */
 #undef HAVE_LIBINTL_H
 
 /* Define if you have the <varargs.h> header file.  */
 #undef HAVE_VARARGS_H
 
+/* Define if you have the <wchar.h> header file.  */
+#undef HAVE_WCHAR_H
+
+/* Define if you have the <varargs.h> header file.  */
+#undef HAVE_WCTYPE_H
+
 /* Presence of certain system libraries. */
 
 #undef HAVE_LIBDL
index a18067f8dfb3d36e4b5359d1200d0225ba16a09b..58b0a7fb2688ce2a7fced098827a690b259ec67f 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,7 +1,7 @@
 #! /bin/sh
-# From configure.in for Bash 2.05a, version 2.128, from autoconf version 2.52.
+# From configure.in for Bash 2.05b, version 2.144, from autoconf version 2.52.
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by Autoconf 2.52 for bash 2.05a.
+# Generated by Autoconf 2.52 for bash 2.05b.
 #
 # Report bugs to <bug-bash@gnu.org>.
 #
@@ -186,8 +186,8 @@ mandir='${prefix}/man'
 # Identity of this package.
 PACKAGE_NAME='bash'
 PACKAGE_TARNAME='bash'
-PACKAGE_VERSION='2.05a'
-PACKAGE_STRING='bash 2.05a'
+PACKAGE_VERSION='2.05b'
+PACKAGE_STRING='bash 2.05b'
 PACKAGE_BUGREPORT='bug-bash@gnu.org'
 
 ac_prev=
@@ -604,7 +604,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<EOF
-\`configure' configures bash 2.05a to adapt to many kinds of systems.
+\`configure' configures bash 2.05b to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -665,52 +665,70 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of bash 2.05a:";;
+     short | recursive ) echo "Configuration of bash 2.05b:";;
    esac
   cat <<\EOF
 
 Optional Features:
   --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
   --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
---enable-minimal-config        a minimal sh-like configuration
---enable-alias         enable shell aliases
---enable-arith-for-command     enable arithmetic for command
---enable-array-variables       include shell array variables
---enable-bang-history  turn on csh-style history substitution
---enable-brace-expansion       include brace expansion
---enable-command-timing        enable the time reserved word and command timing
---enable-cond-command  enable the conditional command
---enable-directory-stack       enable builtins pushd/popd/dirs
---enable-disabled-builtins     allow disabled builtins to still be invoked
---enable-dparen-arithmetic     include ((...)) command
---enable-extended-glob include ksh-style extended pattern matching
---enable-help-builtin  include the help builtin
---enable-history       turn on command history
---enable-job-control   enable job control features
---enable-largefile     enable support for large files
---enable-net-redirections      enable /dev/tcp/host/port redirection
---enable-process-substitution  enable process substitution
---enable-progcomp      enable programmable completion and the complete builtin
---enable-prompt-string-decoding        turn on escape character decoding in prompts
---enable-readline      turn on command line editing
---enable-restricted    enable a restricted shell
---enable-select                include select command
---enable-usg-echo-default      a synonym for --enable-xpg-echo-default
---enable-xpg-echo-default      make the echo builtin expand escape sequences by default
---enable-profiling             allow profiling with gprof
---enable-static-link           link bash statically, for use as a root shell
+  --enable-minimal-config a minimal sh-like configuration
+  --enable-alias          enable shell aliases
+  --enable-arith-for-command
+                          enable arithmetic for command
+  --enable-array-variables
+                          include shell array variables
+  --enable-bang-history   turn on csh-style history substitution
+  --enable-brace-expansion
+                          include brace expansion
+  --enable-command-timing enable the time reserved word and command timing
+  --enable-cond-command   enable the conditional command
+  --enable-directory-stack
+                          enable builtins pushd/popd/dirs
+  --enable-disabled-builtins
+                          allow disabled builtins to still be invoked
+  --enable-dparen-arithmetic
+                          include ((...)) command
+  --enable-extended-glob  include ksh-style extended pattern matching
+  --enable-help-builtin   include the help builtin
+  --enable-history        turn on command history
+  --enable-job-control    enable job control features
+  --enable-net-redirections
+                          enable /dev/tcp/host/port redirection
+  --enable-process-substitution
+                          enable process substitution
+  --enable-progcomp       enable programmable completion and the complete
+                          builtin
+  --enable-prompt-string-decoding
+                          turn on escape character decoding in prompts
+  --enable-readline       turn on command line editing
+  --enable-restricted     enable a restricted shell
+  --enable-select         include select command
+  --enable-separate-helpfiles
+                          use external files for help builtin documentation
+  --enable-usg-echo-default
+                          a synonym for --enable-xpg-echo-default
+  --enable-xpg-echo-default
+                          make the echo builtin expand escape sequences by
+                          default
+  --enable-mem-scramble   scramble memory on calls to malloc and free
+  --enable-profiling      allow profiling with gprof
+  --enable-static-link    link bash statically, for use as a root shell
   --disable-largefile     omit support for large files
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
---with-afs             if you are running AFS
---with-bash-malloc     use the Bash version of malloc
---with-curses          use the curses library instead of the termcap library
---with-gnu-malloc      synonym for --with-bash-malloc
---with-installed-readline      use a version of the readline library that is already installed
---with-purecov         configure to postprocess with pure coverage
---with-purify          configure to postprocess with purify
+  --with-afs              if you are running AFS
+  --with-bash-malloc      use the Bash version of malloc
+  --with-curses           use the curses library instead of the termcap
+                          library
+  --with-gnu-malloc       synonym for --with-bash-malloc
+  --with-installed-readline
+                          use a version of the readline library that is
+                          already installed
+  --with-purecov          configure to postprocess with pure coverage
+  --with-purify           configure to postprocess with purify
 
 Some influential environment variables:
   CC          C compiler command
@@ -767,7 +785,7 @@ fi
 test -n "$ac_init_help" && exit 0
 if $ac_init_version; then
   cat <<\EOF
-bash configure 2.05a
+bash configure 2.05b
 generated by GNU Autoconf 2.52
 
 Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
@@ -782,7 +800,7 @@ cat >&5 <<EOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by bash $as_me 2.05a, which was
+It was created by bash $as_me 2.05b, which was
 generated by GNU Autoconf 2.52.  Invocation command line was
 
   $ $0 $@
@@ -907,7 +925,7 @@ if test -z "$CONFIG_SITE"; then
 fi
 for ac_site_file in $CONFIG_SITE; do
   if test -r "$ac_site_file"; then
-    { echo "$as_me:910: loading site script $ac_site_file" >&5
+    { echo "$as_me:928: loading site script $ac_site_file" >&5
 echo "$as_me: loading site script $ac_site_file" >&6;}
     cat "$ac_site_file" >&5
     . "$ac_site_file"
@@ -918,7 +936,7 @@ if test -r "$cache_file"; then
   # Some versions of bash will fail to source /dev/null (special
   # files actually), so we avoid doing that.
   if test -f "$cache_file"; then
-    { echo "$as_me:921: loading cache $cache_file" >&5
+    { echo "$as_me:939: loading cache $cache_file" >&5
 echo "$as_me: loading cache $cache_file" >&6;}
     case $cache_file in
       [\\/]* | ?:[\\/]* ) . $cache_file;;
@@ -926,7 +944,7 @@ echo "$as_me: loading cache $cache_file" >&6;}
     esac
   fi
 else
-  { echo "$as_me:929: creating cache $cache_file" >&5
+  { echo "$as_me:947: creating cache $cache_file" >&5
 echo "$as_me: creating cache $cache_file" >&6;}
   >$cache_file
 fi
@@ -942,21 +960,21 @@ for ac_var in `(set) 2>&1 |
   eval ac_new_val="\$ac_env_${ac_var}_value"
   case $ac_old_set,$ac_new_set in
     set,)
-      { echo "$as_me:945: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+      { echo "$as_me:963: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
       ac_cache_corrupted=: ;;
     ,set)
-      { echo "$as_me:949: error: \`$ac_var' was not set in the previous run" >&5
+      { echo "$as_me:967: error: \`$ac_var' was not set in the previous run" >&5
 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
       ac_cache_corrupted=: ;;
     ,);;
     *)
       if test "x$ac_old_val" != "x$ac_new_val"; then
-        { echo "$as_me:955: error: \`$ac_var' has changed since the previous run:" >&5
+        { echo "$as_me:973: error: \`$ac_var' has changed since the previous run:" >&5
 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
-        { echo "$as_me:957:   former value:  $ac_old_val" >&5
+        { echo "$as_me:975:   former value:  $ac_old_val" >&5
 echo "$as_me:   former value:  $ac_old_val" >&2;}
-        { echo "$as_me:959:   current value: $ac_new_val" >&5
+        { echo "$as_me:977:   current value: $ac_new_val" >&5
 echo "$as_me:   current value: $ac_new_val" >&2;}
         ac_cache_corrupted=:
       fi;;
@@ -975,9 +993,9 @@ echo "$as_me:   current value: $ac_new_val" >&2;}
   fi
 done
 if $ac_cache_corrupted; then
-  { echo "$as_me:978: error: changes in the environment can compromise the build" >&5
+  { echo "$as_me:996: error: changes in the environment can compromise the build" >&5
 echo "$as_me: error: changes in the environment can compromise the build" >&2;}
-  { { echo "$as_me:980: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+  { { echo "$as_me:998: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
    { (exit 1); exit 1; }; }
 fi
@@ -997,10 +1015,10 @@ esac
 echo "#! $SHELL" >conftest.sh
 echo  "exit 0"   >>conftest.sh
 chmod +x conftest.sh
-if { (echo "$as_me:1000: PATH=\".;.\"; conftest.sh") >&5
+if { (echo "$as_me:1018: PATH=\".;.\"; conftest.sh") >&5
   (PATH=".;."; conftest.sh) 2>&5
   ac_status=$?
-  echo "$as_me:1003: \$? = $ac_status" >&5
+  echo "$as_me:1021: \$? = $ac_status" >&5
   (exit $ac_status); }; then
   ac_path_separator=';'
 else
@@ -1026,7 +1044,7 @@ for ac_dir in ./support $srcdir/./support; do
   fi
 done
 if test -z "$ac_aux_dir"; then
-  { { echo "$as_me:1029: error: cannot find install-sh or install.sh in ./support $srcdir/./support" >&5
+  { { echo "$as_me:1047: error: cannot find install-sh or install.sh in ./support $srcdir/./support" >&5
 echo "$as_me: error: cannot find install-sh or install.sh in ./support $srcdir/./support" >&2;}
    { (exit 1); exit 1; }; }
 fi
@@ -1036,15 +1054,21 @@ ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
 
 ac_config_headers="$ac_config_headers config.h"
 
-BASHVERS=2.05a
+BASHVERS=2.05b
+RELSTATUS=release
+
+case "$RELSTATUS" in
+alp*|bet*|dev*|rc*)    DEBUG='-DDEBUG' MALLOC_DEBUG='-DMALLOC_DEBUG' ;;
+*)     DEBUG= MALLOC_DEBUG= ;;
+esac
 
 # Make sure we can run config.sub.
 $ac_config_sub sun4 >/dev/null 2>&1 ||
-  { { echo "$as_me:1043: error: cannot run $ac_config_sub" >&5
+  { { echo "$as_me:1067: error: cannot run $ac_config_sub" >&5
 echo "$as_me: error: cannot run $ac_config_sub" >&2;}
    { (exit 1); exit 1; }; }
 
-echo "$as_me:1047: checking build system type" >&5
+echo "$as_me:1071: checking build system type" >&5
 echo $ECHO_N "checking build system type... $ECHO_C" >&6
 if test "${ac_cv_build+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1053,23 +1077,23 @@ else
 test -z "$ac_cv_build_alias" &&
   ac_cv_build_alias=`$ac_config_guess`
 test -z "$ac_cv_build_alias" &&
-  { { echo "$as_me:1056: error: cannot guess build type; you must specify one" >&5
+  { { echo "$as_me:1080: error: cannot guess build type; you must specify one" >&5
 echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
    { (exit 1); exit 1; }; }
 ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
-  { { echo "$as_me:1060: error: $ac_config_sub $ac_cv_build_alias failed." >&5
+  { { echo "$as_me:1084: error: $ac_config_sub $ac_cv_build_alias failed." >&5
 echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed." >&2;}
    { (exit 1); exit 1; }; }
 
 fi
-echo "$as_me:1065: result: $ac_cv_build" >&5
+echo "$as_me:1089: result: $ac_cv_build" >&5
 echo "${ECHO_T}$ac_cv_build" >&6
 build=$ac_cv_build
 build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
 build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
 build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
 
-echo "$as_me:1072: checking host system type" >&5
+echo "$as_me:1096: checking host system type" >&5
 echo $ECHO_N "checking host system type... $ECHO_C" >&6
 if test "${ac_cv_host+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1078,12 +1102,12 @@ else
 test -z "$ac_cv_host_alias" &&
   ac_cv_host_alias=$ac_cv_build_alias
 ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
-  { { echo "$as_me:1081: error: $ac_config_sub $ac_cv_host_alias failed" >&5
+  { { echo "$as_me:1105: error: $ac_config_sub $ac_cv_host_alias failed" >&5
 echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
    { (exit 1); exit 1; }; }
 
 fi
-echo "$as_me:1086: result: $ac_cv_host" >&5
+echo "$as_me:1110: result: $ac_cv_host" >&5
 echo "${ECHO_T}$ac_cv_host" >&6
 host=$ac_cv_host
 host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
@@ -1108,7 +1132,7 @@ sparc-netbsd*)    opt_bash_malloc=no ;;   # needs 8-byte alignment
 mips-irix6*)   opt_bash_malloc=no ;;   # needs 8-byte alignment
 m68k-sysv)     opt_bash_malloc=no ;;   # fixes file descriptor leak in closedir
 sparc-linux*)  opt_bash_malloc=no ;;   # sparc running linux; requires ELF
-#*-freebsd*)   opt_bash_malloc=no ;;   # they claim it's better
+#*-freebsd*)   opt_bash_malloc=no ;;   # they claim it's better; I disagree
 *-openbsd*)    opt_bash_malloc=no ;;   # they claim it needs eight-bit alignment
 *-aix*)                opt_bash_malloc=no ;;   # AIX machines
 *-nextstep*)   opt_bash_malloc=no ;;   # NeXT machines running NeXTstep
@@ -1124,6 +1148,12 @@ sparc-linux*)    opt_bash_malloc=no ;;   # sparc running linux; requires ELF
 *-opennt*|*-interix*)  opt_bash_malloc=no ;;   # Interix, now owned by Microsoft
 esac
 
+# memory scrambling on free()
+case "${host_os}" in
+sco3.2v5*|sco3.2v4*)   opt_memscramble=no ;;
+*)                     opt_memscramble=yes ;;
+esac
+
 # Check whether --with-afs or --without-afs was given.
 if test "${with_afs+set}" = set; then
   withval="$with_afs"
@@ -1188,6 +1218,10 @@ fi
 
 if test "$opt_purify" = yes; then
        PURIFY="purify "
+       cat >>confdefs.h <<\EOF
+#define DISABLE_MALLOC_WRAPPERS 1
+EOF
+
 else
        PURIFY=
 fi
@@ -1231,7 +1265,7 @@ opt_cond_command=yes
 opt_arith_for_command=yes
 opt_net_redirs=yes
 opt_progcomp=yes
-opt_largefile=yes
+opt_separate_help=no
 
 opt_static_link=no
 opt_profiling=no
@@ -1249,7 +1283,7 @@ if test $opt_minimal_config = yes; then
        opt_select=no opt_help=no opt_array_variables=no opt_dparen_arith=no
        opt_brace_expansion=no opt_disabled_builtins=no opt_command_timing=no
        opt_extended_glob=no opt_cond_command=no opt_arith_for_command=no
-       opt_net_redirs=no opt_progcomp=no
+       opt_net_redirs=no opt_progcomp=no opt_separate_help=no
 fi
 
 # Check whether --enable-alias or --disable-alias was given.
@@ -1322,11 +1356,6 @@ if test "${enable_job_control+set}" = set; then
   enableval="$enable_job_control"
   opt_job_control=$enableval
 fi;
-# Check whether --enable-largefile or --disable-largefile was given.
-if test "${enable_largefile+set}" = set; then
-  enableval="$enable_largefile"
-  opt_largefile=$enableval
-fi;
 # Check whether --enable-net-redirections or --disable-net-redirections was given.
 if test "${enable_net_redirections+set}" = set; then
   enableval="$enable_net_redirections"
@@ -1362,6 +1391,11 @@ if test "${enable_select+set}" = set; then
   enableval="$enable_select"
   opt_select=$enableval
 fi;
+# Check whether --enable-separate-helpfiles or --disable-separate-helpfiles was given.
+if test "${enable_separate_helpfiles+set}" = set; then
+  enableval="$enable_separate_helpfiles"
+  opt_separate_help=$enableval
+fi;
 # Check whether --enable-usg-echo-default or --disable-usg-echo-default was given.
 if test "${enable_usg_echo_default+set}" = set; then
   enableval="$enable_usg_echo_default"
@@ -1373,6 +1407,11 @@ if test "${enable_xpg_echo_default+set}" = set; then
   opt_xpg_echo=$enableval
 fi;
 
+# Check whether --enable-mem-scramble or --disable-mem-scramble was given.
+if test "${enable_mem_scramble+set}" = set; then
+  enableval="$enable_mem_scramble"
+  opt_memscramble=$enableval
+fi;
 # Check whether --enable-profiling or --disable-profiling was given.
 if test "${enable_profiling+set}" = set; then
   enableval="$enable_profiling"
@@ -1493,14 +1532,32 @@ EOF
 
 fi
 
+if test $opt_memscramble = yes; then
+cat >>confdefs.h <<\EOF
+#define MEMSCRAMBLE 1
+EOF
+
+fi
+
 if test "$opt_minimal_config" = yes; then
        TESTSCRIPT=run-minimal
 else
        TESTSCRIPT=run-all
 fi
 
+HELPDIR= HELPDIRDEFINE= HELPINSTALL=
+if test "$opt_separate_help" != no; then
+       if test "$opt_separate_help" = "yes" ; then
+               HELPDIR='${datadir}/bash'
+       else
+               HELPDIR=$opt_separate_help
+       fi
+       HELPDIRDEFINE='-H ${HELPDIR}'
+       HELPINSTALL='install-help'
+fi
+
 echo ""
-echo "Beginning configuration for bash-$BASHVERS for ${host_cpu}-${host_vendor}-${host_os}"
+echo "Beginning configuration for bash-$BASHVERS-$RELSTATUS for ${host_cpu}-${host_vendor}-${host_os}"
 echo ""
 
 ac_ext=c
@@ -1511,7 +1568,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
 set dummy ${ac_tool_prefix}gcc; ac_word=$2
-echo "$as_me:1514: checking for $ac_word" >&5
+echo "$as_me:1571: checking for $ac_word" >&5
 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1526,7 +1583,7 @@ for ac_dir in $ac_dummy; do
   test -z "$ac_dir" && ac_dir=.
   $as_executable_p "$ac_dir/$ac_word" || continue
 ac_cv_prog_CC="${ac_tool_prefix}gcc"
-echo "$as_me:1529: found $ac_dir/$ac_word" >&5
+echo "$as_me:1586: found $ac_dir/$ac_word" >&5
 break
 done
 
@@ -1534,10 +1591,10 @@ fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  echo "$as_me:1537: result: $CC" >&5
+  echo "$as_me:1594: result: $CC" >&5
 echo "${ECHO_T}$CC" >&6
 else
-  echo "$as_me:1540: result: no" >&5
+  echo "$as_me:1597: result: no" >&5
 echo "${ECHO_T}no" >&6
 fi
 
@@ -1546,7 +1603,7 @@ if test -z "$ac_cv_prog_CC"; then
   ac_ct_CC=$CC
   # Extract the first word of "gcc", so it can be a program name with args.
 set dummy gcc; ac_word=$2
-echo "$as_me:1549: checking for $ac_word" >&5
+echo "$as_me:1606: checking for $ac_word" >&5
 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1561,7 +1618,7 @@ for ac_dir in $ac_dummy; do
   test -z "$ac_dir" && ac_dir=.
   $as_executable_p "$ac_dir/$ac_word" || continue
 ac_cv_prog_ac_ct_CC="gcc"
-echo "$as_me:1564: found $ac_dir/$ac_word" >&5
+echo "$as_me:1621: found $ac_dir/$ac_word" >&5
 break
 done
 
@@ -1569,10 +1626,10 @@ fi
 fi
 ac_ct_CC=$ac_cv_prog_ac_ct_CC
 if test -n "$ac_ct_CC"; then
-  echo "$as_me:1572: result: $ac_ct_CC" >&5
+  echo "$as_me:1629: result: $ac_ct_CC" >&5
 echo "${ECHO_T}$ac_ct_CC" >&6
 else
-  echo "$as_me:1575: result: no" >&5
+  echo "$as_me:1632: result: no" >&5
 echo "${ECHO_T}no" >&6
 fi
 
@@ -1585,7 +1642,7 @@ if test -z "$CC"; then
   if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
 set dummy ${ac_tool_prefix}cc; ac_word=$2
-echo "$as_me:1588: checking for $ac_word" >&5
+echo "$as_me:1645: checking for $ac_word" >&5
 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1600,7 +1657,7 @@ for ac_dir in $ac_dummy; do
   test -z "$ac_dir" && ac_dir=.
   $as_executable_p "$ac_dir/$ac_word" || continue
 ac_cv_prog_CC="${ac_tool_prefix}cc"
-echo "$as_me:1603: found $ac_dir/$ac_word" >&5
+echo "$as_me:1660: found $ac_dir/$ac_word" >&5
 break
 done
 
@@ -1608,10 +1665,10 @@ fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  echo "$as_me:1611: result: $CC" >&5
+  echo "$as_me:1668: result: $CC" >&5
 echo "${ECHO_T}$CC" >&6
 else
-  echo "$as_me:1614: result: no" >&5
+  echo "$as_me:1671: result: no" >&5
 echo "${ECHO_T}no" >&6
 fi
 
@@ -1620,7 +1677,7 @@ if test -z "$ac_cv_prog_CC"; then
   ac_ct_CC=$CC
   # Extract the first word of "cc", so it can be a program name with args.
 set dummy cc; ac_word=$2
-echo "$as_me:1623: checking for $ac_word" >&5
+echo "$as_me:1680: checking for $ac_word" >&5
 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1635,7 +1692,7 @@ for ac_dir in $ac_dummy; do
   test -z "$ac_dir" && ac_dir=.
   $as_executable_p "$ac_dir/$ac_word" || continue
 ac_cv_prog_ac_ct_CC="cc"
-echo "$as_me:1638: found $ac_dir/$ac_word" >&5
+echo "$as_me:1695: found $ac_dir/$ac_word" >&5
 break
 done
 
@@ -1643,10 +1700,10 @@ fi
 fi
 ac_ct_CC=$ac_cv_prog_ac_ct_CC
 if test -n "$ac_ct_CC"; then
-  echo "$as_me:1646: result: $ac_ct_CC" >&5
+  echo "$as_me:1703: result: $ac_ct_CC" >&5
 echo "${ECHO_T}$ac_ct_CC" >&6
 else
-  echo "$as_me:1649: result: no" >&5
+  echo "$as_me:1706: result: no" >&5
 echo "${ECHO_T}no" >&6
 fi
 
@@ -1659,7 +1716,7 @@ fi
 if test -z "$CC"; then
   # Extract the first word of "cc", so it can be a program name with args.
 set dummy cc; ac_word=$2
-echo "$as_me:1662: checking for $ac_word" >&5
+echo "$as_me:1719: checking for $ac_word" >&5
 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1679,7 +1736,7 @@ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
   continue
 fi
 ac_cv_prog_CC="cc"
-echo "$as_me:1682: found $ac_dir/$ac_word" >&5
+echo "$as_me:1739: found $ac_dir/$ac_word" >&5
 break
 done
 
@@ -1701,10 +1758,10 @@ fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  echo "$as_me:1704: result: $CC" >&5
+  echo "$as_me:1761: result: $CC" >&5
 echo "${ECHO_T}$CC" >&6
 else
-  echo "$as_me:1707: result: no" >&5
+  echo "$as_me:1764: result: no" >&5
 echo "${ECHO_T}no" >&6
 fi
 
@@ -1715,7 +1772,7 @@ if test -z "$CC"; then
   do
     # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-echo "$as_me:1718: checking for $ac_word" >&5
+echo "$as_me:1775: checking for $ac_word" >&5
 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1730,7 +1787,7 @@ for ac_dir in $ac_dummy; do
   test -z "$ac_dir" && ac_dir=.
   $as_executable_p "$ac_dir/$ac_word" || continue
 ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
-echo "$as_me:1733: found $ac_dir/$ac_word" >&5
+echo "$as_me:1790: found $ac_dir/$ac_word" >&5
 break
 done
 
@@ -1738,10 +1795,10 @@ fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  echo "$as_me:1741: result: $CC" >&5
+  echo "$as_me:1798: result: $CC" >&5
 echo "${ECHO_T}$CC" >&6
 else
-  echo "$as_me:1744: result: no" >&5
+  echo "$as_me:1801: result: no" >&5
 echo "${ECHO_T}no" >&6
 fi
 
@@ -1754,7 +1811,7 @@ if test -z "$CC"; then
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
-echo "$as_me:1757: checking for $ac_word" >&5
+echo "$as_me:1814: checking for $ac_word" >&5
 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1769,7 +1826,7 @@ for ac_dir in $ac_dummy; do
   test -z "$ac_dir" && ac_dir=.
   $as_executable_p "$ac_dir/$ac_word" || continue
 ac_cv_prog_ac_ct_CC="$ac_prog"
-echo "$as_me:1772: found $ac_dir/$ac_word" >&5
+echo "$as_me:1829: found $ac_dir/$ac_word" >&5
 break
 done
 
@@ -1777,10 +1834,10 @@ fi
 fi
 ac_ct_CC=$ac_cv_prog_ac_ct_CC
 if test -n "$ac_ct_CC"; then
-  echo "$as_me:1780: result: $ac_ct_CC" >&5
+  echo "$as_me:1837: result: $ac_ct_CC" >&5
 echo "${ECHO_T}$ac_ct_CC" >&6
 else
-  echo "$as_me:1783: result: no" >&5
+  echo "$as_me:1840: result: no" >&5
 echo "${ECHO_T}no" >&6
 fi
 
@@ -1792,32 +1849,32 @@ fi
 
 fi
 
-test -z "$CC" && { { echo "$as_me:1795: error: no acceptable cc found in \$PATH" >&5
+test -z "$CC" && { { echo "$as_me:1852: error: no acceptable cc found in \$PATH" >&5
 echo "$as_me: error: no acceptable cc found in \$PATH" >&2;}
    { (exit 1); exit 1; }; }
 
 # Provide some information about the compiler.
-echo "$as_me:1800:" \
+echo "$as_me:1857:" \
      "checking for C compiler version" >&5
 ac_compiler=`set X $ac_compile; echo $2`
-{ (eval echo "$as_me:1803: \"$ac_compiler --version </dev/null >&5\"") >&5
+{ (eval echo "$as_me:1860: \"$ac_compiler --version </dev/null >&5\"") >&5
   (eval $ac_compiler --version </dev/null >&5) 2>&5
   ac_status=$?
-  echo "$as_me:1806: \$? = $ac_status" >&5
+  echo "$as_me:1863: \$? = $ac_status" >&5
   (exit $ac_status); }
-{ (eval echo "$as_me:1808: \"$ac_compiler -v </dev/null >&5\"") >&5
+{ (eval echo "$as_me:1865: \"$ac_compiler -v </dev/null >&5\"") >&5
   (eval $ac_compiler -v </dev/null >&5) 2>&5
   ac_status=$?
-  echo "$as_me:1811: \$? = $ac_status" >&5
+  echo "$as_me:1868: \$? = $ac_status" >&5
   (exit $ac_status); }
-{ (eval echo "$as_me:1813: \"$ac_compiler -V </dev/null >&5\"") >&5
+{ (eval echo "$as_me:1870: \"$ac_compiler -V </dev/null >&5\"") >&5
   (eval $ac_compiler -V </dev/null >&5) 2>&5
   ac_status=$?
-  echo "$as_me:1816: \$? = $ac_status" >&5
+  echo "$as_me:1873: \$? = $ac_status" >&5
   (exit $ac_status); }
 
 cat >conftest.$ac_ext <<_ACEOF
-#line 1820 "configure"
+#line 1877 "configure"
 #include "confdefs.h"
 
 int
@@ -1833,13 +1890,13 @@ ac_clean_files="$ac_clean_files a.out a.exe"
 # Try to create an executable without -o first, disregard a.out.
 # It will help us diagnose broken compilers, and finding out an intuition
 # of exeext.
-echo "$as_me:1836: checking for C compiler default output" >&5
+echo "$as_me:1893: checking for C compiler default output" >&5
 echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6
 ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-if { (eval echo "$as_me:1839: \"$ac_link_default\"") >&5
+if { (eval echo "$as_me:1896: \"$ac_link_default\"") >&5
   (eval $ac_link_default) 2>&5
   ac_status=$?
-  echo "$as_me:1842: \$? = $ac_status" >&5
+  echo "$as_me:1899: \$? = $ac_status" >&5
   (exit $ac_status); }; then
   # Find the output, starting from the most likely.  This scheme is
 # not robust to junk in `.', hence go to wildcards (a.*) only as a last
@@ -1862,34 +1919,34 @@ done
 else
   echo "$as_me: failed program was:" >&5
 cat conftest.$ac_ext >&5
-{ { echo "$as_me:1865: error: C compiler cannot create executables" >&5
+{ { echo "$as_me:1922: error: C compiler cannot create executables" >&5
 echo "$as_me: error: C compiler cannot create executables" >&2;}
    { (exit 77); exit 77; }; }
 fi
 
 ac_exeext=$ac_cv_exeext
-echo "$as_me:1871: result: $ac_file" >&5
+echo "$as_me:1928: result: $ac_file" >&5
 echo "${ECHO_T}$ac_file" >&6
 
 # Check the compiler produces executables we can run.  If not, either
 # the compiler is broken, or we cross compile.
-echo "$as_me:1876: checking whether the C compiler works" >&5
+echo "$as_me:1933: checking whether the C compiler works" >&5
 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
 # FIXME: These cross compiler hacks should be removed for Autoconf 3.0
 # If not cross compiling, check that we can run a simple program.
 if test "$cross_compiling" != yes; then
   if { ac_try='./$ac_file'
-  { (eval echo "$as_me:1882: \"$ac_try\"") >&5
+  { (eval echo "$as_me:1939: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:1885: \$? = $ac_status" >&5
+  echo "$as_me:1942: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
     cross_compiling=no
   else
     if test "$cross_compiling" = maybe; then
        cross_compiling=yes
     else
-       { { echo "$as_me:1892: error: cannot run C compiled programs.
+       { { echo "$as_me:1949: error: cannot run C compiled programs.
 If you meant to cross compile, use \`--host'." >&5
 echo "$as_me: error: cannot run C compiled programs.
 If you meant to cross compile, use \`--host'." >&2;}
@@ -1897,24 +1954,24 @@ If you meant to cross compile, use \`--host'." >&2;}
     fi
   fi
 fi
-echo "$as_me:1900: result: yes" >&5
+echo "$as_me:1957: result: yes" >&5
 echo "${ECHO_T}yes" >&6
 
 rm -f a.out a.exe conftest$ac_cv_exeext
 ac_clean_files=$ac_clean_files_save
 # Check the compiler produces executables we can run.  If not, either
 # the compiler is broken, or we cross compile.
-echo "$as_me:1907: checking whether we are cross compiling" >&5
+echo "$as_me:1964: checking whether we are cross compiling" >&5
 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
-echo "$as_me:1909: result: $cross_compiling" >&5
+echo "$as_me:1966: result: $cross_compiling" >&5
 echo "${ECHO_T}$cross_compiling" >&6
 
-echo "$as_me:1912: checking for executable suffix" >&5
+echo "$as_me:1969: checking for executable suffix" >&5
 echo $ECHO_N "checking for executable suffix... $ECHO_C" >&6
-if { (eval echo "$as_me:1914: \"$ac_link\"") >&5
+if { (eval echo "$as_me:1971: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:1917: \$? = $ac_status" >&5
+  echo "$as_me:1974: \$? = $ac_status" >&5
   (exit $ac_status); }; then
   # If both `conftest.exe' and `conftest' are `present' (well, observable)
 # catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
@@ -1930,25 +1987,25 @@ for ac_file in `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do
   esac
 done
 else
-  { { echo "$as_me:1933: error: cannot compute EXEEXT: cannot compile and link" >&5
+  { { echo "$as_me:1990: error: cannot compute EXEEXT: cannot compile and link" >&5
 echo "$as_me: error: cannot compute EXEEXT: cannot compile and link" >&2;}
    { (exit 1); exit 1; }; }
 fi
 
 rm -f conftest$ac_cv_exeext
-echo "$as_me:1939: result: $ac_cv_exeext" >&5
+echo "$as_me:1996: result: $ac_cv_exeext" >&5
 echo "${ECHO_T}$ac_cv_exeext" >&6
 
 rm -f conftest.$ac_ext
 EXEEXT=$ac_cv_exeext
 ac_exeext=$EXEEXT
-echo "$as_me:1945: checking for object suffix" >&5
+echo "$as_me:2002: checking for object suffix" >&5
 echo $ECHO_N "checking for object suffix... $ECHO_C" >&6
 if test "${ac_cv_objext+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 1951 "configure"
+#line 2008 "configure"
 #include "confdefs.h"
 
 int
@@ -1960,10 +2017,10 @@ main ()
 }
 _ACEOF
 rm -f conftest.o conftest.obj
-if { (eval echo "$as_me:1963: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2020: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:1966: \$? = $ac_status" >&5
+  echo "$as_me:2023: \$? = $ac_status" >&5
   (exit $ac_status); }; then
   for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
   case $ac_file in
@@ -1975,24 +2032,24 @@ done
 else
   echo "$as_me: failed program was:" >&5
 cat conftest.$ac_ext >&5
-{ { echo "$as_me:1978: error: cannot compute OBJEXT: cannot compile" >&5
+{ { echo "$as_me:2035: error: cannot compute OBJEXT: cannot compile" >&5
 echo "$as_me: error: cannot compute OBJEXT: cannot compile" >&2;}
    { (exit 1); exit 1; }; }
 fi
 
 rm -f conftest.$ac_cv_objext conftest.$ac_ext
 fi
-echo "$as_me:1985: result: $ac_cv_objext" >&5
+echo "$as_me:2042: result: $ac_cv_objext" >&5
 echo "${ECHO_T}$ac_cv_objext" >&6
 OBJEXT=$ac_cv_objext
 ac_objext=$OBJEXT
-echo "$as_me:1989: checking whether we are using the GNU C compiler" >&5
+echo "$as_me:2046: checking whether we are using the GNU C compiler" >&5
 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
 if test "${ac_cv_c_compiler_gnu+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 1995 "configure"
+#line 2052 "configure"
 #include "confdefs.h"
 
 int
@@ -2007,16 +2064,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2010: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2067: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:2013: \$? = $ac_status" >&5
+  echo "$as_me:2070: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:2016: \"$ac_try\"") >&5
+  { (eval echo "$as_me:2073: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:2019: \$? = $ac_status" >&5
+  echo "$as_me:2076: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_compiler_gnu=yes
 else
@@ -2028,19 +2085,19 @@ rm -f conftest.$ac_objext conftest.$ac_ext
 ac_cv_c_compiler_gnu=$ac_compiler_gnu
 
 fi
-echo "$as_me:2031: result: $ac_cv_c_compiler_gnu" >&5
+echo "$as_me:2088: result: $ac_cv_c_compiler_gnu" >&5
 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
 GCC=`test $ac_compiler_gnu = yes && echo yes`
 ac_test_CFLAGS=${CFLAGS+set}
 ac_save_CFLAGS=$CFLAGS
 CFLAGS="-g"
-echo "$as_me:2037: checking whether $CC accepts -g" >&5
+echo "$as_me:2094: checking whether $CC accepts -g" >&5
 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
 if test "${ac_cv_prog_cc_g+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 2043 "configure"
+#line 2100 "configure"
 #include "confdefs.h"
 
 int
@@ -2052,16 +2109,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2055: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2112: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:2058: \$? = $ac_status" >&5
+  echo "$as_me:2115: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:2061: \"$ac_try\"") >&5
+  { (eval echo "$as_me:2118: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:2064: \$? = $ac_status" >&5
+  echo "$as_me:2121: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_prog_cc_g=yes
 else
@@ -2071,7 +2128,7 @@ ac_cv_prog_cc_g=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:2074: result: $ac_cv_prog_cc_g" >&5
+echo "$as_me:2131: result: $ac_cv_prog_cc_g" >&5
 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
 if test "$ac_test_CFLAGS" = set; then
   CFLAGS=$ac_save_CFLAGS
@@ -2098,16 +2155,16 @@ cat >conftest.$ac_ext <<_ACEOF
 #endif
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2101: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2158: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:2104: \$? = $ac_status" >&5
+  echo "$as_me:2161: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:2107: \"$ac_try\"") >&5
+  { (eval echo "$as_me:2164: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:2110: \$? = $ac_status" >&5
+  echo "$as_me:2167: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   for ac_declaration in \
    ''\
@@ -2119,7 +2176,7 @@ if { (eval echo "$as_me:2101: \"$ac_compile\"") >&5
    'void exit (int);'
 do
   cat >conftest.$ac_ext <<_ACEOF
-#line 2122 "configure"
+#line 2179 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 $ac_declaration
@@ -2132,16 +2189,16 @@ exit (42);
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2135: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2192: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:2138: \$? = $ac_status" >&5
+  echo "$as_me:2195: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:2141: \"$ac_try\"") >&5
+  { (eval echo "$as_me:2198: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:2144: \$? = $ac_status" >&5
+  echo "$as_me:2201: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   :
 else
@@ -2151,7 +2208,7 @@ continue
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
   cat >conftest.$ac_ext <<_ACEOF
-#line 2154 "configure"
+#line 2211 "configure"
 #include "confdefs.h"
 $ac_declaration
 int
@@ -2163,16 +2220,16 @@ exit (42);
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2166: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2223: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:2169: \$? = $ac_status" >&5
+  echo "$as_me:2226: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:2172: \"$ac_try\"") >&5
+  { (eval echo "$as_me:2229: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:2175: \$? = $ac_status" >&5
+  echo "$as_me:2232: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   break
 else
@@ -2199,12 +2256,12 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
-echo "$as_me:2202: checking for POSIXized ISC" >&5
+echo "$as_me:2259: checking for POSIXized ISC" >&5
 echo $ECHO_N "checking for POSIXized ISC... $ECHO_C" >&6
 if test -d /etc/conf/kconfig.d &&
    grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
 then
-  echo "$as_me:2207: result: yes" >&5
+  echo "$as_me:2264: result: yes" >&5
 echo "${ECHO_T}yes" >&6
   ISC=yes # If later tests want to check for ISC.
 
@@ -2218,7 +2275,7 @@ EOF
     CC="$CC -Xp"
   fi
 else
-  echo "$as_me:2221: result: no" >&5
+  echo "$as_me:2278: result: no" >&5
 echo "${ECHO_T}no" >&6
   ISC=
 fi
@@ -2228,7 +2285,7 @@ ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
-echo "$as_me:2231: checking how to run the C preprocessor" >&5
+echo "$as_me:2288: checking how to run the C preprocessor" >&5
 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
@@ -2249,18 +2306,18 @@ do
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp. "Syntax error" is here to catch this case.
   cat >conftest.$ac_ext <<_ACEOF
-#line 2252 "configure"
+#line 2309 "configure"
 #include "confdefs.h"
 #include <assert.h>
                      Syntax error
 _ACEOF
-if { (eval echo "$as_me:2257: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:2314: \"$ac_cpp conftest.$ac_ext\"") >&5
   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   egrep -v '^ *\+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
-  echo "$as_me:2263: \$? = $ac_status" >&5
+  echo "$as_me:2320: \$? = $ac_status" >&5
   (exit $ac_status); } >/dev/null; then
   if test -s conftest.err; then
     ac_cpp_err=$ac_c_preproc_warn_flag
@@ -2283,17 +2340,17 @@ rm -f conftest.err conftest.$ac_ext
   # OK, works on sane cases.  Now check whether non-existent headers
   # can be detected and how.
   cat >conftest.$ac_ext <<_ACEOF
-#line 2286 "configure"
+#line 2343 "configure"
 #include "confdefs.h"
 #include <ac_nonexistent.h>
 _ACEOF
-if { (eval echo "$as_me:2290: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:2347: \"$ac_cpp conftest.$ac_ext\"") >&5
   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   egrep -v '^ *\+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
-  echo "$as_me:2296: \$? = $ac_status" >&5
+  echo "$as_me:2353: \$? = $ac_status" >&5
   (exit $ac_status); } >/dev/null; then
   if test -s conftest.err; then
     ac_cpp_err=$ac_c_preproc_warn_flag
@@ -2330,7 +2387,7 @@ fi
 else
   ac_cv_prog_CPP=$CPP
 fi
-echo "$as_me:2333: result: $CPP" >&5
+echo "$as_me:2390: result: $CPP" >&5
 echo "${ECHO_T}$CPP" >&6
 ac_preproc_ok=false
 for ac_c_preproc_warn_flag in '' yes
@@ -2340,18 +2397,18 @@ do
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp. "Syntax error" is here to catch this case.
   cat >conftest.$ac_ext <<_ACEOF
-#line 2343 "configure"
+#line 2400 "configure"
 #include "confdefs.h"
 #include <assert.h>
                      Syntax error
 _ACEOF
-if { (eval echo "$as_me:2348: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:2405: \"$ac_cpp conftest.$ac_ext\"") >&5
   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   egrep -v '^ *\+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
-  echo "$as_me:2354: \$? = $ac_status" >&5
+  echo "$as_me:2411: \$? = $ac_status" >&5
   (exit $ac_status); } >/dev/null; then
   if test -s conftest.err; then
     ac_cpp_err=$ac_c_preproc_warn_flag
@@ -2374,17 +2431,17 @@ rm -f conftest.err conftest.$ac_ext
   # OK, works on sane cases.  Now check whether non-existent headers
   # can be detected and how.
   cat >conftest.$ac_ext <<_ACEOF
-#line 2377 "configure"
+#line 2434 "configure"
 #include "confdefs.h"
 #include <ac_nonexistent.h>
 _ACEOF
-if { (eval echo "$as_me:2381: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:2438: \"$ac_cpp conftest.$ac_ext\"") >&5
   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   egrep -v '^ *\+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
-  echo "$as_me:2387: \$? = $ac_status" >&5
+  echo "$as_me:2444: \$? = $ac_status" >&5
   (exit $ac_status); } >/dev/null; then
   if test -s conftest.err; then
     ac_cpp_err=$ac_c_preproc_warn_flag
@@ -2412,7 +2469,7 @@ rm -f conftest.err conftest.$ac_ext
 if $ac_preproc_ok; then
   :
 else
-  { { echo "$as_me:2415: error: C preprocessor \"$CPP\" fails sanity check" >&5
+  { { echo "$as_me:2472: error: C preprocessor \"$CPP\" fails sanity check" >&5
 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check" >&2;}
    { (exit 1); exit 1; }; }
 fi
@@ -2423,23 +2480,23 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
-echo "$as_me:2426: checking for minix/config.h" >&5
+echo "$as_me:2483: checking for minix/config.h" >&5
 echo $ECHO_N "checking for minix/config.h... $ECHO_C" >&6
 if test "${ac_cv_header_minix_config_h+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 2432 "configure"
+#line 2489 "configure"
 #include "confdefs.h"
 #include <minix/config.h>
 _ACEOF
-if { (eval echo "$as_me:2436: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:2493: \"$ac_cpp conftest.$ac_ext\"") >&5
   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   egrep -v '^ *\+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
-  echo "$as_me:2442: \$? = $ac_status" >&5
+  echo "$as_me:2499: \$? = $ac_status" >&5
   (exit $ac_status); } >/dev/null; then
   if test -s conftest.err; then
     ac_cpp_err=$ac_c_preproc_warn_flag
@@ -2458,7 +2515,7 @@ else
 fi
 rm -f conftest.err conftest.$ac_ext
 fi
-echo "$as_me:2461: result: $ac_cv_header_minix_config_h" >&5
+echo "$as_me:2518: result: $ac_cv_header_minix_config_h" >&5
 echo "${ECHO_T}$ac_cv_header_minix_config_h" >&6
 if test $ac_cv_header_minix_config_h = yes; then
   MINIX=yes
@@ -2499,7 +2556,7 @@ if test "${enable_largefile+set}" = set; then
 fi;
 if test "$enable_largefile" != no; then
 
-  echo "$as_me:2502: checking for special C compiler options needed for large files" >&5
+  echo "$as_me:2559: checking for special C compiler options needed for large files" >&5
 echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6
 if test "${ac_cv_sys_largefile_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -2511,7 +2568,7 @@ else
         # IRIX 6.2 and later do not support large files by default,
         # so use the C compiler's -n32 option if that helps.
          cat >conftest.$ac_ext <<_ACEOF
-#line 2514 "configure"
+#line 2571 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
  /* Check that off_t can represent 2**63 - 1 correctly.
@@ -2531,16 +2588,16 @@ main ()
 }
 _ACEOF
         rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2534: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2591: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:2537: \$? = $ac_status" >&5
+  echo "$as_me:2594: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:2540: \"$ac_try\"") >&5
+  { (eval echo "$as_me:2597: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:2543: \$? = $ac_status" >&5
+  echo "$as_me:2600: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   break
 else
@@ -2550,16 +2607,16 @@ fi
 rm -f conftest.$ac_objext
         CC="$CC -n32"
         rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2553: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2610: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:2556: \$? = $ac_status" >&5
+  echo "$as_me:2613: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:2559: \"$ac_try\"") >&5
+  { (eval echo "$as_me:2616: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:2562: \$? = $ac_status" >&5
+  echo "$as_me:2619: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_sys_largefile_CC=' -n32'; break
 else
@@ -2573,13 +2630,13 @@ rm -f conftest.$ac_objext
        rm -f conftest.$ac_ext
     fi
 fi
-echo "$as_me:2576: result: $ac_cv_sys_largefile_CC" >&5
+echo "$as_me:2633: result: $ac_cv_sys_largefile_CC" >&5
 echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6
   if test "$ac_cv_sys_largefile_CC" != no; then
     CC=$CC$ac_cv_sys_largefile_CC
   fi
 
-  echo "$as_me:2582: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+  echo "$as_me:2639: checking for _FILE_OFFSET_BITS value needed for large files" >&5
 echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6
 if test "${ac_cv_sys_file_offset_bits+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -2587,7 +2644,7 @@ else
   while :; do
   ac_cv_sys_file_offset_bits=no
   cat >conftest.$ac_ext <<_ACEOF
-#line 2590 "configure"
+#line 2647 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
  /* Check that off_t can represent 2**63 - 1 correctly.
@@ -2607,16 +2664,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2610: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2667: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:2613: \$? = $ac_status" >&5
+  echo "$as_me:2670: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:2616: \"$ac_try\"") >&5
+  { (eval echo "$as_me:2673: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:2619: \$? = $ac_status" >&5
+  echo "$as_me:2676: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   break
 else
@@ -2625,7 +2682,7 @@ cat conftest.$ac_ext >&5
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
   cat >conftest.$ac_ext <<_ACEOF
-#line 2628 "configure"
+#line 2685 "configure"
 #include "confdefs.h"
 #define _FILE_OFFSET_BITS 64
 #include <sys/types.h>
@@ -2646,16 +2703,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2649: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2706: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:2652: \$? = $ac_status" >&5
+  echo "$as_me:2709: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:2655: \"$ac_try\"") >&5
+  { (eval echo "$as_me:2712: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:2658: \$? = $ac_status" >&5
+  echo "$as_me:2715: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_sys_file_offset_bits=64; break
 else
@@ -2666,7 +2723,7 @@ rm -f conftest.$ac_objext conftest.$ac_ext
   break
 done
 fi
-echo "$as_me:2669: result: $ac_cv_sys_file_offset_bits" >&5
+echo "$as_me:2726: result: $ac_cv_sys_file_offset_bits" >&5
 echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6
 if test "$ac_cv_sys_file_offset_bits" != no; then
 
@@ -2676,7 +2733,7 @@ EOF
 
 fi
 rm -f conftest*
-  echo "$as_me:2679: checking for _LARGE_FILES value needed for large files" >&5
+  echo "$as_me:2736: checking for _LARGE_FILES value needed for large files" >&5
 echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6
 if test "${ac_cv_sys_large_files+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -2684,7 +2741,7 @@ else
   while :; do
   ac_cv_sys_large_files=no
   cat >conftest.$ac_ext <<_ACEOF
-#line 2687 "configure"
+#line 2744 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
  /* Check that off_t can represent 2**63 - 1 correctly.
@@ -2704,16 +2761,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2707: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2764: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:2710: \$? = $ac_status" >&5
+  echo "$as_me:2767: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:2713: \"$ac_try\"") >&5
+  { (eval echo "$as_me:2770: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:2716: \$? = $ac_status" >&5
+  echo "$as_me:2773: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   break
 else
@@ -2722,7 +2779,7 @@ cat conftest.$ac_ext >&5
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
   cat >conftest.$ac_ext <<_ACEOF
-#line 2725 "configure"
+#line 2782 "configure"
 #include "confdefs.h"
 #define _LARGE_FILES 1
 #include <sys/types.h>
@@ -2743,16 +2800,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2746: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2803: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:2749: \$? = $ac_status" >&5
+  echo "$as_me:2806: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:2752: \"$ac_try\"") >&5
+  { (eval echo "$as_me:2809: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:2755: \$? = $ac_status" >&5
+  echo "$as_me:2812: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_sys_large_files=1; break
 else
@@ -2763,7 +2820,7 @@ rm -f conftest.$ac_objext conftest.$ac_ext
   break
 done
 fi
-echo "$as_me:2766: result: $ac_cv_sys_large_files" >&5
+echo "$as_me:2823: result: $ac_cv_sys_large_files" >&5
 echo "${ECHO_T}$ac_cv_sys_large_files" >&6
 if test "$ac_cv_sys_large_files" != no; then
 
@@ -2815,6 +2872,7 @@ if test "$opt_profiling" = "yes"; then
        solaris2*)      ;;
        *)              opt_static_link=yes ;;
        esac
+       DEBUG= MALLOC_DEBUG=
 fi
 
 if test "$opt_static_link" = yes; then
@@ -2828,15 +2886,18 @@ if test "$opt_static_link" = yes; then
        fi
 fi
 
+test -z "$CPPFLAGS_FOR_BUILD" && CPPFLAGS_FOR_BUILD="$CPPFLAGS"
+test -z "$CFLAGS_FOR_BUILD" && CFLAGS_FOR_BUILD="-g"
+
 if test $ac_cv_c_compiler_gnu = yes; then
-    echo "$as_me:2832: checking whether $CC needs -traditional" >&5
+    echo "$as_me:2893: checking whether $CC needs -traditional" >&5
 echo $ECHO_N "checking whether $CC needs -traditional... $ECHO_C" >&6
 if test "${ac_cv_prog_gcc_traditional+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
     ac_pattern="Autoconf.*'x'"
   cat >conftest.$ac_ext <<_ACEOF
-#line 2839 "configure"
+#line 2900 "configure"
 #include "confdefs.h"
 #include <sgtty.h>
 Autoconf TIOCGETP
@@ -2851,7 +2912,7 @@ rm -f conftest*
 
   if test $ac_cv_prog_gcc_traditional = no; then
     cat >conftest.$ac_ext <<_ACEOF
-#line 2854 "configure"
+#line 2915 "configure"
 #include "confdefs.h"
 #include <termio.h>
 Autoconf TCGETA
@@ -2864,7 +2925,7 @@ rm -f conftest*
 
   fi
 fi
-echo "$as_me:2867: result: $ac_cv_prog_gcc_traditional" >&5
+echo "$as_me:2928: result: $ac_cv_prog_gcc_traditional" >&5
 echo "${ECHO_T}$ac_cv_prog_gcc_traditional" >&6
   if test $ac_cv_prog_gcc_traditional = yes; then
     CC="$CC -traditional"
@@ -2873,7 +2934,6 @@ fi
 
 if test "$opt_readline" = yes && test "$opt_with_installed_readline" != "no"
 then
-echo opt_with_installed_readline = $opt_with_installed_readline
        # If the user specified --with-installed-readline=PREFIX and PREFIX
        # is not `yes', set ac_cv_rl_prefix to PREFIX
        test $opt_with_installed_readline != "yes" && ac_cv_rl_prefix=$opt_with_installed_readline
@@ -2881,14 +2941,14 @@ echo opt_with_installed_readline = $opt_with_installed_readline
 if test "X$bash_cv_termcap_lib" = "X"; then
 _bash_needmsg=yes
 else
-echo "$as_me:2884: checking which library has the termcap functions" >&5
+echo "$as_me:2944: checking which library has the termcap functions" >&5
 echo $ECHO_N "checking which library has the termcap functions... $ECHO_C" >&6
 _bash_needmsg=
 fi
 if test "${bash_cv_termcap_lib+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  echo "$as_me:2891: checking for tgetent in -ltermcap" >&5
+  echo "$as_me:2951: checking for tgetent in -ltermcap" >&5
 echo $ECHO_N "checking for tgetent in -ltermcap... $ECHO_C" >&6
 if test "${ac_cv_lib_termcap_tgetent+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -2896,7 +2956,7 @@ else
   ac_check_lib_save_LIBS=$LIBS
 LIBS="-ltermcap  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
-#line 2899 "configure"
+#line 2959 "configure"
 #include "confdefs.h"
 
 /* Override any gcc2 internal prototype to avoid an error.  */
@@ -2915,16 +2975,16 @@ tgetent ();
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:2918: \"$ac_link\"") >&5
+if { (eval echo "$as_me:2978: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:2921: \$? = $ac_status" >&5
+  echo "$as_me:2981: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:2924: \"$ac_try\"") >&5
+  { (eval echo "$as_me:2984: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:2927: \$? = $ac_status" >&5
+  echo "$as_me:2987: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_lib_termcap_tgetent=yes
 else
@@ -2935,12 +2995,12 @@ fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:2938: result: $ac_cv_lib_termcap_tgetent" >&5
+echo "$as_me:2998: result: $ac_cv_lib_termcap_tgetent" >&5
 echo "${ECHO_T}$ac_cv_lib_termcap_tgetent" >&6
 if test $ac_cv_lib_termcap_tgetent = yes; then
   bash_cv_termcap_lib=libtermcap
 else
-  echo "$as_me:2943: checking for tgetent in -ltinfo" >&5
+  echo "$as_me:3003: checking for tgetent in -ltinfo" >&5
 echo $ECHO_N "checking for tgetent in -ltinfo... $ECHO_C" >&6
 if test "${ac_cv_lib_tinfo_tgetent+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -2948,7 +3008,7 @@ else
   ac_check_lib_save_LIBS=$LIBS
 LIBS="-ltinfo  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
-#line 2951 "configure"
+#line 3011 "configure"
 #include "confdefs.h"
 
 /* Override any gcc2 internal prototype to avoid an error.  */
@@ -2967,16 +3027,16 @@ tgetent ();
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:2970: \"$ac_link\"") >&5
+if { (eval echo "$as_me:3030: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:2973: \$? = $ac_status" >&5
+  echo "$as_me:3033: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:2976: \"$ac_try\"") >&5
+  { (eval echo "$as_me:3036: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:2979: \$? = $ac_status" >&5
+  echo "$as_me:3039: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_lib_tinfo_tgetent=yes
 else
@@ -2987,12 +3047,12 @@ fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:2990: result: $ac_cv_lib_tinfo_tgetent" >&5
+echo "$as_me:3050: result: $ac_cv_lib_tinfo_tgetent" >&5
 echo "${ECHO_T}$ac_cv_lib_tinfo_tgetent" >&6
 if test $ac_cv_lib_tinfo_tgetent = yes; then
-  bash_cv_termcal_lib=libtinfo
+  bash_cv_termcap_lib=libtinfo
 else
-  echo "$as_me:2995: checking for tgetent in -lcurses" >&5
+  echo "$as_me:3055: checking for tgetent in -lcurses" >&5
 echo $ECHO_N "checking for tgetent in -lcurses... $ECHO_C" >&6
 if test "${ac_cv_lib_curses_tgetent+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -3000,7 +3060,7 @@ else
   ac_check_lib_save_LIBS=$LIBS
 LIBS="-lcurses  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
-#line 3003 "configure"
+#line 3063 "configure"
 #include "confdefs.h"
 
 /* Override any gcc2 internal prototype to avoid an error.  */
@@ -3019,16 +3079,16 @@ tgetent ();
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:3022: \"$ac_link\"") >&5
+if { (eval echo "$as_me:3082: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:3025: \$? = $ac_status" >&5
+  echo "$as_me:3085: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:3028: \"$ac_try\"") >&5
+  { (eval echo "$as_me:3088: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:3031: \$? = $ac_status" >&5
+  echo "$as_me:3091: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_lib_curses_tgetent=yes
 else
@@ -3039,12 +3099,12 @@ fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:3042: result: $ac_cv_lib_curses_tgetent" >&5
+echo "$as_me:3102: result: $ac_cv_lib_curses_tgetent" >&5
 echo "${ECHO_T}$ac_cv_lib_curses_tgetent" >&6
 if test $ac_cv_lib_curses_tgetent = yes; then
   bash_cv_termcap_lib=libcurses
 else
-  echo "$as_me:3047: checking for tgetent in -lncurses" >&5
+  echo "$as_me:3107: checking for tgetent in -lncurses" >&5
 echo $ECHO_N "checking for tgetent in -lncurses... $ECHO_C" >&6
 if test "${ac_cv_lib_ncurses_tgetent+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -3052,7 +3112,7 @@ else
   ac_check_lib_save_LIBS=$LIBS
 LIBS="-lncurses  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
-#line 3055 "configure"
+#line 3115 "configure"
 #include "confdefs.h"
 
 /* Override any gcc2 internal prototype to avoid an error.  */
@@ -3071,16 +3131,16 @@ tgetent ();
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:3074: \"$ac_link\"") >&5
+if { (eval echo "$as_me:3134: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:3077: \$? = $ac_status" >&5
+  echo "$as_me:3137: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:3080: \"$ac_try\"") >&5
+  { (eval echo "$as_me:3140: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:3083: \$? = $ac_status" >&5
+  echo "$as_me:3143: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_lib_ncurses_tgetent=yes
 else
@@ -3091,7 +3151,7 @@ fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:3094: result: $ac_cv_lib_ncurses_tgetent" >&5
+echo "$as_me:3154: result: $ac_cv_lib_ncurses_tgetent" >&5
 echo "${ECHO_T}$ac_cv_lib_ncurses_tgetent" >&6
 if test $ac_cv_lib_ncurses_tgetent = yes; then
   bash_cv_termcap_lib=libncurses
@@ -3108,10 +3168,10 @@ fi
 fi
 
 if test "X$_bash_needmsg" = "Xyes"; then
-echo "$as_me:3111: checking which library has the termcap functions" >&5
+echo "$as_me:3171: checking which library has the termcap functions" >&5
 echo $ECHO_N "checking which library has the termcap functions... $ECHO_C" >&6
 fi
-echo "$as_me:3114: result: using $bash_cv_termcap_lib" >&5
+echo "$as_me:3174: result: using $bash_cv_termcap_lib" >&5
 echo "${ECHO_T}using $bash_cv_termcap_lib" >&6
 if test $bash_cv_termcap_lib = gnutermcap && test -z "$prefer_curses"; then
 LDFLAGS="$LDFLAGS -L./lib/termcap"
@@ -3131,7 +3191,7 @@ TERMCAP_LIB=-lcurses
 TERMCAP_DEP=
 fi
 
-echo "$as_me:3134: checking version of installed readline library" >&5
+echo "$as_me:3194: checking version of installed readline library" >&5
 echo $ECHO_N "checking version of installed readline library... $ECHO_C" >&6
 
 # What a pain in the ass this is.
@@ -3160,7 +3220,7 @@ if test "$cross_compiling" = yes; then
   ac_cv_rl_version='4.2'
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 3163 "configure"
+#line 3223 "configure"
 #include "confdefs.h"
 
 #include <stdio.h>
@@ -3178,15 +3238,15 @@ main()
 
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:3181: \"$ac_link\"") >&5
+if { (eval echo "$as_me:3241: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:3184: \$? = $ac_status" >&5
+  echo "$as_me:3244: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:3186: \"$ac_try\"") >&5
+  { (eval echo "$as_me:3246: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:3189: \$? = $ac_status" >&5
+  echo "$as_me:3249: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_rl_version=`cat conftest.rlv`
 else
@@ -3209,7 +3269,7 @@ RL_MINOR=0
 case "$ac_cv_rl_version" in
 2*|3*|4*|5*|6*|7*|8*|9*)
        RL_MAJOR=`echo $ac_cv_rl_version | sed 's:\..*$::'`
-       RL_MINOR=`echo $ac_cv_rl_version | sed -e 's:^.*\.::' -e 's:a-zA-Z*$::'`
+       RL_MINOR=`echo $ac_cv_rl_version | sed -e 's:^.*\.::' -e 's:[a-zA-Z]*$::'`
        ;;
 esac
 
@@ -3232,14 +3292,14 @@ RL_VERSION="0x${_RL_MAJOR}${_RL_MINOR}"
 # Readline versions greater than 4.2 have these defines in readline.h
 
 if test $ac_cv_rl_version = '0.0' ; then
-       { echo "$as_me:3235: WARNING: Could not test version of installed readline library." >&5
+       { echo "$as_me:3295: WARNING: Could not test version of installed readline library." >&5
 echo "$as_me: WARNING: Could not test version of installed readline library." >&2;}
 elif test $RL_MAJOR -gt 4 || { test $RL_MAJOR = 4 && test $RL_MINOR -gt 2 ; } ; then
        # set these for use by the caller
        RL_PREFIX=$ac_cv_rl_prefix
        RL_LIBDIR=$ac_cv_rl_libdir
        RL_INCLUDEDIR=$ac_cv_rl_includedir
-       echo "$as_me:3242: result: $ac_cv_rl_version" >&5
+       echo "$as_me:3302: result: $ac_cv_rl_version" >&5
 echo "${ECHO_T}$ac_cv_rl_version" >&6
 else
 
@@ -3260,17 +3320,17 @@ RL_PREFIX=$ac_cv_rl_prefix
 RL_LIBDIR=$ac_cv_rl_libdir
 RL_INCLUDEDIR=$ac_cv_rl_includedir
 
-echo "$as_me:3263: result: $ac_cv_rl_version" >&5
+echo "$as_me:3323: result: $ac_cv_rl_version" >&5
 echo "${ECHO_T}$ac_cv_rl_version" >&6
 
 fi
 
        case "$ac_cv_rl_version" in
-       4.[2-9]*|5*|6*|7*|8*|9*)        ;;
+       4.[3-9]*|5*|6*|7*|8*|9*)        ;;
        *)      opt_with_installed_readline=no
-               { echo "$as_me:3271: WARNING: installed readline library is too old to be linked with bash" >&5
+               { echo "$as_me:3331: WARNING: installed readline library is too old to be linked with bash" >&5
 echo "$as_me: WARNING: installed readline library is too old to be linked with bash" >&2;}
-               { echo "$as_me:3273: WARNING: using private bash version" >&5
+               { echo "$as_me:3333: WARNING: using private bash version" >&5
 echo "$as_me: WARNING: using private bash version" >&2;}
                ;;
        esac
@@ -3338,7 +3398,7 @@ fi
 # AFS /usr/afsws/bin/install, which mishandles nonexistent args
 # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
 # ./install, which can be erroneously created by make from ./install.sh.
-echo "$as_me:3341: checking for a BSD compatible install" >&5
+echo "$as_me:3401: checking for a BSD compatible install" >&5
 echo $ECHO_N "checking for a BSD compatible install... $ECHO_C" >&6
 if test -z "$INSTALL"; then
 if test "${ac_cv_path_install+set}" = set; then
@@ -3387,7 +3447,7 @@ fi
     INSTALL=$ac_install_sh
   fi
 fi
-echo "$as_me:3390: result: $INSTALL" >&5
+echo "$as_me:3450: result: $INSTALL" >&5
 echo "${ECHO_T}$INSTALL" >&6
 
 # Use test -z because SunOS4 sh mishandles braces in ${var-val}.
@@ -3400,7 +3460,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
 
 # Extract the first word of "ar", so it can be a program name with args.
 set dummy ar; ac_word=$2
-echo "$as_me:3403: checking for $ac_word" >&5
+echo "$as_me:3463: checking for $ac_word" >&5
 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_AR+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -3415,7 +3475,7 @@ for ac_dir in $ac_dummy; do
   test -z "$ac_dir" && ac_dir=.
   $as_executable_p "$ac_dir/$ac_word" || continue
 ac_cv_prog_AR=""
-echo "$as_me:3418: found $ac_dir/$ac_word" >&5
+echo "$as_me:3478: found $ac_dir/$ac_word" >&5
 break
 done
 
@@ -3424,10 +3484,10 @@ fi
 fi
 AR=$ac_cv_prog_AR
 if test -n "$AR"; then
-  echo "$as_me:3427: result: $AR" >&5
+  echo "$as_me:3487: result: $AR" >&5
 echo "${ECHO_T}$AR" >&6
 else
-  echo "$as_me:3430: result: no" >&5
+  echo "$as_me:3490: result: no" >&5
 echo "${ECHO_T}no" >&6
 fi
 
@@ -3435,7 +3495,7 @@ test -n "$ARFLAGS" || ARFLAGS="cr"
 if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
 set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-echo "$as_me:3438: checking for $ac_word" >&5
+echo "$as_me:3498: checking for $ac_word" >&5
 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_RANLIB+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -3450,7 +3510,7 @@ for ac_dir in $ac_dummy; do
   test -z "$ac_dir" && ac_dir=.
   $as_executable_p "$ac_dir/$ac_word" || continue
 ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
-echo "$as_me:3453: found $ac_dir/$ac_word" >&5
+echo "$as_me:3513: found $ac_dir/$ac_word" >&5
 break
 done
 
@@ -3458,10 +3518,10 @@ fi
 fi
 RANLIB=$ac_cv_prog_RANLIB
 if test -n "$RANLIB"; then
-  echo "$as_me:3461: result: $RANLIB" >&5
+  echo "$as_me:3521: result: $RANLIB" >&5
 echo "${ECHO_T}$RANLIB" >&6
 else
-  echo "$as_me:3464: result: no" >&5
+  echo "$as_me:3524: result: no" >&5
 echo "${ECHO_T}no" >&6
 fi
 
@@ -3470,7 +3530,7 @@ if test -z "$ac_cv_prog_RANLIB"; then
   ac_ct_RANLIB=$RANLIB
   # Extract the first word of "ranlib", so it can be a program name with args.
 set dummy ranlib; ac_word=$2
-echo "$as_me:3473: checking for $ac_word" >&5
+echo "$as_me:3533: checking for $ac_word" >&5
 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -3485,7 +3545,7 @@ for ac_dir in $ac_dummy; do
   test -z "$ac_dir" && ac_dir=.
   $as_executable_p "$ac_dir/$ac_word" || continue
 ac_cv_prog_ac_ct_RANLIB="ranlib"
-echo "$as_me:3488: found $ac_dir/$ac_word" >&5
+echo "$as_me:3548: found $ac_dir/$ac_word" >&5
 break
 done
 
@@ -3494,10 +3554,10 @@ fi
 fi
 ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
 if test -n "$ac_ct_RANLIB"; then
-  echo "$as_me:3497: result: $ac_ct_RANLIB" >&5
+  echo "$as_me:3557: result: $ac_ct_RANLIB" >&5
 echo "${ECHO_T}$ac_ct_RANLIB" >&6
 else
-  echo "$as_me:3500: result: no" >&5
+  echo "$as_me:3560: result: no" >&5
 echo "${ECHO_T}no" >&6
 fi
 
@@ -3510,7 +3570,7 @@ for ac_prog in 'bison -y' byacc
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
-echo "$as_me:3513: checking for $ac_word" >&5
+echo "$as_me:3573: checking for $ac_word" >&5
 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_YACC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -3525,7 +3585,7 @@ for ac_dir in $ac_dummy; do
   test -z "$ac_dir" && ac_dir=.
   $as_executable_p "$ac_dir/$ac_word" || continue
 ac_cv_prog_YACC="$ac_prog"
-echo "$as_me:3528: found $ac_dir/$ac_word" >&5
+echo "$as_me:3588: found $ac_dir/$ac_word" >&5
 break
 done
 
@@ -3533,10 +3593,10 @@ fi
 fi
 YACC=$ac_cv_prog_YACC
 if test -n "$YACC"; then
-  echo "$as_me:3536: result: $YACC" >&5
+  echo "$as_me:3596: result: $YACC" >&5
 echo "${ECHO_T}$YACC" >&6
 else
-  echo "$as_me:3539: result: no" >&5
+  echo "$as_me:3599: result: no" >&5
 echo "${ECHO_T}no" >&6
 fi
 
@@ -3544,7 +3604,7 @@ fi
 done
 test -n "$YACC" || YACC="yacc"
 
-echo "$as_me:3547: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "$as_me:3607: checking whether ${MAKE-make} sets \${MAKE}" >&5
 echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6
 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'`
 if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
@@ -3564,11 +3624,11 @@ fi
 rm -f conftest.make
 fi
 if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
-  echo "$as_me:3567: result: yes" >&5
+  echo "$as_me:3627: result: yes" >&5
 echo "${ECHO_T}yes" >&6
   SET_MAKE=
 else
-  echo "$as_me:3571: result: no" >&5
+  echo "$as_me:3631: result: no" >&5
 echo "${ECHO_T}no" >&6
   SET_MAKE="MAKE=${MAKE-make}"
 fi
@@ -3582,7 +3642,7 @@ cat >>confdefs.h <<\EOF
 #define _GNU_SOURCE 1
 EOF
 
-echo "$as_me:3585: checking for $CC option to accept ANSI C" >&5
+echo "$as_me:3645: checking for $CC option to accept ANSI C" >&5
 echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
 if test "${ac_cv_prog_cc_stdc+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -3590,7 +3650,7 @@ else
   ac_cv_prog_cc_stdc=no
 ac_save_CC=$CC
 cat >conftest.$ac_ext <<_ACEOF
-#line 3593 "configure"
+#line 3653 "configure"
 #include "confdefs.h"
 #include <stdarg.h>
 #include <stdio.h>
@@ -3639,16 +3699,16 @@ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIO
 do
   CC="$ac_save_CC $ac_arg"
   rm -f conftest.$ac_objext
-if { (eval echo "$as_me:3642: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:3702: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:3645: \$? = $ac_status" >&5
+  echo "$as_me:3705: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:3648: \"$ac_try\"") >&5
+  { (eval echo "$as_me:3708: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:3651: \$? = $ac_status" >&5
+  echo "$as_me:3711: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_prog_cc_stdc=$ac_arg
 break
@@ -3665,21 +3725,21 @@ fi
 
 case "x$ac_cv_prog_cc_stdc" in
   x|xno)
-    echo "$as_me:3668: result: none needed" >&5
+    echo "$as_me:3728: result: none needed" >&5
 echo "${ECHO_T}none needed" >&6 ;;
   *)
-    echo "$as_me:3671: result: $ac_cv_prog_cc_stdc" >&5
+    echo "$as_me:3731: result: $ac_cv_prog_cc_stdc" >&5
 echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
     CC="$CC $ac_cv_prog_cc_stdc" ;;
 esac
 
-echo "$as_me:3676: checking for an ANSI C-conforming const" >&5
+echo "$as_me:3736: checking for an ANSI C-conforming const" >&5
 echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6
 if test "${ac_cv_c_const+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 3682 "configure"
+#line 3742 "configure"
 #include "confdefs.h"
 
 int
@@ -3737,16 +3797,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:3740: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:3800: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:3743: \$? = $ac_status" >&5
+  echo "$as_me:3803: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:3746: \"$ac_try\"") >&5
+  { (eval echo "$as_me:3806: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:3749: \$? = $ac_status" >&5
+  echo "$as_me:3809: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_c_const=yes
 else
@@ -3756,7 +3816,7 @@ ac_cv_c_const=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:3759: result: $ac_cv_c_const" >&5
+echo "$as_me:3819: result: $ac_cv_c_const" >&5
 echo "${ECHO_T}$ac_cv_c_const" >&6
 if test $ac_cv_c_const = no; then
 
@@ -3766,7 +3826,7 @@ EOF
 
 fi
 
-echo "$as_me:3769: checking for inline" >&5
+echo "$as_me:3829: checking for inline" >&5
 echo $ECHO_N "checking for inline... $ECHO_C" >&6
 if test "${ac_cv_c_inline+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -3774,7 +3834,7 @@ else
   ac_cv_c_inline=no
 for ac_kw in inline __inline__ __inline; do
   cat >conftest.$ac_ext <<_ACEOF
-#line 3777 "configure"
+#line 3837 "configure"
 #include "confdefs.h"
 #ifndef __cplusplus
 static $ac_kw int static_foo () {return 0; }
@@ -3783,16 +3843,16 @@ $ac_kw int foo () {return 0; }
 
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:3786: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:3846: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:3789: \$? = $ac_status" >&5
+  echo "$as_me:3849: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:3792: \"$ac_try\"") >&5
+  { (eval echo "$as_me:3852: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:3795: \$? = $ac_status" >&5
+  echo "$as_me:3855: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_c_inline=$ac_kw; break
 else
@@ -3803,7 +3863,7 @@ rm -f conftest.$ac_objext conftest.$ac_ext
 done
 
 fi
-echo "$as_me:3806: result: $ac_cv_c_inline" >&5
+echo "$as_me:3866: result: $ac_cv_c_inline" >&5
 echo "${ECHO_T}$ac_cv_c_inline" >&6
 case $ac_cv_c_inline in
   inline | yes) ;;
@@ -3818,7 +3878,7 @@ EOF
  ;;
 esac
 
-echo "$as_me:3821: checking whether byte ordering is bigendian" >&5
+echo "$as_me:3881: checking whether byte ordering is bigendian" >&5
 echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6
 if test "${ac_cv_c_bigendian+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -3826,7 +3886,7 @@ else
   ac_cv_c_bigendian=unknown
 # See if sys/param.h defines the BYTE_ORDER macro.
 cat >conftest.$ac_ext <<_ACEOF
-#line 3829 "configure"
+#line 3889 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
@@ -3843,20 +3903,20 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:3846: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:3906: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:3849: \$? = $ac_status" >&5
+  echo "$as_me:3909: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:3852: \"$ac_try\"") >&5
+  { (eval echo "$as_me:3912: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:3855: \$? = $ac_status" >&5
+  echo "$as_me:3915: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   # It does; now see whether it defined to BIG_ENDIAN or not.
 cat >conftest.$ac_ext <<_ACEOF
-#line 3859 "configure"
+#line 3919 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
@@ -3873,16 +3933,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:3876: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:3936: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:3879: \$? = $ac_status" >&5
+  echo "$as_me:3939: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:3882: \"$ac_try\"") >&5
+  { (eval echo "$as_me:3942: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:3885: \$? = $ac_status" >&5
+  echo "$as_me:3945: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_c_bigendian=yes
 else
@@ -3898,12 +3958,12 @@ fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 if test $ac_cv_c_bigendian = unknown; then
 if test "$cross_compiling" = yes; then
-  { { echo "$as_me:3901: error: cannot run test program while cross compiling" >&5
+  { { echo "$as_me:3961: error: cannot run test program while cross compiling" >&5
 echo "$as_me: error: cannot run test program while cross compiling" >&2;}
    { (exit 1); exit 1; }; }
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 3906 "configure"
+#line 3966 "configure"
 #include "confdefs.h"
 int
 main ()
@@ -3919,15 +3979,15 @@ main ()
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:3922: \"$ac_link\"") >&5
+if { (eval echo "$as_me:3982: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:3925: \$? = $ac_status" >&5
+  echo "$as_me:3985: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:3927: \"$ac_try\"") >&5
+  { (eval echo "$as_me:3987: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:3930: \$? = $ac_status" >&5
+  echo "$as_me:3990: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_c_bigendian=no
 else
@@ -3940,7 +4000,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
 fi
-echo "$as_me:3943: result: $ac_cv_c_bigendian" >&5
+echo "$as_me:4003: result: $ac_cv_c_bigendian" >&5
 echo "${ECHO_T}$ac_cv_c_bigendian" >&6
 if test $ac_cv_c_bigendian = yes; then
 
@@ -3950,13 +4010,13 @@ EOF
 
 fi
 
-echo "$as_me:3953: checking for preprocessor stringizing operator" >&5
+echo "$as_me:4013: checking for preprocessor stringizing operator" >&5
 echo $ECHO_N "checking for preprocessor stringizing operator... $ECHO_C" >&6
 if test "${ac_cv_c_stringize+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 3959 "configure"
+#line 4019 "configure"
 #include "confdefs.h"
 #define x(y) #y
 
@@ -3971,7 +4031,7 @@ fi
 rm -f conftest*
 
 fi
-echo "$as_me:3974: result: $ac_cv_c_stringize" >&5
+echo "$as_me:4034: result: $ac_cv_c_stringize" >&5
 echo "${ECHO_T}$ac_cv_c_stringize" >&6
 if test $ac_cv_c_stringize = yes; then
 
@@ -3981,7 +4041,7 @@ EOF
 
 fi
 
-echo "$as_me:3984: checking for long double" >&5
+echo "$as_me:4044: checking for long double" >&5
 echo $ECHO_N "checking for long double... $ECHO_C" >&6
 if test "${ac_cv_c_long_double+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -3990,12 +4050,12 @@ else
   ac_cv_c_long_double=yes
 else
 if test "$cross_compiling" = yes; then
-  { { echo "$as_me:3993: error: cannot run test program while cross compiling" >&5
+  { { echo "$as_me:4053: error: cannot run test program while cross compiling" >&5
 echo "$as_me: error: cannot run test program while cross compiling" >&2;}
    { (exit 1); exit 1; }; }
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 3998 "configure"
+#line 4058 "configure"
 #include "confdefs.h"
 int
 main ()
@@ -4008,15 +4068,15 @@ main ()
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:4011: \"$ac_link\"") >&5
+if { (eval echo "$as_me:4071: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:4014: \$? = $ac_status" >&5
+  echo "$as_me:4074: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:4016: \"$ac_try\"") >&5
+  { (eval echo "$as_me:4076: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:4019: \$? = $ac_status" >&5
+  echo "$as_me:4079: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_c_long_double=yes
 else
@@ -4029,7 +4089,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
 fi
-echo "$as_me:4032: result: $ac_cv_c_long_double" >&5
+echo "$as_me:4092: result: $ac_cv_c_long_double" >&5
 echo "${ECHO_T}$ac_cv_c_long_double" >&6
 if test $ac_cv_c_long_double = yes; then
 
@@ -4039,10 +4099,10 @@ EOF
 
 fi
 
-echo "$as_me:4042: checking for function prototypes" >&5
+echo "$as_me:4102: checking for function prototypes" >&5
 echo $ECHO_N "checking for function prototypes... $ECHO_C" >&6
 if test "$ac_cv_prog_cc_stdc" != no; then
-  echo "$as_me:4045: result: yes" >&5
+  echo "$as_me:4105: result: yes" >&5
 echo "${ECHO_T}yes" >&6
 
 cat >>confdefs.h <<\EOF
@@ -4050,17 +4110,17 @@ cat >>confdefs.h <<\EOF
 EOF
 
 else
-  echo "$as_me:4053: result: no" >&5
+  echo "$as_me:4113: result: no" >&5
 echo "${ECHO_T}no" >&6
 fi
 
-echo "$as_me:4057: checking for ANSI C header files" >&5
+echo "$as_me:4117: checking for ANSI C header files" >&5
 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
 if test "${ac_cv_header_stdc+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 4063 "configure"
+#line 4123 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -4068,13 +4128,13 @@ else
 #include <float.h>
 
 _ACEOF
-if { (eval echo "$as_me:4071: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:4131: \"$ac_cpp conftest.$ac_ext\"") >&5
   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   egrep -v '^ *\+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
-  echo "$as_me:4077: \$? = $ac_status" >&5
+  echo "$as_me:4137: \$? = $ac_status" >&5
   (exit $ac_status); } >/dev/null; then
   if test -s conftest.err; then
     ac_cpp_err=$ac_c_preproc_warn_flag
@@ -4096,7 +4156,7 @@ rm -f conftest.err conftest.$ac_ext
 if test $ac_cv_header_stdc = yes; then
   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
   cat >conftest.$ac_ext <<_ACEOF
-#line 4099 "configure"
+#line 4159 "configure"
 #include "confdefs.h"
 #include <string.h>
 
@@ -4114,7 +4174,7 @@ fi
 if test $ac_cv_header_stdc = yes; then
   # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
   cat >conftest.$ac_ext <<_ACEOF
-#line 4117 "configure"
+#line 4177 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 
@@ -4135,7 +4195,7 @@ if test $ac_cv_header_stdc = yes; then
   :
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 4138 "configure"
+#line 4198 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #if ((' ' & 0x0FF) == 0x020)
@@ -4161,15 +4221,15 @@ main ()
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:4164: \"$ac_link\"") >&5
+if { (eval echo "$as_me:4224: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:4167: \$? = $ac_status" >&5
+  echo "$as_me:4227: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:4169: \"$ac_try\"") >&5
+  { (eval echo "$as_me:4229: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:4172: \$? = $ac_status" >&5
+  echo "$as_me:4232: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   :
 else
@@ -4182,7 +4242,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
 fi
-echo "$as_me:4185: result: $ac_cv_header_stdc" >&5
+echo "$as_me:4245: result: $ac_cv_header_stdc" >&5
 echo "${ECHO_T}$ac_cv_header_stdc" >&6
 if test $ac_cv_header_stdc = yes; then
 
@@ -4198,28 +4258,28 @@ for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
                   inttypes.h stdint.h unistd.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-echo "$as_me:4201: checking for $ac_header" >&5
+echo "$as_me:4261: checking for $ac_header" >&5
 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
 if eval "test \"\${$as_ac_Header+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 4207 "configure"
+#line 4267 "configure"
 #include "confdefs.h"
 $ac_includes_default
 #include <$ac_header>
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:4213: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:4273: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:4216: \$? = $ac_status" >&5
+  echo "$as_me:4276: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:4219: \"$ac_try\"") >&5
+  { (eval echo "$as_me:4279: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:4222: \$? = $ac_status" >&5
+  echo "$as_me:4282: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   eval "$as_ac_Header=yes"
 else
@@ -4229,7 +4289,7 @@ eval "$as_ac_Header=no"
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:4232: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "$as_me:4292: result: `eval echo '${'$as_ac_Header'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
 if test `eval echo '${'$as_ac_Header'}'` = yes; then
   cat >>confdefs.h <<EOF
@@ -4239,13 +4299,13 @@ EOF
 fi
 done
 
-echo "$as_me:4242: checking whether char is unsigned" >&5
+echo "$as_me:4302: checking whether char is unsigned" >&5
 echo $ECHO_N "checking whether char is unsigned... $ECHO_C" >&6
 if test "${ac_cv_c_char_unsigned+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 4248 "configure"
+#line 4308 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -4257,16 +4317,16 @@ int _array_ [1 - 2 * !(((char) -1) < 0)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:4260: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:4320: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:4263: \$? = $ac_status" >&5
+  echo "$as_me:4323: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:4266: \"$ac_try\"") >&5
+  { (eval echo "$as_me:4326: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:4269: \$? = $ac_status" >&5
+  echo "$as_me:4329: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_c_char_unsigned=no
 else
@@ -4276,7 +4336,7 @@ ac_cv_c_char_unsigned=yes
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:4279: result: $ac_cv_c_char_unsigned" >&5
+echo "$as_me:4339: result: $ac_cv_c_char_unsigned" >&5
 echo "${ECHO_T}$ac_cv_c_char_unsigned" >&6
 if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then
   cat >>confdefs.h <<\EOF
@@ -4288,13 +4348,13 @@ fi
 ac_header_dirent=no
 for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
   as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
-echo "$as_me:4291: checking for $ac_hdr that defines DIR" >&5
+echo "$as_me:4351: checking for $ac_hdr that defines DIR" >&5
 echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6
 if eval "test \"\${$as_ac_Header+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 4297 "configure"
+#line 4357 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <$ac_hdr>
@@ -4309,16 +4369,16 @@ return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:4312: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:4372: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:4315: \$? = $ac_status" >&5
+  echo "$as_me:4375: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:4318: \"$ac_try\"") >&5
+  { (eval echo "$as_me:4378: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:4321: \$? = $ac_status" >&5
+  echo "$as_me:4381: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   eval "$as_ac_Header=yes"
 else
@@ -4328,7 +4388,7 @@ eval "$as_ac_Header=no"
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:4331: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "$as_me:4391: result: `eval echo '${'$as_ac_Header'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
 if test `eval echo '${'$as_ac_Header'}'` = yes; then
   cat >>confdefs.h <<EOF
@@ -4341,7 +4401,7 @@ fi
 done
 # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
 if test $ac_header_dirent = dirent.h; then
-  echo "$as_me:4344: checking for opendir in -ldir" >&5
+  echo "$as_me:4404: checking for opendir in -ldir" >&5
 echo $ECHO_N "checking for opendir in -ldir... $ECHO_C" >&6
 if test "${ac_cv_lib_dir_opendir+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -4349,7 +4409,7 @@ else
   ac_check_lib_save_LIBS=$LIBS
 LIBS="-ldir  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
-#line 4352 "configure"
+#line 4412 "configure"
 #include "confdefs.h"
 
 /* Override any gcc2 internal prototype to avoid an error.  */
@@ -4368,16 +4428,16 @@ opendir ();
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:4371: \"$ac_link\"") >&5
+if { (eval echo "$as_me:4431: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:4374: \$? = $ac_status" >&5
+  echo "$as_me:4434: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:4377: \"$ac_try\"") >&5
+  { (eval echo "$as_me:4437: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:4380: \$? = $ac_status" >&5
+  echo "$as_me:4440: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_lib_dir_opendir=yes
 else
@@ -4388,14 +4448,14 @@ fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:4391: result: $ac_cv_lib_dir_opendir" >&5
+echo "$as_me:4451: result: $ac_cv_lib_dir_opendir" >&5
 echo "${ECHO_T}$ac_cv_lib_dir_opendir" >&6
 if test $ac_cv_lib_dir_opendir = yes; then
   LIBS="$LIBS -ldir"
 fi
 
 else
-  echo "$as_me:4398: checking for opendir in -lx" >&5
+  echo "$as_me:4458: checking for opendir in -lx" >&5
 echo $ECHO_N "checking for opendir in -lx... $ECHO_C" >&6
 if test "${ac_cv_lib_x_opendir+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -4403,7 +4463,7 @@ else
   ac_check_lib_save_LIBS=$LIBS
 LIBS="-lx  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
-#line 4406 "configure"
+#line 4466 "configure"
 #include "confdefs.h"
 
 /* Override any gcc2 internal prototype to avoid an error.  */
@@ -4422,16 +4482,16 @@ opendir ();
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:4425: \"$ac_link\"") >&5
+if { (eval echo "$as_me:4485: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:4428: \$? = $ac_status" >&5
+  echo "$as_me:4488: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:4431: \"$ac_try\"") >&5
+  { (eval echo "$as_me:4491: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:4434: \$? = $ac_status" >&5
+  echo "$as_me:4494: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_lib_x_opendir=yes
 else
@@ -4442,7 +4502,7 @@ fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:4445: result: $ac_cv_lib_x_opendir" >&5
+echo "$as_me:4505: result: $ac_cv_lib_x_opendir" >&5
 echo "${ECHO_T}$ac_cv_lib_x_opendir" >&6
 if test $ac_cv_lib_x_opendir = yes; then
   LIBS="$LIBS -lx"
@@ -4450,13 +4510,13 @@ fi
 
 fi
 
-echo "$as_me:4453: checking whether time.h and sys/time.h may both be included" >&5
+echo "$as_me:4513: checking whether time.h and sys/time.h may both be included" >&5
 echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6
 if test "${ac_cv_header_time+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 4459 "configure"
+#line 4519 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/time.h>
@@ -4472,16 +4532,16 @@ return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:4475: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:4535: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:4478: \$? = $ac_status" >&5
+  echo "$as_me:4538: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:4481: \"$ac_try\"") >&5
+  { (eval echo "$as_me:4541: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:4484: \$? = $ac_status" >&5
+  echo "$as_me:4544: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_header_time=yes
 else
@@ -4491,7 +4551,7 @@ ac_cv_header_time=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:4494: result: $ac_cv_header_time" >&5
+echo "$as_me:4554: result: $ac_cv_header_time" >&5
 echo "${ECHO_T}$ac_cv_header_time" >&6
 if test $ac_cv_header_time = yes; then
 
@@ -4504,23 +4564,23 @@ fi
 for ac_header in inttypes.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-echo "$as_me:4507: checking for $ac_header" >&5
+echo "$as_me:4567: checking for $ac_header" >&5
 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
 if eval "test \"\${$as_ac_Header+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 4513 "configure"
+#line 4573 "configure"
 #include "confdefs.h"
 #include <$ac_header>
 _ACEOF
-if { (eval echo "$as_me:4517: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:4577: \"$ac_cpp conftest.$ac_ext\"") >&5
   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   egrep -v '^ *\+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
-  echo "$as_me:4523: \$? = $ac_status" >&5
+  echo "$as_me:4583: \$? = $ac_status" >&5
   (exit $ac_status); } >/dev/null; then
   if test -s conftest.err; then
     ac_cpp_err=$ac_c_preproc_warn_flag
@@ -4539,7 +4599,7 @@ else
 fi
 rm -f conftest.err conftest.$ac_ext
 fi
-echo "$as_me:4542: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "$as_me:4602: result: `eval echo '${'$as_ac_Header'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
 if test `eval echo '${'$as_ac_Header'}'` = yes; then
   cat >>confdefs.h <<EOF
@@ -4554,23 +4614,23 @@ for ac_header in unistd.h stdlib.h stdarg.h varargs.h limits.h string.h \
                 stddef.h stdint.h netdb.h grp.h strings.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-echo "$as_me:4557: checking for $ac_header" >&5
+echo "$as_me:4617: checking for $ac_header" >&5
 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
 if eval "test \"\${$as_ac_Header+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 4563 "configure"
+#line 4623 "configure"
 #include "confdefs.h"
 #include <$ac_header>
 _ACEOF
-if { (eval echo "$as_me:4567: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:4627: \"$ac_cpp conftest.$ac_ext\"") >&5
   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   egrep -v '^ *\+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
-  echo "$as_me:4573: \$? = $ac_status" >&5
+  echo "$as_me:4633: \$? = $ac_status" >&5
   (exit $ac_status); } >/dev/null; then
   if test -s conftest.err; then
     ac_cpp_err=$ac_c_preproc_warn_flag
@@ -4589,7 +4649,7 @@ else
 fi
 rm -f conftest.err conftest.$ac_ext
 fi
-echo "$as_me:4592: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "$as_me:4652: result: `eval echo '${'$as_ac_Header'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
 if test `eval echo '${'$as_ac_Header'}'` = yes; then
   cat >>confdefs.h <<EOF
@@ -4604,23 +4664,23 @@ for ac_header in sys/ptem.h sys/pte.h sys/stream.h sys/select.h sys/file.h \
                 sys/time.h sys/times.h sys/wait.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-echo "$as_me:4607: checking for $ac_header" >&5
+echo "$as_me:4667: checking for $ac_header" >&5
 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
 if eval "test \"\${$as_ac_Header+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 4613 "configure"
+#line 4673 "configure"
 #include "confdefs.h"
 #include <$ac_header>
 _ACEOF
-if { (eval echo "$as_me:4617: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:4677: \"$ac_cpp conftest.$ac_ext\"") >&5
   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   egrep -v '^ *\+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
-  echo "$as_me:4623: \$? = $ac_status" >&5
+  echo "$as_me:4683: \$? = $ac_status" >&5
   (exit $ac_status); } >/dev/null; then
   if test -s conftest.err; then
     ac_cpp_err=$ac_c_preproc_warn_flag
@@ -4639,7 +4699,7 @@ else
 fi
 rm -f conftest.err conftest.$ac_ext
 fi
-echo "$as_me:4642: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "$as_me:4702: result: `eval echo '${'$as_ac_Header'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
 if test `eval echo '${'$as_ac_Header'}'` = yes; then
   cat >>confdefs.h <<EOF
@@ -4652,23 +4712,23 @@ done
 for ac_header in netinet/in.h arpa/inet.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-echo "$as_me:4655: checking for $ac_header" >&5
+echo "$as_me:4715: checking for $ac_header" >&5
 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
 if eval "test \"\${$as_ac_Header+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 4661 "configure"
+#line 4721 "configure"
 #include "confdefs.h"
 #include <$ac_header>
 _ACEOF
-if { (eval echo "$as_me:4665: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:4725: \"$ac_cpp conftest.$ac_ext\"") >&5
   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   egrep -v '^ *\+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
-  echo "$as_me:4671: \$? = $ac_status" >&5
+  echo "$as_me:4731: \$? = $ac_status" >&5
   (exit $ac_status); } >/dev/null; then
   if test -s conftest.err; then
     ac_cpp_err=$ac_c_preproc_warn_flag
@@ -4687,7 +4747,7 @@ else
 fi
 rm -f conftest.err conftest.$ac_ext
 fi
-echo "$as_me:4690: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "$as_me:4750: result: `eval echo '${'$as_ac_Header'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
 if test `eval echo '${'$as_ac_Header'}'` = yes; then
   cat >>confdefs.h <<EOF
@@ -4699,13 +4759,13 @@ done
 
 # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
 # for constant arguments.  Useless!
-echo "$as_me:4702: checking for working alloca.h" >&5
+echo "$as_me:4762: checking for working alloca.h" >&5
 echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6
 if test "${ac_cv_working_alloca_h+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 4708 "configure"
+#line 4768 "configure"
 #include "confdefs.h"
 #include <alloca.h>
 int
@@ -4717,16 +4777,16 @@ char *p = (char *) alloca (2 * sizeof (int));
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:4720: \"$ac_link\"") >&5
+if { (eval echo "$as_me:4780: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:4723: \$? = $ac_status" >&5
+  echo "$as_me:4783: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:4726: \"$ac_try\"") >&5
+  { (eval echo "$as_me:4786: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:4729: \$? = $ac_status" >&5
+  echo "$as_me:4789: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_working_alloca_h=yes
 else
@@ -4736,7 +4796,7 @@ ac_cv_working_alloca_h=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:4739: result: $ac_cv_working_alloca_h" >&5
+echo "$as_me:4799: result: $ac_cv_working_alloca_h" >&5
 echo "${ECHO_T}$ac_cv_working_alloca_h" >&6
 if test $ac_cv_working_alloca_h = yes; then
 
@@ -4746,13 +4806,13 @@ EOF
 
 fi
 
-echo "$as_me:4749: checking for alloca" >&5
+echo "$as_me:4809: checking for alloca" >&5
 echo $ECHO_N "checking for alloca... $ECHO_C" >&6
 if test "${ac_cv_func_alloca_works+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 4755 "configure"
+#line 4815 "configure"
 #include "confdefs.h"
 #ifdef __GNUC__
 # define alloca __builtin_alloca
@@ -4784,16 +4844,16 @@ char *p = (char *) alloca (1);
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:4787: \"$ac_link\"") >&5
+if { (eval echo "$as_me:4847: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:4790: \$? = $ac_status" >&5
+  echo "$as_me:4850: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:4793: \"$ac_try\"") >&5
+  { (eval echo "$as_me:4853: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:4796: \$? = $ac_status" >&5
+  echo "$as_me:4856: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_func_alloca_works=yes
 else
@@ -4803,7 +4863,7 @@ ac_cv_func_alloca_works=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:4806: result: $ac_cv_func_alloca_works" >&5
+echo "$as_me:4866: result: $ac_cv_func_alloca_works" >&5
 echo "${ECHO_T}$ac_cv_func_alloca_works" >&6
 
 if test $ac_cv_func_alloca_works = yes; then
@@ -4824,13 +4884,13 @@ cat >>confdefs.h <<\EOF
 #define C_ALLOCA 1
 EOF
 
-echo "$as_me:4827: checking whether \`alloca.c' needs Cray hooks" >&5
+echo "$as_me:4887: checking whether \`alloca.c' needs Cray hooks" >&5
 echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6
 if test "${ac_cv_os_cray+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 4833 "configure"
+#line 4893 "configure"
 #include "confdefs.h"
 #if defined(CRAY) && ! defined(CRAY2)
 webecray
@@ -4848,18 +4908,18 @@ fi
 rm -f conftest*
 
 fi
-echo "$as_me:4851: result: $ac_cv_os_cray" >&5
+echo "$as_me:4911: result: $ac_cv_os_cray" >&5
 echo "${ECHO_T}$ac_cv_os_cray" >&6
 if test $ac_cv_os_cray = yes; then
   for ac_func in _getb67 GETB67 getb67; do
     as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:4856: checking for $ac_func" >&5
+echo "$as_me:4916: checking for $ac_func" >&5
 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
 if eval "test \"\${$as_ac_var+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 4862 "configure"
+#line 4922 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func (); below.  */
@@ -4890,16 +4950,16 @@ f = $ac_func;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:4893: \"$ac_link\"") >&5
+if { (eval echo "$as_me:4953: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:4896: \$? = $ac_status" >&5
+  echo "$as_me:4956: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:4899: \"$ac_try\"") >&5
+  { (eval echo "$as_me:4959: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:4902: \$? = $ac_status" >&5
+  echo "$as_me:4962: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   eval "$as_ac_var=yes"
 else
@@ -4909,7 +4969,7 @@ eval "$as_ac_var=no"
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:4912: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "$as_me:4972: result: `eval echo '${'$as_ac_var'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
 if test `eval echo '${'$as_ac_var'}'` = yes; then
 
@@ -4923,7 +4983,7 @@ fi
   done
 fi
 
-echo "$as_me:4926: checking stack direction for C alloca" >&5
+echo "$as_me:4986: checking stack direction for C alloca" >&5
 echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6
 if test "${ac_cv_c_stack_direction+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -4932,7 +4992,7 @@ else
   ac_cv_c_stack_direction=0
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 4935 "configure"
+#line 4995 "configure"
 #include "confdefs.h"
 int
 find_stack_direction ()
@@ -4955,15 +5015,15 @@ main ()
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:4958: \"$ac_link\"") >&5
+if { (eval echo "$as_me:5018: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:4961: \$? = $ac_status" >&5
+  echo "$as_me:5021: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:4963: \"$ac_try\"") >&5
+  { (eval echo "$as_me:5023: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:4966: \$? = $ac_status" >&5
+  echo "$as_me:5026: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_c_stack_direction=1
 else
@@ -4975,7 +5035,7 @@ fi
 rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
-echo "$as_me:4978: result: $ac_cv_c_stack_direction" >&5
+echo "$as_me:5038: result: $ac_cv_c_stack_direction" >&5
 echo "${ECHO_T}$ac_cv_c_stack_direction" >&6
 
 cat >>confdefs.h <<EOF
@@ -4984,14 +5044,14 @@ EOF
 
 fi
 
-echo "$as_me:4987: checking whether getpgrp takes no argument" >&5
+echo "$as_me:5047: checking whether getpgrp takes no argument" >&5
 echo $ECHO_N "checking whether getpgrp takes no argument... $ECHO_C" >&6
 if test "${ac_cv_func_getpgrp_void+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   # Use it with a single arg.
 cat >conftest.$ac_ext <<_ACEOF
-#line 4994 "configure"
+#line 5054 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -5003,16 +5063,16 @@ getpgrp (0);
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:5006: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:5066: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:5009: \$? = $ac_status" >&5
+  echo "$as_me:5069: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:5012: \"$ac_try\"") >&5
+  { (eval echo "$as_me:5072: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:5015: \$? = $ac_status" >&5
+  echo "$as_me:5075: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_func_getpgrp_1=yes
 else
@@ -5023,7 +5083,7 @@ fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 # Use it with no arg.
 cat >conftest.$ac_ext <<_ACEOF
-#line 5026 "configure"
+#line 5086 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -5035,16 +5095,16 @@ getpgrp ();
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:5038: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:5098: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:5041: \$? = $ac_status" >&5
+  echo "$as_me:5101: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:5044: \"$ac_try\"") >&5
+  { (eval echo "$as_me:5104: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:5047: \$? = $ac_status" >&5
+  echo "$as_me:5107: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_func_getpgrp_0=yes
 else
@@ -5058,12 +5118,12 @@ case $ac_func_getpgrp_0:$ac_func_getpgrp_1 in
   yes:no) ac_cv_func_getpgrp_void=yes;;
   no:yes) ac_cv_func_getpgrp_void=false;;
   *) if test "$cross_compiling" = yes; then
-  { { echo "$as_me:5061: error: cannot check getpgrp if cross compiling" >&5
+  { { echo "$as_me:5121: error: cannot check getpgrp if cross compiling" >&5
 echo "$as_me: error: cannot check getpgrp if cross compiling" >&2;}
    { (exit 1); exit 1; }; }
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 5066 "configure"
+#line 5126 "configure"
 #include "confdefs.h"
 $ac_includes_default
 
@@ -5117,15 +5177,15 @@ main ()
 
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:5120: \"$ac_link\"") >&5
+if { (eval echo "$as_me:5180: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:5123: \$? = $ac_status" >&5
+  echo "$as_me:5183: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:5125: \"$ac_try\"") >&5
+  { (eval echo "$as_me:5185: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:5128: \$? = $ac_status" >&5
+  echo "$as_me:5188: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_func_getpgrp_void=yes
 else
@@ -5139,7 +5199,7 @@ fi;;
 esac # $ac_func_getpgrp_0:$ac_func_getpgrp_1
 
 fi
-echo "$as_me:5142: result: $ac_cv_func_getpgrp_void" >&5
+echo "$as_me:5202: result: $ac_cv_func_getpgrp_void" >&5
 echo "${ECHO_T}$ac_cv_func_getpgrp_void" >&6
 if test $ac_cv_func_getpgrp_void = yes; then
 
@@ -5149,18 +5209,18 @@ EOF
 
 fi
 
-echo "$as_me:5152: checking whether setvbuf arguments are reversed" >&5
+echo "$as_me:5212: checking whether setvbuf arguments are reversed" >&5
 echo $ECHO_N "checking whether setvbuf arguments are reversed... $ECHO_C" >&6
 if test "${ac_cv_func_setvbuf_reversed+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test "$cross_compiling" = yes; then
-  { { echo "$as_me:5158: error: cannot run test program while cross compiling" >&5
+  { { echo "$as_me:5218: error: cannot run test program while cross compiling" >&5
 echo "$as_me: error: cannot run test program while cross compiling" >&2;}
    { (exit 1); exit 1; }; }
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 5163 "configure"
+#line 5223 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 /* If setvbuf has the reversed format, exit 0. */
@@ -5177,15 +5237,15 @@ main ()
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:5180: \"$ac_link\"") >&5
+if { (eval echo "$as_me:5240: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:5183: \$? = $ac_status" >&5
+  echo "$as_me:5243: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:5185: \"$ac_try\"") >&5
+  { (eval echo "$as_me:5245: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:5188: \$? = $ac_status" >&5
+  echo "$as_me:5248: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_func_setvbuf_reversed=yes
 else
@@ -5198,7 +5258,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 rm -f core core.* *.core
 fi
-echo "$as_me:5201: result: $ac_cv_func_setvbuf_reversed" >&5
+echo "$as_me:5261: result: $ac_cv_func_setvbuf_reversed" >&5
 echo "${ECHO_T}$ac_cv_func_setvbuf_reversed" >&6
 if test $ac_cv_func_setvbuf_reversed = yes; then
 
@@ -5211,13 +5271,13 @@ fi
 for ac_func in vprintf
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:5214: checking for $ac_func" >&5
+echo "$as_me:5274: checking for $ac_func" >&5
 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
 if eval "test \"\${$as_ac_var+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 5220 "configure"
+#line 5280 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func (); below.  */
@@ -5248,16 +5308,16 @@ f = $ac_func;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:5251: \"$ac_link\"") >&5
+if { (eval echo "$as_me:5311: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:5254: \$? = $ac_status" >&5
+  echo "$as_me:5314: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:5257: \"$ac_try\"") >&5
+  { (eval echo "$as_me:5317: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:5260: \$? = $ac_status" >&5
+  echo "$as_me:5320: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   eval "$as_ac_var=yes"
 else
@@ -5267,20 +5327,20 @@ eval "$as_ac_var=no"
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:5270: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "$as_me:5330: result: `eval echo '${'$as_ac_var'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
 if test `eval echo '${'$as_ac_var'}'` = yes; then
   cat >>confdefs.h <<EOF
 #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
 EOF
 
-echo "$as_me:5277: checking for _doprnt" >&5
+echo "$as_me:5337: checking for _doprnt" >&5
 echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6
 if test "${ac_cv_func__doprnt+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 5283 "configure"
+#line 5343 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char _doprnt (); below.  */
@@ -5311,16 +5371,16 @@ f = _doprnt;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:5314: \"$ac_link\"") >&5
+if { (eval echo "$as_me:5374: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:5317: \$? = $ac_status" >&5
+  echo "$as_me:5377: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:5320: \"$ac_try\"") >&5
+  { (eval echo "$as_me:5380: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:5323: \$? = $ac_status" >&5
+  echo "$as_me:5383: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_func__doprnt=yes
 else
@@ -5330,7 +5390,7 @@ ac_cv_func__doprnt=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:5333: result: $ac_cv_func__doprnt" >&5
+echo "$as_me:5393: result: $ac_cv_func__doprnt" >&5
 echo "${ECHO_T}$ac_cv_func__doprnt" >&6
 if test $ac_cv_func__doprnt = yes; then
 
@@ -5343,7 +5403,7 @@ fi
 fi
 done
 
-echo "$as_me:5346: checking for working strcoll" >&5
+echo "$as_me:5406: checking for working strcoll" >&5
 echo $ECHO_N "checking for working strcoll... $ECHO_C" >&6
 if test "${ac_cv_func_strcoll_works+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -5352,7 +5412,7 @@ else
   ac_cv_func_strcoll_works=no
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 5355 "configure"
+#line 5415 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -5366,15 +5426,15 @@ exit (strcoll ("abc", "def") >= 0 ||
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:5369: \"$ac_link\"") >&5
+if { (eval echo "$as_me:5429: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:5372: \$? = $ac_status" >&5
+  echo "$as_me:5432: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:5374: \"$ac_try\"") >&5
+  { (eval echo "$as_me:5434: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:5377: \$? = $ac_status" >&5
+  echo "$as_me:5437: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_func_strcoll_works=yes
 else
@@ -5386,7 +5446,7 @@ fi
 rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
-echo "$as_me:5389: result: $ac_cv_func_strcoll_works" >&5
+echo "$as_me:5449: result: $ac_cv_func_strcoll_works" >&5
 echo "${ECHO_T}$ac_cv_func_strcoll_works" >&6
 if test $ac_cv_func_strcoll_works = yes; then
 
@@ -5407,10 +5467,10 @@ if test "$ac_cv_func_alloca_works" = "no" && test "$opt_bash_malloc" = "no"; the
 fi
 
 if test "$ac_cv_func_vprintf" = no; then
-    echo "$as_me:5410: checking for declaration of vprintf in stdio.h" >&5
+    echo "$as_me:5470: checking for declaration of vprintf in stdio.h" >&5
 echo $ECHO_N "checking for declaration of vprintf in stdio.h... $ECHO_C" >&6
     cat >conftest.$ac_ext <<_ACEOF
-#line 5413 "configure"
+#line 5473 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 
@@ -5421,7 +5481,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
 fi
 rm -f conftest*
 
-    echo "$as_me:5424: result: $ac_cv_func_vprintf" >&5
+    echo "$as_me:5484: result: $ac_cv_func_vprintf" >&5
 echo "${ECHO_T}$ac_cv_func_vprintf" >&6
     if test $ac_cv_func_vprintf = yes; then
        cat >>confdefs.h <<\EOF
@@ -5435,13 +5495,13 @@ if test "$ac_cv_func_vprintf" = no && test "$ac_cv_func__doprnt" = "yes"; then
   LIBOBJS="$LIBOBJS vprint.$ac_objext"
 fi
 
-echo "$as_me:5438: checking return type of signal handlers" >&5
+echo "$as_me:5498: checking return type of signal handlers" >&5
 echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6
 if test "${ac_cv_type_signal+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 5444 "configure"
+#line 5504 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <signal.h>
@@ -5463,16 +5523,16 @@ int i;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:5466: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:5526: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:5469: \$? = $ac_status" >&5
+  echo "$as_me:5529: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:5472: \"$ac_try\"") >&5
+  { (eval echo "$as_me:5532: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:5475: \$? = $ac_status" >&5
+  echo "$as_me:5535: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_signal=void
 else
@@ -5482,20 +5542,20 @@ ac_cv_type_signal=int
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:5485: result: $ac_cv_type_signal" >&5
+echo "$as_me:5545: result: $ac_cv_type_signal" >&5
 echo "${ECHO_T}$ac_cv_type_signal" >&6
 
 cat >>confdefs.h <<EOF
 #define RETSIGTYPE $ac_cv_type_signal
 EOF
 
-echo "$as_me:5492: checking for __setostype" >&5
+echo "$as_me:5552: checking for __setostype" >&5
 echo $ECHO_N "checking for __setostype... $ECHO_C" >&6
 if test "${ac_cv_func___setostype+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 5498 "configure"
+#line 5558 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char __setostype (); below.  */
@@ -5526,16 +5586,16 @@ f = __setostype;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:5529: \"$ac_link\"") >&5
+if { (eval echo "$as_me:5589: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:5532: \$? = $ac_status" >&5
+  echo "$as_me:5592: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:5535: \"$ac_try\"") >&5
+  { (eval echo "$as_me:5595: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:5538: \$? = $ac_status" >&5
+  echo "$as_me:5598: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_func___setostype=yes
 else
@@ -5545,7 +5605,7 @@ ac_cv_func___setostype=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:5548: result: $ac_cv_func___setostype" >&5
+echo "$as_me:5608: result: $ac_cv_func___setostype" >&5
 echo "${ECHO_T}$ac_cv_func___setostype" >&6
 if test $ac_cv_func___setostype = yes; then
   cat >>confdefs.h <<\EOF
@@ -5554,13 +5614,13 @@ EOF
 
 fi
 
-echo "$as_me:5557: checking for wait3" >&5
+echo "$as_me:5617: checking for wait3" >&5
 echo $ECHO_N "checking for wait3... $ECHO_C" >&6
 if test "${ac_cv_func_wait3+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 5563 "configure"
+#line 5623 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char wait3 (); below.  */
@@ -5591,16 +5651,16 @@ f = wait3;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:5594: \"$ac_link\"") >&5
+if { (eval echo "$as_me:5654: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:5597: \$? = $ac_status" >&5
+  echo "$as_me:5657: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:5600: \"$ac_try\"") >&5
+  { (eval echo "$as_me:5660: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:5603: \$? = $ac_status" >&5
+  echo "$as_me:5663: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_func_wait3=yes
 else
@@ -5610,7 +5670,7 @@ ac_cv_func_wait3=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:5613: result: $ac_cv_func_wait3" >&5
+echo "$as_me:5673: result: $ac_cv_func_wait3" >&5
 echo "${ECHO_T}$ac_cv_func_wait3" >&6
 if test $ac_cv_func_wait3 = yes; then
   cat >>confdefs.h <<\EOF
@@ -5619,13 +5679,78 @@ EOF
 
 fi
 
-echo "$as_me:5622: checking for mkfifo" >&5
+echo "$as_me:5682: checking for isinf" >&5
+echo $ECHO_N "checking for isinf... $ECHO_C" >&6
+if test "${ac_cv_func_isinf+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 5688 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char isinf (); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char isinf ();
+char (*f) ();
+
+int
+main ()
+{
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_isinf) || defined (__stub___isinf)
+choke me
+#else
+f = isinf;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:5719: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:5722: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:5725: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:5728: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_isinf=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_func_isinf=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:5738: result: $ac_cv_func_isinf" >&5
+echo "${ECHO_T}$ac_cv_func_isinf" >&6
+if test $ac_cv_func_isinf = yes; then
+  cat >>confdefs.h <<\EOF
+#define HAVE_ISINF_IN_LIBC 1
+EOF
+
+fi
+
+echo "$as_me:5747: checking for mkfifo" >&5
 echo $ECHO_N "checking for mkfifo... $ECHO_C" >&6
 if test "${ac_cv_func_mkfifo+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 5628 "configure"
+#line 5753 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char mkfifo (); below.  */
@@ -5656,16 +5781,16 @@ f = mkfifo;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:5659: \"$ac_link\"") >&5
+if { (eval echo "$as_me:5784: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:5662: \$? = $ac_status" >&5
+  echo "$as_me:5787: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:5665: \"$ac_try\"") >&5
+  { (eval echo "$as_me:5790: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:5668: \$? = $ac_status" >&5
+  echo "$as_me:5793: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_func_mkfifo=yes
 else
@@ -5675,7 +5800,7 @@ ac_cv_func_mkfifo=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:5678: result: $ac_cv_func_mkfifo" >&5
+echo "$as_me:5803: result: $ac_cv_func_mkfifo" >&5
 echo "${ECHO_T}$ac_cv_func_mkfifo" >&6
 if test $ac_cv_func_mkfifo = yes; then
   cat >>confdefs.h <<\EOF
@@ -5695,13 +5820,13 @@ for ac_func in dup2 select getdtablesize getgroups gethostname \
                readlink
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:5698: checking for $ac_func" >&5
+echo "$as_me:5823: checking for $ac_func" >&5
 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
 if eval "test \"\${$as_ac_var+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 5704 "configure"
+#line 5829 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func (); below.  */
@@ -5732,16 +5857,16 @@ f = $ac_func;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:5735: \"$ac_link\"") >&5
+if { (eval echo "$as_me:5860: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:5738: \$? = $ac_status" >&5
+  echo "$as_me:5863: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:5741: \"$ac_try\"") >&5
+  { (eval echo "$as_me:5866: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:5744: \$? = $ac_status" >&5
+  echo "$as_me:5869: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   eval "$as_ac_var=yes"
 else
@@ -5751,7 +5876,7 @@ eval "$as_ac_var=no"
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:5754: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "$as_me:5879: result: `eval echo '${'$as_ac_var'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
 if test `eval echo '${'$as_ac_var'}'` = yes; then
   cat >>confdefs.h <<EOF
@@ -5764,13 +5889,13 @@ done
 for ac_func in rename
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:5767: checking for $ac_func" >&5
+echo "$as_me:5892: checking for $ac_func" >&5
 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
 if eval "test \"\${$as_ac_var+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 5773 "configure"
+#line 5898 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func (); below.  */
@@ -5801,16 +5926,16 @@ f = $ac_func;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:5804: \"$ac_link\"") >&5
+if { (eval echo "$as_me:5929: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:5807: \$? = $ac_status" >&5
+  echo "$as_me:5932: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:5810: \"$ac_try\"") >&5
+  { (eval echo "$as_me:5935: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:5813: \$? = $ac_status" >&5
+  echo "$as_me:5938: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   eval "$as_ac_var=yes"
 else
@@ -5820,7 +5945,7 @@ eval "$as_ac_var=no"
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:5823: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "$as_me:5948: result: `eval echo '${'$as_ac_var'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
 if test `eval echo '${'$as_ac_var'}'` = yes; then
   cat >>confdefs.h <<EOF
@@ -5832,20 +5957,20 @@ else
 fi
 done
 
-for ac_func in bcopy bzero confstr sysconf pathconf setenv putenv \
+for ac_func in bcopy bzero confstr sysconf pathconf setenv putenv unsetenv \
                setlinebuf setvbuf setlocale strchr tcgetattr uname \
                ulimit tzset siginterrupt memmove ttyname times \
-               getaddrinfo gethostbyname getservbyname inet_aton \
+               getaddrinfo gethostbyname getservbyname getservent inet_aton \
                vsnprintf snprintf vasprintf asprintf fnmatch
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:5842: checking for $ac_func" >&5
+echo "$as_me:5967: checking for $ac_func" >&5
 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
 if eval "test \"\${$as_ac_var+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 5848 "configure"
+#line 5973 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func (); below.  */
@@ -5876,16 +6001,16 @@ f = $ac_func;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:5879: \"$ac_link\"") >&5
+if { (eval echo "$as_me:6004: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:5882: \$? = $ac_status" >&5
+  echo "$as_me:6007: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:5885: \"$ac_try\"") >&5
+  { (eval echo "$as_me:6010: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:5888: \$? = $ac_status" >&5
+  echo "$as_me:6013: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   eval "$as_ac_var=yes"
 else
@@ -5895,7 +6020,7 @@ eval "$as_ac_var=no"
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:5898: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "$as_me:6023: result: `eval echo '${'$as_ac_var'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
 if test `eval echo '${'$as_ac_var'}'` = yes; then
   cat >>confdefs.h <<EOF
@@ -5908,13 +6033,13 @@ done
 for ac_func in isascii isblank isgraph isprint isspace isxdigit
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:5911: checking for $ac_func" >&5
+echo "$as_me:6036: checking for $ac_func" >&5
 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
 if eval "test \"\${$as_ac_var+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 5917 "configure"
+#line 6042 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func (); below.  */
@@ -5945,16 +6070,16 @@ f = $ac_func;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:5948: \"$ac_link\"") >&5
+if { (eval echo "$as_me:6073: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:5951: \$? = $ac_status" >&5
+  echo "$as_me:6076: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:5954: \"$ac_try\"") >&5
+  { (eval echo "$as_me:6079: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:5957: \$? = $ac_status" >&5
+  echo "$as_me:6082: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   eval "$as_ac_var=yes"
 else
@@ -5964,7 +6089,7 @@ eval "$as_ac_var=no"
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:5967: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "$as_me:6092: result: `eval echo '${'$as_ac_var'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
 if test `eval echo '${'$as_ac_var'}'` = yes; then
   cat >>confdefs.h <<EOF
@@ -5974,16 +6099,16 @@ EOF
 fi
 done
 
-for ac_func in getcwd strcasecmp strerror strpbrk strtod
+for ac_func in getcwd strcasecmp strerror strftime strpbrk memset
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:5980: checking for $ac_func" >&5
+echo "$as_me:6105: checking for $ac_func" >&5
 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
 if eval "test \"\${$as_ac_var+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 5986 "configure"
+#line 6111 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func (); below.  */
@@ -6014,16 +6139,16 @@ f = $ac_func;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:6017: \"$ac_link\"") >&5
+if { (eval echo "$as_me:6142: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:6020: \$? = $ac_status" >&5
+  echo "$as_me:6145: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:6023: \"$ac_try\"") >&5
+  { (eval echo "$as_me:6148: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:6026: \$? = $ac_status" >&5
+  echo "$as_me:6151: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   eval "$as_ac_var=yes"
 else
@@ -6033,7 +6158,7 @@ eval "$as_ac_var=no"
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:6036: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "$as_me:6161: result: `eval echo '${'$as_ac_var'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
 if test `eval echo '${'$as_ac_var'}'` = yes; then
   cat >>confdefs.h <<EOF
@@ -6045,16 +6170,16 @@ else
 fi
 done
 
-for ac_func in strtol strtoul strtoll strtoull strtoimax strtoumax
+for ac_func in strtod strtol strtoul strtoll strtoull strtoimax strtoumax
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:6051: checking for $ac_func" >&5
+echo "$as_me:6176: checking for $ac_func" >&5
 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
 if eval "test \"\${$as_ac_var+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 6057 "configure"
+#line 6182 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func (); below.  */
@@ -6085,16 +6210,16 @@ f = $ac_func;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:6088: \"$ac_link\"") >&5
+if { (eval echo "$as_me:6213: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:6091: \$? = $ac_status" >&5
+  echo "$as_me:6216: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:6094: \"$ac_try\"") >&5
+  { (eval echo "$as_me:6219: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:6097: \$? = $ac_status" >&5
+  echo "$as_me:6222: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   eval "$as_ac_var=yes"
 else
@@ -6104,7 +6229,7 @@ eval "$as_ac_var=no"
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:6107: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "$as_me:6232: result: `eval echo '${'$as_ac_var'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
 if test `eval echo '${'$as_ac_var'}'` = yes; then
   cat >>confdefs.h <<EOF
@@ -6116,20 +6241,20 @@ else
 fi
 done
 
-echo "$as_me:6119: checking whether strtold is declared" >&5
-echo $ECHO_N "checking whether strtold is declared... $ECHO_C" >&6
-if test "${ac_cv_have_decl_strtold+set}" = set; then
+echo "$as_me:6244: checking whether confstr is declared" >&5
+echo $ECHO_N "checking whether confstr is declared... $ECHO_C" >&6
+if test "${ac_cv_have_decl_confstr+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 6125 "configure"
+#line 6250 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
 main ()
 {
-#ifndef strtold
-  char *p = (char *) strtold;
+#ifndef confstr
+  char *p = (char *) confstr;
 #endif
 
   ;
@@ -6137,54 +6262,54 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:6140: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:6265: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:6143: \$? = $ac_status" >&5
+  echo "$as_me:6268: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:6146: \"$ac_try\"") >&5
+  { (eval echo "$as_me:6271: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:6149: \$? = $ac_status" >&5
+  echo "$as_me:6274: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_have_decl_strtold=yes
+  ac_cv_have_decl_confstr=yes
 else
   echo "$as_me: failed program was:" >&5
 cat conftest.$ac_ext >&5
-ac_cv_have_decl_strtold=no
+ac_cv_have_decl_confstr=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:6159: result: $ac_cv_have_decl_strtold" >&5
-echo "${ECHO_T}$ac_cv_have_decl_strtold" >&6
-if test $ac_cv_have_decl_strtold = yes; then
+echo "$as_me:6284: result: $ac_cv_have_decl_confstr" >&5
+echo "${ECHO_T}$ac_cv_have_decl_confstr" >&6
+if test $ac_cv_have_decl_confstr = yes; then
 
 cat >>confdefs.h <<EOF
-#define HAVE_DECL_STRTOLD 1
+#define HAVE_DECL_CONFSTR 1
 EOF
 
 else
   cat >>confdefs.h <<EOF
-#define HAVE_DECL_STRTOLD 0
+#define HAVE_DECL_CONFSTR 0
 EOF
 
 fi
 
-echo "$as_me:6174: checking whether confstr is declared" >&5
-echo $ECHO_N "checking whether confstr is declared... $ECHO_C" >&6
-if test "${ac_cv_have_decl_confstr+set}" = set; then
+echo "$as_me:6299: checking whether printf is declared" >&5
+echo $ECHO_N "checking whether printf is declared... $ECHO_C" >&6
+if test "${ac_cv_have_decl_printf+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 6180 "configure"
+#line 6305 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
 main ()
 {
-#ifndef confstr
-  char *p = (char *) confstr;
+#ifndef printf
+  char *p = (char *) printf;
 #endif
 
   ;
@@ -6192,47 +6317,47 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:6195: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:6320: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:6198: \$? = $ac_status" >&5
+  echo "$as_me:6323: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:6201: \"$ac_try\"") >&5
+  { (eval echo "$as_me:6326: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:6204: \$? = $ac_status" >&5
+  echo "$as_me:6329: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_have_decl_confstr=yes
+  ac_cv_have_decl_printf=yes
 else
   echo "$as_me: failed program was:" >&5
 cat conftest.$ac_ext >&5
-ac_cv_have_decl_confstr=no
+ac_cv_have_decl_printf=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:6214: result: $ac_cv_have_decl_confstr" >&5
-echo "${ECHO_T}$ac_cv_have_decl_confstr" >&6
-if test $ac_cv_have_decl_confstr = yes; then
+echo "$as_me:6339: result: $ac_cv_have_decl_printf" >&5
+echo "${ECHO_T}$ac_cv_have_decl_printf" >&6
+if test $ac_cv_have_decl_printf = yes; then
 
 cat >>confdefs.h <<EOF
-#define HAVE_DECL_CONFSTR 1
+#define HAVE_DECL_PRINTF 1
 EOF
 
 else
   cat >>confdefs.h <<EOF
-#define HAVE_DECL_CONFSTR 0
+#define HAVE_DECL_PRINTF 0
 EOF
 
 fi
 
-echo "$as_me:6229: checking whether sbrk is declared" >&5
+echo "$as_me:6354: checking whether sbrk is declared" >&5
 echo $ECHO_N "checking whether sbrk is declared... $ECHO_C" >&6
 if test "${ac_cv_have_decl_sbrk+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 6235 "configure"
+#line 6360 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -6247,16 +6372,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:6250: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:6375: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:6253: \$? = $ac_status" >&5
+  echo "$as_me:6378: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:6256: \"$ac_try\"") >&5
+  { (eval echo "$as_me:6381: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:6259: \$? = $ac_status" >&5
+  echo "$as_me:6384: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_have_decl_sbrk=yes
 else
@@ -6266,7 +6391,7 @@ ac_cv_have_decl_sbrk=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:6269: result: $ac_cv_have_decl_sbrk" >&5
+echo "$as_me:6394: result: $ac_cv_have_decl_sbrk" >&5
 echo "${ECHO_T}$ac_cv_have_decl_sbrk" >&6
 if test $ac_cv_have_decl_sbrk = yes; then
 
@@ -6281,20 +6406,20 @@ EOF
 
 fi
 
-echo "$as_me:6284: checking whether printf is declared" >&5
-echo $ECHO_N "checking whether printf is declared... $ECHO_C" >&6
-if test "${ac_cv_have_decl_printf+set}" = set; then
+echo "$as_me:6409: checking whether strcpy is declared" >&5
+echo $ECHO_N "checking whether strcpy is declared... $ECHO_C" >&6
+if test "${ac_cv_have_decl_strcpy+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 6290 "configure"
+#line 6415 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
 main ()
 {
-#ifndef printf
-  char *p = (char *) printf;
+#ifndef strcpy
+  char *p = (char *) strcpy;
 #endif
 
   ;
@@ -6302,47 +6427,47 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:6305: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:6430: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:6308: \$? = $ac_status" >&5
+  echo "$as_me:6433: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:6311: \"$ac_try\"") >&5
+  { (eval echo "$as_me:6436: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:6314: \$? = $ac_status" >&5
+  echo "$as_me:6439: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_have_decl_printf=yes
+  ac_cv_have_decl_strcpy=yes
 else
   echo "$as_me: failed program was:" >&5
 cat conftest.$ac_ext >&5
-ac_cv_have_decl_printf=no
+ac_cv_have_decl_strcpy=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:6324: result: $ac_cv_have_decl_printf" >&5
-echo "${ECHO_T}$ac_cv_have_decl_printf" >&6
-if test $ac_cv_have_decl_printf = yes; then
+echo "$as_me:6449: result: $ac_cv_have_decl_strcpy" >&5
+echo "${ECHO_T}$ac_cv_have_decl_strcpy" >&6
+if test $ac_cv_have_decl_strcpy = yes; then
 
 cat >>confdefs.h <<EOF
-#define HAVE_DECL_PRINTF 1
+#define HAVE_DECL_STRCPY 1
 EOF
 
 else
   cat >>confdefs.h <<EOF
-#define HAVE_DECL_PRINTF 0
+#define HAVE_DECL_STRCPY 0
 EOF
 
 fi
 
-echo "$as_me:6339: checking whether strsignal is declared" >&5
+echo "$as_me:6464: checking whether strsignal is declared" >&5
 echo $ECHO_N "checking whether strsignal is declared... $ECHO_C" >&6
 if test "${ac_cv_have_decl_strsignal+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 6345 "configure"
+#line 6470 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -6357,16 +6482,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:6360: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:6485: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:6363: \$? = $ac_status" >&5
+  echo "$as_me:6488: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:6366: \"$ac_try\"") >&5
+  { (eval echo "$as_me:6491: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:6369: \$? = $ac_status" >&5
+  echo "$as_me:6494: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_have_decl_strsignal=yes
 else
@@ -6376,7 +6501,7 @@ ac_cv_have_decl_strsignal=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:6379: result: $ac_cv_have_decl_strsignal" >&5
+echo "$as_me:6504: result: $ac_cv_have_decl_strsignal" >&5
 echo "${ECHO_T}$ac_cv_have_decl_strsignal" >&6
 if test $ac_cv_have_decl_strsignal = yes; then
 
@@ -6391,13 +6516,68 @@ EOF
 
 fi
 
-echo "$as_me:6394: checking for declaration of strtoimax" >&5
+echo "$as_me:6519: checking whether strtold is declared" >&5
+echo $ECHO_N "checking whether strtold is declared... $ECHO_C" >&6
+if test "${ac_cv_have_decl_strtold+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 6525 "configure"
+#include "confdefs.h"
+$ac_includes_default
+int
+main ()
+{
+#ifndef strtold
+  char *p = (char *) strtold;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:6540: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:6543: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:6546: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:6549: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_have_decl_strtold=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_have_decl_strtold=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:6559: result: $ac_cv_have_decl_strtold" >&5
+echo "${ECHO_T}$ac_cv_have_decl_strtold" >&6
+if test $ac_cv_have_decl_strtold = yes; then
+
+cat >>confdefs.h <<EOF
+#define HAVE_DECL_STRTOLD 1
+EOF
+
+else
+  cat >>confdefs.h <<EOF
+#define HAVE_DECL_STRTOLD 0
+EOF
+
+fi
+
+echo "$as_me:6574: checking for declaration of strtoimax" >&5
 echo $ECHO_N "checking for declaration of strtoimax... $ECHO_C" >&6
 if test "${bash_cv_decl_strtoimax+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 6400 "configure"
+#line 6580 "configure"
 #include "confdefs.h"
 
 #if STDC_HEADERS
@@ -6416,16 +6596,16 @@ return !strtoimax;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:6419: \"$ac_link\"") >&5
+if { (eval echo "$as_me:6599: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:6422: \$? = $ac_status" >&5
+  echo "$as_me:6602: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:6425: \"$ac_try\"") >&5
+  { (eval echo "$as_me:6605: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:6428: \$? = $ac_status" >&5
+  echo "$as_me:6608: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_decl_strtoimax=yes
 else
@@ -6435,7 +6615,7 @@ bash_cv_decl_strtoimax=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:6438: result: $bash_cv_decl_strtoimax" >&5
+echo "$as_me:6618: result: $bash_cv_decl_strtoimax" >&5
 echo "${ECHO_T}$bash_cv_decl_strtoimax" >&6
 bash_tr_func=HAVE_DECL_`echo strtoimax | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
 if test $bash_cv_decl_strtoimax = yes; then
@@ -6450,13 +6630,13 @@ EOF
 
 fi
 
-echo "$as_me:6453: checking for declaration of strtol" >&5
+echo "$as_me:6633: checking for declaration of strtol" >&5
 echo $ECHO_N "checking for declaration of strtol... $ECHO_C" >&6
 if test "${bash_cv_decl_strtol+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 6459 "configure"
+#line 6639 "configure"
 #include "confdefs.h"
 
 #if STDC_HEADERS
@@ -6475,16 +6655,16 @@ return !strtol;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:6478: \"$ac_link\"") >&5
+if { (eval echo "$as_me:6658: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:6481: \$? = $ac_status" >&5
+  echo "$as_me:6661: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:6484: \"$ac_try\"") >&5
+  { (eval echo "$as_me:6664: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:6487: \$? = $ac_status" >&5
+  echo "$as_me:6667: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_decl_strtol=yes
 else
@@ -6494,7 +6674,7 @@ bash_cv_decl_strtol=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:6497: result: $bash_cv_decl_strtol" >&5
+echo "$as_me:6677: result: $bash_cv_decl_strtol" >&5
 echo "${ECHO_T}$bash_cv_decl_strtol" >&6
 bash_tr_func=HAVE_DECL_`echo strtol | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
 if test $bash_cv_decl_strtol = yes; then
@@ -6509,13 +6689,13 @@ EOF
 
 fi
 
-echo "$as_me:6512: checking for declaration of strtoll" >&5
+echo "$as_me:6692: checking for declaration of strtoll" >&5
 echo $ECHO_N "checking for declaration of strtoll... $ECHO_C" >&6
 if test "${bash_cv_decl_strtoll+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 6518 "configure"
+#line 6698 "configure"
 #include "confdefs.h"
 
 #if STDC_HEADERS
@@ -6534,16 +6714,16 @@ return !strtoll;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:6537: \"$ac_link\"") >&5
+if { (eval echo "$as_me:6717: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:6540: \$? = $ac_status" >&5
+  echo "$as_me:6720: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:6543: \"$ac_try\"") >&5
+  { (eval echo "$as_me:6723: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:6546: \$? = $ac_status" >&5
+  echo "$as_me:6726: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_decl_strtoll=yes
 else
@@ -6553,7 +6733,7 @@ bash_cv_decl_strtoll=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:6556: result: $bash_cv_decl_strtoll" >&5
+echo "$as_me:6736: result: $bash_cv_decl_strtoll" >&5
 echo "${ECHO_T}$bash_cv_decl_strtoll" >&6
 bash_tr_func=HAVE_DECL_`echo strtoll | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
 if test $bash_cv_decl_strtoll = yes; then
@@ -6568,13 +6748,13 @@ EOF
 
 fi
 
-echo "$as_me:6571: checking for declaration of strtoul" >&5
+echo "$as_me:6751: checking for declaration of strtoul" >&5
 echo $ECHO_N "checking for declaration of strtoul... $ECHO_C" >&6
 if test "${bash_cv_decl_strtoul+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 6577 "configure"
+#line 6757 "configure"
 #include "confdefs.h"
 
 #if STDC_HEADERS
@@ -6593,16 +6773,16 @@ return !strtoul;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:6596: \"$ac_link\"") >&5
+if { (eval echo "$as_me:6776: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:6599: \$? = $ac_status" >&5
+  echo "$as_me:6779: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:6602: \"$ac_try\"") >&5
+  { (eval echo "$as_me:6782: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:6605: \$? = $ac_status" >&5
+  echo "$as_me:6785: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_decl_strtoul=yes
 else
@@ -6612,7 +6792,7 @@ bash_cv_decl_strtoul=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:6615: result: $bash_cv_decl_strtoul" >&5
+echo "$as_me:6795: result: $bash_cv_decl_strtoul" >&5
 echo "${ECHO_T}$bash_cv_decl_strtoul" >&6
 bash_tr_func=HAVE_DECL_`echo strtoul | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
 if test $bash_cv_decl_strtoul = yes; then
@@ -6627,13 +6807,13 @@ EOF
 
 fi
 
-echo "$as_me:6630: checking for declaration of strtoull" >&5
+echo "$as_me:6810: checking for declaration of strtoull" >&5
 echo $ECHO_N "checking for declaration of strtoull... $ECHO_C" >&6
 if test "${bash_cv_decl_strtoull+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 6636 "configure"
+#line 6816 "configure"
 #include "confdefs.h"
 
 #if STDC_HEADERS
@@ -6652,16 +6832,16 @@ return !strtoull;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:6655: \"$ac_link\"") >&5
+if { (eval echo "$as_me:6835: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:6658: \$? = $ac_status" >&5
+  echo "$as_me:6838: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:6661: \"$ac_try\"") >&5
+  { (eval echo "$as_me:6841: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:6664: \$? = $ac_status" >&5
+  echo "$as_me:6844: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_decl_strtoull=yes
 else
@@ -6671,7 +6851,7 @@ bash_cv_decl_strtoull=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:6674: result: $bash_cv_decl_strtoull" >&5
+echo "$as_me:6854: result: $bash_cv_decl_strtoull" >&5
 echo "${ECHO_T}$bash_cv_decl_strtoull" >&6
 bash_tr_func=HAVE_DECL_`echo strtoull | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
 if test $bash_cv_decl_strtoull = yes; then
@@ -6686,13 +6866,13 @@ EOF
 
 fi
 
-echo "$as_me:6689: checking for declaration of strtoumax" >&5
+echo "$as_me:6869: checking for declaration of strtoumax" >&5
 echo $ECHO_N "checking for declaration of strtoumax... $ECHO_C" >&6
 if test "${bash_cv_decl_strtoumax+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 6695 "configure"
+#line 6875 "configure"
 #include "confdefs.h"
 
 #if STDC_HEADERS
@@ -6711,16 +6891,16 @@ return !strtoumax;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:6714: \"$ac_link\"") >&5
+if { (eval echo "$as_me:6894: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:6717: \$? = $ac_status" >&5
+  echo "$as_me:6897: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:6720: \"$ac_try\"") >&5
+  { (eval echo "$as_me:6900: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:6723: \$? = $ac_status" >&5
+  echo "$as_me:6903: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_decl_strtoumax=yes
 else
@@ -6730,7 +6910,7 @@ bash_cv_decl_strtoumax=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:6733: result: $bash_cv_decl_strtoumax" >&5
+echo "$as_me:6913: result: $bash_cv_decl_strtoumax" >&5
 echo "${ECHO_T}$bash_cv_decl_strtoumax" >&6
 bash_tr_func=HAVE_DECL_`echo strtoumax | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
 if test $bash_cv_decl_strtoumax = yes; then
@@ -6745,26 +6925,26 @@ EOF
 
 fi
 
-for ac_header in libintl.h
+for ac_header in sys/time.h unistd.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-echo "$as_me:6751: checking for $ac_header" >&5
+echo "$as_me:6931: checking for $ac_header" >&5
 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
 if eval "test \"\${$as_ac_Header+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 6757 "configure"
+#line 6937 "configure"
 #include "confdefs.h"
 #include <$ac_header>
 _ACEOF
-if { (eval echo "$as_me:6761: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:6941: \"$ac_cpp conftest.$ac_ext\"") >&5
   (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   egrep -v '^ *\+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
-  echo "$as_me:6767: \$? = $ac_status" >&5
+  echo "$as_me:6947: \$? = $ac_status" >&5
   (exit $ac_status); } >/dev/null; then
   if test -s conftest.err; then
     ac_cpp_err=$ac_c_preproc_warn_flag
@@ -6783,7 +6963,7 @@ else
 fi
 rm -f conftest.err conftest.$ac_ext
 fi
-echo "$as_me:6786: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "$as_me:6966: result: `eval echo '${'$as_ac_Header'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
 if test `eval echo '${'$as_ac_Header'}'` = yes; then
   cat >>confdefs.h <<EOF
@@ -6793,16 +6973,16 @@ EOF
 fi
 done
 
-for ac_func in gettext textdomain bindtextdomain
+for ac_func in alarm
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:6799: checking for $ac_func" >&5
+echo "$as_me:6979: checking for $ac_func" >&5
 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
 if eval "test \"\${$as_ac_var+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 6805 "configure"
+#line 6985 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func (); below.  */
@@ -6833,16 +7013,16 @@ f = $ac_func;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:6836: \"$ac_link\"") >&5
+if { (eval echo "$as_me:7016: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:6839: \$? = $ac_status" >&5
+  echo "$as_me:7019: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:6842: \"$ac_try\"") >&5
+  { (eval echo "$as_me:7022: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:6845: \$? = $ac_status" >&5
+  echo "$as_me:7025: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   eval "$as_ac_var=yes"
 else
@@ -6852,7 +7032,7 @@ eval "$as_ac_var=no"
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:6855: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "$as_me:7035: result: `eval echo '${'$as_ac_var'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
 if test `eval echo '${'$as_ac_var'}'` = yes; then
   cat >>confdefs.h <<EOF
@@ -6862,47 +7042,348 @@ EOF
 fi
 done
 
-if test "$ac_cv_func_bindtextdomain" = "no"; then
-
-echo "$as_me:6867: checking for bindtextdomain in -lintl" >&5
-echo $ECHO_N "checking for bindtextdomain in -lintl... $ECHO_C" >&6
-if test "${ac_cv_lib_intl_bindtextdomain+set}" = set; then
+echo "$as_me:7045: checking for working mktime" >&5
+echo $ECHO_N "checking for working mktime... $ECHO_C" >&6
+if test "${ac_cv_func_working_mktime+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lintl  $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-#line 6875 "configure"
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_working_mktime=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 7054 "configure"
 #include "confdefs.h"
+/* Test program from Paul Eggert and Tony Leneis.  */
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
 
-/* Override any gcc2 internal prototype to avoid an error.  */
-#ifdef __cplusplus
-extern "C"
+#if HAVE_UNISTD_H
+# include <unistd.h>
 #endif
-/* We use char because int might match the return type of a gcc2
-   builtin and then its argument prototype would still apply.  */
-char bindtextdomain ();
+
+#if !HAVE_ALARM
+# define alarm(X) /* empty */
+#endif
+
+/* Work around redefinition to rpl_putenv by other config tests.  */
+#undef putenv
+
+static time_t time_t_max;
+
+/* Values we'll use to set the TZ environment variable.  */
+static const char *const tz_strings[] = {
+  (const char *) 0, "TZ=GMT0", "TZ=JST-9",
+  "TZ=EST+3EDT+2,M10.1.0/00:00:00,M2.3.0/00:00:00"
+};
+#define N_STRINGS (sizeof (tz_strings) / sizeof (tz_strings[0]))
+
+/* Fail if mktime fails to convert a date in the spring-forward gap.
+   Based on a problem report from Andreas Jaeger.  */
+static void
+spring_forward_gap ()
+{
+  /* glibc (up to about 1998-10-07) failed this test. */
+  struct tm tm;
+
+  /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0"
+     instead of "TZ=America/Vancouver" in order to detect the bug even
+     on systems that don't support the Olson extension, or don't have the
+     full zoneinfo tables installed.  */
+  putenv ("TZ=PST8PDT,M4.1.0,M10.5.0");
+
+  tm.tm_year = 98;
+  tm.tm_mon = 3;
+  tm.tm_mday = 5;
+  tm.tm_hour = 2;
+  tm.tm_min = 0;
+  tm.tm_sec = 0;
+  tm.tm_isdst = -1;
+  if (mktime (&tm) == (time_t)-1)
+    exit (1);
+}
+
+static void
+mktime_test (now)
+     time_t now;
+{
+  struct tm *lt;
+  if ((lt = localtime (&now)) && mktime (lt) != now)
+    exit (1);
+  now = time_t_max - now;
+  if ((lt = localtime (&now)) && mktime (lt) != now)
+    exit (1);
+}
+
+static void
+irix_6_4_bug ()
+{
+  /* Based on code from Ariel Faigon.  */
+  struct tm tm;
+  tm.tm_year = 96;
+  tm.tm_mon = 3;
+  tm.tm_mday = 0;
+  tm.tm_hour = 0;
+  tm.tm_min = 0;
+  tm.tm_sec = 0;
+  tm.tm_isdst = -1;
+  mktime (&tm);
+  if (tm.tm_mon != 2 || tm.tm_mday != 31)
+    exit (1);
+}
+
+static void
+bigtime_test (j)
+     int j;
+{
+  struct tm tm;
+  time_t now;
+  tm.tm_year = tm.tm_mon = tm.tm_mday = tm.tm_hour = tm.tm_min = tm.tm_sec = j;
+  now = mktime (&tm);
+  if (now != (time_t) -1)
+    {
+      struct tm *lt = localtime (&now);
+      if (! (lt
+            && lt->tm_year == tm.tm_year
+            && lt->tm_mon == tm.tm_mon
+            && lt->tm_mday == tm.tm_mday
+            && lt->tm_hour == tm.tm_hour
+            && lt->tm_min == tm.tm_min
+            && lt->tm_sec == tm.tm_sec
+            && lt->tm_yday == tm.tm_yday
+            && lt->tm_wday == tm.tm_wday
+            && ((lt->tm_isdst < 0 ? -1 : 0 < lt->tm_isdst)
+                 == (tm.tm_isdst < 0 ? -1 : 0 < tm.tm_isdst))))
+       exit (1);
+    }
+}
+
 int
 main ()
 {
-bindtextdomain ();
-  ;
-  return 0;
+  time_t t, delta;
+  int i, j;
+
+  /* This test makes some buggy mktime implementations loop.
+     Give up after 60 seconds; a mktime slower than that
+     isn't worth using anyway.  */
+  alarm (60);
+
+  for (time_t_max = 1; 0 < time_t_max; time_t_max *= 2)
+    continue;
+  time_t_max--;
+  delta = time_t_max / 997; /* a suitable prime number */
+  for (i = 0; i < N_STRINGS; i++)
+    {
+      if (tz_strings[i])
+       putenv (tz_strings[i]);
+
+      for (t = 0; t <= time_t_max - delta; t += delta)
+       mktime_test (t);
+      mktime_test ((time_t) 60 * 60);
+      mktime_test ((time_t) 60 * 60 * 24);
+
+      for (j = 1; 0 < j; j *= 2)
+        bigtime_test (j);
+      bigtime_test (j - 1);
+    }
+  irix_6_4_bug ();
+  spring_forward_gap ();
+  exit (0);
 }
 _ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:6894: \"$ac_link\"") >&5
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:7203: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:6897: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-         { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:6900: \"$ac_try\"") >&5
+  echo "$as_me:7206: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:7208: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:6903: \$? = $ac_status" >&5
+  echo "$as_me:7211: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_lib_intl_bindtextdomain=yes
+  ac_cv_func_working_mktime=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_func_working_mktime=no
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:7223: result: $ac_cv_func_working_mktime" >&5
+echo "${ECHO_T}$ac_cv_func_working_mktime" >&6
+if test $ac_cv_func_working_mktime = no; then
+  LIBOBJS="$LIBOBJS mktime.$ac_objext"
+fi
+
+for ac_header in libintl.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:7232: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 7238 "configure"
+#include "confdefs.h"
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:7242: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:7248: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_ext
+fi
+echo "$as_me:7267: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+EOF
+
+fi
+done
+
+for ac_func in gettext textdomain bindtextdomain
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:7280: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 7286 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+char (*f) ();
+
+int
+main ()
+{
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+f = $ac_func;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:7317: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:7320: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:7323: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:7326: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$as_ac_var=no"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:7336: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+EOF
+
+fi
+done
+
+if test "$ac_cv_func_bindtextdomain" = "no"; then
+
+echo "$as_me:7348: checking for bindtextdomain in -lintl" >&5
+echo $ECHO_N "checking for bindtextdomain in -lintl... $ECHO_C" >&6
+if test "${ac_cv_lib_intl_bindtextdomain+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lintl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line 7356 "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char bindtextdomain ();
+int
+main ()
+{
+bindtextdomain ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:7375: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:7378: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:7381: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:7384: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_intl_bindtextdomain=yes
 else
   echo "$as_me: failed program was:" >&5
 cat conftest.$ac_ext >&5
@@ -6911,7 +7392,7 @@ fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:6914: result: $ac_cv_lib_intl_bindtextdomain" >&5
+echo "$as_me:7395: result: $ac_cv_lib_intl_bindtextdomain" >&5
 echo "${ECHO_T}$ac_cv_lib_intl_bindtextdomain" >&6
 if test $ac_cv_lib_intl_bindtextdomain = yes; then
   cat >>confdefs.h <<EOF
@@ -6927,13 +7408,13 @@ fi
 for ac_func in gettext textdomain bindtextdomain
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:6930: checking for $ac_func" >&5
+echo "$as_me:7411: checking for $ac_func" >&5
 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
 if eval "test \"\${$as_ac_var+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 6936 "configure"
+#line 7417 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func (); below.  */
@@ -6964,16 +7445,16 @@ f = $ac_func;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:6967: \"$ac_link\"") >&5
+if { (eval echo "$as_me:7448: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:6970: \$? = $ac_status" >&5
+  echo "$as_me:7451: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:6973: \"$ac_try\"") >&5
+  { (eval echo "$as_me:7454: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:6976: \$? = $ac_status" >&5
+  echo "$as_me:7457: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   eval "$as_ac_var=yes"
 else
@@ -6983,7 +7464,7 @@ eval "$as_ac_var=no"
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:6986: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "$as_me:7467: result: `eval echo '${'$as_ac_var'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
 if test `eval echo '${'$as_ac_var'}'` = yes; then
   cat >>confdefs.h <<EOF
@@ -6996,9 +7477,381 @@ done
     fi
 fi
 
+for ac_header in wctype.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:7483: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 7489 "configure"
+#include "confdefs.h"
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:7493: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:7499: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_ext
+fi
+echo "$as_me:7518: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+EOF
+
+fi
+done
+
+for ac_header in wchar.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:7531: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 7537 "configure"
+#include "confdefs.h"
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:7541: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:7547: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_ext
+fi
+echo "$as_me:7566: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+EOF
+
+fi
+done
+
+for ac_header in langinfo.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:7579: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 7585 "configure"
+#include "confdefs.h"
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:7589: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:7595: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_ext
+fi
+echo "$as_me:7614: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+EOF
+
+fi
+done
+
+echo "$as_me:7624: checking for mbsrtowcs" >&5
+echo $ECHO_N "checking for mbsrtowcs... $ECHO_C" >&6
+if test "${ac_cv_func_mbsrtowcs+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 7630 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char mbsrtowcs (); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char mbsrtowcs ();
+char (*f) ();
+
+int
+main ()
+{
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_mbsrtowcs) || defined (__stub___mbsrtowcs)
+choke me
+#else
+f = mbsrtowcs;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:7661: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:7664: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:7667: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:7670: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_mbsrtowcs=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_func_mbsrtowcs=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:7680: result: $ac_cv_func_mbsrtowcs" >&5
+echo "${ECHO_T}$ac_cv_func_mbsrtowcs" >&6
+if test $ac_cv_func_mbsrtowcs = yes; then
+  cat >>confdefs.h <<\EOF
+#define HAVE_MBSRTOWCS 1
+EOF
+
+fi
+
+echo "$as_me:7689: checking for wcwidth" >&5
+echo $ECHO_N "checking for wcwidth... $ECHO_C" >&6
+if test "${ac_cv_func_wcwidth+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 7695 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char wcwidth (); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char wcwidth ();
+char (*f) ();
+
+int
+main ()
+{
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_wcwidth) || defined (__stub___wcwidth)
+choke me
+#else
+f = wcwidth;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:7726: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:7729: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:7732: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:7735: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_wcwidth=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_func_wcwidth=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:7745: result: $ac_cv_func_wcwidth" >&5
+echo "${ECHO_T}$ac_cv_func_wcwidth" >&6
+if test $ac_cv_func_wcwidth = yes; then
+  cat >>confdefs.h <<\EOF
+#define HAVE_WCWIDTH 1
+EOF
+
+fi
+
+echo "$as_me:7754: checking for mbstate_t" >&5
+echo $ECHO_N "checking for mbstate_t... $ECHO_C" >&6
+if test "${bash_cv_have_mbstate_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  { { echo "$as_me:7760: error: cannot run test program while cross compiling" >&5
+echo "$as_me: error: cannot run test program while cross compiling" >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 7765 "configure"
+#include "confdefs.h"
+
+#include <wchar.h>
+int
+main ()
+{
+  mbstate_t ps;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:7777: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:7780: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:7782: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:7785: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  bash_cv_have_mbstate_t=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+bash_cv_have_mbstate_t=no
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:7797: result: $bash_cv_have_mbstate_t" >&5
+echo "${ECHO_T}$bash_cv_have_mbstate_t" >&6
+if test $bash_cv_have_mbstate_t = yes; then
+       cat >>confdefs.h <<\EOF
+#define HAVE_MBSTATE_T 1
+EOF
+
+fi
+
+echo "$as_me:7806: checking for nl_langinfo and CODESET" >&5
+echo $ECHO_N "checking for nl_langinfo and CODESET... $ECHO_C" >&6
+if test "${bash_cv_langinfo_codeset+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 7812 "configure"
+#include "confdefs.h"
+#include <langinfo.h>
+int
+main ()
+{
+char* cs = nl_langinfo(CODESET);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:7824: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:7827: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:7830: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:7833: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  bash_cv_langinfo_codeset=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+bash_cv_langinfo_codeset=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:7843: result: $bash_cv_langinfo_codeset" >&5
+echo "${ECHO_T}$bash_cv_langinfo_codeset" >&6
+if test $bash_cv_langinfo_codeset = yes; then
+  cat >>confdefs.h <<\EOF
+#define HAVE_LANGINFO_CODESET 1
+EOF
+
+fi
+
 if test "$opt_static_link" != yes; then
 
-echo "$as_me:7001: checking for dlopen in -ldl" >&5
+echo "$as_me:7854: checking for dlopen in -ldl" >&5
 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
 if test "${ac_cv_lib_dl_dlopen+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -7006,7 +7859,7 @@ else
   ac_check_lib_save_LIBS=$LIBS
 LIBS="-ldl  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
-#line 7009 "configure"
+#line 7862 "configure"
 #include "confdefs.h"
 
 /* Override any gcc2 internal prototype to avoid an error.  */
@@ -7025,16 +7878,16 @@ dlopen ();
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:7028: \"$ac_link\"") >&5
+if { (eval echo "$as_me:7881: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:7031: \$? = $ac_status" >&5
+  echo "$as_me:7884: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:7034: \"$ac_try\"") >&5
+  { (eval echo "$as_me:7887: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:7037: \$? = $ac_status" >&5
+  echo "$as_me:7890: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_lib_dl_dlopen=yes
 else
@@ -7045,7 +7898,7 @@ fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:7048: result: $ac_cv_lib_dl_dlopen" >&5
+echo "$as_me:7901: result: $ac_cv_lib_dl_dlopen" >&5
 echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
 if test $ac_cv_lib_dl_dlopen = yes; then
   cat >>confdefs.h <<EOF
@@ -7059,13 +7912,13 @@ fi
 for ac_func in dlopen dlclose dlsym
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:7062: checking for $ac_func" >&5
+echo "$as_me:7915: checking for $ac_func" >&5
 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
 if eval "test \"\${$as_ac_var+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 7068 "configure"
+#line 7921 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func (); below.  */
@@ -7096,16 +7949,16 @@ f = $ac_func;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:7099: \"$ac_link\"") >&5
+if { (eval echo "$as_me:7952: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:7102: \$? = $ac_status" >&5
+  echo "$as_me:7955: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:7105: \"$ac_try\"") >&5
+  { (eval echo "$as_me:7958: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:7108: \$? = $ac_status" >&5
+  echo "$as_me:7961: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   eval "$as_ac_var=yes"
 else
@@ -7115,7 +7968,7 @@ eval "$as_ac_var=no"
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:7118: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "$as_me:7971: result: `eval echo '${'$as_ac_var'}'`" >&5
 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
 if test `eval echo '${'$as_ac_var'}'` = yes; then
   cat >>confdefs.h <<EOF
@@ -7127,13 +7980,13 @@ done
 
 fi
 
-echo "$as_me:7130: checking for sys_siglist declaration in signal.h or unistd.h" >&5
+echo "$as_me:7983: checking for sys_siglist declaration in signal.h or unistd.h" >&5
 echo $ECHO_N "checking for sys_siglist declaration in signal.h or unistd.h... $ECHO_C" >&6
 if test "${ac_cv_decl_sys_siglist+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 7136 "configure"
+#line 7989 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <signal.h>
@@ -7151,16 +8004,16 @@ char *msg = *(sys_siglist + 1);
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:7154: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:8007: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:7157: \$? = $ac_status" >&5
+  echo "$as_me:8010: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:7160: \"$ac_try\"") >&5
+  { (eval echo "$as_me:8013: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:7163: \$? = $ac_status" >&5
+  echo "$as_me:8016: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_decl_sys_siglist=yes
 else
@@ -7170,7 +8023,7 @@ ac_cv_decl_sys_siglist=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:7173: result: $ac_cv_decl_sys_siglist" >&5
+echo "$as_me:8026: result: $ac_cv_decl_sys_siglist" >&5
 echo "${ECHO_T}$ac_cv_decl_sys_siglist" >&6
 if test $ac_cv_decl_sys_siglist = yes; then
 
@@ -7182,13 +8035,13 @@ fi
 
 if test "$ac_cv_func_inet_aton" != 'yes'; then
 
-echo "$as_me:7185: checking for inet_aton" >&5
+echo "$as_me:8038: checking for inet_aton" >&5
 echo $ECHO_N "checking for inet_aton... $ECHO_C" >&6
 if test "${bash_cv_func_inet_aton+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 7191 "configure"
+#line 8044 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -7204,16 +8057,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:7207: \"$ac_link\"") >&5
+if { (eval echo "$as_me:8060: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:7210: \$? = $ac_status" >&5
+  echo "$as_me:8063: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:7213: \"$ac_try\"") >&5
+  { (eval echo "$as_me:8066: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:7216: \$? = $ac_status" >&5
+  echo "$as_me:8069: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_func_inet_aton=yes
 else
@@ -7223,7 +8076,7 @@ bash_cv_func_inet_aton=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:7226: result: $bash_cv_func_inet_aton" >&5
+echo "$as_me:8079: result: $bash_cv_func_inet_aton" >&5
 echo "${ECHO_T}$bash_cv_func_inet_aton" >&6
 if test $bash_cv_func_inet_aton = yes; then
   cat >>confdefs.h <<\EOF
@@ -7238,7 +8091,7 @@ fi
 
 case "$host_os" in
 irix4*)
-echo "$as_me:7241: checking for getpwent in -lsun" >&5
+echo "$as_me:8094: checking for getpwent in -lsun" >&5
 echo $ECHO_N "checking for getpwent in -lsun... $ECHO_C" >&6
 if test "${ac_cv_lib_sun_getpwent+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -7246,7 +8099,7 @@ else
   ac_check_lib_save_LIBS=$LIBS
 LIBS="-lsun  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
-#line 7249 "configure"
+#line 8102 "configure"
 #include "confdefs.h"
 
 /* Override any gcc2 internal prototype to avoid an error.  */
@@ -7265,16 +8118,16 @@ getpwent ();
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:7268: \"$ac_link\"") >&5
+if { (eval echo "$as_me:8121: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:7271: \$? = $ac_status" >&5
+  echo "$as_me:8124: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:7274: \"$ac_try\"") >&5
+  { (eval echo "$as_me:8127: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:7277: \$? = $ac_status" >&5
+  echo "$as_me:8130: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_lib_sun_getpwent=yes
 else
@@ -7285,7 +8138,7 @@ fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:7288: result: $ac_cv_lib_sun_getpwent" >&5
+echo "$as_me:8141: result: $ac_cv_lib_sun_getpwent" >&5
 echo "${ECHO_T}$ac_cv_lib_sun_getpwent" >&6
 if test $ac_cv_lib_sun_getpwent = yes; then
   cat >>confdefs.h <<EOF
@@ -7303,14 +8156,14 @@ if test "$ac_cv_func_getpeername" = no; then
 if test "X$bash_cv_have_socklib" = "X"; then
 _bash_needmsg=
 else
-echo "$as_me:7306: checking for socket library" >&5
+echo "$as_me:8159: checking for socket library" >&5
 echo $ECHO_N "checking for socket library... $ECHO_C" >&6
 _bash_needmsg=yes
 fi
 if test "${bash_cv_have_socklib+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  echo "$as_me:7313: checking for getpeername in -lsocket" >&5
+  echo "$as_me:8166: checking for getpeername in -lsocket" >&5
 echo $ECHO_N "checking for getpeername in -lsocket... $ECHO_C" >&6
 if test "${ac_cv_lib_socket_getpeername+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -7318,7 +8171,7 @@ else
   ac_check_lib_save_LIBS=$LIBS
 LIBS="-lsocket -lnsl $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
-#line 7321 "configure"
+#line 8174 "configure"
 #include "confdefs.h"
 
 /* Override any gcc2 internal prototype to avoid an error.  */
@@ -7337,16 +8190,16 @@ getpeername ();
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:7340: \"$ac_link\"") >&5
+if { (eval echo "$as_me:8193: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:7343: \$? = $ac_status" >&5
+  echo "$as_me:8196: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:7346: \"$ac_try\"") >&5
+  { (eval echo "$as_me:8199: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:7349: \$? = $ac_status" >&5
+  echo "$as_me:8202: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_lib_socket_getpeername=yes
 else
@@ -7357,7 +8210,7 @@ fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:7360: result: $ac_cv_lib_socket_getpeername" >&5
+echo "$as_me:8213: result: $ac_cv_lib_socket_getpeername" >&5
 echo "${ECHO_T}$ac_cv_lib_socket_getpeername" >&6
 if test $ac_cv_lib_socket_getpeername = yes; then
   bash_cv_have_socklib=yes
@@ -7368,7 +8221,7 @@ fi
 fi
 
 if test "X$_bash_needmsg" = Xyes; then
-  echo "$as_me:7371: result: $bash_cv_have_socklib" >&5
+  echo "$as_me:8224: result: $bash_cv_have_socklib" >&5
 echo "${ECHO_T}$bash_cv_have_socklib" >&6
   _bash_needmsg=
 fi
@@ -7377,14 +8230,14 @@ if test $bash_cv_have_socklib = yes; then
   if test "X$bash_cv_have_libnsl" = "X"; then
     _bash_needmsg=
   else
-    echo "$as_me:7380: checking for libnsl" >&5
+    echo "$as_me:8233: checking for libnsl" >&5
 echo $ECHO_N "checking for libnsl... $ECHO_C" >&6
     _bash_needmsg=yes
   fi
   if test "${bash_cv_have_libnsl+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  echo "$as_me:7387: checking for t_open in -lnsl" >&5
+  echo "$as_me:8240: checking for t_open in -lnsl" >&5
 echo $ECHO_N "checking for t_open in -lnsl... $ECHO_C" >&6
 if test "${ac_cv_lib_nsl_t_open+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -7392,7 +8245,7 @@ else
   ac_check_lib_save_LIBS=$LIBS
 LIBS="-lnsl  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
-#line 7395 "configure"
+#line 8248 "configure"
 #include "confdefs.h"
 
 /* Override any gcc2 internal prototype to avoid an error.  */
@@ -7411,16 +8264,16 @@ t_open ();
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:7414: \"$ac_link\"") >&5
+if { (eval echo "$as_me:8267: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:7417: \$? = $ac_status" >&5
+  echo "$as_me:8270: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:7420: \"$ac_try\"") >&5
+  { (eval echo "$as_me:8273: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:7423: \$? = $ac_status" >&5
+  echo "$as_me:8276: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_lib_nsl_t_open=yes
 else
@@ -7431,7 +8284,7 @@ fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:7434: result: $ac_cv_lib_nsl_t_open" >&5
+echo "$as_me:8287: result: $ac_cv_lib_nsl_t_open" >&5
 echo "${ECHO_T}$ac_cv_lib_nsl_t_open" >&6
 if test $ac_cv_lib_nsl_t_open = yes; then
   bash_cv_have_libnsl=yes
@@ -7442,7 +8295,7 @@ fi
 fi
 
   if test "X$_bash_needmsg" = Xyes; then
-    echo "$as_me:7445: result: $bash_cv_have_libnsl" >&5
+    echo "$as_me:8298: result: $bash_cv_have_libnsl" >&5
 echo "${ECHO_T}$bash_cv_have_libnsl" >&6
     _bash_needmsg=
   fi
@@ -7466,7 +8319,7 @@ if test "$ac_cv_func_gethostbyname" = no; then
        if test "X$bash_cv_have_gethostbyname" = "X"; then
 _bash_needmsg=yes
 else
-echo "$as_me:7469: checking for gethostbyname in socket library" >&5
+echo "$as_me:8322: checking for gethostbyname in socket library" >&5
 echo $ECHO_N "checking for gethostbyname in socket library... $ECHO_C" >&6
 _bash_needmsg=
 fi
@@ -7474,7 +8327,7 @@ if test "${bash_cv_have_gethostbyname+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 7477 "configure"
+#line 8330 "configure"
 #include "confdefs.h"
 #include <netdb.h>
 int
@@ -7488,16 +8341,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:7491: \"$ac_link\"") >&5
+if { (eval echo "$as_me:8344: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:7494: \$? = $ac_status" >&5
+  echo "$as_me:8347: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:7497: \"$ac_try\"") >&5
+  { (eval echo "$as_me:8350: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:7500: \$? = $ac_status" >&5
+  echo "$as_me:8353: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_have_gethostbyname=yes
 else
@@ -7510,10 +8363,10 @@ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
 
 if test "X$_bash_needmsg" = Xyes; then
-    echo "$as_me:7513: checking for gethostbyname in socket library" >&5
+    echo "$as_me:8366: checking for gethostbyname in socket library" >&5
 echo $ECHO_N "checking for gethostbyname in socket library... $ECHO_C" >&6
 fi
-echo "$as_me:7516: result: $bash_cv_have_gethostbyname" >&5
+echo "$as_me:8369: result: $bash_cv_have_gethostbyname" >&5
 echo "${ECHO_T}$bash_cv_have_gethostbyname" >&6
 if test "$bash_cv_have_gethostbyname" = yes; then
 cat >>confdefs.h <<\EOF
@@ -7524,13 +8377,13 @@ fi
 
 fi
 
-echo "$as_me:7527: checking for uid_t in sys/types.h" >&5
+echo "$as_me:8380: checking for uid_t in sys/types.h" >&5
 echo $ECHO_N "checking for uid_t in sys/types.h... $ECHO_C" >&6
 if test "${ac_cv_type_uid_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 7533 "configure"
+#line 8386 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 
@@ -7544,7 +8397,7 @@ fi
 rm -f conftest*
 
 fi
-echo "$as_me:7547: result: $ac_cv_type_uid_t" >&5
+echo "$as_me:8400: result: $ac_cv_type_uid_t" >&5
 echo "${ECHO_T}$ac_cv_type_uid_t" >&6
 if test $ac_cv_type_uid_t = no; then
 
@@ -7558,7 +8411,7 @@ EOF
 
 fi
 
-echo "$as_me:7561: checking type of array argument to getgroups" >&5
+echo "$as_me:8414: checking type of array argument to getgroups" >&5
 echo $ECHO_N "checking type of array argument to getgroups... $ECHO_C" >&6
 if test "${ac_cv_type_getgroups+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -7567,7 +8420,7 @@ else
   ac_cv_type_getgroups=cross
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 7570 "configure"
+#line 8423 "configure"
 #include "confdefs.h"
 /* Thanks to Mike Rendell for this test.  */
 #include <sys/types.h>
@@ -7593,15 +8446,15 @@ main ()
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:7596: \"$ac_link\"") >&5
+if { (eval echo "$as_me:8449: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:7599: \$? = $ac_status" >&5
+  echo "$as_me:8452: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:7601: \"$ac_try\"") >&5
+  { (eval echo "$as_me:8454: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:7604: \$? = $ac_status" >&5
+  echo "$as_me:8457: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_getgroups=gid_t
 else
@@ -7614,7 +8467,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 if test $ac_cv_type_getgroups = cross; then
         cat >conftest.$ac_ext <<_ACEOF
-#line 7617 "configure"
+#line 8470 "configure"
 #include "confdefs.h"
 #include <unistd.h>
 
@@ -7629,20 +8482,20 @@ rm -f conftest*
 
 fi
 fi
-echo "$as_me:7632: result: $ac_cv_type_getgroups" >&5
+echo "$as_me:8485: result: $ac_cv_type_getgroups" >&5
 echo "${ECHO_T}$ac_cv_type_getgroups" >&6
 
 cat >>confdefs.h <<EOF
 #define GETGROUPS_T $ac_cv_type_getgroups
 EOF
 
-echo "$as_me:7639: checking for off_t" >&5
+echo "$as_me:8492: checking for off_t" >&5
 echo $ECHO_N "checking for off_t... $ECHO_C" >&6
 if test "${ac_cv_type_off_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 7645 "configure"
+#line 8498 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -7657,16 +8510,16 @@ if (sizeof (off_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:7660: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:8513: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:7663: \$? = $ac_status" >&5
+  echo "$as_me:8516: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:7666: \"$ac_try\"") >&5
+  { (eval echo "$as_me:8519: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:7669: \$? = $ac_status" >&5
+  echo "$as_me:8522: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_off_t=yes
 else
@@ -7676,7 +8529,7 @@ ac_cv_type_off_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:7679: result: $ac_cv_type_off_t" >&5
+echo "$as_me:8532: result: $ac_cv_type_off_t" >&5
 echo "${ECHO_T}$ac_cv_type_off_t" >&6
 if test $ac_cv_type_off_t = yes; then
   :
@@ -7688,13 +8541,13 @@ EOF
 
 fi
 
-echo "$as_me:7691: checking for mode_t" >&5
+echo "$as_me:8544: checking for mode_t" >&5
 echo $ECHO_N "checking for mode_t... $ECHO_C" >&6
 if test "${ac_cv_type_mode_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 7697 "configure"
+#line 8550 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -7709,16 +8562,16 @@ if (sizeof (mode_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:7712: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:8565: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:7715: \$? = $ac_status" >&5
+  echo "$as_me:8568: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:7718: \"$ac_try\"") >&5
+  { (eval echo "$as_me:8571: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:7721: \$? = $ac_status" >&5
+  echo "$as_me:8574: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_mode_t=yes
 else
@@ -7728,7 +8581,7 @@ ac_cv_type_mode_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:7731: result: $ac_cv_type_mode_t" >&5
+echo "$as_me:8584: result: $ac_cv_type_mode_t" >&5
 echo "${ECHO_T}$ac_cv_type_mode_t" >&6
 if test $ac_cv_type_mode_t = yes; then
   :
@@ -7740,13 +8593,13 @@ EOF
 
 fi
 
-echo "$as_me:7743: checking for uid_t in sys/types.h" >&5
+echo "$as_me:8596: checking for uid_t in sys/types.h" >&5
 echo $ECHO_N "checking for uid_t in sys/types.h... $ECHO_C" >&6
 if test "${ac_cv_type_uid_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 7749 "configure"
+#line 8602 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 
@@ -7760,7 +8613,7 @@ fi
 rm -f conftest*
 
 fi
-echo "$as_me:7763: result: $ac_cv_type_uid_t" >&5
+echo "$as_me:8616: result: $ac_cv_type_uid_t" >&5
 echo "${ECHO_T}$ac_cv_type_uid_t" >&6
 if test $ac_cv_type_uid_t = no; then
 
@@ -7774,13 +8627,13 @@ EOF
 
 fi
 
-echo "$as_me:7777: checking for pid_t" >&5
+echo "$as_me:8630: checking for pid_t" >&5
 echo $ECHO_N "checking for pid_t... $ECHO_C" >&6
 if test "${ac_cv_type_pid_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 7783 "configure"
+#line 8636 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -7795,16 +8648,16 @@ if (sizeof (pid_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:7798: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:8651: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:7801: \$? = $ac_status" >&5
+  echo "$as_me:8654: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:7804: \"$ac_try\"") >&5
+  { (eval echo "$as_me:8657: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:7807: \$? = $ac_status" >&5
+  echo "$as_me:8660: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_pid_t=yes
 else
@@ -7814,7 +8667,7 @@ ac_cv_type_pid_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:7817: result: $ac_cv_type_pid_t" >&5
+echo "$as_me:8670: result: $ac_cv_type_pid_t" >&5
 echo "${ECHO_T}$ac_cv_type_pid_t" >&6
 if test $ac_cv_type_pid_t = yes; then
   :
@@ -7826,13 +8679,13 @@ EOF
 
 fi
 
-echo "$as_me:7829: checking for size_t" >&5
+echo "$as_me:8682: checking for size_t" >&5
 echo $ECHO_N "checking for size_t... $ECHO_C" >&6
 if test "${ac_cv_type_size_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 7835 "configure"
+#line 8688 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -7847,16 +8700,16 @@ if (sizeof (size_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:7850: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:8703: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:7853: \$? = $ac_status" >&5
+  echo "$as_me:8706: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:7856: \"$ac_try\"") >&5
+  { (eval echo "$as_me:8709: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:7859: \$? = $ac_status" >&5
+  echo "$as_me:8712: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_size_t=yes
 else
@@ -7866,7 +8719,7 @@ ac_cv_type_size_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:7869: result: $ac_cv_type_size_t" >&5
+echo "$as_me:8722: result: $ac_cv_type_size_t" >&5
 echo "${ECHO_T}$ac_cv_type_size_t" >&6
 if test $ac_cv_type_size_t = yes; then
   :
@@ -7878,13 +8731,13 @@ EOF
 
 fi
 
-echo "$as_me:7881: checking for ssize_t" >&5
+echo "$as_me:8734: checking for ssize_t" >&5
 echo $ECHO_N "checking for ssize_t... $ECHO_C" >&6
 if test "${ac_cv_type_ssize_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 7887 "configure"
+#line 8740 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -7899,16 +8752,16 @@ if (sizeof (ssize_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:7902: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:8755: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:7905: \$? = $ac_status" >&5
+  echo "$as_me:8758: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:7908: \"$ac_try\"") >&5
+  { (eval echo "$as_me:8761: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:7911: \$? = $ac_status" >&5
+  echo "$as_me:8764: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_ssize_t=yes
 else
@@ -7918,7 +8771,7 @@ ac_cv_type_ssize_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:7921: result: $ac_cv_type_ssize_t" >&5
+echo "$as_me:8774: result: $ac_cv_type_ssize_t" >&5
 echo "${ECHO_T}$ac_cv_type_ssize_t" >&6
 if test $ac_cv_type_ssize_t = yes; then
   :
@@ -7930,13 +8783,13 @@ EOF
 
 fi
 
-echo "$as_me:7933: checking for time_t" >&5
+echo "$as_me:8786: checking for time_t" >&5
 echo $ECHO_N "checking for time_t... $ECHO_C" >&6
 if test "${ac_cv_type_time_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 7939 "configure"
+#line 8792 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -7951,16 +8804,16 @@ if (sizeof (time_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:7954: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:8807: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:7957: \$? = $ac_status" >&5
+  echo "$as_me:8810: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:7960: \"$ac_try\"") >&5
+  { (eval echo "$as_me:8813: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:7963: \$? = $ac_status" >&5
+  echo "$as_me:8816: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_time_t=yes
 else
@@ -7970,7 +8823,7 @@ ac_cv_type_time_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:7973: result: $ac_cv_type_time_t" >&5
+echo "$as_me:8826: result: $ac_cv_type_time_t" >&5
 echo "${ECHO_T}$ac_cv_type_time_t" >&6
 if test $ac_cv_type_time_t = yes; then
   :
@@ -7982,13 +8835,13 @@ EOF
 
 fi
 
-echo "$as_me:7985: checking for long long" >&5
+echo "$as_me:8838: checking for long long" >&5
 echo $ECHO_N "checking for long long... $ECHO_C" >&6
 if test "${bash_cv_type_long_long+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 7991 "configure"
+#line 8844 "configure"
 #include "confdefs.h"
 
 long long ll = 1; int i = 63;
@@ -8004,16 +8857,16 @@ return ll << i | ll >> i | llm / ll | llm % ll;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:8007: \"$ac_link\"") >&5
+if { (eval echo "$as_me:8860: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:8010: \$? = $ac_status" >&5
+  echo "$as_me:8863: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:8013: \"$ac_try\"") >&5
+  { (eval echo "$as_me:8866: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8016: \$? = $ac_status" >&5
+  echo "$as_me:8869: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_type_long_long='long long'
 else
@@ -8023,7 +8876,7 @@ bash_cv_type_long_long='long'
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:8026: result: $bash_cv_type_long_long" >&5
+echo "$as_me:8879: result: $bash_cv_type_long_long" >&5
 echo "${ECHO_T}$bash_cv_type_long_long" >&6
 if test "$bash_cv_type_long_long" = 'long long'; then
   cat >>confdefs.h <<\EOF
@@ -8032,13 +8885,13 @@ EOF
 
 fi
 
-echo "$as_me:8035: checking for unsigned long long" >&5
+echo "$as_me:8888: checking for unsigned long long" >&5
 echo $ECHO_N "checking for unsigned long long... $ECHO_C" >&6
 if test "${bash_cv_type_unsigned_long_long+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 8041 "configure"
+#line 8894 "configure"
 #include "confdefs.h"
 
 unsigned long long ull = 1; int i = 63;
@@ -8054,16 +8907,16 @@ return ull << i | ull >> i | ullmax / ull | ullmax % ull;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:8057: \"$ac_link\"") >&5
+if { (eval echo "$as_me:8910: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:8060: \$? = $ac_status" >&5
+  echo "$as_me:8913: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:8063: \"$ac_try\"") >&5
+  { (eval echo "$as_me:8916: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8066: \$? = $ac_status" >&5
+  echo "$as_me:8919: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_type_unsigned_long_long='unsigned long long'
 else
@@ -8073,7 +8926,7 @@ bash_cv_type_unsigned_long_long='unsigned long'
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:8076: result: $bash_cv_type_unsigned_long_long" >&5
+echo "$as_me:8929: result: $bash_cv_type_unsigned_long_long" >&5
 echo "${ECHO_T}$bash_cv_type_unsigned_long_long" >&6
 if test "$bash_cv_type_unsigned_long_long" = 'unsigned long long'; then
   cat >>confdefs.h <<\EOF
@@ -8082,13 +8935,13 @@ EOF
 
 fi
 
-echo "$as_me:8085: checking return type of signal handlers" >&5
+echo "$as_me:8938: checking return type of signal handlers" >&5
 echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6
 if test "${ac_cv_type_signal+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 8091 "configure"
+#line 8944 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <signal.h>
@@ -8110,16 +8963,16 @@ int i;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8113: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:8966: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8116: \$? = $ac_status" >&5
+  echo "$as_me:8969: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8119: \"$ac_try\"") >&5
+  { (eval echo "$as_me:8972: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8122: \$? = $ac_status" >&5
+  echo "$as_me:8975: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_signal=void
 else
@@ -8129,20 +8982,20 @@ ac_cv_type_signal=int
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:8132: result: $ac_cv_type_signal" >&5
+echo "$as_me:8985: result: $ac_cv_type_signal" >&5
 echo "${ECHO_T}$ac_cv_type_signal" >&6
 
 cat >>confdefs.h <<EOF
 #define RETSIGTYPE $ac_cv_type_signal
 EOF
 
-echo "$as_me:8139: checking for char" >&5
+echo "$as_me:8992: checking for char" >&5
 echo $ECHO_N "checking for char... $ECHO_C" >&6
 if test "${ac_cv_type_char+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 8145 "configure"
+#line 8998 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8157,16 +9010,16 @@ if (sizeof (char))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8160: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9013: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8163: \$? = $ac_status" >&5
+  echo "$as_me:9016: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8166: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9019: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8169: \$? = $ac_status" >&5
+  echo "$as_me:9022: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_char=yes
 else
@@ -8176,10 +9029,10 @@ ac_cv_type_char=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:8179: result: $ac_cv_type_char" >&5
+echo "$as_me:9032: result: $ac_cv_type_char" >&5
 echo "${ECHO_T}$ac_cv_type_char" >&6
 
-echo "$as_me:8182: checking size of char" >&5
+echo "$as_me:9035: checking size of char" >&5
 echo $ECHO_N "checking size of char... $ECHO_C" >&6
 if test "${ac_cv_sizeof_char+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -8188,7 +9041,7 @@ else
   if test "$cross_compiling" = yes; then
   # Depending upon the size, compute the lo and hi bounds.
 cat >conftest.$ac_ext <<_ACEOF
-#line 8191 "configure"
+#line 9044 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8200,21 +9053,21 @@ int _array_ [1 - 2 * !((sizeof (char)) >= 0)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8203: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9056: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8206: \$? = $ac_status" >&5
+  echo "$as_me:9059: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8209: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9062: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8212: \$? = $ac_status" >&5
+  echo "$as_me:9065: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_lo=0 ac_mid=0
   while :; do
     cat >conftest.$ac_ext <<_ACEOF
-#line 8217 "configure"
+#line 9070 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8226,16 +9079,16 @@ int _array_ [1 - 2 * !((sizeof (char)) <= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8229: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9082: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8232: \$? = $ac_status" >&5
+  echo "$as_me:9085: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8235: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9088: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8238: \$? = $ac_status" >&5
+  echo "$as_me:9091: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_hi=$ac_mid; break
 else
@@ -8251,7 +9104,7 @@ cat conftest.$ac_ext >&5
 ac_hi=-1 ac_mid=-1
   while :; do
     cat >conftest.$ac_ext <<_ACEOF
-#line 8254 "configure"
+#line 9107 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8263,16 +9116,16 @@ int _array_ [1 - 2 * !((sizeof (char)) >= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8266: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9119: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8269: \$? = $ac_status" >&5
+  echo "$as_me:9122: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8272: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9125: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8275: \$? = $ac_status" >&5
+  echo "$as_me:9128: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_lo=$ac_mid; break
 else
@@ -8288,7 +9141,7 @@ rm -f conftest.$ac_objext conftest.$ac_ext
 while test "x$ac_lo" != "x$ac_hi"; do
   ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
   cat >conftest.$ac_ext <<_ACEOF
-#line 8291 "configure"
+#line 9144 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8300,16 +9153,16 @@ int _array_ [1 - 2 * !((sizeof (char)) <= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8303: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9156: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8306: \$? = $ac_status" >&5
+  echo "$as_me:9159: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8309: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9162: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8312: \$? = $ac_status" >&5
+  echo "$as_me:9165: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_hi=$ac_mid
 else
@@ -8322,12 +9175,12 @@ done
 ac_cv_sizeof_char=$ac_lo
 else
   if test "$cross_compiling" = yes; then
-  { { echo "$as_me:8325: error: cannot run test program while cross compiling" >&5
+  { { echo "$as_me:9178: error: cannot run test program while cross compiling" >&5
 echo "$as_me: error: cannot run test program while cross compiling" >&2;}
    { (exit 1); exit 1; }; }
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 8330 "configure"
+#line 9183 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8343,15 +9196,15 @@ fclose (f);
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:8346: \"$ac_link\"") >&5
+if { (eval echo "$as_me:9199: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:8349: \$? = $ac_status" >&5
+  echo "$as_me:9202: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:8351: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9204: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8354: \$? = $ac_status" >&5
+  echo "$as_me:9207: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_sizeof_char=`cat conftest.val`
 else
@@ -8367,19 +9220,19 @@ else
   ac_cv_sizeof_char=0
 fi
 fi
-echo "$as_me:8370: result: $ac_cv_sizeof_char" >&5
+echo "$as_me:9223: result: $ac_cv_sizeof_char" >&5
 echo "${ECHO_T}$ac_cv_sizeof_char" >&6
 cat >>confdefs.h <<EOF
 #define SIZEOF_CHAR $ac_cv_sizeof_char
 EOF
 
-echo "$as_me:8376: checking for short" >&5
+echo "$as_me:9229: checking for short" >&5
 echo $ECHO_N "checking for short... $ECHO_C" >&6
 if test "${ac_cv_type_short+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 8382 "configure"
+#line 9235 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8394,16 +9247,16 @@ if (sizeof (short))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8397: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9250: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8400: \$? = $ac_status" >&5
+  echo "$as_me:9253: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8403: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9256: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8406: \$? = $ac_status" >&5
+  echo "$as_me:9259: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_short=yes
 else
@@ -8413,10 +9266,10 @@ ac_cv_type_short=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:8416: result: $ac_cv_type_short" >&5
+echo "$as_me:9269: result: $ac_cv_type_short" >&5
 echo "${ECHO_T}$ac_cv_type_short" >&6
 
-echo "$as_me:8419: checking size of short" >&5
+echo "$as_me:9272: checking size of short" >&5
 echo $ECHO_N "checking size of short... $ECHO_C" >&6
 if test "${ac_cv_sizeof_short+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -8425,7 +9278,7 @@ else
   if test "$cross_compiling" = yes; then
   # Depending upon the size, compute the lo and hi bounds.
 cat >conftest.$ac_ext <<_ACEOF
-#line 8428 "configure"
+#line 9281 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8437,21 +9290,21 @@ int _array_ [1 - 2 * !((sizeof (short)) >= 0)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8440: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9293: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8443: \$? = $ac_status" >&5
+  echo "$as_me:9296: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8446: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9299: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8449: \$? = $ac_status" >&5
+  echo "$as_me:9302: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_lo=0 ac_mid=0
   while :; do
     cat >conftest.$ac_ext <<_ACEOF
-#line 8454 "configure"
+#line 9307 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8463,16 +9316,16 @@ int _array_ [1 - 2 * !((sizeof (short)) <= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8466: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9319: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8469: \$? = $ac_status" >&5
+  echo "$as_me:9322: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8472: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9325: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8475: \$? = $ac_status" >&5
+  echo "$as_me:9328: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_hi=$ac_mid; break
 else
@@ -8488,7 +9341,7 @@ cat conftest.$ac_ext >&5
 ac_hi=-1 ac_mid=-1
   while :; do
     cat >conftest.$ac_ext <<_ACEOF
-#line 8491 "configure"
+#line 9344 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8500,16 +9353,16 @@ int _array_ [1 - 2 * !((sizeof (short)) >= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8503: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9356: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8506: \$? = $ac_status" >&5
+  echo "$as_me:9359: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8509: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9362: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8512: \$? = $ac_status" >&5
+  echo "$as_me:9365: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_lo=$ac_mid; break
 else
@@ -8525,7 +9378,7 @@ rm -f conftest.$ac_objext conftest.$ac_ext
 while test "x$ac_lo" != "x$ac_hi"; do
   ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
   cat >conftest.$ac_ext <<_ACEOF
-#line 8528 "configure"
+#line 9381 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8537,16 +9390,16 @@ int _array_ [1 - 2 * !((sizeof (short)) <= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8540: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9393: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8543: \$? = $ac_status" >&5
+  echo "$as_me:9396: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8546: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9399: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8549: \$? = $ac_status" >&5
+  echo "$as_me:9402: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_hi=$ac_mid
 else
@@ -8559,12 +9412,12 @@ done
 ac_cv_sizeof_short=$ac_lo
 else
   if test "$cross_compiling" = yes; then
-  { { echo "$as_me:8562: error: cannot run test program while cross compiling" >&5
+  { { echo "$as_me:9415: error: cannot run test program while cross compiling" >&5
 echo "$as_me: error: cannot run test program while cross compiling" >&2;}
    { (exit 1); exit 1; }; }
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 8567 "configure"
+#line 9420 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8580,15 +9433,15 @@ fclose (f);
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:8583: \"$ac_link\"") >&5
+if { (eval echo "$as_me:9436: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:8586: \$? = $ac_status" >&5
+  echo "$as_me:9439: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:8588: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9441: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8591: \$? = $ac_status" >&5
+  echo "$as_me:9444: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_sizeof_short=`cat conftest.val`
 else
@@ -8604,19 +9457,19 @@ else
   ac_cv_sizeof_short=0
 fi
 fi
-echo "$as_me:8607: result: $ac_cv_sizeof_short" >&5
+echo "$as_me:9460: result: $ac_cv_sizeof_short" >&5
 echo "${ECHO_T}$ac_cv_sizeof_short" >&6
 cat >>confdefs.h <<EOF
 #define SIZEOF_SHORT $ac_cv_sizeof_short
 EOF
 
-echo "$as_me:8613: checking for int" >&5
+echo "$as_me:9466: checking for int" >&5
 echo $ECHO_N "checking for int... $ECHO_C" >&6
 if test "${ac_cv_type_int+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 8619 "configure"
+#line 9472 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8631,16 +9484,16 @@ if (sizeof (int))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8634: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9487: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8637: \$? = $ac_status" >&5
+  echo "$as_me:9490: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8640: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9493: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8643: \$? = $ac_status" >&5
+  echo "$as_me:9496: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_int=yes
 else
@@ -8650,10 +9503,10 @@ ac_cv_type_int=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:8653: result: $ac_cv_type_int" >&5
+echo "$as_me:9506: result: $ac_cv_type_int" >&5
 echo "${ECHO_T}$ac_cv_type_int" >&6
 
-echo "$as_me:8656: checking size of int" >&5
+echo "$as_me:9509: checking size of int" >&5
 echo $ECHO_N "checking size of int... $ECHO_C" >&6
 if test "${ac_cv_sizeof_int+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -8662,7 +9515,7 @@ else
   if test "$cross_compiling" = yes; then
   # Depending upon the size, compute the lo and hi bounds.
 cat >conftest.$ac_ext <<_ACEOF
-#line 8665 "configure"
+#line 9518 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8674,21 +9527,21 @@ int _array_ [1 - 2 * !((sizeof (int)) >= 0)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8677: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9530: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8680: \$? = $ac_status" >&5
+  echo "$as_me:9533: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8683: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9536: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8686: \$? = $ac_status" >&5
+  echo "$as_me:9539: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_lo=0 ac_mid=0
   while :; do
     cat >conftest.$ac_ext <<_ACEOF
-#line 8691 "configure"
+#line 9544 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8700,16 +9553,16 @@ int _array_ [1 - 2 * !((sizeof (int)) <= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8703: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9556: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8706: \$? = $ac_status" >&5
+  echo "$as_me:9559: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8709: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9562: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8712: \$? = $ac_status" >&5
+  echo "$as_me:9565: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_hi=$ac_mid; break
 else
@@ -8725,7 +9578,7 @@ cat conftest.$ac_ext >&5
 ac_hi=-1 ac_mid=-1
   while :; do
     cat >conftest.$ac_ext <<_ACEOF
-#line 8728 "configure"
+#line 9581 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8737,16 +9590,16 @@ int _array_ [1 - 2 * !((sizeof (int)) >= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8740: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9593: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8743: \$? = $ac_status" >&5
+  echo "$as_me:9596: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8746: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9599: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8749: \$? = $ac_status" >&5
+  echo "$as_me:9602: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_lo=$ac_mid; break
 else
@@ -8762,7 +9615,7 @@ rm -f conftest.$ac_objext conftest.$ac_ext
 while test "x$ac_lo" != "x$ac_hi"; do
   ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
   cat >conftest.$ac_ext <<_ACEOF
-#line 8765 "configure"
+#line 9618 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8774,16 +9627,16 @@ int _array_ [1 - 2 * !((sizeof (int)) <= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8777: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9630: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8780: \$? = $ac_status" >&5
+  echo "$as_me:9633: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8783: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9636: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8786: \$? = $ac_status" >&5
+  echo "$as_me:9639: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_hi=$ac_mid
 else
@@ -8796,12 +9649,12 @@ done
 ac_cv_sizeof_int=$ac_lo
 else
   if test "$cross_compiling" = yes; then
-  { { echo "$as_me:8799: error: cannot run test program while cross compiling" >&5
+  { { echo "$as_me:9652: error: cannot run test program while cross compiling" >&5
 echo "$as_me: error: cannot run test program while cross compiling" >&2;}
    { (exit 1); exit 1; }; }
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 8804 "configure"
+#line 9657 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8817,15 +9670,15 @@ fclose (f);
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:8820: \"$ac_link\"") >&5
+if { (eval echo "$as_me:9673: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:8823: \$? = $ac_status" >&5
+  echo "$as_me:9676: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:8825: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9678: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8828: \$? = $ac_status" >&5
+  echo "$as_me:9681: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_sizeof_int=`cat conftest.val`
 else
@@ -8841,19 +9694,19 @@ else
   ac_cv_sizeof_int=0
 fi
 fi
-echo "$as_me:8844: result: $ac_cv_sizeof_int" >&5
+echo "$as_me:9697: result: $ac_cv_sizeof_int" >&5
 echo "${ECHO_T}$ac_cv_sizeof_int" >&6
 cat >>confdefs.h <<EOF
 #define SIZEOF_INT $ac_cv_sizeof_int
 EOF
 
-echo "$as_me:8850: checking for long" >&5
+echo "$as_me:9703: checking for long" >&5
 echo $ECHO_N "checking for long... $ECHO_C" >&6
 if test "${ac_cv_type_long+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 8856 "configure"
+#line 9709 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8868,16 +9721,16 @@ if (sizeof (long))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8871: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9724: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8874: \$? = $ac_status" >&5
+  echo "$as_me:9727: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8877: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9730: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8880: \$? = $ac_status" >&5
+  echo "$as_me:9733: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_long=yes
 else
@@ -8887,10 +9740,10 @@ ac_cv_type_long=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:8890: result: $ac_cv_type_long" >&5
+echo "$as_me:9743: result: $ac_cv_type_long" >&5
 echo "${ECHO_T}$ac_cv_type_long" >&6
 
-echo "$as_me:8893: checking size of long" >&5
+echo "$as_me:9746: checking size of long" >&5
 echo $ECHO_N "checking size of long... $ECHO_C" >&6
 if test "${ac_cv_sizeof_long+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -8899,7 +9752,7 @@ else
   if test "$cross_compiling" = yes; then
   # Depending upon the size, compute the lo and hi bounds.
 cat >conftest.$ac_ext <<_ACEOF
-#line 8902 "configure"
+#line 9755 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8911,21 +9764,21 @@ int _array_ [1 - 2 * !((sizeof (long)) >= 0)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8914: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9767: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8917: \$? = $ac_status" >&5
+  echo "$as_me:9770: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8920: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9773: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8923: \$? = $ac_status" >&5
+  echo "$as_me:9776: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_lo=0 ac_mid=0
   while :; do
     cat >conftest.$ac_ext <<_ACEOF
-#line 8928 "configure"
+#line 9781 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8937,16 +9790,16 @@ int _array_ [1 - 2 * !((sizeof (long)) <= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8940: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9793: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8943: \$? = $ac_status" >&5
+  echo "$as_me:9796: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8946: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9799: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8949: \$? = $ac_status" >&5
+  echo "$as_me:9802: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_hi=$ac_mid; break
 else
@@ -8962,7 +9815,7 @@ cat conftest.$ac_ext >&5
 ac_hi=-1 ac_mid=-1
   while :; do
     cat >conftest.$ac_ext <<_ACEOF
-#line 8965 "configure"
+#line 9818 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -8974,16 +9827,16 @@ int _array_ [1 - 2 * !((sizeof (long)) >= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:8977: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9830: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:8980: \$? = $ac_status" >&5
+  echo "$as_me:9833: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:8983: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9836: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:8986: \$? = $ac_status" >&5
+  echo "$as_me:9839: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_lo=$ac_mid; break
 else
@@ -8999,7 +9852,7 @@ rm -f conftest.$ac_objext conftest.$ac_ext
 while test "x$ac_lo" != "x$ac_hi"; do
   ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
   cat >conftest.$ac_ext <<_ACEOF
-#line 9002 "configure"
+#line 9855 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9011,16 +9864,16 @@ int _array_ [1 - 2 * !((sizeof (long)) <= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9014: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9867: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9017: \$? = $ac_status" >&5
+  echo "$as_me:9870: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9020: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9873: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9023: \$? = $ac_status" >&5
+  echo "$as_me:9876: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_hi=$ac_mid
 else
@@ -9033,12 +9886,12 @@ done
 ac_cv_sizeof_long=$ac_lo
 else
   if test "$cross_compiling" = yes; then
-  { { echo "$as_me:9036: error: cannot run test program while cross compiling" >&5
+  { { echo "$as_me:9889: error: cannot run test program while cross compiling" >&5
 echo "$as_me: error: cannot run test program while cross compiling" >&2;}
    { (exit 1); exit 1; }; }
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 9041 "configure"
+#line 9894 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9054,15 +9907,15 @@ fclose (f);
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:9057: \"$ac_link\"") >&5
+if { (eval echo "$as_me:9910: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:9060: \$? = $ac_status" >&5
+  echo "$as_me:9913: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:9062: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9915: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9065: \$? = $ac_status" >&5
+  echo "$as_me:9918: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_sizeof_long=`cat conftest.val`
 else
@@ -9078,19 +9931,19 @@ else
   ac_cv_sizeof_long=0
 fi
 fi
-echo "$as_me:9081: result: $ac_cv_sizeof_long" >&5
+echo "$as_me:9934: result: $ac_cv_sizeof_long" >&5
 echo "${ECHO_T}$ac_cv_sizeof_long" >&6
 cat >>confdefs.h <<EOF
 #define SIZEOF_LONG $ac_cv_sizeof_long
 EOF
 
-echo "$as_me:9087: checking for char *" >&5
+echo "$as_me:9940: checking for char *" >&5
 echo $ECHO_N "checking for char *... $ECHO_C" >&6
 if test "${ac_cv_type_char_p+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 9093 "configure"
+#line 9946 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9105,16 +9958,16 @@ if (sizeof (char *))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9108: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:9961: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9111: \$? = $ac_status" >&5
+  echo "$as_me:9964: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9114: \"$ac_try\"") >&5
+  { (eval echo "$as_me:9967: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9117: \$? = $ac_status" >&5
+  echo "$as_me:9970: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_char_p=yes
 else
@@ -9124,10 +9977,10 @@ ac_cv_type_char_p=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:9127: result: $ac_cv_type_char_p" >&5
+echo "$as_me:9980: result: $ac_cv_type_char_p" >&5
 echo "${ECHO_T}$ac_cv_type_char_p" >&6
 
-echo "$as_me:9130: checking size of char *" >&5
+echo "$as_me:9983: checking size of char *" >&5
 echo $ECHO_N "checking size of char *... $ECHO_C" >&6
 if test "${ac_cv_sizeof_char_p+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -9136,7 +9989,7 @@ else
   if test "$cross_compiling" = yes; then
   # Depending upon the size, compute the lo and hi bounds.
 cat >conftest.$ac_ext <<_ACEOF
-#line 9139 "configure"
+#line 9992 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9148,21 +10001,21 @@ int _array_ [1 - 2 * !((sizeof (char *)) >= 0)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9151: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10004: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9154: \$? = $ac_status" >&5
+  echo "$as_me:10007: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9157: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10010: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9160: \$? = $ac_status" >&5
+  echo "$as_me:10013: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_lo=0 ac_mid=0
   while :; do
     cat >conftest.$ac_ext <<_ACEOF
-#line 9165 "configure"
+#line 10018 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9174,16 +10027,16 @@ int _array_ [1 - 2 * !((sizeof (char *)) <= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9177: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10030: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9180: \$? = $ac_status" >&5
+  echo "$as_me:10033: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9183: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10036: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9186: \$? = $ac_status" >&5
+  echo "$as_me:10039: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_hi=$ac_mid; break
 else
@@ -9199,7 +10052,7 @@ cat conftest.$ac_ext >&5
 ac_hi=-1 ac_mid=-1
   while :; do
     cat >conftest.$ac_ext <<_ACEOF
-#line 9202 "configure"
+#line 10055 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9211,16 +10064,16 @@ int _array_ [1 - 2 * !((sizeof (char *)) >= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9214: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10067: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9217: \$? = $ac_status" >&5
+  echo "$as_me:10070: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9220: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10073: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9223: \$? = $ac_status" >&5
+  echo "$as_me:10076: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_lo=$ac_mid; break
 else
@@ -9236,7 +10089,7 @@ rm -f conftest.$ac_objext conftest.$ac_ext
 while test "x$ac_lo" != "x$ac_hi"; do
   ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
   cat >conftest.$ac_ext <<_ACEOF
-#line 9239 "configure"
+#line 10092 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9248,16 +10101,16 @@ int _array_ [1 - 2 * !((sizeof (char *)) <= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9251: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10104: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9254: \$? = $ac_status" >&5
+  echo "$as_me:10107: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9257: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10110: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9260: \$? = $ac_status" >&5
+  echo "$as_me:10113: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_hi=$ac_mid
 else
@@ -9270,12 +10123,12 @@ done
 ac_cv_sizeof_char_p=$ac_lo
 else
   if test "$cross_compiling" = yes; then
-  { { echo "$as_me:9273: error: cannot run test program while cross compiling" >&5
+  { { echo "$as_me:10126: error: cannot run test program while cross compiling" >&5
 echo "$as_me: error: cannot run test program while cross compiling" >&2;}
    { (exit 1); exit 1; }; }
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 9278 "configure"
+#line 10131 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9291,15 +10144,15 @@ fclose (f);
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:9294: \"$ac_link\"") >&5
+if { (eval echo "$as_me:10147: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:9297: \$? = $ac_status" >&5
+  echo "$as_me:10150: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:9299: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10152: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9302: \$? = $ac_status" >&5
+  echo "$as_me:10155: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_sizeof_char_p=`cat conftest.val`
 else
@@ -9315,19 +10168,19 @@ else
   ac_cv_sizeof_char_p=0
 fi
 fi
-echo "$as_me:9318: result: $ac_cv_sizeof_char_p" >&5
+echo "$as_me:10171: result: $ac_cv_sizeof_char_p" >&5
 echo "${ECHO_T}$ac_cv_sizeof_char_p" >&6
 cat >>confdefs.h <<EOF
 #define SIZEOF_CHAR_P $ac_cv_sizeof_char_p
 EOF
 
-echo "$as_me:9324: checking for double" >&5
+echo "$as_me:10177: checking for double" >&5
 echo $ECHO_N "checking for double... $ECHO_C" >&6
 if test "${ac_cv_type_double+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 9330 "configure"
+#line 10183 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9342,16 +10195,16 @@ if (sizeof (double))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9345: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10198: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9348: \$? = $ac_status" >&5
+  echo "$as_me:10201: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9351: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10204: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9354: \$? = $ac_status" >&5
+  echo "$as_me:10207: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_double=yes
 else
@@ -9361,10 +10214,10 @@ ac_cv_type_double=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:9364: result: $ac_cv_type_double" >&5
+echo "$as_me:10217: result: $ac_cv_type_double" >&5
 echo "${ECHO_T}$ac_cv_type_double" >&6
 
-echo "$as_me:9367: checking size of double" >&5
+echo "$as_me:10220: checking size of double" >&5
 echo $ECHO_N "checking size of double... $ECHO_C" >&6
 if test "${ac_cv_sizeof_double+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -9373,7 +10226,7 @@ else
   if test "$cross_compiling" = yes; then
   # Depending upon the size, compute the lo and hi bounds.
 cat >conftest.$ac_ext <<_ACEOF
-#line 9376 "configure"
+#line 10229 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9385,21 +10238,21 @@ int _array_ [1 - 2 * !((sizeof (double)) >= 0)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9388: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10241: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9391: \$? = $ac_status" >&5
+  echo "$as_me:10244: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9394: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10247: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9397: \$? = $ac_status" >&5
+  echo "$as_me:10250: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_lo=0 ac_mid=0
   while :; do
     cat >conftest.$ac_ext <<_ACEOF
-#line 9402 "configure"
+#line 10255 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9411,16 +10264,16 @@ int _array_ [1 - 2 * !((sizeof (double)) <= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9414: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10267: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9417: \$? = $ac_status" >&5
+  echo "$as_me:10270: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9420: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10273: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9423: \$? = $ac_status" >&5
+  echo "$as_me:10276: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_hi=$ac_mid; break
 else
@@ -9436,7 +10289,7 @@ cat conftest.$ac_ext >&5
 ac_hi=-1 ac_mid=-1
   while :; do
     cat >conftest.$ac_ext <<_ACEOF
-#line 9439 "configure"
+#line 10292 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9448,16 +10301,16 @@ int _array_ [1 - 2 * !((sizeof (double)) >= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9451: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10304: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9454: \$? = $ac_status" >&5
+  echo "$as_me:10307: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9457: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10310: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9460: \$? = $ac_status" >&5
+  echo "$as_me:10313: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_lo=$ac_mid; break
 else
@@ -9473,7 +10326,7 @@ rm -f conftest.$ac_objext conftest.$ac_ext
 while test "x$ac_lo" != "x$ac_hi"; do
   ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
   cat >conftest.$ac_ext <<_ACEOF
-#line 9476 "configure"
+#line 10329 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9485,16 +10338,16 @@ int _array_ [1 - 2 * !((sizeof (double)) <= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9488: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10341: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9491: \$? = $ac_status" >&5
+  echo "$as_me:10344: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9494: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10347: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9497: \$? = $ac_status" >&5
+  echo "$as_me:10350: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_hi=$ac_mid
 else
@@ -9507,12 +10360,12 @@ done
 ac_cv_sizeof_double=$ac_lo
 else
   if test "$cross_compiling" = yes; then
-  { { echo "$as_me:9510: error: cannot run test program while cross compiling" >&5
+  { { echo "$as_me:10363: error: cannot run test program while cross compiling" >&5
 echo "$as_me: error: cannot run test program while cross compiling" >&2;}
    { (exit 1); exit 1; }; }
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 9515 "configure"
+#line 10368 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9528,15 +10381,15 @@ fclose (f);
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:9531: \"$ac_link\"") >&5
+if { (eval echo "$as_me:10384: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:9534: \$? = $ac_status" >&5
+  echo "$as_me:10387: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:9536: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10389: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9539: \$? = $ac_status" >&5
+  echo "$as_me:10392: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_sizeof_double=`cat conftest.val`
 else
@@ -9552,19 +10405,19 @@ else
   ac_cv_sizeof_double=0
 fi
 fi
-echo "$as_me:9555: result: $ac_cv_sizeof_double" >&5
+echo "$as_me:10408: result: $ac_cv_sizeof_double" >&5
 echo "${ECHO_T}$ac_cv_sizeof_double" >&6
 cat >>confdefs.h <<EOF
 #define SIZEOF_DOUBLE $ac_cv_sizeof_double
 EOF
 
-echo "$as_me:9561: checking for long long" >&5
+echo "$as_me:10414: checking for long long" >&5
 echo $ECHO_N "checking for long long... $ECHO_C" >&6
 if test "${ac_cv_type_long_long+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 9567 "configure"
+#line 10420 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9579,16 +10432,16 @@ if (sizeof (long long))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9582: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10435: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9585: \$? = $ac_status" >&5
+  echo "$as_me:10438: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9588: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10441: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9591: \$? = $ac_status" >&5
+  echo "$as_me:10444: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_long_long=yes
 else
@@ -9598,10 +10451,10 @@ ac_cv_type_long_long=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:9601: result: $ac_cv_type_long_long" >&5
+echo "$as_me:10454: result: $ac_cv_type_long_long" >&5
 echo "${ECHO_T}$ac_cv_type_long_long" >&6
 
-echo "$as_me:9604: checking size of long long" >&5
+echo "$as_me:10457: checking size of long long" >&5
 echo $ECHO_N "checking size of long long... $ECHO_C" >&6
 if test "${ac_cv_sizeof_long_long+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -9610,7 +10463,7 @@ else
   if test "$cross_compiling" = yes; then
   # Depending upon the size, compute the lo and hi bounds.
 cat >conftest.$ac_ext <<_ACEOF
-#line 9613 "configure"
+#line 10466 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9622,21 +10475,21 @@ int _array_ [1 - 2 * !((sizeof (long long)) >= 0)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9625: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10478: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9628: \$? = $ac_status" >&5
+  echo "$as_me:10481: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9631: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10484: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9634: \$? = $ac_status" >&5
+  echo "$as_me:10487: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_lo=0 ac_mid=0
   while :; do
     cat >conftest.$ac_ext <<_ACEOF
-#line 9639 "configure"
+#line 10492 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9648,16 +10501,16 @@ int _array_ [1 - 2 * !((sizeof (long long)) <= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9651: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10504: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9654: \$? = $ac_status" >&5
+  echo "$as_me:10507: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9657: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10510: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9660: \$? = $ac_status" >&5
+  echo "$as_me:10513: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_hi=$ac_mid; break
 else
@@ -9673,7 +10526,7 @@ cat conftest.$ac_ext >&5
 ac_hi=-1 ac_mid=-1
   while :; do
     cat >conftest.$ac_ext <<_ACEOF
-#line 9676 "configure"
+#line 10529 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9685,16 +10538,16 @@ int _array_ [1 - 2 * !((sizeof (long long)) >= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9688: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10541: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9691: \$? = $ac_status" >&5
+  echo "$as_me:10544: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9694: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10547: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9697: \$? = $ac_status" >&5
+  echo "$as_me:10550: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_lo=$ac_mid; break
 else
@@ -9710,7 +10563,7 @@ rm -f conftest.$ac_objext conftest.$ac_ext
 while test "x$ac_lo" != "x$ac_hi"; do
   ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
   cat >conftest.$ac_ext <<_ACEOF
-#line 9713 "configure"
+#line 10566 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9722,16 +10575,16 @@ int _array_ [1 - 2 * !((sizeof (long long)) <= $ac_mid)]
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9725: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10578: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9728: \$? = $ac_status" >&5
+  echo "$as_me:10581: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9731: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10584: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9734: \$? = $ac_status" >&5
+  echo "$as_me:10587: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_hi=$ac_mid
 else
@@ -9744,12 +10597,12 @@ done
 ac_cv_sizeof_long_long=$ac_lo
 else
   if test "$cross_compiling" = yes; then
-  { { echo "$as_me:9747: error: cannot run test program while cross compiling" >&5
+  { { echo "$as_me:10600: error: cannot run test program while cross compiling" >&5
 echo "$as_me: error: cannot run test program while cross compiling" >&2;}
    { (exit 1); exit 1; }; }
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 9752 "configure"
+#line 10605 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9765,15 +10618,15 @@ fclose (f);
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:9768: \"$ac_link\"") >&5
+if { (eval echo "$as_me:10621: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:9771: \$? = $ac_status" >&5
+  echo "$as_me:10624: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:9773: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10626: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9776: \$? = $ac_status" >&5
+  echo "$as_me:10629: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_sizeof_long_long=`cat conftest.val`
 else
@@ -9789,19 +10642,19 @@ else
   ac_cv_sizeof_long_long=0
 fi
 fi
-echo "$as_me:9792: result: $ac_cv_sizeof_long_long" >&5
+echo "$as_me:10645: result: $ac_cv_sizeof_long_long" >&5
 echo "${ECHO_T}$ac_cv_sizeof_long_long" >&6
 cat >>confdefs.h <<EOF
 #define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
 EOF
 
-echo "$as_me:9798: checking for u_int" >&5
+echo "$as_me:10651: checking for u_int" >&5
 echo $ECHO_N "checking for u_int... $ECHO_C" >&6
 if test "${ac_cv_type_u_int+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 9804 "configure"
+#line 10657 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9816,16 +10669,16 @@ if (sizeof (u_int))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9819: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10672: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9822: \$? = $ac_status" >&5
+  echo "$as_me:10675: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9825: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10678: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9828: \$? = $ac_status" >&5
+  echo "$as_me:10681: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_u_int=yes
 else
@@ -9835,7 +10688,7 @@ ac_cv_type_u_int=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:9838: result: $ac_cv_type_u_int" >&5
+echo "$as_me:10691: result: $ac_cv_type_u_int" >&5
 echo "${ECHO_T}$ac_cv_type_u_int" >&6
 if test $ac_cv_type_u_int = yes; then
   :
@@ -9847,13 +10700,13 @@ EOF
 
 fi
 
-echo "$as_me:9850: checking for u_long" >&5
+echo "$as_me:10703: checking for u_long" >&5
 echo $ECHO_N "checking for u_long... $ECHO_C" >&6
 if test "${ac_cv_type_u_long+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 9856 "configure"
+#line 10709 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9868,16 +10721,16 @@ if (sizeof (u_long))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9871: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10724: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9874: \$? = $ac_status" >&5
+  echo "$as_me:10727: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9877: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10730: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9880: \$? = $ac_status" >&5
+  echo "$as_me:10733: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_u_long=yes
 else
@@ -9887,7 +10740,7 @@ ac_cv_type_u_long=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:9890: result: $ac_cv_type_u_long" >&5
+echo "$as_me:10743: result: $ac_cv_type_u_long" >&5
 echo "${ECHO_T}$ac_cv_type_u_long" >&6
 if test $ac_cv_type_u_long = yes; then
   :
@@ -9900,13 +10753,13 @@ EOF
 fi
 
 if test "$ac_cv_sizeof_short" = 2; then
-  echo "$as_me:9903: checking for bits16_t" >&5
+  echo "$as_me:10756: checking for bits16_t" >&5
 echo $ECHO_N "checking for bits16_t... $ECHO_C" >&6
 if test "${ac_cv_type_bits16_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 9909 "configure"
+#line 10762 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9921,16 +10774,16 @@ if (sizeof (bits16_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9924: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10777: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9927: \$? = $ac_status" >&5
+  echo "$as_me:10780: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9930: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10783: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9933: \$? = $ac_status" >&5
+  echo "$as_me:10786: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_bits16_t=yes
 else
@@ -9940,7 +10793,7 @@ ac_cv_type_bits16_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:9943: result: $ac_cv_type_bits16_t" >&5
+echo "$as_me:10796: result: $ac_cv_type_bits16_t" >&5
 echo "${ECHO_T}$ac_cv_type_bits16_t" >&6
 if test $ac_cv_type_bits16_t = yes; then
   :
@@ -9953,13 +10806,13 @@ EOF
 fi
 
 elif test "$ac_cv_sizeof_char" = 2; then
-  echo "$as_me:9956: checking for bits16_t" >&5
+  echo "$as_me:10809: checking for bits16_t" >&5
 echo $ECHO_N "checking for bits16_t... $ECHO_C" >&6
 if test "${ac_cv_type_bits16_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 9962 "configure"
+#line 10815 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -9974,16 +10827,16 @@ if (sizeof (bits16_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:9977: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10830: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:9980: \$? = $ac_status" >&5
+  echo "$as_me:10833: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:9983: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10836: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:9986: \$? = $ac_status" >&5
+  echo "$as_me:10839: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_bits16_t=yes
 else
@@ -9993,7 +10846,7 @@ ac_cv_type_bits16_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:9996: result: $ac_cv_type_bits16_t" >&5
+echo "$as_me:10849: result: $ac_cv_type_bits16_t" >&5
 echo "${ECHO_T}$ac_cv_type_bits16_t" >&6
 if test $ac_cv_type_bits16_t = yes; then
   :
@@ -10006,13 +10859,13 @@ EOF
 fi
 
 else
-  echo "$as_me:10009: checking for bits16_t" >&5
+  echo "$as_me:10862: checking for bits16_t" >&5
 echo $ECHO_N "checking for bits16_t... $ECHO_C" >&6
 if test "${ac_cv_type_bits16_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10015 "configure"
+#line 10868 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10027,16 +10880,16 @@ if (sizeof (bits16_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10030: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10883: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10033: \$? = $ac_status" >&5
+  echo "$as_me:10886: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10036: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10889: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10039: \$? = $ac_status" >&5
+  echo "$as_me:10892: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_bits16_t=yes
 else
@@ -10046,7 +10899,7 @@ ac_cv_type_bits16_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10049: result: $ac_cv_type_bits16_t" >&5
+echo "$as_me:10902: result: $ac_cv_type_bits16_t" >&5
 echo "${ECHO_T}$ac_cv_type_bits16_t" >&6
 if test $ac_cv_type_bits16_t = yes; then
   :
 fi
 
 if test "$ac_cv_sizeof_short" = 2; then
-  echo "$as_me:10064: checking for u_bits16_t" >&5
+  echo "$as_me:10917: checking for u_bits16_t" >&5
 echo $ECHO_N "checking for u_bits16_t... $ECHO_C" >&6
 if test "${ac_cv_type_u_bits16_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10070 "configure"
+#line 10923 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10082,16 +10935,16 @@ if (sizeof (u_bits16_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10085: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10938: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10088: \$? = $ac_status" >&5
+  echo "$as_me:10941: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10091: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10944: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10094: \$? = $ac_status" >&5
+  echo "$as_me:10947: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_u_bits16_t=yes
 else
@@ -10101,7 +10954,7 @@ ac_cv_type_u_bits16_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10104: result: $ac_cv_type_u_bits16_t" >&5
+echo "$as_me:10957: result: $ac_cv_type_u_bits16_t" >&5
 echo "${ECHO_T}$ac_cv_type_u_bits16_t" >&6
 if test $ac_cv_type_u_bits16_t = yes; then
   :
@@ -10114,13 +10967,13 @@ EOF
 fi
 
 elif test "$ac_cv_sizeof_char" = 2; then
-  echo "$as_me:10117: checking for u_bits16_t" >&5
+  echo "$as_me:10970: checking for u_bits16_t" >&5
 echo $ECHO_N "checking for u_bits16_t... $ECHO_C" >&6
 if test "${ac_cv_type_u_bits16_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10123 "configure"
+#line 10976 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10135,16 +10988,16 @@ if (sizeof (u_bits16_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10138: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:10991: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10141: \$? = $ac_status" >&5
+  echo "$as_me:10994: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10144: \"$ac_try\"") >&5
+  { (eval echo "$as_me:10997: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10147: \$? = $ac_status" >&5
+  echo "$as_me:11000: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_u_bits16_t=yes
 else
@@ -10154,7 +11007,7 @@ ac_cv_type_u_bits16_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10157: result: $ac_cv_type_u_bits16_t" >&5
+echo "$as_me:11010: result: $ac_cv_type_u_bits16_t" >&5
 echo "${ECHO_T}$ac_cv_type_u_bits16_t" >&6
 if test $ac_cv_type_u_bits16_t = yes; then
   :
@@ -10167,13 +11020,13 @@ EOF
 fi
 
 else
-  echo "$as_me:10170: checking for u_bits16_t" >&5
+  echo "$as_me:11023: checking for u_bits16_t" >&5
 echo $ECHO_N "checking for u_bits16_t... $ECHO_C" >&6
 if test "${ac_cv_type_u_bits16_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10176 "configure"
+#line 11029 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10188,16 +11041,16 @@ if (sizeof (u_bits16_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10191: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:11044: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10194: \$? = $ac_status" >&5
+  echo "$as_me:11047: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10197: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11050: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10200: \$? = $ac_status" >&5
+  echo "$as_me:11053: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_u_bits16_t=yes
 else
@@ -10207,7 +11060,7 @@ ac_cv_type_u_bits16_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10210: result: $ac_cv_type_u_bits16_t" >&5
+echo "$as_me:11063: result: $ac_cv_type_u_bits16_t" >&5
 echo "${ECHO_T}$ac_cv_type_u_bits16_t" >&6
 if test $ac_cv_type_u_bits16_t = yes; then
   :
 fi
 
 if test "$ac_cv_sizeof_int" = 4; then
-  echo "$as_me:10225: checking for bits32_t" >&5
+  echo "$as_me:11078: checking for bits32_t" >&5
 echo $ECHO_N "checking for bits32_t... $ECHO_C" >&6
 if test "${ac_cv_type_bits32_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10231 "configure"
+#line 11084 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10243,16 +11096,16 @@ if (sizeof (bits32_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10246: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:11099: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10249: \$? = $ac_status" >&5
+  echo "$as_me:11102: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10252: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11105: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10255: \$? = $ac_status" >&5
+  echo "$as_me:11108: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_bits32_t=yes
 else
@@ -10262,7 +11115,7 @@ ac_cv_type_bits32_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10265: result: $ac_cv_type_bits32_t" >&5
+echo "$as_me:11118: result: $ac_cv_type_bits32_t" >&5
 echo "${ECHO_T}$ac_cv_type_bits32_t" >&6
 if test $ac_cv_type_bits32_t = yes; then
   :
@@ -10275,13 +11128,13 @@ EOF
 fi
 
 elif test "$ac_cv_sizeof_long" = 4; then
-  echo "$as_me:10278: checking for bits32_t" >&5
+  echo "$as_me:11131: checking for bits32_t" >&5
 echo $ECHO_N "checking for bits32_t... $ECHO_C" >&6
 if test "${ac_cv_type_bits32_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10284 "configure"
+#line 11137 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10296,16 +11149,16 @@ if (sizeof (bits32_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10299: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:11152: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10302: \$? = $ac_status" >&5
+  echo "$as_me:11155: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10305: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11158: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10308: \$? = $ac_status" >&5
+  echo "$as_me:11161: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_bits32_t=yes
 else
@@ -10315,7 +11168,7 @@ ac_cv_type_bits32_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10318: result: $ac_cv_type_bits32_t" >&5
+echo "$as_me:11171: result: $ac_cv_type_bits32_t" >&5
 echo "${ECHO_T}$ac_cv_type_bits32_t" >&6
 if test $ac_cv_type_bits32_t = yes; then
   :
@@ -10328,13 +11181,13 @@ EOF
 fi
 
 else
-  echo "$as_me:10331: checking for bits32_t" >&5
+  echo "$as_me:11184: checking for bits32_t" >&5
 echo $ECHO_N "checking for bits32_t... $ECHO_C" >&6
 if test "${ac_cv_type_bits32_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10337 "configure"
+#line 11190 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10349,16 +11202,16 @@ if (sizeof (bits32_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10352: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:11205: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10355: \$? = $ac_status" >&5
+  echo "$as_me:11208: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10358: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11211: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10361: \$? = $ac_status" >&5
+  echo "$as_me:11214: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_bits32_t=yes
 else
@@ -10368,7 +11221,7 @@ ac_cv_type_bits32_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10371: result: $ac_cv_type_bits32_t" >&5
+echo "$as_me:11224: result: $ac_cv_type_bits32_t" >&5
 echo "${ECHO_T}$ac_cv_type_bits32_t" >&6
 if test $ac_cv_type_bits32_t = yes; then
   :
 fi
 
 if test "$ac_cv_sizeof_int" = 4; then
-  echo "$as_me:10386: checking for u_bits32_t" >&5
+  echo "$as_me:11239: checking for u_bits32_t" >&5
 echo $ECHO_N "checking for u_bits32_t... $ECHO_C" >&6
 if test "${ac_cv_type_u_bits32_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10392 "configure"
+#line 11245 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10404,16 +11257,16 @@ if (sizeof (u_bits32_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10407: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:11260: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10410: \$? = $ac_status" >&5
+  echo "$as_me:11263: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10413: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11266: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10416: \$? = $ac_status" >&5
+  echo "$as_me:11269: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_u_bits32_t=yes
 else
@@ -10423,7 +11276,7 @@ ac_cv_type_u_bits32_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10426: result: $ac_cv_type_u_bits32_t" >&5
+echo "$as_me:11279: result: $ac_cv_type_u_bits32_t" >&5
 echo "${ECHO_T}$ac_cv_type_u_bits32_t" >&6
 if test $ac_cv_type_u_bits32_t = yes; then
   :
@@ -10436,13 +11289,13 @@ EOF
 fi
 
 elif test "$ac_cv_sizeof_long" = 4; then
-  echo "$as_me:10439: checking for u_bits32_t" >&5
+  echo "$as_me:11292: checking for u_bits32_t" >&5
 echo $ECHO_N "checking for u_bits32_t... $ECHO_C" >&6
 if test "${ac_cv_type_u_bits32_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10445 "configure"
+#line 11298 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10457,16 +11310,16 @@ if (sizeof (u_bits32_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10460: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:11313: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10463: \$? = $ac_status" >&5
+  echo "$as_me:11316: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10466: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11319: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10469: \$? = $ac_status" >&5
+  echo "$as_me:11322: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_u_bits32_t=yes
 else
@@ -10476,7 +11329,7 @@ ac_cv_type_u_bits32_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10479: result: $ac_cv_type_u_bits32_t" >&5
+echo "$as_me:11332: result: $ac_cv_type_u_bits32_t" >&5
 echo "${ECHO_T}$ac_cv_type_u_bits32_t" >&6
 if test $ac_cv_type_u_bits32_t = yes; then
   :
@@ -10489,13 +11342,13 @@ EOF
 fi
 
 else
-  echo "$as_me:10492: checking for u_bits32_t" >&5
+  echo "$as_me:11345: checking for u_bits32_t" >&5
 echo $ECHO_N "checking for u_bits32_t... $ECHO_C" >&6
 if test "${ac_cv_type_u_bits32_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10498 "configure"
+#line 11351 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10510,16 +11363,16 @@ if (sizeof (u_bits32_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10513: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:11366: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10516: \$? = $ac_status" >&5
+  echo "$as_me:11369: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10519: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11372: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10522: \$? = $ac_status" >&5
+  echo "$as_me:11375: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_u_bits32_t=yes
 else
@@ -10529,7 +11382,7 @@ ac_cv_type_u_bits32_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10532: result: $ac_cv_type_u_bits32_t" >&5
+echo "$as_me:11385: result: $ac_cv_type_u_bits32_t" >&5
 echo "${ECHO_T}$ac_cv_type_u_bits32_t" >&6
 if test $ac_cv_type_u_bits32_t = yes; then
   :
 fi
 
 if test "$ac_cv_sizeof_char_p" = 8; then
-  echo "$as_me:10547: checking for bits64_t" >&5
+  echo "$as_me:11400: checking for bits64_t" >&5
 echo $ECHO_N "checking for bits64_t... $ECHO_C" >&6
 if test "${ac_cv_type_bits64_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10553 "configure"
+#line 11406 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10565,16 +11418,16 @@ if (sizeof (bits64_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10568: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:11421: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10571: \$? = $ac_status" >&5
+  echo "$as_me:11424: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10574: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11427: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10577: \$? = $ac_status" >&5
+  echo "$as_me:11430: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_bits64_t=yes
 else
@@ -10584,7 +11437,7 @@ ac_cv_type_bits64_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10587: result: $ac_cv_type_bits64_t" >&5
+echo "$as_me:11440: result: $ac_cv_type_bits64_t" >&5
 echo "${ECHO_T}$ac_cv_type_bits64_t" >&6
 if test $ac_cv_type_bits64_t = yes; then
   :
@@ -10597,13 +11450,13 @@ EOF
 fi
 
 elif test "$ac_cv_sizeof_double" = 8; then
-  echo "$as_me:10600: checking for bits64_t" >&5
+  echo "$as_me:11453: checking for bits64_t" >&5
 echo $ECHO_N "checking for bits64_t... $ECHO_C" >&6
 if test "${ac_cv_type_bits64_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10606 "configure"
+#line 11459 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10618,16 +11471,16 @@ if (sizeof (bits64_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10621: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:11474: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10624: \$? = $ac_status" >&5
+  echo "$as_me:11477: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10627: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11480: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10630: \$? = $ac_status" >&5
+  echo "$as_me:11483: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_bits64_t=yes
 else
@@ -10637,7 +11490,7 @@ ac_cv_type_bits64_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10640: result: $ac_cv_type_bits64_t" >&5
+echo "$as_me:11493: result: $ac_cv_type_bits64_t" >&5
 echo "${ECHO_T}$ac_cv_type_bits64_t" >&6
 if test $ac_cv_type_bits64_t = yes; then
   :
@@ -10650,13 +11503,13 @@ EOF
 fi
 
 elif test -n "$ac_cv_type_long_long" && test "$ac_cv_sizeof_long_long" = 8; then
-  echo "$as_me:10653: checking for bits64_t" >&5
+  echo "$as_me:11506: checking for bits64_t" >&5
 echo $ECHO_N "checking for bits64_t... $ECHO_C" >&6
 if test "${ac_cv_type_bits64_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10659 "configure"
+#line 11512 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10671,16 +11524,16 @@ if (sizeof (bits64_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10674: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:11527: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10677: \$? = $ac_status" >&5
+  echo "$as_me:11530: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10680: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11533: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10683: \$? = $ac_status" >&5
+  echo "$as_me:11536: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_bits64_t=yes
 else
@@ -10690,7 +11543,7 @@ ac_cv_type_bits64_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10693: result: $ac_cv_type_bits64_t" >&5
+echo "$as_me:11546: result: $ac_cv_type_bits64_t" >&5
 echo "${ECHO_T}$ac_cv_type_bits64_t" >&6
 if test $ac_cv_type_bits64_t = yes; then
   :
@@ -10703,13 +11556,13 @@ EOF
 fi
 
 elif test "$ac_cv_sizeof_long" = 8; then
-  echo "$as_me:10706: checking for bits64_t" >&5
+  echo "$as_me:11559: checking for bits64_t" >&5
 echo $ECHO_N "checking for bits64_t... $ECHO_C" >&6
 if test "${ac_cv_type_bits64_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10712 "configure"
+#line 11565 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10724,16 +11577,16 @@ if (sizeof (bits64_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10727: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:11580: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10730: \$? = $ac_status" >&5
+  echo "$as_me:11583: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10733: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11586: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10736: \$? = $ac_status" >&5
+  echo "$as_me:11589: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_bits64_t=yes
 else
@@ -10743,7 +11596,7 @@ ac_cv_type_bits64_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10746: result: $ac_cv_type_bits64_t" >&5
+echo "$as_me:11599: result: $ac_cv_type_bits64_t" >&5
 echo "${ECHO_T}$ac_cv_type_bits64_t" >&6
 if test $ac_cv_type_bits64_t = yes; then
   :
@@ -10756,13 +11609,13 @@ EOF
 fi
 
 else
-  echo "$as_me:10759: checking for bits64_t" >&5
+  echo "$as_me:11612: checking for bits64_t" >&5
 echo $ECHO_N "checking for bits64_t... $ECHO_C" >&6
 if test "${ac_cv_type_bits64_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10765 "configure"
+#line 11618 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10777,16 +11630,16 @@ if (sizeof (bits64_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10780: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:11633: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10783: \$? = $ac_status" >&5
+  echo "$as_me:11636: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10786: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11639: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10789: \$? = $ac_status" >&5
+  echo "$as_me:11642: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_bits64_t=yes
 else
@@ -10796,7 +11649,7 @@ ac_cv_type_bits64_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10799: result: $ac_cv_type_bits64_t" >&5
+echo "$as_me:11652: result: $ac_cv_type_bits64_t" >&5
 echo "${ECHO_T}$ac_cv_type_bits64_t" >&6
 if test $ac_cv_type_bits64_t = yes; then
   :
 fi
 
 if test "$ac_cv_sizeof_int" = "$ac_cv_sizeof_char_p"; then
-  echo "$as_me:10814: checking for ptrdiff_t" >&5
+  echo "$as_me:11667: checking for ptrdiff_t" >&5
 echo $ECHO_N "checking for ptrdiff_t... $ECHO_C" >&6
 if test "${ac_cv_type_ptrdiff_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10820 "configure"
+#line 11673 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10832,16 +11685,16 @@ if (sizeof (ptrdiff_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10835: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:11688: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10838: \$? = $ac_status" >&5
+  echo "$as_me:11691: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10841: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11694: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10844: \$? = $ac_status" >&5
+  echo "$as_me:11697: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_ptrdiff_t=yes
 else
@@ -10851,7 +11704,7 @@ ac_cv_type_ptrdiff_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10854: result: $ac_cv_type_ptrdiff_t" >&5
+echo "$as_me:11707: result: $ac_cv_type_ptrdiff_t" >&5
 echo "${ECHO_T}$ac_cv_type_ptrdiff_t" >&6
 if test $ac_cv_type_ptrdiff_t = yes; then
   :
@@ -10864,13 +11717,13 @@ EOF
 fi
 
 elif test "$ac_cv_sizeof_long" = "$ac_cv_sizeof_char_p"; then
-  echo "$as_me:10867: checking for ptrdiff_t" >&5
+  echo "$as_me:11720: checking for ptrdiff_t" >&5
 echo $ECHO_N "checking for ptrdiff_t... $ECHO_C" >&6
 if test "${ac_cv_type_ptrdiff_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10873 "configure"
+#line 11726 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10885,16 +11738,16 @@ if (sizeof (ptrdiff_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10888: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:11741: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10891: \$? = $ac_status" >&5
+  echo "$as_me:11744: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10894: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11747: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10897: \$? = $ac_status" >&5
+  echo "$as_me:11750: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_ptrdiff_t=yes
 else
@@ -10904,7 +11757,7 @@ ac_cv_type_ptrdiff_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10907: result: $ac_cv_type_ptrdiff_t" >&5
+echo "$as_me:11760: result: $ac_cv_type_ptrdiff_t" >&5
 echo "${ECHO_T}$ac_cv_type_ptrdiff_t" >&6
 if test $ac_cv_type_ptrdiff_t = yes; then
   :
@@ -10917,13 +11770,13 @@ EOF
 fi
 
 elif test "$ac_cv_type_long_long" = yes && test "$ac_cv_sizeof_long_long" = "$ac_cv_sizeof_char_p"; then
-  echo "$as_me:10920: checking for ptrdiff_t" >&5
+  echo "$as_me:11773: checking for ptrdiff_t" >&5
 echo $ECHO_N "checking for ptrdiff_t... $ECHO_C" >&6
 if test "${ac_cv_type_ptrdiff_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10926 "configure"
+#line 11779 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10938,16 +11791,16 @@ if (sizeof (ptrdiff_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10941: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:11794: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10944: \$? = $ac_status" >&5
+  echo "$as_me:11797: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:10947: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11800: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:10950: \$? = $ac_status" >&5
+  echo "$as_me:11803: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_ptrdiff_t=yes
 else
@@ -10957,7 +11810,7 @@ ac_cv_type_ptrdiff_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:10960: result: $ac_cv_type_ptrdiff_t" >&5
+echo "$as_me:11813: result: $ac_cv_type_ptrdiff_t" >&5
 echo "${ECHO_T}$ac_cv_type_ptrdiff_t" >&6
 if test $ac_cv_type_ptrdiff_t = yes; then
   :
@@ -10970,13 +11823,13 @@ EOF
 fi
 
 else
-  echo "$as_me:10973: checking for ptrdiff_t" >&5
+  echo "$as_me:11826: checking for ptrdiff_t" >&5
 echo $ECHO_N "checking for ptrdiff_t... $ECHO_C" >&6
 if test "${ac_cv_type_ptrdiff_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 10979 "configure"
+#line 11832 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -10991,16 +11844,16 @@ if (sizeof (ptrdiff_t))
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:10994: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:11847: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:10997: \$? = $ac_status" >&5
+  echo "$as_me:11850: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:11000: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11853: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:11003: \$? = $ac_status" >&5
+  echo "$as_me:11856: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_type_ptrdiff_t=yes
 else
@@ -11010,7 +11863,7 @@ ac_cv_type_ptrdiff_t=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:11013: result: $ac_cv_type_ptrdiff_t" >&5
+echo "$as_me:11866: result: $ac_cv_type_ptrdiff_t" >&5
 echo "${ECHO_T}$ac_cv_type_ptrdiff_t" >&6
 if test $ac_cv_type_ptrdiff_t = yes; then
   :
 
 fi
 
-echo "$as_me:11027: checking whether stat file-mode macros are broken" >&5
+echo "$as_me:11880: checking whether stat file-mode macros are broken" >&5
 echo $ECHO_N "checking whether stat file-mode macros are broken... $ECHO_C" >&6
 if test "${ac_cv_header_stat_broken+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 11033 "configure"
+#line 11886 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -11069,7 +11922,7 @@ fi
 rm -f conftest*
 
 fi
-echo "$as_me:11072: result: $ac_cv_header_stat_broken" >&5
+echo "$as_me:11925: result: $ac_cv_header_stat_broken" >&5
 echo "${ECHO_T}$ac_cv_header_stat_broken" >&6
 if test $ac_cv_header_stat_broken = yes; then
 
@@ -11079,7 +11932,7 @@ EOF
 
 fi
 
-echo "$as_me:11082: checking whether #! works in shell scripts" >&5
+echo "$as_me:11935: checking whether #! works in shell scripts" >&5
 echo $ECHO_N "checking whether #! works in shell scripts... $ECHO_C" >&6
 if test "${ac_cv_sys_interpreter+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -11096,7 +11949,7 @@ else
 fi
 rm -f conftest
 fi
-echo "$as_me:11099: result: $ac_cv_sys_interpreter" >&5
+echo "$as_me:11952: result: $ac_cv_sys_interpreter" >&5
 echo "${ECHO_T}$ac_cv_sys_interpreter" >&6
 interpval=$ac_cv_sys_interpreter
 
@@ -11108,13 +11961,13 @@ EOF
 fi
 
 if test "$ac_cv_func_lstat" = "no"; then
-echo "$as_me:11111: checking for lstat" >&5
+echo "$as_me:11964: checking for lstat" >&5
 echo $ECHO_N "checking for lstat... $ECHO_C" >&6
 if test "${bash_cv_func_lstat+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 11117 "configure"
+#line 11970 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -11129,16 +11982,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:11132: \"$ac_link\"") >&5
+if { (eval echo "$as_me:11985: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:11135: \$? = $ac_status" >&5
+  echo "$as_me:11988: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:11138: \"$ac_try\"") >&5
+  { (eval echo "$as_me:11991: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:11141: \$? = $ac_status" >&5
+  echo "$as_me:11994: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_func_lstat=yes
 else
@@ -11148,7 +12001,7 @@ bash_cv_func_lstat=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:11151: result: $bash_cv_func_lstat" >&5
+echo "$as_me:12004: result: $bash_cv_func_lstat" >&5
 echo "${ECHO_T}$bash_cv_func_lstat" >&6
 if test $bash_cv_func_lstat = yes; then
   cat >>confdefs.h <<\EOF
 
 fi
 
-echo "$as_me:11162: checking if dup2 fails to clear the close-on-exec flag" >&5
+echo "$as_me:12015: checking if dup2 fails to clear the close-on-exec flag" >&5
 echo $ECHO_N "checking if dup2 fails to clear the close-on-exec flag... $ECHO_C" >&6
 if test "${bash_cv_dup2_broken+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test "$cross_compiling" = yes; then
-  { echo "$as_me:11168: WARNING: cannot check dup2 if cross compiling -- defaulting to no" >&5
+  { echo "$as_me:12021: WARNING: cannot check dup2 if cross compiling -- defaulting to no" >&5
 echo "$as_me: WARNING: cannot check dup2 if cross compiling -- defaulting to no" >&2;}
      bash_cv_dup2_broken=no
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 11173 "configure"
+#line 12026 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -11191,15 +12044,15 @@ main()
 
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:11194: \"$ac_link\"") >&5
+if { (eval echo "$as_me:12047: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:11197: \$? = $ac_status" >&5
+  echo "$as_me:12050: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:11199: \"$ac_try\"") >&5
+  { (eval echo "$as_me:12052: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:11202: \$? = $ac_status" >&5
+  echo "$as_me:12055: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_dup2_broken=yes
 else
@@ -11213,7 +12066,7 @@ fi
 
 fi
 
-echo "$as_me:11216: result: $bash_cv_dup2_broken" >&5
+echo "$as_me:12069: result: $bash_cv_dup2_broken" >&5
 echo "${ECHO_T}$bash_cv_dup2_broken" >&6
 if test $bash_cv_dup2_broken = yes; then
 cat >>confdefs.h <<\EOF
@@ -11222,18 +12075,18 @@ EOF
 
 fi
 
-echo "$as_me:11225: checking whether pgrps need synchronization" >&5
+echo "$as_me:12078: checking whether pgrps need synchronization" >&5
 echo $ECHO_N "checking whether pgrps need synchronization... $ECHO_C" >&6
 if test "${bash_cv_pgrp_pipe+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test "$cross_compiling" = yes; then
-  { echo "$as_me:11231: WARNING: cannot check pgrp synchronization if cross compiling -- defaulting to no" >&5
+  { echo "$as_me:12084: WARNING: cannot check pgrp synchronization if cross compiling -- defaulting to no" >&5
 echo "$as_me: WARNING: cannot check pgrp synchronization if cross compiling -- defaulting to no" >&2;}
     bash_cv_pgrp_pipe=no
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 11236 "configure"
+#line 12089 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_UNISTD_H
@@ -11286,15 +12139,15 @@ main()
 
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:11289: \"$ac_link\"") >&5
+if { (eval echo "$as_me:12142: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:11292: \$? = $ac_status" >&5
+  echo "$as_me:12145: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:11294: \"$ac_try\"") >&5
+  { (eval echo "$as_me:12147: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:11297: \$? = $ac_status" >&5
+  echo "$as_me:12150: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_pgrp_pipe=no
 else
@@ -11308,7 +12161,7 @@ fi
 
 fi
 
-echo "$as_me:11311: result: $bash_cv_pgrp_pipe" >&5
+echo "$as_me:12164: result: $bash_cv_pgrp_pipe" >&5
 echo "${ECHO_T}$bash_cv_pgrp_pipe" >&6
 if test $bash_cv_pgrp_pipe = yes; then
 cat >>confdefs.h <<\EOF
@@ -11317,14 +12170,14 @@ EOF
 
 fi
 
-echo "$as_me:11320: checking for type of signal functions" >&5
+echo "$as_me:12173: checking for type of signal functions" >&5
 echo $ECHO_N "checking for type of signal functions... $ECHO_C" >&6
 if test "${bash_cv_signal_vintage+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
 
   cat >conftest.$ac_ext <<_ACEOF
-#line 11327 "configure"
+#line 12180 "configure"
 #include "confdefs.h"
 #include <signal.h>
 int
@@ -11342,16 +12195,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:11345: \"$ac_link\"") >&5
+if { (eval echo "$as_me:12198: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:11348: \$? = $ac_status" >&5
+  echo "$as_me:12201: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:11351: \"$ac_try\"") >&5
+  { (eval echo "$as_me:12204: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:11354: \$? = $ac_status" >&5
+  echo "$as_me:12207: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_signal_vintage=posix
 else
@@ -11359,7 +12212,7 @@ else
 cat conftest.$ac_ext >&5
 
     cat >conftest.$ac_ext <<_ACEOF
-#line 11362 "configure"
+#line 12215 "configure"
 #include "confdefs.h"
 #include <signal.h>
 int
@@ -11374,16 +12227,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:11377: \"$ac_link\"") >&5
+if { (eval echo "$as_me:12230: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:11380: \$? = $ac_status" >&5
+  echo "$as_me:12233: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:11383: \"$ac_try\"") >&5
+  { (eval echo "$as_me:12236: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:11386: \$? = $ac_status" >&5
+  echo "$as_me:12239: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_signal_vintage=4.2bsd
 else
@@ -11391,7 +12244,7 @@ else
 cat conftest.$ac_ext >&5
 
       cat >conftest.$ac_ext <<_ACEOF
-#line 11394 "configure"
+#line 12247 "configure"
 #include "confdefs.h"
 
        #include <signal.h>
@@ -11409,16 +12262,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:11412: \"$ac_link\"") >&5
+if { (eval echo "$as_me:12265: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:11415: \$? = $ac_status" >&5
+  echo "$as_me:12268: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:11418: \"$ac_try\"") >&5
+  { (eval echo "$as_me:12271: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:11421: \$? = $ac_status" >&5
+  echo "$as_me:12274: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_signal_vintage=svr3
 else
@@ -11437,7 +12290,7 @@ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 
 fi
 
-echo "$as_me:11440: result: $bash_cv_signal_vintage" >&5
+echo "$as_me:12293: result: $bash_cv_signal_vintage" >&5
 echo "${ECHO_T}$bash_cv_signal_vintage" >&6
 if test "$bash_cv_signal_vintage" = posix; then
 cat >>confdefs.h <<\EOF
@@ -11456,13 +12309,13 @@ EOF
 
 fi
 
-echo "$as_me:11459: checking for sys_errlist and sys_nerr" >&5
+echo "$as_me:12312: checking for sys_errlist and sys_nerr" >&5
 echo $ECHO_N "checking for sys_errlist and sys_nerr... $ECHO_C" >&6
 if test "${bash_cv_sys_errlist+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 11465 "configure"
+#line 12318 "configure"
 #include "confdefs.h"
 #include <errno.h>
 int
@@ -11476,16 +12329,16 @@ extern char *sys_errlist[];
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:11479: \"$ac_link\"") >&5
+if { (eval echo "$as_me:12332: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:11482: \$? = $ac_status" >&5
+  echo "$as_me:12335: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:11485: \"$ac_try\"") >&5
+  { (eval echo "$as_me:12338: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:11488: \$? = $ac_status" >&5
+  echo "$as_me:12341: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_sys_errlist=yes
 else
@@ -11495,7 +12348,7 @@ bash_cv_sys_errlist=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:11498: result: $bash_cv_sys_errlist" >&5
+echo "$as_me:12351: result: $bash_cv_sys_errlist" >&5
 echo "${ECHO_T}$bash_cv_sys_errlist" >&6
 if test $bash_cv_sys_errlist = yes; then
 cat >>confdefs.h <<\EOF
@@ -11504,18 +12357,18 @@ EOF
 
 fi
 
-echo "$as_me:11507: checking for sys_siglist in system C library" >&5
+echo "$as_me:12360: checking for sys_siglist in system C library" >&5
 echo $ECHO_N "checking for sys_siglist in system C library... $ECHO_C" >&6
 if test "${bash_cv_sys_siglist+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test "$cross_compiling" = yes; then
-  { echo "$as_me:11513: WARNING: cannot check for sys_siglist if cross compiling -- defaulting to no" >&5
+  { echo "$as_me:12366: WARNING: cannot check for sys_siglist if cross compiling -- defaulting to no" >&5
 echo "$as_me: WARNING: cannot check for sys_siglist if cross compiling -- defaulting to no" >&2;}
         bash_cv_sys_siglist=no
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 11518 "configure"
+#line 12371 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -11533,15 +12386,15 @@ exit(msg == 0);
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:11536: \"$ac_link\"") >&5
+if { (eval echo "$as_me:12389: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:11539: \$? = $ac_status" >&5
+  echo "$as_me:12392: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:11541: \"$ac_try\"") >&5
+  { (eval echo "$as_me:12394: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:11544: \$? = $ac_status" >&5
+  echo "$as_me:12397: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_sys_siglist=yes
 else
@@ -11554,7 +12407,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
 
-echo "$as_me:11557: result: $bash_cv_sys_siglist" >&5
+echo "$as_me:12410: result: $bash_cv_sys_siglist" >&5
 echo "${ECHO_T}$bash_cv_sys_siglist" >&6
 if test $bash_cv_sys_siglist = yes; then
 cat >>confdefs.h <<\EOF
@@ -11563,13 +12416,13 @@ EOF
 
 fi
 
-echo "$as_me:11566: checking for _sys_siglist in signal.h or unistd.h" >&5
+echo "$as_me:12419: checking for _sys_siglist in signal.h or unistd.h" >&5
 echo $ECHO_N "checking for _sys_siglist in signal.h or unistd.h... $ECHO_C" >&6
 if test "${bash_cv_decl_under_sys_siglist+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 11572 "configure"
+#line 12425 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -11586,16 +12439,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:11589: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:12442: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:11592: \$? = $ac_status" >&5
+  echo "$as_me:12445: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:11595: \"$ac_try\"") >&5
+  { (eval echo "$as_me:12448: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:11598: \$? = $ac_status" >&5
+  echo "$as_me:12451: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_decl_under_sys_siglist=yes
 else
@@ -11605,7 +12458,7 @@ bash_cv_decl_under_sys_siglist=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:11608: result: $bash_cv_decl_under_sys_siglist" >&5
+echo "$as_me:12461: result: $bash_cv_decl_under_sys_siglist" >&5
 echo "${ECHO_T}$bash_cv_decl_under_sys_siglist" >&6
 if test $bash_cv_decl_under_sys_siglist = yes; then
 cat >>confdefs.h <<\EOF
@@ -11614,18 +12467,18 @@ EOF
 
 fi
 
-echo "$as_me:11617: checking for _sys_siglist in system C library" >&5
+echo "$as_me:12470: checking for _sys_siglist in system C library" >&5
 echo $ECHO_N "checking for _sys_siglist in system C library... $ECHO_C" >&6
 if test "${bash_cv_under_sys_siglist+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test "$cross_compiling" = yes; then
-  { echo "$as_me:11623: WARNING: cannot check for _sys_siglist if cross compiling -- defaulting to no" >&5
+  { echo "$as_me:12476: WARNING: cannot check for _sys_siglist if cross compiling -- defaulting to no" >&5
 echo "$as_me: WARNING: cannot check for _sys_siglist if cross compiling -- defaulting to no" >&2;}
         bash_cv_under_sys_siglist=no
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 11628 "configure"
+#line 12481 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -11643,15 +12496,15 @@ exit(msg == 0);
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:11646: \"$ac_link\"") >&5
+if { (eval echo "$as_me:12499: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:11649: \$? = $ac_status" >&5
+  echo "$as_me:12502: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:11651: \"$ac_try\"") >&5
+  { (eval echo "$as_me:12504: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:11654: \$? = $ac_status" >&5
+  echo "$as_me:12507: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_under_sys_siglist=yes
 else
@@ -11664,7 +12517,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
 
-echo "$as_me:11667: result: $bash_cv_under_sys_siglist" >&5
+echo "$as_me:12520: result: $bash_cv_under_sys_siglist" >&5
 echo "${ECHO_T}$bash_cv_under_sys_siglist" >&6
 if test $bash_cv_under_sys_siglist = yes; then
 cat >>confdefs.h <<\EOF
@@ -11673,13 +12526,13 @@ EOF
 
 fi
 
-echo "$as_me:11676: checking whether signal handlers are of type void" >&5
+echo "$as_me:12529: checking whether signal handlers are of type void" >&5
 echo $ECHO_N "checking whether signal handlers are of type void... $ECHO_C" >&6
 if test "${bash_cv_void_sighandler+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 11682 "configure"
+#line 12535 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <signal.h>
@@ -11699,16 +12552,16 @@ int i;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:11702: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:12555: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:11705: \$? = $ac_status" >&5
+  echo "$as_me:12558: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:11708: \"$ac_try\"") >&5
+  { (eval echo "$as_me:12561: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:11711: \$? = $ac_status" >&5
+  echo "$as_me:12564: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_void_sighandler=yes
 else
@@ -11718,7 +12571,7 @@ bash_cv_void_sighandler=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:11721: result: $bash_cv_void_sighandler" >&5
+echo "$as_me:12574: result: $bash_cv_void_sighandler" >&5
 echo "${ECHO_T}$bash_cv_void_sighandler" >&6
 if test $bash_cv_void_sighandler = yes; then
 cat >>confdefs.h <<\EOF
@@ -11727,13 +12580,13 @@ EOF
 
 fi
 
-echo "$as_me:11730: checking for clock_t" >&5
+echo "$as_me:12583: checking for clock_t" >&5
 echo $ECHO_N "checking for clock_t... $ECHO_C" >&6
 if test "${bash_cv_type_clock_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 11736 "configure"
+#line 12589 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -11756,7 +12609,7 @@ rm -f conftest*
 
 fi
 
-echo "$as_me:11759: result: $bash_cv_type_clock_t" >&5
+echo "$as_me:12612: result: $bash_cv_type_clock_t" >&5
 echo "${ECHO_T}$bash_cv_type_clock_t" >&6
 
 if test $bash_cv_type_clock_t = no; then
@@ -11766,13 +12619,13 @@ EOF
 
 fi
 
-echo "$as_me:11769: checking for sigset_t" >&5
+echo "$as_me:12622: checking for sigset_t" >&5
 echo $ECHO_N "checking for sigset_t... $ECHO_C" >&6
 if test "${bash_cv_type_sigset_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 11775 "configure"
+#line 12628 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -11795,7 +12648,7 @@ rm -f conftest*
 
 fi
 
-echo "$as_me:11798: result: $bash_cv_type_sigset_t" >&5
+echo "$as_me:12651: result: $bash_cv_type_sigset_t" >&5
 echo "${ECHO_T}$bash_cv_type_sigset_t" >&6
 
 if test $bash_cv_type_sigset_t = no; then
@@ -11805,13 +12658,13 @@ EOF
 
 fi
 
-echo "$as_me:11808: checking for quad_t" >&5
+echo "$as_me:12661: checking for quad_t" >&5
 echo $ECHO_N "checking for quad_t... $ECHO_C" >&6
 if test "${bash_cv_type_quad_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 11814 "configure"
+#line 12667 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -11833,7 +12686,7 @@ rm -f conftest*
 
 fi
 
-echo "$as_me:11836: result: $bash_cv_type_quad_t" >&5
+echo "$as_me:12689: result: $bash_cv_type_quad_t" >&5
 echo "${ECHO_T}$bash_cv_type_quad_t" >&6
 if test $bash_cv_type_quad_t = yes; then
        cat >>confdefs.h <<\EOF
@@ -11848,13 +12701,13 @@ EOF
 
 fi
 
-echo "$as_me:11851: checking for intmax_t" >&5
+echo "$as_me:12704: checking for intmax_t" >&5
 echo $ECHO_N "checking for intmax_t... $ECHO_C" >&6
 if test "${bash_cv_type_intmax_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 11857 "configure"
+#line 12710 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -11876,7 +12729,7 @@ rm -f conftest*
 
 fi
 
-echo "$as_me:11879: result: $bash_cv_type_intmax_t" >&5
+echo "$as_me:12732: result: $bash_cv_type_intmax_t" >&5
 echo "${ECHO_T}$bash_cv_type_intmax_t" >&6
 
 if test $bash_cv_type_intmax_t = no; then
@@ -11886,13 +12739,13 @@ EOF
 
 fi
 
-echo "$as_me:11889: checking for uintmax_t" >&5
+echo "$as_me:12742: checking for uintmax_t" >&5
 echo $ECHO_N "checking for uintmax_t... $ECHO_C" >&6
 if test "${bash_cv_type_uintmax_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 11895 "configure"
+#line 12748 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -11914,7 +12767,7 @@ rm -f conftest*
 
 fi
 
-echo "$as_me:11917: result: $bash_cv_type_uintmax_t" >&5
+echo "$as_me:12770: result: $bash_cv_type_uintmax_t" >&5
 echo "${ECHO_T}$bash_cv_type_uintmax_t" >&6
 
 if test $bash_cv_type_uintmax_t = no; then
 
 if test "$ac_cv_header_sys_socket_h" = "yes"; then
 
-echo "$as_me:11929: checking for socklen_t" >&5
+echo "$as_me:12782: checking for socklen_t" >&5
 echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6
 if test "${bash_cv_type_socklen_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 11935 "configure"
+#line 12788 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -11955,7 +12808,7 @@ rm -f conftest*
 
 fi
 
-echo "$as_me:11958: result: $bash_cv_type_socklen_t" >&5
+echo "$as_me:12811: result: $bash_cv_type_socklen_t" >&5
 echo "${ECHO_T}$bash_cv_type_socklen_t" >&6
 if test $bash_cv_type_socklen_t = yes; then
        cat >>confdefs.h <<\EOF
@@ -11971,13 +12824,13 @@ EOF
 fi
 
 fi
-echo "$as_me:11974: checking for size and type of struct rlimit fields" >&5
+echo "$as_me:12827: checking for size and type of struct rlimit fields" >&5
 echo $ECHO_N "checking for size and type of struct rlimit fields... $ECHO_C" >&6
 if test "${bash_cv_type_rlimit+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 11980 "configure"
+#line 12833 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/resource.h>
@@ -11990,16 +12843,16 @@ rlim_t xxx;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:11993: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:12846: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:11996: \$? = $ac_status" >&5
+  echo "$as_me:12849: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:11999: \"$ac_try\"") >&5
+  { (eval echo "$as_me:12852: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:12002: \$? = $ac_status" >&5
+  echo "$as_me:12855: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_type_rlimit=rlim_t
 else
@@ -12007,12 +12860,12 @@ else
 cat conftest.$ac_ext >&5
 
 if test "$cross_compiling" = yes; then
-  { echo "$as_me:12010: WARNING: cannot check quad_t if cross compiling -- defaulting to long" >&5
+  { echo "$as_me:12863: WARNING: cannot check quad_t if cross compiling -- defaulting to long" >&5
 echo "$as_me: WARNING: cannot check quad_t if cross compiling -- defaulting to long" >&2;}
          bash_cv_type_rlimit=long
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 12015 "configure"
+#line 12868 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -12029,15 +12882,15 @@ main()
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:12032: \"$ac_link\"") >&5
+if { (eval echo "$as_me:12885: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:12035: \$? = $ac_status" >&5
+  echo "$as_me:12888: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:12037: \"$ac_try\"") >&5
+  { (eval echo "$as_me:12890: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:12040: \$? = $ac_status" >&5
+  echo "$as_me:12893: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_type_rlimit=quad_t
 else
@@ -12053,7 +12906,7 @@ rm -f conftest.$ac_objext conftest.$ac_ext
 
 fi
 
-echo "$as_me:12056: result: $bash_cv_type_rlimit" >&5
+echo "$as_me:12909: result: $bash_cv_type_rlimit" >&5
 echo "${ECHO_T}$bash_cv_type_rlimit" >&6
 if test $bash_cv_type_rlimit = quad_t; then
 cat >>confdefs.h <<\EOF
@@ -12067,13 +12920,13 @@ EOF
 
 fi
 
-echo "$as_me:12070: checking for struct termios.c_line" >&5
+echo "$as_me:12923: checking for struct termios.c_line" >&5
 echo $ECHO_N "checking for struct termios.c_line... $ECHO_C" >&6
 if test "${ac_cv_member_struct_termios_c_line+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 12076 "configure"
+#line 12929 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -12090,16 +12943,16 @@ return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:12093: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:12946: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:12096: \$? = $ac_status" >&5
+  echo "$as_me:12949: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:12099: \"$ac_try\"") >&5
+  { (eval echo "$as_me:12952: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:12102: \$? = $ac_status" >&5
+  echo "$as_me:12955: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_member_struct_termios_c_line=yes
 else
@@ -12109,7 +12962,7 @@ ac_cv_member_struct_termios_c_line=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:12112: result: $ac_cv_member_struct_termios_c_line" >&5
+echo "$as_me:12965: result: $ac_cv_member_struct_termios_c_line" >&5
 echo "${ECHO_T}$ac_cv_member_struct_termios_c_line" >&6
 if test $ac_cv_member_struct_termios_c_line = yes; then
   cat >>confdefs.h <<\EOF
@@ -12118,13 +12971,13 @@ EOF
 
 fi
 
-echo "$as_me:12121: checking for struct termio.c_line" >&5
+echo "$as_me:12974: checking for struct termio.c_line" >&5
 echo $ECHO_N "checking for struct termio.c_line... $ECHO_C" >&6
 if test "${ac_cv_member_struct_termio_c_line+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 12127 "configure"
+#line 12980 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -12141,16 +12994,16 @@ return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:12144: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:12997: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:12147: \$? = $ac_status" >&5
+  echo "$as_me:13000: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:12150: \"$ac_try\"") >&5
+  { (eval echo "$as_me:13003: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:12153: \$? = $ac_status" >&5
+  echo "$as_me:13006: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_member_struct_termio_c_line=yes
 else
@@ -12160,7 +13013,7 @@ ac_cv_member_struct_termio_c_line=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:12163: result: $ac_cv_member_struct_termio_c_line" >&5
+echo "$as_me:13016: result: $ac_cv_member_struct_termio_c_line" >&5
 echo "${ECHO_T}$ac_cv_member_struct_termio_c_line" >&6
 if test $ac_cv_member_struct_termio_c_line = yes; then
   cat >>confdefs.h <<\EOF
@@ -12169,13 +13022,13 @@ EOF
 
 fi
 
-echo "$as_me:12172: checking if struct dirent has a d_ino member" >&5
+echo "$as_me:13025: checking if struct dirent has a d_ino member" >&5
 echo $ECHO_N "checking if struct dirent has a d_ino member... $ECHO_C" >&6
 if test "${bash_cv_dirent_has_dino+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 12178 "configure"
+#line 13031 "configure"
 #include "confdefs.h"
 
 #include <stdio.h>
@@ -12209,16 +13062,16 @@ struct dirent d; int z; z = d.d_ino;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:12212: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:13065: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:12215: \$? = $ac_status" >&5
+  echo "$as_me:13068: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:12218: \"$ac_try\"") >&5
+  { (eval echo "$as_me:13071: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:12221: \$? = $ac_status" >&5
+  echo "$as_me:13074: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_dirent_has_dino=yes
 else
@@ -12229,7 +13082,7 @@ fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
 
-echo "$as_me:12232: result: $bash_cv_dirent_has_dino" >&5
+echo "$as_me:13085: result: $bash_cv_dirent_has_dino" >&5
 echo "${ECHO_T}$bash_cv_dirent_has_dino" >&6
 if test $bash_cv_dirent_has_dino = yes; then
 cat >>confdefs.h <<\EOF
@@ -12238,13 +13091,13 @@ EOF
 
 fi
 
-echo "$as_me:12241: checking if struct dirent has a d_fileno member" >&5
+echo "$as_me:13094: checking if struct dirent has a d_fileno member" >&5
 echo $ECHO_N "checking if struct dirent has a d_fileno member... $ECHO_C" >&6
 if test "${bash_cv_dirent_has_d_fileno+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 12247 "configure"
+#line 13100 "configure"
 #include "confdefs.h"
 
 #include <stdio.h>
@@ -12278,16 +13131,16 @@ struct dirent d; int z; z = d.d_fileno;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:12281: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:13134: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:12284: \$? = $ac_status" >&5
+  echo "$as_me:13137: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:12287: \"$ac_try\"") >&5
+  { (eval echo "$as_me:13140: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:12290: \$? = $ac_status" >&5
+  echo "$as_me:13143: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_dirent_has_d_fileno=yes
 else
@@ -12298,7 +13151,7 @@ fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
 
-echo "$as_me:12301: result: $bash_cv_dirent_has_d_fileno" >&5
+echo "$as_me:13154: result: $bash_cv_dirent_has_d_fileno" >&5
 echo "${ECHO_T}$bash_cv_dirent_has_d_fileno" >&6
 if test $bash_cv_dirent_has_d_fileno = yes; then
 cat >>confdefs.h <<\EOF
@@ -12307,13 +13160,13 @@ EOF
 
 fi
 
-echo "$as_me:12310: checking for struct winsize in sys/ioctl.h and termios.h" >&5
+echo "$as_me:13163: checking for struct winsize in sys/ioctl.h and termios.h" >&5
 echo $ECHO_N "checking for struct winsize in sys/ioctl.h and termios.h... $ECHO_C" >&6
 if test "${bash_cv_struct_winsize_header+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 12316 "configure"
+#line 13169 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/ioctl.h>
@@ -12326,23 +13179,23 @@ struct winsize x;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:12329: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:13182: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:12332: \$? = $ac_status" >&5
+  echo "$as_me:13185: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:12335: \"$ac_try\"") >&5
+  { (eval echo "$as_me:13188: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:12338: \$? = $ac_status" >&5
+  echo "$as_me:13191: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_struct_winsize_header=ioctl_h
 else
   echo "$as_me: failed program was:" >&5
 cat conftest.$ac_ext >&5
 cat >conftest.$ac_ext <<_ACEOF
-#line 12345 "configure"
+#line 13198 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <termios.h>
@@ -12355,16 +13208,16 @@ struct winsize x;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:12358: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:13211: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:12361: \$? = $ac_status" >&5
+  echo "$as_me:13214: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:12364: \"$ac_try\"") >&5
+  { (eval echo "$as_me:13217: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:12367: \$? = $ac_status" >&5
+  echo "$as_me:13220: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_struct_winsize_header=termios_h
 else
@@ -12379,32 +13232,32 @@ rm -f conftest.$ac_objext conftest.$ac_ext
 fi
 
 if test $bash_cv_struct_winsize_header = ioctl_h; then
-  echo "$as_me:12382: result: sys/ioctl.h" >&5
+  echo "$as_me:13235: result: sys/ioctl.h" >&5
 echo "${ECHO_T}sys/ioctl.h" >&6
   cat >>confdefs.h <<\EOF
 #define STRUCT_WINSIZE_IN_SYS_IOCTL 1
 EOF
 
 elif test $bash_cv_struct_winsize_header = termios_h; then
-  echo "$as_me:12389: result: termios.h" >&5
+  echo "$as_me:13242: result: termios.h" >&5
 echo "${ECHO_T}termios.h" >&6
   cat >>confdefs.h <<\EOF
 #define STRUCT_WINSIZE_IN_TERMIOS 1
 EOF
 
 else
-  echo "$as_me:12396: result: not found" >&5
+  echo "$as_me:13249: result: not found" >&5
 echo "${ECHO_T}not found" >&6
 fi
 
-echo "$as_me:12400: checking for struct timeval in sys/time.h and time.h" >&5
+echo "$as_me:13253: checking for struct timeval in sys/time.h and time.h" >&5
 echo $ECHO_N "checking for struct timeval in sys/time.h and time.h... $ECHO_C" >&6
 if test "${bash_cv_struct_timeval+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
 
 cat >conftest.$ac_ext <<_ACEOF
-#line 12407 "configure"
+#line 13260 "configure"
 #include "confdefs.h"
 #include <sys/time.h>
 
@@ -12414,7 +13267,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
   bash_cv_struct_timeval=yes
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 12417 "configure"
+#line 13270 "configure"
 #include "confdefs.h"
 #include <time.h>
 
@@ -12432,7 +13285,7 @@ rm -f conftest*
 
 fi
 
-echo "$as_me:12435: result: $bash_cv_struct_timeval" >&5
+echo "$as_me:13288: result: $bash_cv_struct_timeval" >&5
 echo "${ECHO_T}$bash_cv_struct_timeval" >&6
 if test $bash_cv_struct_timeval = yes; then
   cat >>confdefs.h <<\EOF
@@ -12441,13 +13294,13 @@ EOF
 
 fi
 
-echo "$as_me:12444: checking for struct stat.st_blocks" >&5
+echo "$as_me:13297: checking for struct stat.st_blocks" >&5
 echo $ECHO_N "checking for struct stat.st_blocks... $ECHO_C" >&6
 if test "${ac_cv_member_struct_stat_st_blocks+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 12450 "configure"
+#line 13303 "configure"
 #include "confdefs.h"
 $ac_includes_default
 int
@@ -12461,16 +13314,16 @@ return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:12464: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:13317: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:12467: \$? = $ac_status" >&5
+  echo "$as_me:13320: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:12470: \"$ac_try\"") >&5
+  { (eval echo "$as_me:13323: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:12473: \$? = $ac_status" >&5
+  echo "$as_me:13326: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_member_struct_stat_st_blocks=yes
 else
@@ -12480,7 +13333,7 @@ ac_cv_member_struct_stat_st_blocks=no
 fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:12483: result: $ac_cv_member_struct_stat_st_blocks" >&5
+echo "$as_me:13336: result: $ac_cv_member_struct_stat_st_blocks" >&5
 echo "${ECHO_T}$ac_cv_member_struct_stat_st_blocks" >&6
 if test $ac_cv_member_struct_stat_st_blocks = yes; then
 
 
 fi
 
-echo "$as_me:12493: checking for the existence of strsignal" >&5
+echo "$as_me:13346: checking whether struct tm is in sys/time.h or time.h" >&5
+echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6
+if test "${ac_cv_struct_tm+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 13352 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm *tp; tp->tm_sec;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:13366: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:13369: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:13372: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:13375: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_struct_tm=time.h
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_struct_tm=sys/time.h
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:13385: result: $ac_cv_struct_tm" >&5
+echo "${ECHO_T}$ac_cv_struct_tm" >&6
+if test $ac_cv_struct_tm = sys/time.h; then
+
+cat >>confdefs.h <<\EOF
+#define TM_IN_SYS_TIME 1
+EOF
+
+fi
+
+echo "$as_me:13395: checking for struct tm.tm_zone" >&5
+echo $ECHO_N "checking for struct tm.tm_zone... $ECHO_C" >&6
+if test "${ac_cv_member_struct_tm_tm_zone+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 13401 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <$ac_cv_struct_tm>
+
+int
+main ()
+{
+static struct tm ac_aggr;
+if (ac_aggr.tm_zone)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:13417: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:13420: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:13423: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:13426: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_member_struct_tm_tm_zone=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_member_struct_tm_tm_zone=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:13436: result: $ac_cv_member_struct_tm_tm_zone" >&5
+echo "${ECHO_T}$ac_cv_member_struct_tm_tm_zone" >&6
+if test $ac_cv_member_struct_tm_tm_zone = yes; then
+
+cat >>confdefs.h <<EOF
+#define HAVE_STRUCT_TM_TM_ZONE 1
+EOF
+
+fi
+
+if test "$ac_cv_member_struct_tm_tm_zone" = yes; then
+
+cat >>confdefs.h <<\EOF
+#define HAVE_TM_ZONE 1
+EOF
+
+else
+  echo "$as_me:13453: checking for tzname" >&5
+echo $ECHO_N "checking for tzname... $ECHO_C" >&6
+if test "${ac_cv_var_tzname+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 13459 "configure"
+#include "confdefs.h"
+#include <time.h>
+#ifndef tzname /* For SGI.  */
+extern char *tzname[]; /* RS6000 and others reject char **tzname.  */
+#endif
+
+int
+main ()
+{
+atoi(*tzname);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:13475: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:13478: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:13481: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:13484: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_var_tzname=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_var_tzname=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:13494: result: $ac_cv_var_tzname" >&5
+echo "${ECHO_T}$ac_cv_var_tzname" >&6
+  if test $ac_cv_var_tzname = yes; then
+
+cat >>confdefs.h <<\EOF
+#define HAVE_TZNAME 1
+EOF
+
+  fi
+fi
+
+echo "$as_me:13505: checking for the existence of strsignal" >&5
 echo $ECHO_N "checking for the existence of strsignal... $ECHO_C" >&6
 if test "${bash_cv_have_strsignal+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 12499 "configure"
+#line 13511 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <signal.h>
@@ -12509,16 +13521,16 @@ char *s = (char *)strsignal(2);
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:12512: \"$ac_link\"") >&5
+if { (eval echo "$as_me:13524: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:12515: \$? = $ac_status" >&5
+  echo "$as_me:13527: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:12518: \"$ac_try\"") >&5
+  { (eval echo "$as_me:13530: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:12521: \$? = $ac_status" >&5
+  echo "$as_me:13533: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_have_strsignal=yes
 else
@@ -12529,7 +13541,7 @@ fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
 
-echo "$as_me:12532: result: $bash_cv_have_strsignal" >&5
+echo "$as_me:13544: result: $bash_cv_have_strsignal" >&5
 echo "${ECHO_T}$bash_cv_have_strsignal" >&6
 if test $bash_cv_have_strsignal = yes; then
 cat >>confdefs.h <<\EOF
@@ -12538,19 +13550,19 @@ EOF
 
 fi
 
-echo "$as_me:12541: checking if opendir() opens non-directories" >&5
+echo "$as_me:13553: checking if opendir() opens non-directories" >&5
 echo $ECHO_N "checking if opendir() opens non-directories... $ECHO_C" >&6
 if test "${bash_cv_opendir_not_robust+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test "$cross_compiling" = yes; then
-  { echo "$as_me:12547: WARNING: cannot check opendir if cross compiling -- defaulting to no" >&5
+  { echo "$as_me:13559: WARNING: cannot check opendir if cross compiling -- defaulting to no" >&5
 echo "$as_me: WARNING: cannot check opendir if cross compiling -- defaulting to no" >&2;}
      bash_cv_opendir_not_robust=no
 
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 12553 "configure"
+#line 13565 "configure"
 #include "confdefs.h"
 
 #include <stdio.h>
@@ -12593,15 +13605,15 @@ exit (dir == 0);
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:12596: \"$ac_link\"") >&5
+if { (eval echo "$as_me:13608: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:12599: \$? = $ac_status" >&5
+  echo "$as_me:13611: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:12601: \"$ac_try\"") >&5
+  { (eval echo "$as_me:13613: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:12604: \$? = $ac_status" >&5
+  echo "$as_me:13616: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_opendir_not_robust=yes
 else
@@ -12614,7 +13626,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
 
-echo "$as_me:12617: result: $bash_cv_opendir_not_robust" >&5
+echo "$as_me:13629: result: $bash_cv_opendir_not_robust" >&5
 echo "${ECHO_T}$bash_cv_opendir_not_robust" >&6
 if test $bash_cv_opendir_not_robust = yes; then
 cat >>confdefs.h <<\EOF
@@ -12623,19 +13635,19 @@ EOF
 
 fi
 
-echo "$as_me:12626: checking whether ulimit can substitute for getdtablesize" >&5
+echo "$as_me:13638: checking whether ulimit can substitute for getdtablesize" >&5
 echo $ECHO_N "checking whether ulimit can substitute for getdtablesize... $ECHO_C" >&6
 if test "${bash_cv_ulimit_maxfds+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test "$cross_compiling" = yes; then
-  { echo "$as_me:12632: WARNING: cannot check ulimit if cross compiling -- defaulting to no" >&5
+  { echo "$as_me:13644: WARNING: cannot check ulimit if cross compiling -- defaulting to no" >&5
 echo "$as_me: WARNING: cannot check ulimit if cross compiling -- defaulting to no" >&2;}
     bash_cv_ulimit_maxfds=no
 
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 12638 "configure"
+#line 13650 "configure"
 #include "confdefs.h"
 
 main()
@@ -12646,15 +13658,15 @@ exit (maxfds == -1L);
 
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:12649: \"$ac_link\"") >&5
+if { (eval echo "$as_me:13661: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:12652: \$? = $ac_status" >&5
+  echo "$as_me:13664: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:12654: \"$ac_try\"") >&5
+  { (eval echo "$as_me:13666: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:12657: \$? = $ac_status" >&5
+  echo "$as_me:13669: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_ulimit_maxfds=yes
 else
@@ -12667,7 +13679,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
 
-echo "$as_me:12670: result: $bash_cv_ulimit_maxfds" >&5
+echo "$as_me:13682: result: $bash_cv_ulimit_maxfds" >&5
 echo "${ECHO_T}$bash_cv_ulimit_maxfds" >&6
 if test $bash_cv_ulimit_maxfds = yes; then
 cat >>confdefs.h <<\EOF
@@ -12676,19 +13688,19 @@ EOF
 
 fi
 
-echo "$as_me:12679: checking to see if getenv can be redefined" >&5
+echo "$as_me:13691: checking to see if getenv can be redefined" >&5
 echo $ECHO_N "checking to see if getenv can be redefined... $ECHO_C" >&6
 if test "${bash_cv_getenv_redef+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test "$cross_compiling" = yes; then
-  { echo "$as_me:12685: WARNING: cannot check getenv redefinition if cross compiling -- defaulting to yes" >&5
+  { echo "$as_me:13697: WARNING: cannot check getenv redefinition if cross compiling -- defaulting to yes" >&5
 echo "$as_me: WARNING: cannot check getenv redefinition if cross compiling -- defaulting to yes" >&2;}
     bash_cv_getenv_redef=yes
 
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 12691 "configure"
+#line 13703 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_UNISTD_H
@@ -12724,15 +13736,15 @@ exit(s == 0); /* force optimizer to leave getenv in */
 
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:12727: \"$ac_link\"") >&5
+if { (eval echo "$as_me:13739: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:12730: \$? = $ac_status" >&5
+  echo "$as_me:13742: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:12732: \"$ac_try\"") >&5
+  { (eval echo "$as_me:13744: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:12735: \$? = $ac_status" >&5
+  echo "$as_me:13747: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_getenv_redef=yes
 else
@@ -12745,7 +13757,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
 
-echo "$as_me:12748: result: $bash_cv_getenv_redef" >&5
+echo "$as_me:13760: result: $bash_cv_getenv_redef" >&5
 echo "${ECHO_T}$bash_cv_getenv_redef" >&6
 if test $bash_cv_getenv_redef = yes; then
 cat >>confdefs.h <<\EOF
@@ -12754,20 +13766,20 @@ EOF
 
 fi
 
-if test "$ac_func_getcwd" = "yes"; then
-echo "$as_me:12758: checking if getcwd() calls popen()" >&5
+if test "$ac_cv_func_getcwd" = "yes"; then
+echo "$as_me:13770: checking if getcwd() calls popen()" >&5
 echo $ECHO_N "checking if getcwd() calls popen()... $ECHO_C" >&6
 if test "${bash_cv_getcwd_calls_popen+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test "$cross_compiling" = yes; then
-  { echo "$as_me:12764: WARNING: cannot check whether getcwd calls popen if cross compiling -- defaulting to no" >&5
+  { echo "$as_me:13776: WARNING: cannot check whether getcwd calls popen if cross compiling -- defaulting to no" >&5
 echo "$as_me: WARNING: cannot check whether getcwd calls popen if cross compiling -- defaulting to no" >&2;}
     bash_cv_getcwd_calls_popen=no
 
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 12770 "configure"
+#line 13782 "configure"
 #include "confdefs.h"
 
 #include <stdio.h>
@@ -12823,15 +13835,15 @@ main()
 
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:12826: \"$ac_link\"") >&5
+if { (eval echo "$as_me:13838: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:12829: \$? = $ac_status" >&5
+  echo "$as_me:13841: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:12831: \"$ac_try\"") >&5
+  { (eval echo "$as_me:13843: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:12834: \$? = $ac_status" >&5
+  echo "$as_me:13846: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_getcwd_calls_popen=no
 else
@@ -12844,7 +13856,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
 
-echo "$as_me:12847: result: $bash_cv_getcwd_calls_popen" >&5
+echo "$as_me:13859: result: $bash_cv_getcwd_calls_popen" >&5
 echo "${ECHO_T}$bash_cv_getcwd_calls_popen" >&6
 if test $bash_cv_getcwd_calls_popen = yes; then
 cat >>confdefs.h <<\EOF
 
 fi
 
-echo "$as_me:12859: checking for presence of POSIX-style sigsetjmp/siglongjmp" >&5
+echo "$as_me:13871: checking for presence of POSIX-style sigsetjmp/siglongjmp" >&5
 echo $ECHO_N "checking for presence of POSIX-style sigsetjmp/siglongjmp... $ECHO_C" >&6
 if test "${bash_cv_func_sigsetjmp+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test "$cross_compiling" = yes; then
-  { echo "$as_me:12865: WARNING: cannot check for sigsetjmp/siglongjmp if cross-compiling -- defaulting to missing" >&5
+  { echo "$as_me:13877: WARNING: cannot check for sigsetjmp/siglongjmp if cross-compiling -- defaulting to missing" >&5
 echo "$as_me: WARNING: cannot check for sigsetjmp/siglongjmp if cross-compiling -- defaulting to missing" >&2;}
      bash_cv_func_sigsetjmp=missing
 
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 12871 "configure"
+#line 13883 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_UNISTD_H
@@ -12910,15 +13922,15 @@ exit(1);
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:12913: \"$ac_link\"") >&5
+if { (eval echo "$as_me:13925: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:12916: \$? = $ac_status" >&5
+  echo "$as_me:13928: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:12918: \"$ac_try\"") >&5
+  { (eval echo "$as_me:13930: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:12921: \$? = $ac_status" >&5
+  echo "$as_me:13933: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_func_sigsetjmp=present
 else
@@ -12931,7 +13943,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
 
-echo "$as_me:12934: result: $bash_cv_func_sigsetjmp" >&5
+echo "$as_me:13946: result: $bash_cv_func_sigsetjmp" >&5
 echo "${ECHO_T}$bash_cv_func_sigsetjmp" >&6
 if test $bash_cv_func_sigsetjmp = present; then
 cat >>confdefs.h <<\EOF
@@ -12940,19 +13952,19 @@ EOF
 
 fi
 
-echo "$as_me:12943: checking whether or not strcoll and strcmp differ" >&5
+echo "$as_me:13955: checking whether or not strcoll and strcmp differ" >&5
 echo $ECHO_N "checking whether or not strcoll and strcmp differ... $ECHO_C" >&6
 if test "${bash_cv_func_strcoll_broken+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test "$cross_compiling" = yes; then
-  { echo "$as_me:12949: WARNING: cannot check strcoll if cross compiling -- defaulting to no" >&5
+  { echo "$as_me:13961: WARNING: cannot check strcoll if cross compiling -- defaulting to no" >&5
 echo "$as_me: WARNING: cannot check strcoll if cross compiling -- defaulting to no" >&2;}
     bash_cv_func_strcoll_broken=no
 
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 12955 "configure"
+#line 13967 "configure"
 #include "confdefs.h"
 
 #include <stdio.h>
@@ -12992,15 +14004,15 @@ char    *v[];
 
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:12995: \"$ac_link\"") >&5
+if { (eval echo "$as_me:14007: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:12998: \$? = $ac_status" >&5
+  echo "$as_me:14010: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:13000: \"$ac_try\"") >&5
+  { (eval echo "$as_me:14012: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:13003: \$? = $ac_status" >&5
+  echo "$as_me:14015: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_func_strcoll_broken=yes
 else
@@ -13013,7 +14025,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
 
-echo "$as_me:13016: result: $bash_cv_func_strcoll_broken" >&5
+echo "$as_me:14028: result: $bash_cv_func_strcoll_broken" >&5
 echo "${ECHO_T}$bash_cv_func_strcoll_broken" >&6
 if test $bash_cv_func_strcoll_broken = yes; then
 cat >>confdefs.h <<\EOF
 
 fi
 
-echo "$as_me:13025: checking for printf floating point output in hex notation" >&5
+if test "$ac_cv_func_putenv" = "yes"; then
+
+echo "$as_me:14039: checking for standard-conformant putenv declaration" >&5
+echo $ECHO_N "checking for standard-conformant putenv declaration... $ECHO_C" >&6
+if test "${bash_cv_std_putenv+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 14045 "configure"
+#include "confdefs.h"
+
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#ifndef __STDC__
+#  ifndef const
+#    define const
+#  endif
+#endif
+#ifdef PROTOTYPES
+extern int putenv (char *);
+#else
+extern int putenv ();
+#endif
+
+int
+main ()
+{
+return (putenv == 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:14072: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:14075: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:14078: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:14081: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  bash_cv_std_putenv=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+bash_cv_std_putenv=no
+
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:14092: result: $bash_cv_std_putenv" >&5
+echo "${ECHO_T}$bash_cv_std_putenv" >&6
+if test $bash_cv_std_putenv = yes; then
+cat >>confdefs.h <<\EOF
+#define HAVE_STD_PUTENV 1
+EOF
+
+fi
+
+else
+cat >>confdefs.h <<\EOF
+#define HAVE_STD_PUTENV 1
+EOF
+
+fi
+if test "$ac_cv_func_unsetenv" = "yes"; then
+
+echo "$as_me:14109: checking for standard-conformant unsetenv declaration" >&5
+echo $ECHO_N "checking for standard-conformant unsetenv declaration... $ECHO_C" >&6
+if test "${bash_cv_std_unsetenv+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 14115 "configure"
+#include "confdefs.h"
+
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#ifndef __STDC__
+#  ifndef const
+#    define const
+#  endif
+#endif
+#ifdef PROTOTYPES
+extern int unsetenv (const char *);
+#else
+extern int unsetenv ();
+#endif
+
+int
+main ()
+{
+return (unsetenv == 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:14142: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:14145: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:14148: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:14151: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  bash_cv_std_unsetenv=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+bash_cv_std_unsetenv=no
+
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:14162: result: $bash_cv_std_unsetenv" >&5
+echo "${ECHO_T}$bash_cv_std_unsetenv" >&6
+if test $bash_cv_std_unsetenv = yes; then
+cat >>confdefs.h <<\EOF
+#define HAVE_STD_UNSETENV 1
+EOF
+
+fi
+
+else
+cat >>confdefs.h <<\EOF
+#define HAVE_STD_UNSETENV 1
+EOF
+
+fi
+
+echo "$as_me:14178: checking for printf floating point output in hex notation" >&5
 echo $ECHO_N "checking for printf floating point output in hex notation... $ECHO_C" >&6
 if test "${bash_cv_printf_a_format+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test "$cross_compiling" = yes; then
-  { echo "$as_me:13031: WARNING: cannot check printf if cross compiling -- defaulting to no" >&5
+  { echo "$as_me:14184: WARNING: cannot check printf if cross compiling -- defaulting to no" >&5
 echo "$as_me: WARNING: cannot check printf if cross compiling -- defaulting to no" >&2;}
     bash_cv_printf_a_format=no
 
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 13037 "configure"
+#line 14190 "configure"
 #include "confdefs.h"
 
 #include <stdio.h>
@@ -13052,15 +14205,15 @@ main()
 
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:13055: \"$ac_link\"") >&5
+if { (eval echo "$as_me:14208: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:13058: \$? = $ac_status" >&5
+  echo "$as_me:14211: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:13060: \"$ac_try\"") >&5
+  { (eval echo "$as_me:14213: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:13063: \$? = $ac_status" >&5
+  echo "$as_me:14216: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_printf_a_format=yes
 else
@@ -13073,7 +14226,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
 
-echo "$as_me:13076: result: $bash_cv_printf_a_format" >&5
+echo "$as_me:14229: result: $bash_cv_printf_a_format" >&5
 echo "${ECHO_T}$bash_cv_printf_a_format" >&6
 if test $bash_cv_printf_a_format = yes; then
 cat >>confdefs.h <<\EOF
@@ -13082,19 +14235,19 @@ EOF
 
 fi
 
-echo "$as_me:13085: checking if signal handlers must be reinstalled when invoked" >&5
+echo "$as_me:14238: checking if signal handlers must be reinstalled when invoked" >&5
 echo $ECHO_N "checking if signal handlers must be reinstalled when invoked... $ECHO_C" >&6
 if test "${bash_cv_must_reinstall_sighandlers+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test "$cross_compiling" = yes; then
-  { echo "$as_me:13091: WARNING: cannot check signal handling if cross compiling -- defaulting to no" >&5
+  { echo "$as_me:14244: WARNING: cannot check signal handling if cross compiling -- defaulting to no" >&5
 echo "$as_me: WARNING: cannot check signal handling if cross compiling -- defaulting to no" >&2;}
     bash_cv_must_reinstall_sighandlers=no
 
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 13097 "configure"
+#line 14250 "configure"
 #include "confdefs.h"
 
 #include <signal.h>
@@ -13142,15 +14295,15 @@ main()
 
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:13145: \"$ac_link\"") >&5
+if { (eval echo "$as_me:14298: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:13148: \$? = $ac_status" >&5
+  echo "$as_me:14301: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:13150: \"$ac_try\"") >&5
+  { (eval echo "$as_me:14303: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:13153: \$? = $ac_status" >&5
+  echo "$as_me:14306: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_must_reinstall_sighandlers=no
 else
@@ -13163,7 +14316,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
 
-echo "$as_me:13166: result: $bash_cv_must_reinstall_sighandlers" >&5
+echo "$as_me:14319: result: $bash_cv_must_reinstall_sighandlers" >&5
 echo "${ECHO_T}$bash_cv_must_reinstall_sighandlers" >&6
 if test $bash_cv_must_reinstall_sighandlers = yes; then
 cat >>confdefs.h <<\EOF
@@ -13172,19 +14325,19 @@ EOF
 
 fi
 
-echo "$as_me:13175: checking for presence of necessary job control definitions" >&5
+echo "$as_me:14328: checking for presence of necessary job control definitions" >&5
 echo $ECHO_N "checking for presence of necessary job control definitions... $ECHO_C" >&6
 if test "${bash_cv_job_control_missing+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test "$cross_compiling" = yes; then
-  { echo "$as_me:13181: WARNING: cannot check job control if cross-compiling -- defaulting to missing" >&5
+  { echo "$as_me:14334: WARNING: cannot check job control if cross-compiling -- defaulting to missing" >&5
 echo "$as_me: WARNING: cannot check job control if cross-compiling -- defaulting to missing" >&2;}
      bash_cv_job_control_missing=missing
 
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 13187 "configure"
+#line 14340 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -13232,15 +14385,15 @@ exit(0);
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:13235: \"$ac_link\"") >&5
+if { (eval echo "$as_me:14388: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:13238: \$? = $ac_status" >&5
+  echo "$as_me:14391: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:13240: \"$ac_try\"") >&5
+  { (eval echo "$as_me:14393: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:13243: \$? = $ac_status" >&5
+  echo "$as_me:14396: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_job_control_missing=present
 else
@@ -13253,7 +14406,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
 
-echo "$as_me:13256: result: $bash_cv_job_control_missing" >&5
+echo "$as_me:14409: result: $bash_cv_job_control_missing" >&5
 echo "${ECHO_T}$bash_cv_job_control_missing" >&6
 if test $bash_cv_job_control_missing = missing; then
 cat >>confdefs.h <<\EOF
@@ -13262,19 +14415,19 @@ EOF
 
 fi
 
-echo "$as_me:13265: checking for presence of named pipes" >&5
+echo "$as_me:14418: checking for presence of named pipes" >&5
 echo $ECHO_N "checking for presence of named pipes... $ECHO_C" >&6
 if test "${bash_cv_sys_named_pipes+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test "$cross_compiling" = yes; then
-  { echo "$as_me:13271: WARNING: cannot check for named pipes if cross-compiling -- defaulting to missing" >&5
+  { echo "$as_me:14424: WARNING: cannot check for named pipes if cross-compiling -- defaulting to missing" >&5
 echo "$as_me: WARNING: cannot check for named pipes if cross-compiling -- defaulting to missing" >&2;}
      bash_cv_sys_named_pipes=missing
 
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 13277 "configure"
+#line 14430 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -13316,15 +14469,15 @@ exit(0);
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:13319: \"$ac_link\"") >&5
+if { (eval echo "$as_me:14472: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:13322: \$? = $ac_status" >&5
+  echo "$as_me:14475: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:13324: \"$ac_try\"") >&5
+  { (eval echo "$as_me:14477: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:13327: \$? = $ac_status" >&5
+  echo "$as_me:14480: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_sys_named_pipes=present
 else
@@ -13337,7 +14490,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
 
-echo "$as_me:13340: result: $bash_cv_sys_named_pipes" >&5
+echo "$as_me:14493: result: $bash_cv_sys_named_pipes" >&5
 echo "${ECHO_T}$bash_cv_sys_named_pipes" >&6
 if test $bash_cv_sys_named_pipes = missing; then
 cat >>confdefs.h <<\EOF
@@ -13346,13 +14499,13 @@ EOF
 
 fi
 
-echo "$as_me:13349: checking POSIX termios" >&5
+echo "$as_me:14502: checking POSIX termios" >&5
 echo $ECHO_N "checking POSIX termios... $ECHO_C" >&6
 if test "${ac_cv_sys_posix_termios+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 13355 "configure"
+#line 14508 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <unistd.h>
@@ -13367,16 +14520,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:13370: \"$ac_link\"") >&5
+if { (eval echo "$as_me:14523: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:13373: \$? = $ac_status" >&5
+  echo "$as_me:14526: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:13376: \"$ac_try\"") >&5
+  { (eval echo "$as_me:14529: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:13379: \$? = $ac_status" >&5
+  echo "$as_me:14532: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_sys_posix_termios=yes
 else
@@ -13386,17 +14539,17 @@ ac_cv_sys_posix_termios=no
 fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:13389: result: $ac_cv_sys_posix_termios" >&5
+echo "$as_me:14542: result: $ac_cv_sys_posix_termios" >&5
 echo "${ECHO_T}$ac_cv_sys_posix_termios" >&6
 
 if test $ac_cv_sys_posix_termios = yes; then
-  echo "$as_me:13393: checking whether termios.h defines TIOCGWINSZ" >&5
+  echo "$as_me:14546: checking whether termios.h defines TIOCGWINSZ" >&5
 echo $ECHO_N "checking whether termios.h defines TIOCGWINSZ... $ECHO_C" >&6
 if test "${ac_cv_sys_tiocgwinsz_in_termios_h+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 13399 "configure"
+#line 14552 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <termios.h>
 rm -f conftest*
 
 fi
-echo "$as_me:13417: result: $ac_cv_sys_tiocgwinsz_in_termios_h" >&5
+echo "$as_me:14570: result: $ac_cv_sys_tiocgwinsz_in_termios_h" >&5
 echo "${ECHO_T}$ac_cv_sys_tiocgwinsz_in_termios_h" >&6
 
 fi
 if test $ac_cv_sys_tiocgwinsz_in_termios_h != yes; then
-  echo "$as_me:13422: checking whether sys/ioctl.h defines TIOCGWINSZ" >&5
+  echo "$as_me:14575: checking whether sys/ioctl.h defines TIOCGWINSZ" >&5
 echo $ECHO_N "checking whether sys/ioctl.h defines TIOCGWINSZ... $ECHO_C" >&6
 if test "${ac_cv_sys_tiocgwinsz_in_sys_ioctl_h+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 13428 "configure"
+#line 14581 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/ioctl.h>
@@ -13443,7 +14596,7 @@ fi
 rm -f conftest*
 
 fi
-echo "$as_me:13446: result: $ac_cv_sys_tiocgwinsz_in_sys_ioctl_h" >&5
+echo "$as_me:14599: result: $ac_cv_sys_tiocgwinsz_in_sys_ioctl_h" >&5
 echo "${ECHO_T}$ac_cv_sys_tiocgwinsz_in_sys_ioctl_h" >&6
 
   if test $ac_cv_sys_tiocgwinsz_in_sys_ioctl_h = yes; then
@@ -13455,13 +14608,13 @@ EOF
   fi
 fi
 
-echo "$as_me:13458: checking for TIOCSTAT in sys/ioctl.h" >&5
+echo "$as_me:14611: checking for TIOCSTAT in sys/ioctl.h" >&5
 echo $ECHO_N "checking for TIOCSTAT in sys/ioctl.h... $ECHO_C" >&6
 if test "${bash_cv_tiocstat_in_ioctl+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 13464 "configure"
+#line 14617 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/ioctl.h>
@@ -13474,16 +14627,16 @@ int x = TIOCSTAT;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:13477: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:14630: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:13480: \$? = $ac_status" >&5
+  echo "$as_me:14633: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:13483: \"$ac_try\"") >&5
+  { (eval echo "$as_me:14636: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:13486: \$? = $ac_status" >&5
+  echo "$as_me:14639: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_tiocstat_in_ioctl=yes
 else
@@ -13494,7 +14647,7 @@ fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
 
-echo "$as_me:13497: result: $bash_cv_tiocstat_in_ioctl" >&5
+echo "$as_me:14650: result: $bash_cv_tiocstat_in_ioctl" >&5
 echo "${ECHO_T}$bash_cv_tiocstat_in_ioctl" >&6
 if test $bash_cv_tiocstat_in_ioctl = yes; then
 cat >>confdefs.h <<\EOF
@@ -13503,13 +14656,13 @@ EOF
 
 fi
 
-echo "$as_me:13506: checking for FIONREAD in sys/ioctl.h" >&5
+echo "$as_me:14659: checking for FIONREAD in sys/ioctl.h" >&5
 echo $ECHO_N "checking for FIONREAD in sys/ioctl.h... $ECHO_C" >&6
 if test "${bash_cv_fionread_in_ioctl+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 13512 "configure"
+#line 14665 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/ioctl.h>
@@ -13522,16 +14675,16 @@ int x = FIONREAD;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:13525: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:14678: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:13528: \$? = $ac_status" >&5
+  echo "$as_me:14681: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:13531: \"$ac_try\"") >&5
+  { (eval echo "$as_me:14684: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:13534: \$? = $ac_status" >&5
+  echo "$as_me:14687: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_fionread_in_ioctl=yes
 else
@@ -13542,7 +14695,7 @@ fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
 
-echo "$as_me:13545: result: $bash_cv_fionread_in_ioctl" >&5
+echo "$as_me:14698: result: $bash_cv_fionread_in_ioctl" >&5
 echo "${ECHO_T}$bash_cv_fionread_in_ioctl" >&6
 if test $bash_cv_fionread_in_ioctl = yes; then
 cat >>confdefs.h <<\EOF
@@ -13551,13 +14704,13 @@ EOF
 
 fi
 
-echo "$as_me:13554: checking for speed_t in sys/types.h" >&5
+echo "$as_me:14707: checking for speed_t in sys/types.h" >&5
 echo $ECHO_N "checking for speed_t in sys/types.h... $ECHO_C" >&6
 if test "${bash_cv_speed_t_in_sys_types+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 13560 "configure"
+#line 14713 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 int
@@ -13569,16 +14722,16 @@ speed_t x;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:13572: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:14725: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:13575: \$? = $ac_status" >&5
+  echo "$as_me:14728: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:13578: \"$ac_try\"") >&5
+  { (eval echo "$as_me:14731: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:13581: \$? = $ac_status" >&5
+  echo "$as_me:14734: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_speed_t_in_sys_types=yes
 else
@@ -13589,7 +14742,7 @@ fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
 
-echo "$as_me:13592: result: $bash_cv_speed_t_in_sys_types" >&5
+echo "$as_me:14745: result: $bash_cv_speed_t_in_sys_types" >&5
 echo "${ECHO_T}$bash_cv_speed_t_in_sys_types" >&6
 if test $bash_cv_speed_t_in_sys_types = yes; then
 cat >>confdefs.h <<\EOF
@@ -13598,13 +14751,13 @@ EOF
 
 fi
 
-echo "$as_me:13601: checking whether getpw functions are declared in pwd.h" >&5
+echo "$as_me:14754: checking whether getpw functions are declared in pwd.h" >&5
 echo $ECHO_N "checking whether getpw functions are declared in pwd.h... $ECHO_C" >&6
 if test "${bash_cv_getpw_declared+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 13607 "configure"
+#line 14760 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -13624,7 +14777,7 @@ rm -f conftest*
 
 fi
 
-echo "$as_me:13627: result: $bash_cv_getpw_declared" >&5
+echo "$as_me:14780: result: $bash_cv_getpw_declared" >&5
 echo "${ECHO_T}$bash_cv_getpw_declared" >&6
 if test $bash_cv_getpw_declared = yes; then
 cat >>confdefs.h <<\EOF
@@ -13633,19 +14786,19 @@ EOF
 
 fi
 
-echo "$as_me:13636: checking for unusable real-time signals due to large values" >&5
+echo "$as_me:14789: checking for unusable real-time signals due to large values" >&5
 echo $ECHO_N "checking for unusable real-time signals due to large values... $ECHO_C" >&6
 if test "${bash_cv_unusable_rtsigs+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test "$cross_compiling" = yes; then
-  { echo "$as_me:13642: WARNING: cannot check real-time signals if cross compiling -- defaulting to yes" >&5
+  { echo "$as_me:14795: WARNING: cannot check real-time signals if cross compiling -- defaulting to yes" >&5
 echo "$as_me: WARNING: cannot check real-time signals if cross compiling -- defaulting to yes" >&2;}
      bash_cv_unusable_rtsigs=yes
 
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 13648 "configure"
+#line 14801 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -13668,15 +14821,15 @@ main ()
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:13671: \"$ac_link\"") >&5
+if { (eval echo "$as_me:14824: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:13674: \$? = $ac_status" >&5
+  echo "$as_me:14827: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:13676: \"$ac_try\"") >&5
+  { (eval echo "$as_me:14829: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:13679: \$? = $ac_status" >&5
+  echo "$as_me:14832: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_unusable_rtsigs=yes
 else
@@ -13689,7 +14842,7 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
 fi
 
-echo "$as_me:13692: result: $bash_cv_unusable_rtsigs" >&5
+echo "$as_me:14845: result: $bash_cv_unusable_rtsigs" >&5
 echo "${ECHO_T}$bash_cv_unusable_rtsigs" >&6
 if test $bash_cv_unusable_rtsigs = yes; then
 cat >>confdefs.h <<\EOF
@@ -13705,13 +14858,13 @@ else
 fi
 
 case "$host_os" in
-hpux*) echo "$as_me:13708: checking whether $host_os needs _KERNEL for RLIMIT defines" >&5
+hpux*) echo "$as_me:14861: checking whether $host_os needs _KERNEL for RLIMIT defines" >&5
 echo $ECHO_N "checking whether $host_os needs _KERNEL for RLIMIT defines... $ECHO_C" >&6
 if test "${bash_cv_kernel_rlimit+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
-#line 13714 "configure"
+#line 14867 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -13729,23 +14882,23 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:13732: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:14885: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:13735: \$? = $ac_status" >&5
+  echo "$as_me:14888: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:13738: \"$ac_try\"") >&5
+  { (eval echo "$as_me:14891: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:13741: \$? = $ac_status" >&5
+  echo "$as_me:14894: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_kernel_rlimit=no
 else
   echo "$as_me: failed program was:" >&5
 cat conftest.$ac_ext >&5
 cat >conftest.$ac_ext <<_ACEOF
-#line 13748 "configure"
+#line 14901 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -13765,16 +14918,16 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:13768: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:14921: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
-  echo "$as_me:13771: \$? = $ac_status" >&5
+  echo "$as_me:14924: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:13774: \"$ac_try\"") >&5
+  { (eval echo "$as_me:14927: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:13777: \$? = $ac_status" >&5
+  echo "$as_me:14930: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   bash_cv_kernel_rlimit=yes
 else
@@ -13788,7 +14941,7 @@ fi
 rm -f conftest.$ac_objext conftest.$ac_ext
 fi
 
-echo "$as_me:13791: result: $bash_cv_kernel_rlimit" >&5
+echo "$as_me:14944: result: $bash_cv_kernel_rlimit" >&5
 echo "${ECHO_T}$bash_cv_kernel_rlimit" >&6
 if test $bash_cv_kernel_rlimit = yes; then
 cat >>confdefs.h <<\EOF
@@ -13807,14 +14960,14 @@ esac
 if test "X$bash_cv_termcap_lib" = "X"; then
 _bash_needmsg=yes
 else
-echo "$as_me:13810: checking which library has the termcap functions" >&5
+echo "$as_me:14963: checking which library has the termcap functions" >&5
 echo $ECHO_N "checking which library has the termcap functions... $ECHO_C" >&6
 _bash_needmsg=
 fi
 if test "${bash_cv_termcap_lib+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  echo "$as_me:13817: checking for tgetent in -ltermcap" >&5
+  echo "$as_me:14970: checking for tgetent in -ltermcap" >&5
 echo $ECHO_N "checking for tgetent in -ltermcap... $ECHO_C" >&6
 if test "${ac_cv_lib_termcap_tgetent+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -13822,7 +14975,7 @@ else
   ac_check_lib_save_LIBS=$LIBS
 LIBS="-ltermcap  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
-#line 13825 "configure"
+#line 14978 "configure"
 #include "confdefs.h"
 
 /* Override any gcc2 internal prototype to avoid an error.  */
@@ -13841,16 +14994,16 @@ tgetent ();
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:13844: \"$ac_link\"") >&5
+if { (eval echo "$as_me:14997: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:13847: \$? = $ac_status" >&5
+  echo "$as_me:15000: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:13850: \"$ac_try\"") >&5
+  { (eval echo "$as_me:15003: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:13853: \$? = $ac_status" >&5
+  echo "$as_me:15006: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_lib_termcap_tgetent=yes
 else
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:13864: result: $ac_cv_lib_termcap_tgetent" >&5
+echo "$as_me:15017: result: $ac_cv_lib_termcap_tgetent" >&5
 echo "${ECHO_T}$ac_cv_lib_termcap_tgetent" >&6
 if test $ac_cv_lib_termcap_tgetent = yes; then
   bash_cv_termcap_lib=libtermcap
 else
-  echo "$as_me:13869: checking for tgetent in -ltinfo" >&5
+  echo "$as_me:15022: checking for tgetent in -ltinfo" >&5
 echo $ECHO_N "checking for tgetent in -ltinfo... $ECHO_C" >&6
 if test "${ac_cv_lib_tinfo_tgetent+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -13874,7 +15027,7 @@ else
   ac_check_lib_save_LIBS=$LIBS
 LIBS="-ltinfo  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
-#line 13877 "configure"
+#line 15030 "configure"
 #include "confdefs.h"
 
 /* Override any gcc2 internal prototype to avoid an error.  */
@@ -13893,16 +15046,16 @@ tgetent ();
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:13896: \"$ac_link\"") >&5
+if { (eval echo "$as_me:15049: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:13899: \$? = $ac_status" >&5
+  echo "$as_me:15052: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:13902: \"$ac_try\"") >&5
+  { (eval echo "$as_me:15055: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:13905: \$? = $ac_status" >&5
+  echo "$as_me:15058: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_lib_tinfo_tgetent=yes
 else
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:13916: result: $ac_cv_lib_tinfo_tgetent" >&5
+echo "$as_me:15069: result: $ac_cv_lib_tinfo_tgetent" >&5
 echo "${ECHO_T}$ac_cv_lib_tinfo_tgetent" >&6
 if test $ac_cv_lib_tinfo_tgetent = yes; then
-  bash_cv_termcal_lib=libtinfo
+  bash_cv_termcap_lib=libtinfo
 else
-  echo "$as_me:13921: checking for tgetent in -lcurses" >&5
+  echo "$as_me:15074: checking for tgetent in -lcurses" >&5
 echo $ECHO_N "checking for tgetent in -lcurses... $ECHO_C" >&6
 if test "${ac_cv_lib_curses_tgetent+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -13926,7 +15079,7 @@ else
   ac_check_lib_save_LIBS=$LIBS
 LIBS="-lcurses  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
-#line 13929 "configure"
+#line 15082 "configure"
 #include "confdefs.h"
 
 /* Override any gcc2 internal prototype to avoid an error.  */
@@ -13945,16 +15098,16 @@ tgetent ();
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:13948: \"$ac_link\"") >&5
+if { (eval echo "$as_me:15101: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:13951: \$? = $ac_status" >&5
+  echo "$as_me:15104: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:13954: \"$ac_try\"") >&5
+  { (eval echo "$as_me:15107: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:13957: \$? = $ac_status" >&5
+  echo "$as_me:15110: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_lib_curses_tgetent=yes
 else
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:13968: result: $ac_cv_lib_curses_tgetent" >&5
+echo "$as_me:15121: result: $ac_cv_lib_curses_tgetent" >&5
 echo "${ECHO_T}$ac_cv_lib_curses_tgetent" >&6
 if test $ac_cv_lib_curses_tgetent = yes; then
   bash_cv_termcap_lib=libcurses
 else
-  echo "$as_me:13973: checking for tgetent in -lncurses" >&5
+  echo "$as_me:15126: checking for tgetent in -lncurses" >&5
 echo $ECHO_N "checking for tgetent in -lncurses... $ECHO_C" >&6
 if test "${ac_cv_lib_ncurses_tgetent+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -13978,7 +15131,7 @@ else
   ac_check_lib_save_LIBS=$LIBS
 LIBS="-lncurses  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
-#line 13981 "configure"
+#line 15134 "configure"
 #include "confdefs.h"
 
 /* Override any gcc2 internal prototype to avoid an error.  */
@@ -13997,16 +15150,16 @@ tgetent ();
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:14000: \"$ac_link\"") >&5
+if { (eval echo "$as_me:15153: \"$ac_link\"") >&5
   (eval $ac_link) 2>&5
   ac_status=$?
-  echo "$as_me:14003: \$? = $ac_status" >&5
+  echo "$as_me:15156: \$? = $ac_status" >&5
   (exit $ac_status); } &&
          { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:14006: \"$ac_try\"") >&5
+  { (eval echo "$as_me:15159: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
-  echo "$as_me:14009: \$? = $ac_status" >&5
+  echo "$as_me:15162: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   ac_cv_lib_ncurses_tgetent=yes
 else
@@ -14017,7 +15170,7 @@ fi
 rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:14020: result: $ac_cv_lib_ncurses_tgetent" >&5
+echo "$as_me:15173: result: $ac_cv_lib_ncurses_tgetent" >&5
 echo "${ECHO_T}$ac_cv_lib_ncurses_tgetent" >&6
 if test $ac_cv_lib_ncurses_tgetent = yes; then
   bash_cv_termcap_lib=libncurses
 fi
 
 if test "X$_bash_needmsg" = "Xyes"; then
-echo "$as_me:14037: checking which library has the termcap functions" >&5
+echo "$as_me:15190: checking which library has the termcap functions" >&5
 echo $ECHO_N "checking which library has the termcap functions... $ECHO_C" >&6
 fi
-echo "$as_me:14040: result: using $bash_cv_termcap_lib" >&5
+echo "$as_me:15193: result: using $bash_cv_termcap_lib" >&5
 echo "${ECHO_T}using $bash_cv_termcap_lib" >&6
 if test $bash_cv_termcap_lib = gnutermcap && test -z "$prefer_curses"; then
 LDFLAGS="$LDFLAGS -L./lib/termcap"
@@ -14059,7 +15212,7 @@ fi
 
 fi
 
-echo "$as_me:14062: checking whether /dev/fd is available" >&5
+echo "$as_me:15215: checking whether /dev/fd is available" >&5
 echo $ECHO_N "checking whether /dev/fd is available... $ECHO_C" >&6
 if test "${bash_cv_dev_fd+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -14074,7 +15227,7 @@ else
 
 fi
 
-echo "$as_me:14077: result: $bash_cv_dev_fd" >&5
+echo "$as_me:15230: result: $bash_cv_dev_fd" >&5
 echo "${ECHO_T}$bash_cv_dev_fd" >&6
 if test $bash_cv_dev_fd = "standard"; then
   cat >>confdefs.h <<\EOF
@@ -14096,7 +15249,7 @@ EOF
 
 fi
 
-echo "$as_me:14099: checking whether /dev/stdin stdout stderr are available" >&5
+echo "$as_me:15252: checking whether /dev/stdin stdout stderr are available" >&5
 echo $ECHO_N "checking whether /dev/stdin stdout stderr are available... $ECHO_C" >&6
 if test "${bash_cv_dev_stdin+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -14111,7 +15264,7 @@ else
 
 fi
 
-echo "$as_me:14114: result: $bash_cv_dev_stdin" >&5
+echo "$as_me:15267: result: $bash_cv_dev_stdin" >&5
 echo "${ECHO_T}$bash_cv_dev_stdin" >&6
 if test $bash_cv_dev_stdin = "present"; then
   cat >>confdefs.h <<\EOF
@@ -14120,17 +15273,17 @@ EOF
 
 fi
 
-echo "$as_me:14123: checking for default mail directory" >&5
+echo "$as_me:15276: checking for default mail directory" >&5
 echo $ECHO_N "checking for default mail directory... $ECHO_C" >&6
 if test "${bash_cv_mail_dir+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   if test -d /var/mail; then
    bash_cv_mail_dir=/var/mail
- elif test -d /usr/mail; then
-   bash_cv_mail_dir=/usr/mail
  elif test -d /var/spool/mail; then
    bash_cv_mail_dir=/var/spool/mail
+ elif test -d /usr/mail; then
+   bash_cv_mail_dir=/usr/mail
  elif test -d /usr/spool/mail; then
    bash_cv_mail_dir=/usr/spool/mail
  else
@@ -14139,35 +15292,12 @@ else
 
 fi
 
-echo "$as_me:14142: result: $bash_cv_mail_dir" >&5
+echo "$as_me:15295: result: $bash_cv_mail_dir" >&5
 echo "${ECHO_T}$bash_cv_mail_dir" >&6
-if test $bash_cv_mail_dir = "/var/mail"; then
-   cat >>confdefs.h <<\EOF
-#define DEFAULT_MAIL_DIRECTORY "/var/mail"
-EOF
-
-elif test $bash_cv_mail_dir = "/usr/mail"; then
-   cat >>confdefs.h <<\EOF
-#define DEFAULT_MAIL_DIRECTORY "/usr/mail"
-EOF
-
-elif test $bash_cv_mail_dir = "/var/spool/mail"; then
-   cat >>confdefs.h <<\EOF
-#define DEFAULT_MAIL_DIRECTORY "/var/spool/mail"
-EOF
-
-elif test $bash_cv_mail_dir = "/usr/spool/mail"; then
-   cat >>confdefs.h <<\EOF
-#define DEFAULT_MAIL_DIRECTORY "/usr/spool/mail"
-EOF
-
-else
-   cat >>confdefs.h <<\EOF
-#define DEFAULT_MAIL_DIRECTORY "unknown"
+cat >>confdefs.h <<EOF
+#define DEFAULT_MAIL_DIRECTORY "$bash_cv_mail_dir"
 EOF
 
-fi
-
 if test "$bash_cv_job_control_missing" = missing; then
        opt_job_control=no
 fi
@@ -14207,14 +15337,14 @@ dgux*)                LOCAL_CFLAGS=-D_DGUX_SOURCE; LOCAL_LIBS=-ldgc ;;
 isc*)          LOCAL_CFLAGS=-Disc386 ;;
 rhapsody*)     LOCAL_CFLAGS=-DRHAPSODY ;;
 darwin*)       LOCAL_CFLAGS=-DMACOSX ;;
-sco3.2v5*)     LOCAL_CFLAGS="-b elf -DWAITPID_BROKEN -DNO_MEMSCRAMBLE -DPATH_MAX=1024" ;;
-sco3.2v4*)     LOCAL_CFLAGS="-DMUST_UNBLOCK_CHLD -DNO_MEMSCRAMBLE -DPATH_MAX=1024" ;;
+sco3.2v5*)     LOCAL_CFLAGS="-b elf -DWAITPID_BROKEN -DPATH_MAX=1024" ;;
+sco3.2v4*)     LOCAL_CFLAGS="-DMUST_UNBLOCK_CHLD -DPATH_MAX=1024" ;;
 sco3.2*)       LOCAL_CFLAGS=-DMUST_UNBLOCK_CHLD ;;
 sunos4*)       LOCAL_CFLAGS=-DSunOS4 ;;
 solaris2.5*)   LOCAL_CFLAGS=-DSunOS5 ;;
 lynxos*)       LOCAL_CFLAGS=-DRECYCLES_PIDS ;;
 linux*)                LOCAL_LDFLAGS=-rdynamic ;;       # allow dynamic loading
-*qnx*)         LOCAL_CFLAGS="-Dqnx -F -3s" LOCAL_LDFLAGS="-3s -lunix -lncurses" ;;
+*qnx*)         LOCAL_CFLAGS="-Dqnx -F -3s" LOCAL_LDFLAGS="-3s" LOCAL_LIBS="-lunix -lncurses" ;;
 powerux*)      LOCAL_LIBS="-lgen" ;;
 cygwin*)       LOCAL_LIBS="-luser32" ;;
 opennt*|interix*) LOCAL_CFLAGS="-DNO_MAIN_ENV_ARG -DBROKEN_DIRENT_D_INO" ;;
@@ -14253,11 +15383,11 @@ esac
 #
 if test "$ac_cv_func_dlopen" = "yes" && test -f ${srcdir}/support/shobj-conf
 then
-       echo "$as_me:14256: checking shared object configuration for loadable builtins" >&5
+       echo "$as_me:15386: checking shared object configuration for loadable builtins" >&5
 echo $ECHO_N "checking shared object configuration for loadable builtins... $ECHO_C" >&6
        eval `${CONFIG_SHELL-/bin/sh} ${srcdir}/support/shobj-conf -C "${CC}" -c "${host_cpu}" -o "${host_os}" -v "${host_vendor}"`
 
-       echo "$as_me:14260: result: $SHOBJ_STATUS" >&5
+       echo "$as_me:15390: result: $SHOBJ_STATUS" >&5
 echo "${ECHO_T}$SHOBJ_STATUS" >&6
 fi
 
@@ -14362,7 +15492,7 @@ DEFS=-DHAVE_CONFIG_H
 : ${CONFIG_STATUS=./config.status}
 ac_clean_files_save=$ac_clean_files
 ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ echo "$as_me:14365: creating $CONFIG_STATUS" >&5
+{ echo "$as_me:15495: creating $CONFIG_STATUS" >&5
 echo "$as_me: creating $CONFIG_STATUS" >&6;}
 cat >$CONFIG_STATUS <<_ACEOF
 #! $SHELL
@@ -14493,7 +15623,7 @@ EOF
 
 cat >>$CONFIG_STATUS <<EOF
 ac_cs_version="\\
-bash config.status 2.05a
+bash config.status 2.05b
 configured by $0, generated by GNU Autoconf 2.52,
   with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
 
@@ -14538,7 +15668,7 @@ cat >>$CONFIG_STATUS <<\EOF
     echo "$ac_cs_version"; exit 0 ;;
   --he | --h)
     # Conflict between --help and --header
-    { { echo "$as_me:14541: error: ambiguous option: $1
+    { { echo "$as_me:15671: error: ambiguous option: $1
 Try \`$0 --help' for more information." >&5
 echo "$as_me: error: ambiguous option: $1
 Try \`$0 --help' for more information." >&2;}
@@ -14557,7 +15687,7 @@ Try \`$0 --help' for more information." >&2;}
     ac_need_defaults=false;;
 
   # This is an error.
-  -*) { { echo "$as_me:14560: error: unrecognized option: $1
+  -*) { { echo "$as_me:15690: error: unrecognized option: $1
 Try \`$0 --help' for more information." >&5
 echo "$as_me: error: unrecognized option: $1
 Try \`$0 --help' for more information." >&2;}
@@ -14576,7 +15706,7 @@ cat >&5 << _ACEOF
 ## Running config.status.  ##
 ## ----------------------- ##
 
-This file was extended by $as_me (bash 2.05a) 2.52, executed with
+This file was extended by $as_me (bash 2.05b) 2.52, executed with
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
   CONFIG_LINKS    = $CONFIG_LINKS
@@ -14606,7 +15736,7 @@ do
   "examples/loadables/perl/Makefile" ) CONFIG_FILES="$CONFIG_FILES examples/loadables/perl/Makefile" ;;
   "default" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;;
   "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
-  *) { { echo "$as_me:14609: error: invalid argument: $ac_config_target" >&5
+  *) { { echo "$as_me:15739: error: invalid argument: $ac_config_target" >&5
 echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
    { (exit 1); exit 1; }; };;
   esac
@@ -14705,6 +15835,9 @@ s,@MALLOC_LIBRARY@,$MALLOC_LIBRARY,;t t
 s,@MALLOC_LDFLAGS@,$MALLOC_LDFLAGS,;t t
 s,@MALLOC_DEP@,$MALLOC_DEP,;t t
 s,@htmldir@,$htmldir,;t t
+s,@HELPDIR@,$HELPDIR,;t t
+s,@HELPDIRDEFINE@,$HELPDIRDEFINE,;t t
+s,@HELPINSTALL@,$HELPINSTALL,;t t
 s,@CC@,$CC,;t t
 s,@CFLAGS@,$CFLAGS,;t t
 s,@LDFLAGS@,$LDFLAGS,;t t
@@ -14716,6 +15849,9 @@ s,@CPP@,$CPP,;t t
 s,@SIGNAMES_H@,$SIGNAMES_H,;t t
 s,@CC_FOR_BUILD@,$CC_FOR_BUILD,;t t
 s,@STATIC_LD@,$STATIC_LD,;t t
+s,@CFLAGS_FOR_BUILD@,$CFLAGS_FOR_BUILD,;t t
+s,@CPPFLAGS_FOR_BUILD@,$CPPFLAGS_FOR_BUILD,;t t
+s,@LDFLAGS_FOR_BUILD@,$LDFLAGS_FOR_BUILD,;t t
 s,@RL_VERSION@,$RL_VERSION,;t t
 s,@RL_MAJOR@,$RL_MAJOR,;t t
 s,@RL_MINOR@,$RL_MINOR,;t t
@@ -14754,6 +15890,9 @@ s,@incdir@,$incdir,;t t
 s,@BUILD_DIR@,$BUILD_DIR,;t t
 s,@ARFLAGS@,$ARFLAGS,;t t
 s,@BASHVERS@,$BASHVERS,;t t
+s,@RELSTATUS@,$RELSTATUS,;t t
+s,@DEBUG@,$DEBUG,;t t
+s,@MALLOC_DEBUG@,$MALLOC_DEBUG,;t t
 s,@LOCAL_LIBS@,$LOCAL_LIBS,;t t
 s,@LOCAL_CFLAGS@,$LOCAL_CFLAGS,;t t
 s,@LOCAL_LDFLAGS@,$LOCAL_LDFLAGS,;t t
@@ -14872,7 +16011,7 @@ done; }
   esac
 
   if test x"$ac_file" != x-; then
-    { echo "$as_me:14875: creating $ac_file" >&5
+    { echo "$as_me:16014: creating $ac_file" >&5
 echo "$as_me: creating $ac_file" >&6;}
     rm -f "$ac_file"
   fi
@@ -14890,7 +16029,7 @@ echo "$as_me: creating $ac_file" >&6;}
       -) echo $tmp/stdin ;;
       [\\/$]*)
          # Absolute (can't be DOS-style, as IFS=:)
-         test -f "$f" || { { echo "$as_me:14893: error: cannot find input file: $f" >&5
+         test -f "$f" || { { echo "$as_me:16032: error: cannot find input file: $f" >&5
 echo "$as_me: error: cannot find input file: $f" >&2;}
    { (exit 1); exit 1; }; }
          echo $f;;
@@ -14903,7 +16042,7 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
            echo $srcdir/$f
          else
            # /dev/null tree
-           { { echo "$as_me:14906: error: cannot find input file: $f" >&5
+           { { echo "$as_me:16045: error: cannot find input file: $f" >&5
 echo "$as_me: error: cannot find input file: $f" >&2;}
    { (exit 1); exit 1; }; }
          fi;;
@@ -14964,7 +16103,7 @@ for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
   * )   ac_file_in=$ac_file.in ;;
   esac
 
-  test x"$ac_file" != x- && { echo "$as_me:14967: creating $ac_file" >&5
+  test x"$ac_file" != x- && { echo "$as_me:16106: creating $ac_file" >&5
 echo "$as_me: creating $ac_file" >&6;}
 
   # First look for the input files in the build tree, otherwise in the
@@ -14975,7 +16114,7 @@ echo "$as_me: creating $ac_file" >&6;}
       -) echo $tmp/stdin ;;
       [\\/$]*)
          # Absolute (can't be DOS-style, as IFS=:)
-         test -f "$f" || { { echo "$as_me:14978: error: cannot find input file: $f" >&5
+         test -f "$f" || { { echo "$as_me:16117: error: cannot find input file: $f" >&5
 echo "$as_me: error: cannot find input file: $f" >&2;}
    { (exit 1); exit 1; }; }
          echo $f;;
@@ -14988,7 +16127,7 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
            echo $srcdir/$f
          else
            # /dev/null tree
-           { { echo "$as_me:14991: error: cannot find input file: $f" >&5
+           { { echo "$as_me:16130: error: cannot find input file: $f" >&5
 echo "$as_me: error: cannot find input file: $f" >&2;}
    { (exit 1); exit 1; }; }
          fi;;
@@ -15105,7 +16244,7 @@ cat >>$CONFIG_STATUS <<\EOF
   rm -f $tmp/in
   if test x"$ac_file" != x-; then
     if cmp -s $ac_file $tmp/config.h 2>/dev/null; then
-      { echo "$as_me:15108: $ac_file is unchanged" >&5
+      { echo "$as_me:16247: $ac_file is unchanged" >&5
 echo "$as_me: $ac_file is unchanged" >&6;}
     else
       ac_dir=`$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
index bb80193fea140ed2c44b4ebe5ceffbb60d9e0993..5f069788720ac3217a7ff4766787484feb6d3b43 100644 (file)
@@ -5,7 +5,7 @@ dnl report bugs to chet@po.cwru.edu
 dnl
 dnl Process this file with autoconf to produce a configure script.
 
-# Copyright (C) 1987-2001 Free Software Foundation, Inc.
+# Copyright (C) 1987-2002 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
@@ -22,9 +22,9 @@ dnl Process this file with autoconf to produce a configure script.
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 # 02111-1307, USA.
 
-AC_REVISION([for Bash 2.05a, version 2.128, from autoconf version] AC_ACVERSION)dnl
+AC_REVISION([for Bash 2.05b, version 2.144, from autoconf version] AC_ACVERSION)dnl
 
-AC_INIT(bash, 2.05a, bug-bash@gnu.org)
+AC_INIT(bash, 2.05b, bug-bash@gnu.org)
 
 dnl make sure we are using a recent autoconf version
 AC_PREREQ(2.50)
@@ -35,7 +35,14 @@ AC_CONFIG_AUX_DIR(./support)
 AC_CONFIG_HEADERS(config.h)
 
 dnl checks for version info
-BASHVERS=2.05a
+BASHVERS=2.05b
+RELSTATUS=release
+
+dnl defaults for debug settings
+case "$RELSTATUS" in
+alp*|bet*|dev*|rc*)    DEBUG='-DDEBUG' MALLOC_DEBUG='-DMALLOC_DEBUG' ;;
+*)     DEBUG= MALLOC_DEBUG= ;;
+esac
 
 dnl canonicalize the host and os so we can do some tricky things before
 dnl parsing options
@@ -63,7 +70,7 @@ sparc-netbsd*)        opt_bash_malloc=no ;;   # needs 8-byte alignment
 mips-irix6*)   opt_bash_malloc=no ;;   # needs 8-byte alignment
 m68k-sysv)     opt_bash_malloc=no ;;   # fixes file descriptor leak in closedir
 sparc-linux*)  opt_bash_malloc=no ;;   # sparc running linux; requires ELF
-#*-freebsd*)   opt_bash_malloc=no ;;   # they claim it's better
+#*-freebsd*)   opt_bash_malloc=no ;;   # they claim it's better; I disagree
 *-openbsd*)    opt_bash_malloc=no ;;   # they claim it needs eight-bit alignment
 *-aix*)                opt_bash_malloc=no ;;   # AIX machines
 *-nextstep*)   opt_bash_malloc=no ;;   # NeXT machines running NeXTstep
@@ -79,15 +86,21 @@ sparc-linux*)       opt_bash_malloc=no ;;   # sparc running linux; requires ELF
 *-opennt*|*-interix*)  opt_bash_malloc=no ;;   # Interix, now owned by Microsoft
 esac
 
+# memory scrambling on free()
+case "${host_os}" in
+sco3.2v5*|sco3.2v4*)   opt_memscramble=no ;;
+*)                     opt_memscramble=yes ;;
+esac
+
 dnl arguments to configure
 dnl packages
-AC_ARG_WITH(afs, --with-afs            if you are running AFS, opt_afs=$withval)
-AC_ARG_WITH(bash-malloc, --with-bash-malloc    use the Bash version of malloc,opt_bash_malloc=$withval)
-AC_ARG_WITH(curses, --with-curses              use the curses library instead of the termcap library,opt_curses=$withval)
-AC_ARG_WITH(gnu-malloc, --with-gnu-malloc      synonym for --with-bash-malloc,opt_bash_malloc=$withval)
-AC_ARG_WITH(installed-readline, --with-installed-readline      use a version of the readline library that is already installed, opt_with_installed_readline=$withval)
-AC_ARG_WITH(purecov, --with-purecov            configure to postprocess with pure coverage, opt_purecov=$withval)
-AC_ARG_WITH(purify, --with-purify              configure to postprocess with purify, opt_purify=$withval)
+AC_ARG_WITH(afs, AC_HELP_STRING([--with-afs], [if you are running AFS]), opt_afs=$withval)
+AC_ARG_WITH(bash-malloc, AC_HELP_STRING([--with-bash-malloc], [use the Bash version of malloc]), opt_bash_malloc=$withval)
+AC_ARG_WITH(curses, AC_HELP_STRING([--with-curses], [use the curses library instead of the termcap library]), opt_curses=$withval)
+AC_ARG_WITH(gnu-malloc, AC_HELP_STRING([--with-gnu-malloc], [synonym for --with-bash-malloc]), opt_bash_malloc=$withval)
+AC_ARG_WITH(installed-readline, AC_HELP_STRING([--with-installed-readline], [use a version of the readline library that is already installed]), opt_with_installed_readline=$withval)
+AC_ARG_WITH(purecov, AC_HELP_STRING([--with-purecov], [configure to postprocess with pure coverage]), opt_purecov=$withval)
+AC_ARG_WITH(purify, AC_HELP_STRING([--with-purify], [configure to postprocess with purify]), opt_purify=$withval)
 
 if test "$opt_bash_malloc" = yes; then
        MALLOC_TARGET=malloc
@@ -108,6 +121,7 @@ fi
 
 if test "$opt_purify" = yes; then
        PURIFY="purify "
+       AC_DEFINE(DISABLE_MALLOC_WRAPPERS)
 else
        PURIFY=
 fi
@@ -149,14 +163,14 @@ opt_cond_command=yes
 opt_arith_for_command=yes
 opt_net_redirs=yes
 opt_progcomp=yes
-opt_largefile=yes
+opt_separate_help=no
 
 dnl options that affect how bash is compiled and linked
 opt_static_link=no
 opt_profiling=no
 
 dnl argument parsing for optional features
-AC_ARG_ENABLE(minimal-config, --enable-minimal-config  a minimal sh-like configuration, opt_minimal_config=$enableval)
+AC_ARG_ENABLE(minimal-config, AC_HELP_STRING([--enable-minimal-config], [a minimal sh-like configuration]), opt_minimal_config=$enableval)
 
 dnl a minimal configuration turns everything off, but features can be
 dnl added individually
@@ -167,37 +181,38 @@ if test $opt_minimal_config = yes; then
        opt_select=no opt_help=no opt_array_variables=no opt_dparen_arith=no
        opt_brace_expansion=no opt_disabled_builtins=no opt_command_timing=no
        opt_extended_glob=no opt_cond_command=no opt_arith_for_command=no
-       opt_net_redirs=no opt_progcomp=no
-fi
-
-AC_ARG_ENABLE(alias, --enable-alias            enable shell aliases, opt_alias=$enableval)
-AC_ARG_ENABLE(arith-for-command, --enable-arith-for-command    enable arithmetic for command, opt_arith_for_command=$enableval)
-AC_ARG_ENABLE(array-variables, --enable-array-variables        include shell array variables, opt_array_variables=$enableval)
-AC_ARG_ENABLE(bang-history, --enable-bang-history      turn on csh-style history substitution, opt_bang_history=$enableval)
-AC_ARG_ENABLE(brace-expansion, --enable-brace-expansion        include brace expansion, opt_brace_expansion=$enableval)
-AC_ARG_ENABLE(command-timing, --enable-command-timing  enable the time reserved word and command timing, opt_command_timing=$enableval)
-AC_ARG_ENABLE(cond-command, --enable-cond-command      enable the conditional command, opt_cond_command=$enableval)
-AC_ARG_ENABLE(directory-stack, --enable-directory-stack        enable builtins pushd/popd/dirs, opt_dirstack=$enableval)
-AC_ARG_ENABLE(disabled-builtins, --enable-disabled-builtins    allow disabled builtins to still be invoked, opt_disabled_builtins=$enableval)
-AC_ARG_ENABLE(dparen-arithmetic, [--enable-dparen-arithmetic   include ((...)) command], opt_dparen_arith=$enableval)
-AC_ARG_ENABLE(extended-glob, --enable-extended-glob    include ksh-style extended pattern matching, opt_extended_glob=$enableval)
-AC_ARG_ENABLE(help-builtin, --enable-help-builtin      include the help builtin, opt_help=$enableval)
-AC_ARG_ENABLE(history, --enable-history        turn on command history, opt_history=$enableval)
-AC_ARG_ENABLE(job-control, --enable-job-control        enable job control features, opt_job_control=$enableval)
-AC_ARG_ENABLE(largefile, --enable-largefile    enable support for large files, opt_largefile=$enableval)
-AC_ARG_ENABLE(net-redirections, --enable-net-redirections      enable /dev/tcp/host/port redirection, opt_net_redirs=$enableval)
-AC_ARG_ENABLE(process-substitution, --enable-process-substitution      enable process substitution, opt_process_subst=$enableval)
-AC_ARG_ENABLE(progcomp, --enable-progcomp      enable programmable completion and the complete builtin, opt_progcomp=$enableval)
-AC_ARG_ENABLE(prompt-string-decoding, --enable-prompt-string-decoding  turn on escape character decoding in prompts, opt_prompt_decoding=$enableval)
-AC_ARG_ENABLE(readline, --enable-readline      turn on command line editing, opt_readline=$enableval)
-AC_ARG_ENABLE(restricted, --enable-restricted  enable a restricted shell, opt_restricted=$enableval)
-AC_ARG_ENABLE(select, --enable-select          include select command, opt_select=$enableval)
-AC_ARG_ENABLE(usg-echo-default, --enable-usg-echo-default      a synonym for --enable-xpg-echo-default, opt_xpg_echo=$enableval)
-AC_ARG_ENABLE(xpg-echo-default, --enable-xpg-echo-default      make the echo builtin expand escape sequences by default, opt_xpg_echo=$enableval)
+       opt_net_redirs=no opt_progcomp=no opt_separate_help=no
+fi
+
+AC_ARG_ENABLE(alias, AC_HELP_STRING([--enable-alias], [enable shell aliases]), opt_alias=$enableval)
+AC_ARG_ENABLE(arith-for-command, AC_HELP_STRING([--enable-arith-for-command], [enable arithmetic for command]), opt_arith_for_command=$enableval)
+AC_ARG_ENABLE(array-variables, AC_HELP_STRING([--enable-array-variables], [include shell array variables]), opt_array_variables=$enableval)
+AC_ARG_ENABLE(bang-history, AC_HELP_STRING([--enable-bang-history], [turn on csh-style history substitution]), opt_bang_history=$enableval)
+AC_ARG_ENABLE(brace-expansion, AC_HELP_STRING([--enable-brace-expansion], [include brace expansion]), opt_brace_expansion=$enableval)
+AC_ARG_ENABLE(command-timing, AC_HELP_STRING([--enable-command-timing], [enable the time reserved word and command timing]), opt_command_timing=$enableval)
+AC_ARG_ENABLE(cond-command, AC_HELP_STRING([--enable-cond-command], [enable the conditional command]), opt_cond_command=$enableval)
+AC_ARG_ENABLE(directory-stack, AC_HELP_STRING([--enable-directory-stack], [enable builtins pushd/popd/dirs]), opt_dirstack=$enableval)
+AC_ARG_ENABLE(disabled-builtins, AC_HELP_STRING([--enable-disabled-builtins], [allow disabled builtins to still be invoked]), opt_disabled_builtins=$enableval)
+AC_ARG_ENABLE(dparen-arithmetic, AC_HELP_STRING([--enable-dparen-arithmetic], [include ((...)) command]), opt_dparen_arith=$enableval)
+AC_ARG_ENABLE(extended-glob, AC_HELP_STRING([--enable-extended-glob], [include ksh-style extended pattern matching]), opt_extended_glob=$enableval)
+AC_ARG_ENABLE(help-builtin, AC_HELP_STRING([--enable-help-builtin], [include the help builtin]), opt_help=$enableval)
+AC_ARG_ENABLE(history, AC_HELP_STRING([--enable-history], [turn on command history]), opt_history=$enableval)
+AC_ARG_ENABLE(job-control, AC_HELP_STRING([--enable-job-control], [enable job control features]), opt_job_control=$enableval)
+AC_ARG_ENABLE(net-redirections, AC_HELP_STRING([--enable-net-redirections], [enable /dev/tcp/host/port redirection]), opt_net_redirs=$enableval)
+AC_ARG_ENABLE(process-substitution, AC_HELP_STRING([--enable-process-substitution], [enable process substitution]), opt_process_subst=$enableval)
+AC_ARG_ENABLE(progcomp, AC_HELP_STRING([--enable-progcomp], [enable programmable completion and the complete builtin]), opt_progcomp=$enableval)
+AC_ARG_ENABLE(prompt-string-decoding, AC_HELP_STRING([--enable-prompt-string-decoding], [turn on escape character decoding in prompts]), opt_prompt_decoding=$enableval)
+AC_ARG_ENABLE(readline, AC_HELP_STRING([--enable-readline], [turn on command line editing]), opt_readline=$enableval)
+AC_ARG_ENABLE(restricted, AC_HELP_STRING([--enable-restricted], [enable a restricted shell]), opt_restricted=$enableval)
+AC_ARG_ENABLE(select, AC_HELP_STRING([--enable-select], [include select command]), opt_select=$enableval)
+AC_ARG_ENABLE(separate-helpfiles, AC_HELP_STRING([--enable-separate-helpfiles], [use external files for help builtin documentation]), opt_separate_help=$enableval)
+AC_ARG_ENABLE(usg-echo-default, AC_HELP_STRING([--enable-usg-echo-default], [a synonym for --enable-xpg-echo-default]), opt_xpg_echo=$enableval)
+AC_ARG_ENABLE(xpg-echo-default, AC_HELP_STRING([--enable-xpg-echo-default], [make the echo builtin expand escape sequences by default]), opt_xpg_echo=$enableval)
 
 dnl options that alter how bash is compiled and linked
-AC_ARG_ENABLE(profiling, --enable-profiling            allow profiling with gprof, opt_profiling=$enableval)
-AC_ARG_ENABLE(static-link, --enable-static-link                [link bash statically, for use as a root shell], opt_static_link=$enableval)
+AC_ARG_ENABLE(mem-scramble, AC_HELP_STRING([--enable-mem-scramble], [scramble memory on calls to malloc and free]), opt_memscramble=$enableval)
+AC_ARG_ENABLE(profiling, AC_HELP_STRING([--enable-profiling], [allow profiling with gprof]), opt_profiling=$enableval)
+AC_ARG_ENABLE(static-link, AC_HELP_STRING([--enable-static-link], [link bash statically, for use as a root shell]), opt_static_link=$enableval)
 
 dnl opt_job_control is handled later, after BASH_JOB_CONTROL_MISSING runs
 
@@ -260,12 +275,27 @@ if test $opt_progcomp = yes; then
 AC_DEFINE(PROGRAMMABLE_COMPLETION)
 fi
 
+if test $opt_memscramble = yes; then
+AC_DEFINE(MEMSCRAMBLE)
+fi
+
 if test "$opt_minimal_config" = yes; then
        TESTSCRIPT=run-minimal
 else
        TESTSCRIPT=run-all
 fi
 
+HELPDIR= HELPDIRDEFINE= HELPINSTALL=
+if test "$opt_separate_help" != no; then
+       if test "$opt_separate_help" = "yes" ; then
+               HELPDIR='${datadir}/bash'
+       else
+               HELPDIR=$opt_separate_help
+       fi
+       HELPDIRDEFINE='-H ${HELPDIR}'
+       HELPINSTALL='install-help'
+fi
+
 dnl now substitute in the values generated by arguments
 AC_SUBST(TESTSCRIPT)
 AC_SUBST(PURIFY)
@@ -279,8 +309,12 @@ AC_SUBST(MALLOC_DEP)
 
 AC_SUBST(htmldir)
 
+AC_SUBST(HELPDIR)
+AC_SUBST(HELPDIRDEFINE)
+AC_SUBST(HELPINSTALL)
+
 echo ""
-echo "Beginning configuration for bash-$BASHVERS for ${host_cpu}-${host_vendor}-${host_os}"
+echo "Beginning configuration for bash-$BASHVERS-$RELSTATUS for ${host_cpu}-${host_vendor}-${host_os}"
 echo ""
 
 dnl compilation checks
@@ -355,6 +389,7 @@ if test "$opt_profiling" = "yes"; then
        solaris2*)      ;;
        *)              opt_static_link=yes ;;
        esac
+       DEBUG= MALLOC_DEBUG=
 fi
 
 if test "$opt_static_link" = yes; then
@@ -368,11 +403,18 @@ if test "$opt_static_link" = yes; then
        fi
 fi
 
+test -z "$CPPFLAGS_FOR_BUILD" && CPPFLAGS_FOR_BUILD="$CPPFLAGS"
+test -z "$CFLAGS_FOR_BUILD" && CFLAGS_FOR_BUILD="-g"
+
 AC_SUBST(CFLAGS)
 AC_SUBST(CPPFLAGS)
 AC_SUBST(LDFLAGS)
 AC_SUBST(STATIC_LD)
 
+AC_SUBST(CFLAGS_FOR_BUILD)
+AC_SUBST(CPPFLAGS_FOR_BUILD)
+AC_SUBST(LDFLAGS_FOR_BUILD)
+
 AC_PROG_GCC_TRADITIONAL
 
 dnl BEGIN READLINE and HISTORY LIBRARY SECTION
@@ -381,7 +423,6 @@ dnl prepare to allow bash to be linked against an already-installed readline
 dnl first test that the readline version is new enough to link bash against
 if test "$opt_readline" = yes && test "$opt_with_installed_readline" != "no"
 then
-echo opt_with_installed_readline = $opt_with_installed_readline
        # If the user specified --with-installed-readline=PREFIX and PREFIX
        # is not `yes', set ac_cv_rl_prefix to PREFIX
        test $opt_with_installed_readline != "yes" && ac_cv_rl_prefix=$opt_with_installed_readline
@@ -389,7 +430,7 @@ echo opt_with_installed_readline = $opt_with_installed_readline
        RL_LIB_READLINE_VERSION
 
        case "$ac_cv_rl_version" in
-       4.[[2-9]]*|5*|6*|7*|8*|9*)      ;;
+       4.[[3-9]]*|5*|6*|7*|8*|9*)      ;;
        *)      opt_with_installed_readline=no 
                AC_MSG_WARN(installed readline library is too old to be linked with bash)
                AC_MSG_WARN(using private bash version)
@@ -530,6 +571,7 @@ AC_TYPE_SIGNAL
 dnl checks for certain version-specific system calls and libc functions
 AC_CHECK_FUNC(__setostype, AC_DEFINE(HAVE_SETOSTYPE))
 AC_CHECK_FUNC(wait3, AC_DEFINE(HAVE_WAIT3))
+AC_CHECK_FUNC(isinf, AC_DEFINE(HAVE_ISINF_IN_LIBC))
 
 dnl checks for missing libc functions
 AC_CHECK_FUNC(mkfifo,AC_DEFINE(HAVE_MKFIFO),AC_DEFINE(MKFIFO_MISSING))
@@ -542,20 +584,21 @@ AC_CHECK_FUNCS(dup2 select getdtablesize getgroups gethostname \
 AC_REPLACE_FUNCS(rename)
 
 dnl checks for c library functions
-AC_CHECK_FUNCS(bcopy bzero confstr sysconf pathconf setenv putenv \
+AC_CHECK_FUNCS(bcopy bzero confstr sysconf pathconf setenv putenv unsetenv \
                setlinebuf setvbuf setlocale strchr tcgetattr uname \
                ulimit tzset siginterrupt memmove ttyname times \
-               getaddrinfo gethostbyname getservbyname inet_aton \
+               getaddrinfo gethostbyname getservbyname getservent inet_aton \
                vsnprintf snprintf vasprintf asprintf fnmatch)
 AC_CHECK_FUNCS(isascii isblank isgraph isprint isspace isxdigit)
-AC_REPLACE_FUNCS(getcwd strcasecmp strerror strpbrk strtod)
-AC_REPLACE_FUNCS(strtol strtoul strtoll strtoull strtoimax strtoumax)
+AC_REPLACE_FUNCS(getcwd strcasecmp strerror strftime strpbrk memset)
+AC_REPLACE_FUNCS(strtod strtol strtoul strtoll strtoull strtoimax strtoumax)
 
-AC_CHECK_DECLS([strtold])
 AC_CHECK_DECLS([confstr])
-AC_CHECK_DECLS([sbrk])
 AC_CHECK_DECLS([printf])
+AC_CHECK_DECLS([sbrk])
+AC_CHECK_DECLS([strcpy])
 AC_CHECK_DECLS([strsignal])
+AC_CHECK_DECLS([strtold])
 
 BASH_CHECK_DECL(strtoimax)
 BASH_CHECK_DECL(strtol)
@@ -564,6 +607,8 @@ BASH_CHECK_DECL(strtoul)
 BASH_CHECK_DECL(strtoull)
 BASH_CHECK_DECL(strtoumax)
 
+AC_FUNC_MKTIME
+
 dnl checks for locale functions
 AC_CHECK_HEADERS(libintl.h)
 AC_CHECK_FUNCS(gettext textdomain bindtextdomain)
@@ -577,6 +622,8 @@ if test "$ac_cv_func_bindtextdomain" = "no"; then
     fi
 fi
 
+BASH_CHECK_MULTIBYTE
+
 dnl checks for the dynamic loading library functions in libc and libdl
 if test "$opt_static_link" != yes; then
 AC_CHECK_LIB(dl, dlopen)
@@ -684,18 +731,34 @@ BASH_STRUCT_DIRENT_D_FILENO
 BASH_STRUCT_WINSIZE
 BASH_STRUCT_TIMEVAL
 AC_CHECK_MEMBERS([struct stat.st_blocks])
+AC_STRUCT_TM
+AC_STRUCT_TIMEZONE
 
 dnl presence and behavior of C library functions
 BASH_FUNC_STRSIGNAL
 BASH_FUNC_OPENDIR_CHECK
 BASH_FUNC_ULIMIT_MAXFDS
 BASH_FUNC_GETENV
-if test "$ac_func_getcwd" = "yes"; then
+if test "$ac_cv_func_getcwd" = "yes"; then
 BASH_FUNC_GETCWD
 fi
 BASH_FUNC_POSIX_SETJMP
 BASH_FUNC_STRCOLL
 
+dnl If putenv or unsetenv is not present, set the right define so the
+dnl prototype and declaration in lib/sh/getenv.c will be standard-conformant
+
+if test "$ac_cv_func_putenv" = "yes"; then
+BASH_FUNC_STD_PUTENV
+else
+AC_DEFINE(HAVE_STD_PUTENV)
+fi
+if test "$ac_cv_func_unsetenv" = "yes"; then
+BASH_FUNC_STD_UNSETENV
+else
+AC_DEFINE(HAVE_STD_UNSETENV)
+fi
+
 dnl I have removed this check.  The existing libc FNM_EXTMATCH implementation
 dnl (glibc-2.2.4) disagrees with bash on the matching of incorrectly-formed
 dnl patterns (bash treats them as strings or characters to be matched without
@@ -779,14 +842,14 @@ dgux*)            LOCAL_CFLAGS=-D_DGUX_SOURCE; LOCAL_LIBS=-ldgc ;;
 isc*)          LOCAL_CFLAGS=-Disc386 ;;
 rhapsody*)     LOCAL_CFLAGS=-DRHAPSODY ;;
 darwin*)       LOCAL_CFLAGS=-DMACOSX ;;
-sco3.2v5*)     LOCAL_CFLAGS="-b elf -DWAITPID_BROKEN -DNO_MEMSCRAMBLE -DPATH_MAX=1024" ;;
-sco3.2v4*)     LOCAL_CFLAGS="-DMUST_UNBLOCK_CHLD -DNO_MEMSCRAMBLE -DPATH_MAX=1024" ;;
+sco3.2v5*)     LOCAL_CFLAGS="-b elf -DWAITPID_BROKEN -DPATH_MAX=1024" ;;
+sco3.2v4*)     LOCAL_CFLAGS="-DMUST_UNBLOCK_CHLD -DPATH_MAX=1024" ;;
 sco3.2*)       LOCAL_CFLAGS=-DMUST_UNBLOCK_CHLD ;;
 sunos4*)       LOCAL_CFLAGS=-DSunOS4 ;;
 solaris2.5*)   LOCAL_CFLAGS=-DSunOS5 ;;
 lynxos*)       LOCAL_CFLAGS=-DRECYCLES_PIDS ;;
 linux*)                LOCAL_LDFLAGS=-rdynamic ;;       # allow dynamic loading
-*qnx*)         LOCAL_CFLAGS="-Dqnx -F -3s" LOCAL_LDFLAGS="-3s -lunix -lncurses" ;;
+*qnx*)         LOCAL_CFLAGS="-Dqnx -F -3s" LOCAL_LDFLAGS="-3s" LOCAL_LIBS="-lunix -lncurses" ;;
 powerux*)      LOCAL_LIBS="-lgen" ;;
 cygwin*)       LOCAL_LIBS="-luser32" ;;
 opennt*|interix*) LOCAL_CFLAGS="-DNO_MAIN_ENV_ARG -DBROKEN_DIRENT_D_INO" ;;
@@ -866,6 +929,9 @@ AC_SUBST(AR)
 AC_SUBST(ARFLAGS)
 
 AC_SUBST(BASHVERS)
+AC_SUBST(RELSTATUS)
+AC_SUBST(DEBUG)
+AC_SUBST(MALLOC_DEBUG)
 
 AC_SUBST(host_cpu)
 AC_SUBST(host_vendor)
index 730d18e0511a07cbea2066544973e0aa5844d733..07c0693fa1d5ce571b0a9ae6be12493cc9f7b626 100644 (file)
@@ -58,13 +58,8 @@ copy_word (w)
 {
   WORD_DESC *new_word;
 
-  new_word = (WORD_DESC *)xmalloc (sizeof (WORD_DESC));
-#if 1
+  new_word = make_bare_word (w->word);
   new_word->flags = w->flags;
-#else
-  FASTCOPY ((char *)w, (char *)new_word, sizeof (WORD_DESC));
-#endif
-  new_word->word = savestring (w->word);
   return (new_word);
 }
 
@@ -74,15 +69,11 @@ WORD_LIST *
 copy_word_list (list)
      WORD_LIST *list;
 {
-  WORD_LIST *new_list, *temp;
+  WORD_LIST *new_list;
 
   for (new_list = (WORD_LIST *)NULL; list; list = list->next)
-    {
-      temp = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
-      temp->next = new_list;
-      new_list = temp;
-      new_list->word = copy_word (list->word);
-    }
+    new_list = make_word_list (copy_word (list->word), new_list);
+
   return (REVERSE_LIST (new_list, WORD_LIST *));
 }
 
@@ -128,6 +119,7 @@ copy_redirect (redirect)
     case r_deblank_reading_until:
       new_redirect->here_doc_eof = savestring (redirect->here_doc_eof);
       /*FALLTHROUGH*/
+    case r_reading_string:
     case r_appending_to:
     case r_output_direction:
     case r_input_direction:
@@ -137,10 +129,14 @@ copy_redirect (redirect)
     case r_output_force:
     case r_duplicating_input_word:
     case r_duplicating_output_word:
+    case r_move_input_word:
+    case r_move_output_word:
       new_redirect->redirectee.filename = copy_word (redirect->redirectee.filename);
       break;
     case r_duplicating_input:
     case r_duplicating_output:
+    case r_move_input:
+    case r_move_output:
     case r_close_this:
       break;
     }
@@ -253,7 +249,7 @@ copy_if_command (com)
   new_if->flags = com->flags;
   new_if->test = copy_command (com->test);
   new_if->true_case = copy_command (com->true_case);
-  new_if->false_case = copy_command (com->false_case);
+  new_if->false_case = com->false_case ? copy_command (com->false_case) : com->false_case;
   return (new_if);
 }
 
@@ -301,7 +297,7 @@ copy_simple_command (com)
   new_simple = (SIMPLE_COM *)xmalloc (sizeof (SIMPLE_COM));
   new_simple->flags = com->flags;
   new_simple->words = copy_word_list (com->words);
-  new_simple->redirects = copy_redirects (com->redirects);
+  new_simple->redirects = com->redirects ? copy_redirects (com->redirects) : (REDIRECT *)NULL;
   new_simple->line = com->line;
   return (new_simple);
 }
index 7a9f2027d6176d0ac9557c4e79cb56fd48e06401..90515df8f4e45656cd2eeedb8eb11842fa4b2c66 100644 (file)
@@ -29,6 +29,8 @@
 #include "bashansi.h"
 #include "shell.h"
 
+extern sh_obj_cache_t wdcache, wlcache;
+
 /* Dispose of the command structure passed. */
 void
 dispose_command (command)
@@ -222,7 +224,11 @@ dispose_word (w)
      WORD_DESC *w;
 {
   FREE (w->word);
+#if 0
   free (w);
+#else
+  ocache_free (wdcache, WORD_DESC, w);
+#endif
 }
 
 /* How to get rid of a linked list of words.  A WORD_LIST. */
@@ -237,7 +243,11 @@ dispose_words (list)
       t = list;
       list = list->next;
       dispose_word (t->word);
+#if 0
       free (t);
+#else
+      ocache_free (wlcache, WORD_LIST, t);
+#endif
     }
 }
 
@@ -277,6 +287,7 @@ dispose_redirects (list)
        case r_deblank_reading_until:
          free (t->here_doc_eof);
        /*FALLTHROUGH*/
+       case r_reading_string:
        case r_output_direction:
        case r_input_direction:
        case r_inputa_direction:
@@ -286,6 +297,8 @@ dispose_redirects (list)
        case r_output_force:
        case r_duplicating_input_word:
        case r_duplicating_output_word:
+       case r_move_input_word:
+       case r_move_output_word:
          dispose_word (t->redirectee.filename);
          /* FALLTHROUGH */
        default:
diff --git a/doc/FAQ b/doc/FAQ
index 2a4c7526c58a7b2bc217cd7dec1230089ac77e7f..b81d339a899dfdb71e64cf75e7d0b90d981cbdc8 100644 (file)
--- a/doc/FAQ
+++ b/doc/FAQ
@@ -1,4 +1,4 @@
-This is the Bash FAQ, version 3.17, for Bash version 2.05a.
+This is the Bash FAQ, version 3.20, 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
@@ -36,8 +36,8 @@ A10) What is the bash `posix mode'?
 
 Section B:  The latest version
 
-B1) What's new in version 2.05a?
-B2) Are there any user-visible incompatibilities between bash-2.05a and
+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
@@ -74,6 +74,7 @@ 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 `//'?
 
 Section F:  Things to watch out for on certain Unix versions
 
@@ -86,6 +87,8 @@ 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?
 
@@ -134,23 +137,23 @@ of Case Western Reserve University.
 
 A2)  What's the latest version?
 
-The latest version is 2.05a, first made available on Thursday, 15
-November, 2001.
+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.05a:
+The following URLs tell how to get version 2.05b:
 
-ftp://ftp.gnu.org/pub/gnu/bash/bash-2.05a.tar.gz
-ftp://ftp.cwru.edu/pub/bash/bash-2.05a.tar.gz
+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.05a.tar.gz
-ftp://ftp.cwru.edu/pub/bash/bash-doc-2.05a.tar.gz
+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?
 
@@ -187,7 +190,7 @@ 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.05a should require no local Cygnus changes to build and run under
+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
@@ -363,6 +366,10 @@ 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
@@ -370,29 +377,61 @@ 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 option or
-executing `set -o posix' after bash is running.
+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 CWRU/POSIX.NOTES in the bash
-distribution.  They are also listed in a section in the Bash
-Reference Manual.
+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.05a?
+B1) What's new in version 2.05b?
 
-The raison d'etre for bash-2.05a is to make an intermediate release
-containing principally bug fixes (some very good work was done and
-contributed after bash-2.05 was released) available before I start to
-work on the major new features to be available in the next release
-(bash-2.06 or bash-3.0 or whatever I tag it).  As such, there are
-only a few relatively minor new features.
+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.05a contains the following new features (see the manual page for
-complete descriptions and the CHANGES and NEWS files in the bash-2.05a
+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
@@ -418,8 +457,6 @@ o Readline can be configured to place the user at the same point on the line
 o Readline can be configured to skip `hidden' files (filenames with a leading
   `.' on Unix) when performing completion
 
-A short feature history dating from bash-2.0:
-
 Bash-2.05 introduced the following new features:
 
 o This version has once again reverted to using locales and strcoll(3) when
@@ -570,13 +607,13 @@ 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.05a and
+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.05a.
-They are detailed in the file COMPAT in the bash-2.05a distribution.  That
-file is not meant to be all-encompassing; send mail to bash-maintainers@gnu.org
-if you find something that's not mentioned there.
+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
 
@@ -589,6 +626,7 @@ 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
@@ -601,7 +639,7 @@ Things bash has that sh does not:
        the ${#param} parameter value length operator
        the ${!param} indirect parameter expansion operator
        the ${!param*} prefix expansion operator
-       the ${param:length[:offset]} parameter substring 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}
@@ -616,18 +654,18 @@ Things bash has that sh does not:
        DEBUG trap
        ERR trap
        variable arrays with new compound assignment syntax
-       redirections: <>, &>, >|
+       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 -p/-t.
+       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,
+                 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, suspend -f, kill -n,
+                 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
@@ -690,15 +728,17 @@ 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:length[:offset]} parameter substring 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,
@@ -707,7 +747,7 @@ Things bash has or uses that ksh88 does not:
                   PIPESTATUS, HOSTNAME, OPTERR, SHELLOPTS, GLOBIGNORE,
                   GROUPS, FUNCNAME, histchars, auto_resume
        prompt expansion with backslash escapes and command substitution
-       redirection: &> (stdout and stderr)
+       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,
@@ -727,6 +767,7 @@ Things bash has or uses that ksh88 does not:
        `**' 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)
@@ -736,7 +777,7 @@ Things ksh88 has or uses that bash does not:
        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/-u/var?prompt, set -A/-o gmacs/
+                 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
@@ -754,7 +795,7 @@ Implementation differences:
 
 C3)  Which new features in ksh-93 are not in bash, and which are?
 
-New things in ksh-93 not in bash-2.05a:
+New things in ksh-93 not in bash-2.05b:
        associative arrays
        floating point arithmetic and variables
        math library functions
@@ -775,15 +816,14 @@ New things in ksh-93 not in bash-2.05a:
        exit statuses between 0 and 255
        set -o pipefail
        `+=' variable assignment operator
-       TMOUT is default timeout for `read' and `select'
-       <&N- and >&N- redirections (combination dup and close)
        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
 
-New things in ksh-93 present in bash-2.05a:
+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]},
@@ -980,7 +1020,7 @@ ksh-93 feature             Bash equivalent
 sleep, getconf         Bash has loadable versions in examples/loadables
 ${.sh.version}         $BASH_VERSION
 print -f               printf
-hist                   alias fc=hist
+hist                   alias hist=fc
 $HISTEDIT              $FCEDIT
 
 Section E:  How can I get bash to do certain things, and why does bash do
@@ -1139,7 +1179,7 @@ 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
+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.
 
@@ -1215,10 +1255,9 @@ 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.05 and later versions have reverted to the bash-2.03 behavior of
-honoring the current locale setting when processing ranges within pattern
-matching bracket expressions ([A-Z]).  This is what POSIX.2 and SUSv2/XPG5
-specify. 
+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
@@ -1229,7 +1268,11 @@ this:
 
        AaBb...Zz
 
-which means that [A-Z] matches every letter except `z'.
+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.
@@ -1252,6 +1295,16 @@ 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'.
+
 Section F:  Things to watch out for on certain Unix versions
 
 F1) Why can't I use command line editing in my `cmdtool'?
@@ -1386,6 +1439,21 @@ to the beginning of /etc/inputrc, or bracket the key bindings in
                [...]
        $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?
@@ -1607,11 +1675,8 @@ 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.05a)
+a better bash debugger (a minimally-tested version is included with bash-2.05b)
 associative arrays
-changes to the DEBUG trap to be compatible with ksh93 (which runs the
-trap before each simple command, instead of after each one like previous
-versions)
 co-processes, but with a new-style syntax that looks like function declaration
 
 H4) What's on the bash `wish list' for future versions?
@@ -1621,7 +1686,6 @@ 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'
-an option to use external files for the long `help' text
 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
@@ -1637,7 +1701,7 @@ H5) When will the next release appear?
 The next version will appear sometime in 2002.  Never make predictions. 
 
 
-This document is Copyright 1995-2001 by Chester Ramey.
+This document is Copyright 1995-2002 by Chester Ramey.
 
 Permission is hereby granted, without written agreement and
 without license or royalty fees, to use, copy, and distribute
index f7231c7a42668ff49b35e8c4ce497209aff33f8e..3ecc5d88cb78f0a7638c72bc25f22c0f99a3fd4a 100644 (file)
@@ -65,6 +65,10 @@ PSDPI       = 300    # could be 600 if you like
 DVIPS      = dvips -D ${PSDPI} $(QUIETPS) -t ${PAPERSIZE} -o $@        # tricky
 TEXINPUTDIR = $(RL_LIBDIR)/doc
 
+# These tools might not be available; they're not required
+DVIPDF     = dvipdfm -o $@ -p ${PAPERSIZE}
+PSPDF       = gs -sPAPERSIZE=${PAPERSIZE} -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -sOutputFile=$@
+
 MKDIRS      = ${topdir}/support/mkdirs
 
 # This should be a program that converts troff to an ascii-readable format
@@ -76,7 +80,7 @@ GROFF     = groff
 HSUSER      = $(RL_LIBDIR)/doc/hsuser.texinfo
 RLUSER      = $(RL_LIBDIR)/doc/rluser.texinfo
 
-.SUFFIXES:     .0 .1 .3 .ms .ps .txt .dvi .html
+.SUFFIXES:     .0 .1 .3 .ms .ps .txt .dvi .html .pdf
 
 .1.ps:
        $(RM) $@
@@ -110,6 +114,14 @@ RLUSER      = $(RL_LIBDIR)/doc/rluser.texinfo
        $(RM) $@
        -${MAN2HTML} $< > $@
 
+.ps.pdf:
+       $(RM) $@
+       -${PSPDF} $<
+
+.dvi.pdf:
+       $(RM) $@
+       -${DVIPDF} $<
+
 all: ps info dvi text html
 nodvi: ps info text html
 
@@ -118,12 +130,14 @@ DVIFILES = bashref.dvi bashref.ps
 INFOFILES = bashref.info
 MAN0FILES = bash.0 bashbug.0 builtins.0 rbash.0
 HTMLFILES = bashref.html bash.html
+PDFFILES = bash.pdf bashref.pdf article.pdf rose94.pdf
 
 ps: ${PSFILES}
 dvi: ${DVIFILES}
 info: ${INFOFILES}
 text: ${MAN0FILES}
 html: ${HTMLFILES}
+pdf: ${PDFFILES}
 
 bashref.dvi: $(srcdir)/bashref.texi $(HSUSER) $(RLUSER)
        TEXINPUTS=.:$(TEXINPUTDIR):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/bashref.texi
@@ -148,12 +162,12 @@ new-bashref.ps: new-bashref.dvi
 new-bashref.info: $(srcdir)/new-bashref.texi $(HSUSER) $(RLUSER)
        $(MAKEINFO) --no-split -I$(TEXINPUTDIR) $(srcdir)/new-bashref.texi
 
-bash.dvi: bash.texinfo $(HSUSER) $(RLUSER)
-       TEXINPUTS=.:$(TEXINPUTDIR):$$TEXINPUTS $(TEXI2DVI) bash.texinfo
-
-bashman.ps: bash.dvi
-       $(RM) $@
-       $(DVIPS) bash.dvi
+#bash.dvi: bash.texinfo $(HSUSER) $(RLUSER)
+#      TEXINPUTS=.:$(TEXINPUTDIR):$$TEXINPUTS $(TEXI2DVI) bash.texinfo
+#
+#bashman.ps: bash.dvi
+#      $(RM) $@
+#      $(DVIPS) bash.dvi
 
 bash.txt: bash.1
 bash.ps: bash.1
@@ -167,6 +181,11 @@ builtins.0: builtins.1 bash.1
 rbash.0: rbash.1 bash.1
 article.ps: article.ms
 
+article.pdf: article.ps
+bashref.pdf: bashref.dvi
+bash.pdf: bash.ps
+rose94.pdf: rose94.ps
+
 $(MAN2HTML):   ${topdir}/support/man2html.c
        -( cd ${BUILD_DIR}/support ; ${MAKE} ${MFLAGS} man2html)
 
@@ -175,7 +194,10 @@ clean:
                *.pgs *.bt *.bts *.rw *.rws *.fns *.kys *.tps *.vrs *.o
        ${RM} core *.core
 
-distclean mostlyclean: clean
+mostlyclean: clean
+       $(RM) Makefile
+
+distclean: clean maybe-clean
        $(RM) Makefile
 
 maintainer-clean:      clean
@@ -183,6 +205,11 @@ maintainer-clean:  clean
        ${RM} ${CREATED_FAQ}
        $(RM) Makefile
 
+maybe-clean:
+       -if test "X$(topdir)" != "X$(BUILD_DIR)"; then \
+               $(RM) ${PSFILES} ${DVIFILES} ${INFOFILES} ${MAN0FILES} ${HTMLFILES}; \
+       fi
+
 installdirs:
        -test -d $(man1dir) || $(SHELL) ${MKDIRS} $(DESTDIR)$(man1dir)
        -test -d $(infodir) || $(SHELL) ${MKDIRS} $(DESTDIR)$(infodir)
@@ -250,7 +277,12 @@ inst:      bashref.texi
 
 posix: bashref.texi
        $(SHELL) ./mkposix
-       cmp -s POSIX.NOTES ../CWRU/POSIX.NOTES || mv POSIX.NOTES ../CWRU/POSIX.NOTES
-       $(RM) POSIX.NOTES
+       cmp -s POSIX ../POSIX || mv POSIX ../POSIX
+       $(RM) POSIX
+
+rbash: bashref.texi
+       $(SH) ./mkrbash
+       cmp -s RBASH ../RBASH || mv RBASH ../RBASH
+       $(RM) RBASH
 
-xdist: inst posix
+xdist: inst posix rbash
index b3e9372d083e59f15906e36c81d445d24afb1617..2b35d253e01bd5b1a1e394013946fc587e3d2cc2 100644 (file)
@@ -6,12 +6,12 @@
 .\"    Case Western Reserve University
 .\"    chet@ins.CWRU.Edu
 .\"
-.\"    Last Change: Tue Nov 13 12:55:51 EST 2001
+.\"    Last Change: Mon Jul 15 15:20:56 EDT 2002
 .\"
 .\" bash_builtins, strip all but Built-Ins section
 .if \n(zZ=1 .ig zZ
 .if \n(zY=1 .ig zY
-.TH BASH 1 "2001 November 13" "GNU Bash-2.05a"
+.TH BASH 1 "2002 July 15" "GNU Bash-2.05b"
 .\"
 .\" There's some problem with having a `@'
 .\" in a tagged paragraph with the BSD man macros.
@@ -51,8 +51,8 @@ bash \- GNU Bourne-Again SHell
 [options]
 [file]
 .SH COPYRIGHT
-.if n Bash is Copyright (C) 1989-2001 by the Free Software Foundation, Inc.
-.if t Bash is Copyright \(co 1989-2001 by the Free Software Foundation, Inc.
+.if n Bash is Copyright (C) 1989-2002 by the Free Software Foundation, Inc.
+.if t Bash is Copyright \(co 1989-2002 by the Free Software Foundation, Inc.
 .SH DESCRIPTION
 .B Bash
 is an \fBsh\fR-compatible command language interpreter that
@@ -81,6 +81,20 @@ If there are arguments after the
 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
@@ -91,12 +105,6 @@ option is present, the shell becomes
 .B "RESTRICTED SHELL"
 below).
 .TP
-.B \-i
-If the
-.B \-i
-option is present, the shell is
-.IR interactive .
-.TP
 .B \-s
 If the
 .B \-s
@@ -140,7 +148,7 @@ is equivalent to \fB\-\-\fP.
 .B Bash
 also interprets a number of multi-character options.
 These options must appear on the command line before the
-single-character options in order for them to be recognized.
+single-character options to be recognized.
 .PP
 .PD 0
 .TP
@@ -154,8 +162,8 @@ Equivalent to \fB\-D\fP.
 .B \-\-help
 Display a usage message on standard output and exit successfully.
 .TP
-.PD 0
 \fB\-\-init\-file\fP \fIfile\fP
+.PD 0
 .TP
 \fB\-\-rcfile\fP \fIfile\fP
 .PD
@@ -169,12 +177,7 @@ if the shell is interactive (see
 below).
 .TP
 .B \-\-login
-Make
-.B bash
-act as if it had been invoked as a login shell (see
-.SM
-.B INVOCATION
-below).
+Equivalent to \fB\-l\fP.
 .TP
 .B \-\-noediting
 Do not use the GNU
@@ -560,6 +563,9 @@ 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
@@ -685,7 +691,7 @@ is true.
 The \fB&&\fP and
 .if t \fB\(bv\(bv\fP
 .if n \fB||\fP
-operators do not execute \fIexpression2\fP if the value of
+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
@@ -773,8 +779,8 @@ 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
-.PD 0
 \fBwhile\fP \fIlist\fP; \fBdo\fP \fIlist\fP; \fBdone\fP
+.PD 0
 .TP
 \fBuntil\fP \fIlist\fP; \fBdo\fP \fIlist\fP; \fBdone\fP
 .PD
@@ -929,6 +935,9 @@ the eight-bit character whose value is the octal value \fInnn\fP
 .B \ex\fIHH\fP
 the eight-bit character whose value is the hexadecimal value \fIHH\fP
 (one or two hex digits)
+.TP
+.B \ec\fIx\fP
+a control-\fIx\fP character
 .PD
 .RE
 .LP
@@ -1417,7 +1426,9 @@ 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 ``.:~:/usr''.
+A sample value is
+.if t \f(CW".:~:/usr"\fP.
+.if n ".:~:/usr".
 .TP
 .B COLUMNS
 Used by the \fBselect\fP builtin command to determine the terminal width
@@ -1443,7 +1454,9 @@ 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 ``.o:~''.
+A sample value is
+.if t \f(CW".o:~"\fP.
+.if n ".o:~".
 .TP
 .B GLOBIGNORE
 A colon-separated list of patterns defining the set of filenames to
@@ -1761,7 +1774,11 @@ If the value is null, no timing information is displayed.
 A trailing newline is added when the format string is displayed.
 .TP
 .B TMOUT
-If set to a value greater than zero, the value is interpreted as the
+If set to a value greater than zero, \fBTMOUT\fP is treated as the
+default timeout for the \fBread\fP builtin.
+The \fBselect\fP command terminates if input does not arrive
+after \fBTMOUT\fP seconds when input is coming from a terminal.
+In an interactive shell, the value is interpreted as the
 number of seconds to wait for input after issuing the primary prompt.
 .B Bash
 terminates after waiting for that number of seconds if input does
@@ -2150,8 +2167,8 @@ is null or unset, nothing is substituted, otherwise the expansion of
 .I word
 is substituted.
 .TP
-.PD 0
 ${\fIparameter\fP\fB:\fP\fIoffset\fP}
+.PD 0
 .TP
 ${\fIparameter\fP\fB:\fP\fIoffset\fP\fB:\fP\fIlength\fP}
 .PD
@@ -2200,8 +2217,8 @@ or
 .BR @ ,
 the value substituted is the number of elements in the array.
 .TP
-.PD 0
 ${\fIparameter\fP\fB#\fP\fIword\fP}
+.PD 0
 .TP
 ${\fIparameter\fP\fB##\fP\fIword\fP}
 .PD
@@ -2232,8 +2249,8 @@ or
 the pattern removal operation is applied to each member of the
 array in turn, and the expansion is the resultant list.
 .TP
-.PD 0
 ${\fIparameter\fP\fB%\fP\fIword\fP}
+.PD 0
 .TP
 ${\fIparameter\fP\fB%%\fP\fIword\fP}
 .PD
@@ -2262,8 +2279,8 @@ or
 the pattern removal operation is applied to each member of the
 array in turn, and the expansion is the resultant list.
 .TP
-.PD 0
 ${\fIparameter\fP\fB/\fP\fIpattern\fP\fB/\fP\fIstring\fP}
+.PD 0
 .TP
 ${\fIparameter\fP\fB//\fP\fIpattern\fP\fB/\fP\fIstring\fP}
 .PD
@@ -2596,10 +2613,11 @@ following classes defined in the POSIX.2 standard:
 .PP
 .RS
 .B
-.if n alnum alpha ascii blank cntrl digit graph lower print punct space upper xdigit
-.if t alnum   alpha   ascii   blank   cntrl   digit   graph   lower   print   punct   space   upper   xdigit
+.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
@@ -2849,7 +2867,7 @@ 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 as follows:
+The format of here-documents is:
 .RS
 .PP
 .nf
@@ -2890,6 +2908,17 @@ line containing
 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 is expanded and supplied to the command on its standard
+input.
 .SS "Duplicating File Descriptors"
 .PP
 The redirection operator
@@ -2932,6 +2961,28 @@ do not specify a file descriptor open for output, a redirection error occurs.
 As a special case, if \fIn\fP is omitted, and \fIword\fP does not
 expand to one or more digits, 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
@@ -3058,7 +3109,11 @@ trap (see the description of the
 builtin under
 .SM
 .B SHELL BUILTIN COMMANDS
-below) is not inherited.
+below) is not inherited unless the function has been given the
+\fBtrace\fP attribute (see the description of the
+.SM
+.B declare
+builtin below).
 .PP
 Variables local to the function may be declared with the
 .B local
@@ -3101,7 +3156,7 @@ of recursive calls.
 The shell allows arithmetic expressions to be evaluated, under
 certain circumstances (see the \fBlet\fP builtin command and
 \fBArithmetic Expansion\fP).
-Evaluation is done in long integers with no check for overflow,
+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 and associativity are the same
 as in the C language.
@@ -3269,14 +3324,15 @@ True if \fIfile\fP exists and is a socket.
 True if \fIfile\fP exists and has been modified since it was last read.
 .TP
 \fIfile1\fP \-\fBnt\fP \fIfile2\fP
-True if \fIfile1\fP is newer (according to
-modification date) than \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.
+True if \fIfile1\fP is older than \fIfile2\fP, or if \fIfile2\fP exists
+and \fIfile1\fP does not.
 .TP
 \fIfile1\fP \fB\-ef\fP \fIfile2\fP
-True if \fIfile1\fP and \fIfile2\fP have the same device and
+True if \fIfile1\fP and \fIfile2\fP refer to the same device and
 inode numbers.
 .TP
 .B \-o \fIoptname\fP
@@ -3301,7 +3357,7 @@ is non-zero.
 .TP
 \fIstring1\fP \fB==\fP \fIstring2\fP
 True if the strings are equal.  \fB=\fP may be used in place of
-\fB==\fP.
+\fB==\fP for strict POSIX compliance.
 .TP
 \fIstring1\fP \fB!=\fP \fIstring2\fP
 True if the strings are not equal.
@@ -3851,6 +3907,11 @@ an ASCII bell character (07)
 .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
@@ -4328,6 +4389,11 @@ appended.
 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 
@@ -4339,6 +4405,10 @@ 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.
@@ -4616,6 +4686,16 @@ A synonym for \fByank\-last\-arg\fP.
 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 $FCEDIT ,
+.SM
+.BR $EDITOR ,
+and \fIemacs\fP as the editor, in that order.
 .PD
 .SS Commands for Changing Text
 .PP
@@ -4672,6 +4752,17 @@ lowercase the previous word, but do not move point.
 .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
@@ -4915,21 +5006,38 @@ A character is read and point is moved to the previous occurrence of that
 character.  A negative count searches for subsequent occurrences.
 .TP
 .B insert\-comment (M\-#)
-The value of the readline
+Without a numeric argument, the value of the readline
 .B comment\-begin
-variable is inserted at the beginning of the current line, and the line
-is accepted as if a newline had been typed.  The default value of
+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 file names 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 file names 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
@@ -5083,6 +5191,12 @@ default of filename completion is disabled.
 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 generates 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.
 .SH HISTORY
 When the
 .B \-o history
@@ -5460,8 +5574,8 @@ No effect; the command does nothing beyond expanding
 and performing any specified
 redirections.  A zero exit code is returned.
 .TP
-.PD 0
 \fB .\| \fP \fIfilename\fP [\fIarguments\fP]
+.PD 0
 .TP
 \fBsource\fP \fIfilename\fP [\fIarguments\fP]
 .PD
@@ -5528,8 +5642,8 @@ returns 0 unless run when job control is disabled or, when run with
 job control enabled, if \fIjobspec\fP was not found or started without
 job control.
 .TP
-.PD 0
 \fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lpsvPSV\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
@@ -5538,16 +5652,21 @@ job control.
 \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, or bind a key sequence to a
+key and function bindings, bind a key sequence to a
 .B readline
-function or macro.  The binding syntax accepted is identical to that of
+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 must be passed as a separate argument;
-e.g., '"\eC\-x\eC\-r": re\-read\-init\-file'.  Options, if supplied, have the
-following meanings:
+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
@@ -5639,7 +5758,7 @@ The return status is false if
 .I shell\-builtin
 is not a shell builtin command.
 .TP
-\fBcd\fP [\fB\-LP\fP] [\fIdir\fP]
+\fBcd\fP [\fB\-L|-P\fP] [\fIdir\fP]
 Change the current directory to \fIdir\fP.  The variable
 .SM
 .B HOME
@@ -5743,10 +5862,10 @@ will be displayed.
 The return value is true unless an invalid option is supplied, or no
 matches were generated.
 .TP
-.PD 0
-\fBcomplete\fP [\fB\-abcdefgjkvu\fP] [\fB\-o\fP \fIcomp-option\fP] [\fB\-A\fP \fIaction\fP] [\fB\-G\fP \fIglobpat\fP] [\fB\-W\fP \fIwordlist\fP] [\fB\-P\fP \fIprefix\fP] [\fB\-S\fP \fIsuffix\fP]
+\fBcomplete\fP [\fB\-abcdefgjksuv\fP] [\fB\-o\fP \fIcomp-option\fP] [\fB\-A\fP \fIaction\fP] [\fB\-G\fP \fIglobpat\fP] [\fB\-W\fP \fIwordlist\fP] [\fB\-P\fP \fIprefix\fP] [\fB\-S\fP \fIsuffix\fP]
 .br
 [\fB\-X\fP \fIfilterpat\fP] [\fB\-F\fP \fIfunction\fP] [\fB\-C\fP \fIcommand\fP] \fIname\fP [\fIname ...\fP]
+.PD 0
 .TP
 \fBcomplete\fP \fB\-pr\fP [\fIname\fP ...]
 .PD
@@ -5777,7 +5896,8 @@ beyond the simple generation of completions.
 .RS
 .TP 8
 .B default
-Use readline's default completion if the compspec generates no matches.
+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.
@@ -5786,6 +5906,10 @@ Perform directory name completion if the compspec generates no matches.
 Tell readline that the compspec generates filenames, so it can perform any
 filename\-specific processing (like adding a slash to directory names or
 suppressing trailing spaces).  Intended to be used with shell functions.
+.TP 8
+.B nospace
+Tell readline not to append a space (the default) to words completed at
+the end of the line.
 .RE
 .TP 8
 \fB\-A\fP \fIaction\fP
@@ -5847,6 +5971,9 @@ Shell reserved words.  May also be specified as \fB\-k\fP.
 .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
@@ -5935,10 +6062,10 @@ shell is not executing a loop when
 .B continue
 is executed.
 .TP
+\fBdeclare\fP [\fB\-afFirtx\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP]]
 .PD 0
-\fBdeclare\fP [\fB\-afFirx\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP]]
 .TP
-\fBtypeset\fP [\fB\-afFirx\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP]]
+\fBtypeset\fP [\fB\-afFirtx\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.
@@ -5981,6 +6108,11 @@ is performed when the variable is assigned a value.
 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 trap from the calling shell.
+The trace attribute has no special meaning for variables.
+.TP
 .B \-x
 Mark \fIname\fPs for export to subsequent commands via the environment.
 .PD
@@ -6132,9 +6264,13 @@ vertical tab
 .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 \e\fInnn\fP
 the eight-bit character whose value is the octal value \fInnn\fP
-(one to three digits)
+(one to three octal digits)
 .TP
 .B \ex\fIHH\fP
 the eight-bit character whose value is the hexadecimal value \fIHH\fP
@@ -6239,8 +6375,8 @@ A trap on
 .B EXIT
 is executed before the shell terminates.
 .TP
-.PD 0
 \fBexport\fP [\fB\-fn\fP\^] [\fIname\fP[=\fIword\fP]] ...
+.PD 0
 .TP
 .B export \-p
 .PD
@@ -6272,8 +6408,8 @@ is supplied with a
 .I name
 that is not a function.
 .TP
-.PD 0
 \fBfc\fP [\fB\-e\fP \fIename\fP] [\fB\-nlr\fP] [\fIfirst\fP] [\fIlast\fP]
+.PD 0
 .TP
 \fBfc\fP \fB\-s\fP [\fIpat\fP=\fIrep\fP] [\fIcmd\fP]
 .PD
@@ -6484,7 +6620,7 @@ 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\-r\fP] [\fB\-p\fP \fIfilename\fP] [\fB\-t\fP] [\fIname\fP]
+\fBhash\fP [\fB\-lr\fP] [\fB\-p\fP \fIfilename\fP] [\fB\-dt\fP] [\fIname\fP]
 For each
 .IR name ,
 the full file name of the command is determined by searching
@@ -6500,12 +6636,19 @@ 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.
-If no arguments are given, information about remembered commands is printed.
+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.
@@ -6524,8 +6667,8 @@ usage synopsis.
 The return status is 0 unless no command matches
 .IR pattern .
 .TP
-.PD 0
 \fBhistory [\fIn\fP]
+.PD 0
 .TP
 \fBhistory\fP \fB\-c\fP
 .TP
@@ -6598,8 +6741,8 @@ error occurs while reading or writing the history file, an invalid
 history expansion supplied as an argument to \fB\-p\fP fails.
 .RE
 .TP
-.PD 0
 \fBjobs\fP [\fB\-lnprs\fP] [ \fIjobspec\fP ... ]
+.PD 0
 .TP
 \fBjobs\fP \fB\-x\fP \fIcommand\fP [ \fIargs\fP ... ]
 .PD
@@ -6652,8 +6795,8 @@ passing it
 returning its exit status.
 .RE
 .TP
-.PD 0
 \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
@@ -6805,8 +6948,8 @@ 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.
 .TP
-.PD 0
 \fBpushd\fP [\fB\-n\fP] [\fIdir\fP]
+.PD 0
 .TP
 \fBpushd\fP [\fB\-n\fP] [+\fIn\fP] [\-\fIn\fP]
 .PD
@@ -6875,8 +7018,9 @@ 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\-t\fP \fItimeout\fP] [\fB\-a\fP \fIaname\fP] [\fB\-p\fP \fIprompt\fP] [\fB\-n\fP \fInchars\fP] [\fB\-d\fP \fIdelim\fP] [\fIname\fP ...]
-One line is read from the standard input, and the first word
+\fBread\fP [\fB\-ers\fP] [\fB\-u\fP \fIfd\fP] [\fB\-t\fP \fItimeout\fP] [\fB\-a\fP \fIaname\fP] [\fB\-p\fP \fIprompt\fP] [\fB\-n\fP \fInchars\fP] [\fB\-d\fP \fIdelim\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
@@ -6884,7 +7028,7 @@ the second word to the second
 and so on, with leftover words and their intervening separators assigned
 to the last
 .IR name .
-If there are fewer words read from the standard input than names,
+If there are fewer words read from the input stream than names,
 the remaining names are assigned empty values.
 The characters in 
 .SM
@@ -6942,6 +7086,9 @@ Cause \fBread\fP to time out and return failure if a complete line of
 input is not read within \fItimeout\fP seconds.
 This option has no effect if \fBread\fP is not reading input from the
 terminal or a pipe.
+.TP
+.B \-u \fIfd\FP
+Read input from file descriptor \fIfd\fP.
 .PD
 .PP
 If no
@@ -6949,8 +7096,9 @@ If no
 are supplied, the line read is assigned to the variable
 .SM
 .BR REPLY .
-The return code is zero, unless end-of-file is encountered or \fBread\fP
-times out.
+The return code is zero, unless end-of-file is encountered, \fBread\fP
+times out, or an invalid file descriptor is supplied as the argument to
+\fB\-u\fP.
 .RE
 .TP
 \fBreadonly\fP [\fB\-apf\fP] [\fIname\fP ...]
@@ -7573,8 +7721,8 @@ the shell is a login shell and
 .B \-f
 is not supplied, or if job control is not enabled.
 .TP
-.PD 0
 \fBtest\fP \fIexpr\fP
+.PD 0
 .TP
 \fB[\fP \fIexpr\fP \fB]\fP
 Return a status of 0 or 1 depending on
@@ -7761,7 +7909,7 @@ is invalid; otherwise
 .B trap
 returns true.
 .TP
-\fBtype\fP [\fB\-atp\fP] \fIname\fP [\fIname\fP ...]
+\fBtype\fP [\fB\-aftpP\fP] \fIname\fP [\fIname\fP ...]
 With no options, 
 indicate how each
 .I name
@@ -7798,9 +7946,21 @@ or nothing if
 .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
-prints the hashed value, not necessarily the file that appears
+and
+.B \-P
+print the hashed value, not necessarily the file that appears
 first in 
 .SM
 .BR PATH .
@@ -7818,6 +7978,9 @@ 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 any of the arguments are found, false if
 none are found.
@@ -8057,6 +8220,8 @@ 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
index b1995a7f2f043005bb654a2397cb7886d9047df4..8f1b799c6b233eab2e0fac115d5c4944143db28d 100644 (file)
@@ -1,4 +1,4 @@
-This is bashref.info, produced by makeinfo version 4.0 from
+This is bashref.info, produced by makeinfo version 4.1 from
 /usr/homes/chet/src/bash/src/doc/bashref.texi.
 
 INFO-DIR-SECTION Utilities
@@ -9,11 +9,11 @@ END-INFO-DIR-ENTRY
 This text is a brief description of the features that are present in
 the Bash shell.
 
-This is Edition 2.5a, last updated 13 November 2001,
+This is Edition 2.5b, last updated 15 July 2002,
 of `The GNU Bash Reference Manual',
-for `Bash', Version 2.05a.
+for `Bash', Version 2.05b.
 
-Copyright (C) 1991-2001 Free Software Foundation, Inc.
+Copyright (C) 1991-2002 Free Software Foundation, Inc.
 
 Permission is granted to make and distribute verbatim copies of
 this manual provided the copyright notice and this permission notice
@@ -38,10 +38,10 @@ Bash Features
    This text is a brief description of the features that are present in
 the Bash shell.
 
-   This is Edition 2.5a, last updated 13 November 2001, of `The GNU
-Bash Reference Manual', for `Bash', Version 2.05a.
+   This is Edition 2.5b, last updated 15 July 2002, of `The GNU Bash
+Reference Manual', for `Bash', Version 2.05b.
 
-   Copyright (C) 1991, 1993, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1991-2002 Free Software Foundation, Inc.
 
    Bash contains features that appear in other popular shells, and some
 features that only appear in Bash.  Some of the shells that Bash has
@@ -482,6 +482,9 @@ present, are decoded as follows:
      the eight-bit character whose value is the hexadecimal value HH
      (one or two hex digits)
 
+`\cX'
+     a control-X character
+
 The expanded result is single-quoted, as if the dollar sign had not
 been present.
 
@@ -607,6 +610,9 @@ of `;', `&', or a `newline'.
    Of these list operators, `&&' and `||' have equal precedence,
 followed by `;' and `&', which have equal precedence.
 
+   A sequence of one or more newlines may appear in a `list' to delimit
+commands, equivalent to a semicolon.
+
    If a command is terminated by the control operator `&', the shell
 executes the command asynchronously in a subshell.  This is known as
 executing the command in the BACKGROUND.  The shell does not wait for
@@ -832,9 +838,9 @@ Conditional Constructs
     `EXPRESSION1 || EXPRESSION2'
           True if either EXPRESSION1 or EXPRESSION2 is true.
 
-     The `&&' and `||' commands do not execute EXPRESSION2 if the value
-     of EXPRESSION1 is sufficient to determine the return value of the
-     entire conditional expression.
+     The `&&' and `||' operators do not evaluate EXPRESSION2 if the
+     value of EXPRESSION1 is sufficient to determine the return value
+     of the entire conditional expression.
 
 \1f
 File: bashref.info,  Node: Command Grouping,  Prev: Conditional Constructs,  Up: Shell Commands
@@ -1530,9 +1536,11 @@ quoted if they are to be matched literally.
      syntax `[:'CLASS`:]', where CLASS is one of the following classes
      defined in the POSIX 1003.2 standard:
           alnum   alpha   ascii   blank   cntrl   digit   graph   lower
-          print   punct   space   upper   xdigit
+          print   punct   space   upper   word    xdigit
 
      A character class matches any character belonging to that class.
+     The `word' character class matches letters, digits, and the
+     character `_'.
 
      Within `[' and `]', an EQUIVALENCE CLASS can be specified using
      the syntax `[='C`=]', which matches all characters with the same
@@ -1645,19 +1653,19 @@ expansion of WORD to be opened for reading on file descriptor `n', or
 the standard input (file descriptor 0) if `n' is not specified.
 
    The general format for redirecting input is:
-     [n]<WORD
+     [N]<WORD
 
 Redirecting Output
 ------------------
 
    Redirection of output causes the file whose name results from the
-expansion of WORD to be opened for writing on file descriptor `n', or
-the standard output (file descriptor 1) if `n' is not specified.  If
-the file does not exist it is created; if it does exist it is truncated
-to zero size.
+expansion of WORD to be opened for writing on file descriptor N, or the
+standard output (file descriptor 1) if 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:
-     [n]>[|]WORD
+     [N]>[|]WORD
 
    If the redirection operator is `>', and the `noclobber' option to
 the `set' builtin has been enabled, the redirection will fail if the
@@ -1671,11 +1679,11 @@ Appending Redirected Output
 
    Redirection of output in this fashion causes the file whose name
 results from the expansion of WORD to be opened for appending on file
-descriptor `n', or the standard output (file descriptor 1) if `n' is
-not specified.  If the file does not exist it is created.
+descriptor N, or the standard output (file descriptor 1) if N is not
+specified.  If the file does not exist it is created.
 
    The general format for appending output is:
-     [n]>>WORD
+     [N]>>WORD
 
 Redirecting Standard Output and Standard Error
 ----------------------------------------------
@@ -1703,7 +1711,7 @@ current source until a line containing only 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 as follows:
+   The format of here-documents is:
      <<[-]WORD
              HERE-DOCUMENT
      DELIMITER
@@ -1722,38 +1730,63 @@ characters are stripped from input lines and the line containing
 DELIMITER.  This allows here-documents within shell scripts to be
 indented in a natural fashion.
 
+Here Strings
+------------
+
+   A variant of here documents, the format is:
+     <<< WORD
+
+   The WORD is expanded and supplied to the command on its standard
+input.
+
 Duplicating File Descriptors
 ----------------------------
 
    The redirection operator
-     [n]<&WORD
+     [N]<&WORD
 
 is used to duplicate input file descriptors.  If WORD expands to one or
-more digits, the file descriptor denoted by `n' is made to be a copy of
+more digits, the file descriptor denoted by N is made to be a copy of
 that file descriptor.  If the digits in WORD do not specify a file
 descriptor open for input, a redirection error occurs.  If WORD
-evaluates to `-', file descriptor `n' is closed.  If `n' is not
-specified, the standard input (file descriptor 0) is used.
+evaluates to `-', file descriptor N is closed.  If N is not specified,
+the standard input (file descriptor 0) is used.
 
    The operator
-     [n]>&WORD
+     [N]>&WORD
 
-is used similarly to duplicate output file descriptors.  If `n' is not
+is used similarly to duplicate output file descriptors.  If N is not
 specified, the standard output (file descriptor 1) is used.  If the
 digits in WORD do not specify a file descriptor open for output, a
-redirection error occurs.  As a special case, if `n' is omitted, and
-WORD does not expand to one or more digits, the standard output and
-standard error are redirected as described previously.
+redirection error occurs.  As a special case, if N is omitted, and WORD
+does not expand to one or more digits, the standard output and standard
+error are redirected as described previously.
+
+Moving File Descriptors
+-----------------------
+
+   The redirection operator
+     [N]<&DIGIT-
+
+moves the file descriptor DIGIT to file descriptor N, or the standard
+input (file descriptor 0) if N is not specified.  DIGIT is closed after
+being duplicated to N.
+
+   Similarly, the redirection operator
+     [N]>&DIGIT-
+
+moves the file descriptor DIGIT to file descriptor N, or the standard
+output (file descriptor 1) if N is not specified.
 
 Opening File Descriptors for Reading and Writing
 ------------------------------------------------
 
    The redirection operator
-     [n]<>WORD
+     [N]<>WORD
 
 causes the file whose name is the expansion of WORD to be opened for
-both reading and writing on file descriptor `n', or on file descriptor
-0 if `n' is not specified.  If the file does not exist, it is created.
+both reading and writing on file descriptor N, or on file descriptor 0
+if N is not specified.  If the file does not exist, it is created.
 
 \1f
 File: bashref.info,  Node: Executing Commands,  Next: Shell Scripts,  Prev: Redirections,  Up: Basic Shell Features
@@ -2169,7 +2202,7 @@ standard.
      greater than or equal to 1.
 
 `cd'
-          cd [-LP] [DIRECTORY]
+          cd [-L|-P] [DIRECTORY]
      Change the current working directory to DIRECTORY.  If DIRECTORY
      is not given, the value of the `HOME' shell variable is used.  If
      the shell variable `CDPATH' exists, it is used as a search path.
@@ -2268,19 +2301,22 @@ standard.
      character found.
 
 `hash'
-          hash [-r] [-p FILENAME] [-t] [NAME]
+          hash [-'r] [-p FILENAME] [-dt] [NAME]
      Remember the full pathnames of commands specified as NAME
      arguments, so they need not be searched for on subsequent
      invocations.  The commands are found by searching through the
      directories listed in `$PATH'.  The `-p' option inhibits the path
      search, and FILENAME is used as the location of NAME.  The `-r'
-     option causes the shell to forget all remembered locations.  If
-     the `-t' option is supplied, the full pathname to which each NAME
-     corresponds is printed.  If multiple NAME arguments are supplied
-     with `-t' the NAME is printed before the hashed full pathname.  If
-     no arguments are given, information about remembered commands is
-     printed.  The return status is zero unless a NAME is not found or
-     an invalid option is supplied.
+     option causes the shell to forget all remembered locations.  The
+     `-d' option causes the shell to forget the remembered location of
+     each NAME.  If the `-t' option is supplied, the full pathname to
+     which each NAME corresponds is printed.  If multiple NAME
+     arguments are supplied with `-t' the NAME is printed before the
+     hashed full pathname.  The `-l' option causes output to be
+     displayed in a format that may be reused as input.  If no
+     arguments are given, or if only `-l' is supplied, information
+     about remembered commands is printed.  The return status is zero
+     unless a NAME is not found or an invalid option is supplied.
 
 `pwd'
           pwd [-LP]
@@ -2479,12 +2515,14 @@ POSIX 1003.2 standard.
           bind [-m KEYMAP] -f FILENAME
           bind [-m KEYMAP] -x KEYSEQ:SHELL-COMMAND
           bind [-m KEYMAP] KEYSEQ:FUNCTION-NAME
+          bind READLINE-COMMAND
 
      Display current Readline (*note Command Line Editing::) key and
-     function bindings, or bind a key sequence to a Readline function
-     or macro.  The binding syntax accepted is identical to that of a
-     Readline initialization file (*note Readline Init File::), but
-     each binding must be passed as a separate argument:  e.g.,
+     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 a Readline initialization file
+     (*note Readline Init File::), but each binding or command must be
+     passed as a separate argument;  e.g.,
      `"\C-x\C-r":re-read-init-file'.  Options, if supplied, have the
      following meanings:
 
@@ -2569,7 +2607,7 @@ POSIX 1003.2 standard.
      non-zero if not.
 
 `declare'
-          declare [-afFrxi] [-p] [NAME[=VALUE]]
+          declare [-afFirtx] [-p] [NAME[=VALUE]]
 
      Declare variables and give them attributes.  If no NAMEs are
      given, then display the values of variables instead.
@@ -2596,6 +2634,11 @@ POSIX 1003.2 standard.
           Make NAMEs readonly.  These names cannot then be assigned
           values by subsequent assignment statements or unset.
 
+    `-t'
+          Give each NAME the `trace' attribute.  Traced functions
+          inherit the `DEBUG' trap from the calling shell.  The trace
+          attribute has no special meaning for variables.
+
     `-x'
           Mark each NAME for export to subsequent commands via the
           environment.
@@ -2655,9 +2698,13 @@ POSIX 1003.2 standard.
     `\\'
           backslash
 
+    `\0NNN'
+          the eight-bit character whose value is the octal value NNN
+          (zero to three octal digits)
+
     `\NNN'
           the eight-bit character whose value is the octal value NNN
-          (one to three digits)
+          (one to three octal digits)
 
     `\xHH'
           the eight-bit character whose value is the hexadecimal value
@@ -2742,19 +2789,22 @@ POSIX 1003.2 standard.
      success, non-zero on failure.
 
 `read'
-          read [-ers] [-a ANAME] [-p PROMPT] [-t TIMEOUT] [-n NCHARS] [-d DELIM] [NAME ...]
-     One line is read from the standard input, and the first word is
-     assigned to the first NAME, the second word to the second NAME,
-     and so on, with leftover words and their intervening separators
-     assigned to the last NAME.  If there are fewer words read from the
-     standard input than names, the remaining names are assigned empty
-     values.  The characters in the value of the `IFS' variable are
-     used to split the line into words.  The backslash character `\'
-     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 `REPLY'.  The return code is
-     zero, unless end-of-file is encountered or `read' times out.
-     Options, if supplied, have the following meanings:
+          read [-ers] [-a ANAME] [-d DELIM] [-n NCHARS] [-p PROMPT] [-t TIMEOUT] [-u FD] [NAME ...]
+     One line is read from the standard input, or from the file
+     descriptor FD supplied as an argument to the `-u' option, and the
+     first word is assigned to the first NAME, the second word to the
+     second NAME, and so on, with leftover words and their intervening
+     separators assigned to the last 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 `IFS'
+     variable are used to split the line into words.  The backslash
+     character `\' 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 `REPLY'.  The
+     return code is zero, unless end-of-file is encountered, `read'
+     times out, or an invalid file descriptor is supplied as the
+     argument to `-u'.  Options, if supplied, have the following
+     meanings:
 
     `-a ANAME'
           The words are assigned to sequential indices of the array
@@ -2795,6 +2845,9 @@ POSIX 1003.2 standard.
           option has no effect if `read' is not reading input from the
           terminal or a pipe.
 
+    `-u FD'
+          Read input from file descriptor FD.
+
 `shopt'
           shopt [-pqsu] [-o] [OPTNAME ...]
      Toggle the values of variables controlling optional shell behavior.
@@ -2976,7 +3029,7 @@ POSIX 1003.2 standard.
      A synonym for `.' (*note Bourne Shell Builtins::).
 
 `type'
-          type [-atp] [NAME ...]
+          type [-afptP] [NAME ...]
      For each NAME, indicate how it would be interpreted if used as a
      command name.
 
@@ -2990,10 +3043,19 @@ POSIX 1003.2 standard.
      disk file that would be executed, or nothing if `-t' would not
      return `file'.
 
+     The `-P' option forces a path search for each NAME, even if `-t'
+     would not return `file'.
+
+     If a command is hashed, `-p' and `-P' print the hashed value, not
+     necessarily the file that appears first in `$PATH'.
+
      If the `-a' option is used, `type' returns all of the places that
      contain an executable named FILE.  This includes aliases and
      functions, if and only if the `-p' option is not also used.
 
+     If the `-f' option is used, `type' does not attempt to find shell
+     functions, as with the `command' builtin.
+
      The return status is zero if any of the NAMES are found, non-zero
      if none are found.
 
@@ -3768,10 +3830,16 @@ Variables::).
      trailing newline is added when the format string is displayed.
 
 `TMOUT'
-     If set to a value greater than zero, the value is interpreted as
-     the number of seconds to wait for input after issuing the primary
-     prompt when the shell is interactive.  Bash terminates after that
-     number of seconds if input does not arrive.
+     If set to a value greater than zero, `TMOUT' is treated as the
+     default timeout for the `read' builtin (*note Bash Builtins::).
+     The `select' command (*note Conditional Constructs::) terminates
+     if input does not arrive after `TMOUT' seconds when input is coming
+     from a terminal.
+
+     In an interative shell, the value is interpreted as the number of
+     seconds to wait for input after issuing the primary prompt when
+     the shell is interactive.  Bash terminates after that number of
+     seconds if input does not arrive.
 
 `UID'
      The numeric real user id of the current user.  This variable is
@@ -3815,7 +3883,7 @@ Invoking Bash
    In addition to the single-character shell command-line options
 (*note The Set Builtin::), there are several multi-character options
 that you can use.  These options must appear on the command line before
-the single-character options in order for them to be recognized.
+the single-character options to be recognized.
 
 `--dump-po-strings'
      A list of all double-quoted strings preceded by `$' is printed on
@@ -3834,13 +3902,7 @@ the single-character options in order for them to be recognized.
      interactive shell.
 
 `--login'
-     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 `exec -l bash'.  When the shell is not
-     interactive, the login shell startup files will be executed.
-     `exec bash --login' will replace the current shell with a Bash
-     login shell.  *Note Bash Startup Files::, for a description of the
-     special behavior of a login shell.
+     Equivalent to `-l'.
 
 `--noediting'
      Do not use the GNU Readline library (*note Command Line Editing::)
@@ -3885,6 +3947,15 @@ invocation which are not available with the `set' builtin.
      Force the shell to run interactively.  Interactive shells are
      described in *Note Interactive Shells::.
 
+`-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 `exec -l bash'.  When the shell is not
+     interactive, the login shell startup files will be executed.
+     `exec bash -l' or `exec bash --login' will replace the current
+     shell with a Bash login shell.  *Note Bash Startup Files::, for a
+     description of the special behavior of a login shell.
+
 `-r'
      Make the shell a restricted shell (*note The Restricted Shell::).
 
@@ -4262,13 +4333,15 @@ checked.  If the FILE argument to one of the primaries is one of
      True if FILE exists and has been modified since it was last read.
 
 `FILE1 -nt FILE2'
-     True if FILE1 is newer (according to modification date) than FILE2.
+     True if FILE1 is newer (according to modification date) than
+     FILE2, or if FILE1 exists and FILE2 does not.
 
 `FILE1 -ot FILE2'
-     True if FILE1 is older than FILE2.
+     True if FILE1 is older than FILE2, or if FILE2 exists and FILE1
+     does not.
 
 `FILE1 -ef FILE2'
-     True if FILE1 and FILE2 have the same device and inode numbers.
+     True if FILE1 and FILE2 refer to the same device and inode numbers.
 
 `-o OPTNAME'
      True if shell option OPTNAME is enabled.  The list of options
@@ -4283,7 +4356,8 @@ checked.  If the FILE argument to one of the primaries is one of
      True if the length of STRING is non-zero.
 
 `STRING1 == STRING2'
-     True if the strings are equal.  `=' may be used in place of `=='.
+     True if the strings are equal.  `=' may be used in place of `=='
+     for strict POSIX compliance.
 
 `STRING1 != STRING2'
      True if the strings are not equal.
@@ -4312,10 +4386,10 @@ Shell Arithmetic
    The shell allows arithmetic expressions to be evaluated, as one of
 the shell expansions or by the `let' builtin.
 
-   Evaluation is done in long integers with no check for overflow,
-though division by 0 is trapped and flagged as an error.  The operators
-and their precedence and associativity are the same as in the C
-language.  The following list of operators is grouped into levels of
+   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 and associativity are the same as in the
+language.  The following list of operators is grouped into levels of
 equal-precedence operators.  The levels are listed in order of
 decreasing precedence.
 
@@ -4634,6 +4708,11 @@ which can appear in the prompt variables:
 `\d'
      The date, in "Weekday Month Date" format (e.g., "Tue May 26").
 
+`\D{FORMAT}'
+     The FORMAT is passed to `strftime'(3) and the result is inserted
+     into the prompt string; an empty FORMAT results in a
+     locale-specific time representation.  The braces are required.
+
 `\e'
      An escape character.
 
@@ -4724,11 +4803,12 @@ File: bashref.info,  Node: The Restricted Shell,  Next: Bash POSIX Mode,  Prev:
 The Restricted Shell
 ====================
 
-   If Bash is started with the name `rbash', or the `--restricted'
-option is supplied at invocation, the shell becomes restricted.  A
+   If Bash is started with the name `rbash', or the `--restricted' or
+`-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 `bash'
-with the exception that the following are disallowed:
+with the exception that the following are disallowed or not performed:
+
    * Changing directories with the `cd' builtin.
 
    * Setting or unsetting the values of the `SHELL', `PATH', `ENV', or
@@ -4756,10 +4836,19 @@ with the exception that the following are disallowed:
    * Adding or deleting builtin commands with the `-f' and `-d' options
      to the `enable' builtin.
 
+   * Using the `enable' builtin command to enable disabled shell
+     builtins.
+
    * Specifying the `-p' option to the `command' builtin.
 
    * Turning off restricted mode with `set +r' or `set +o restricted'.
 
+   These restrictions are enforced after any startup files are read.
+
+   When a command that is found to be a shell script is executed (*note
+Shell Scripts::), `rbash' turns off any restrictions in the shell
+spawned to execute the script.
+
 \1f
 File: bashref.info,  Node: Bash POSIX Mode,  Prev: The Restricted Shell,  Up: Bash Features
 
@@ -4771,6 +4860,9 @@ Bash POSIX Mode
 closely to the POSIX 1003.2 standard by changing the behavior to match
 that specified by POSIX in areas where the Bash default differs.
 
+   When invoked as `sh', Bash enters POSIX mode after reading the
+startup files.
+
    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
@@ -4881,6 +4973,11 @@ that specified by POSIX in areas where the Bash default differs.
      variable values without quotes, unless they contain shell
      metacharacters, even if the result contains nonprinting characters.
 
+ 32. When the `cd' builtin is invoked in LOGICAL mode, and the pathname
+     constructed from `$PWD' and the directory name supplied as an
+     argument does not refer to an existing directory, `cd' will fail
+     instead of falling back to PHYSICAL mode.
+
    There is other POSIX 1003.2 behavior that Bash does not implement.
 Specifically:
 
@@ -5558,6 +5655,11 @@ Variable Settings
           asterisk (`*') at the start of history lines which have been
           modified.  This variable is `off' by default.
 
+    `mark-symlinked-directories'
+          If set to `on', completed names which are symbolic links to
+          directories have a slash appended (subject to the value of
+          `mark-directories').  The default is `off'.
+
     `match-hidden-files'
           This variable, when set to `on', causes Readline to match
           files whose names begin with a `.' (hidden files) when
@@ -5570,6 +5672,11 @@ Variable Settings
           eighth bit set directly rather than as a meta-prefixed escape
           sequence.  The default is `off'.
 
+    `page-completions'
+          If set to `on', Readline uses an internal `more'-like pager
+          to display a screenful of possible completions at a time.
+          This variable is `on' by default.
+
     `print-completions-horizontally'
           If set to `on', Readline will display completions with matches
           sorted horizontally in alphabetical order, rather than down
@@ -5776,14 +5883,14 @@ binding, variable assignment, and conditional syntax.
 
 
      # This file controls the behaviour of line input editing for
-     # programs that use the Gnu Readline library.  Existing programs
-     # include FTP, Bash, and Gdb.
+     # programs that use the GNU Readline library.  Existing
+     # programs include FTP, Bash, and GDB.
      #
      # You can re-read the inputrc file with C-x C-r.
      # Lines beginning with '#' are comments.
      #
-     # First, include any systemwide bindings and variable assignments from
-     # /etc/Inputrc
+     # First, include any systemwide bindings and variable
+     # assignments from /etc/Inputrc
      $include /etc/Inputrc
      
      #
@@ -5835,10 +5942,12 @@ binding, variable assignment, and conditional syntax.
      $if Bash
      # edit the path
      "\C-xp": "PATH=${PATH}\e\C-e\C-a\ef\C-f"
-     # prepare to type a quoted word -- insert open and close double quotes
+     # prepare to type a quoted word --
+     # insert open and close double quotes
      # and move to just after the open quote
      "\C-x\"": "\"\"\C-b"
-     # insert a backslash (testing backslash escapes in sequences and macros)
+     # insert a backslash (testing backslash escapes
+     # in sequences and macros)
      "\C-x\\": "\\"
      # Quote the current or previous word
      "\C-xq": "\eb\"\ef\""
@@ -5854,16 +5963,16 @@ binding, variable assignment, and conditional syntax.
      # don't strip characters to 7 bits when reading
      set input-meta on
      
-     # allow iso-latin1 characters to be inserted rather than converted to
-     # prefix-meta sequences
+     # allow iso-latin1 characters to be inserted rather
+     # than converted to prefix-meta sequences
      set convert-meta off
      
-     # display characters with the eighth bit set directly rather than
-     # as meta-prefixed characters
+     # display characters with the eighth bit set directly
+     # rather than as meta-prefixed characters
      set output-meta on
      
-     # if there are more than 150 possible completions for a word, ask the
-     # user if he wants to see all of them
+     # if there are more than 150 possible completions for
+     # a word, ask the user if he wants to see all of them
      set completion-query-items 150
      
      # For FTP
@@ -6054,6 +6163,20 @@ Commands For Changing Text
      Capitalize the current (or following) word.  With a negative
      argument, capitalize the previous word, but do not move the cursor.
 
+`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
+     `emacs' mode; `vi' mode does overwrite differently.  Each call to
+     `readline()' starts in insert mode.
+
+     In overwrite mode, characters bound to `self-insert' replace the
+     text at point rather than pushing the text to the right.
+     Characters bound to `backward-delete-char' replace the character
+     before point with a space.
+
+     By default, this command is unbound.
+
 \1f
 File: bashref.info,  Node: Commands For Killing,  Next: Numeric Arguments,  Prev: Commands For Text,  Up: Bindable Readline Commands
 
@@ -6298,10 +6421,17 @@ Some Miscellaneous Commands
      occurrences.
 
 `insert-comment (M-#)'
-     The value of the `comment-begin' variable is inserted at the
-     beginning of the current line, and the line is accepted as if a
-     newline had been typed.  The default value of `comment-begin'
-     causes this command to make the current line a shell comment.
+     Without a numeric argument, the value of the `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 `comment-begin', the value is inserted, otherwise the
+     characters in `comment-begin' 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 `comment-begin' 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.
 
 `dump-functions ()'
      Print all of the functions and their key bindings to the Readline
@@ -6321,14 +6451,23 @@ Some Miscellaneous Commands
      output is formatted in such a way that it can be made part of an
      INPUTRC file.  This command is unbound by default.
 
+`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 file names for possible
+     completions.
+
 `glob-expand-word (C-x *)'
      The word before point is treated as a pattern for pathname
      expansion, and the list of matching file names is inserted,
-     replacing the word.
+     replacing the word.  If a numeric argument is supplied, a `*' is
+     appended before pathname expansion.
 
 `glob-list-expansions (C-x g)'
      The list of expansions that would have been generated by
-     `glob-expand-word' is displayed, and the line is redrawn.
+     `glob-expand-word' is displayed, and the line is redrawn.  If a
+     numeric argument is supplied, a `*' is appended before pathname
+     expansion.
 
 `display-shell-version (C-x C-v)'
      Display version information about the current instance of Bash.
@@ -6359,9 +6498,10 @@ Some Miscellaneous Commands
      relative to the current line from the history for editing.  Any
      argument is ignored.
 
-`emacs-editing-mode (C-e)'
-     When in `vi' editing mode, this causes a switch back to `emacs'
-     editing mode, as if the command `set -o emacs' had been executed.
+`edit-and-execute-command (C-xC-e)'
+     Invoke an editor on the current command line, and execute the
+     result as shell commands.  Bash attempts to invoke `$FCEDIT',
+     `$EDITOR', and `emacs' as the editor, in that order.
 
 \1f
 File: bashref.info,  Node: Readline vi Mode,  Next: Programmable Completion,  Prev: Bindable Readline Commands,  Up: Command Line Editing
@@ -6479,6 +6619,12 @@ supplied to `complete' when the compspec was defined, Readline's
 default completion will be performed if the compspec generates no
 matches.
 
+   When a compspec indicates that directory name completion is desired,
+the programmable completion functions force Readline to append a slash
+to completed names which are symbolic links to directories, subject to
+the value of the MARK-DIRECTORIES Readline variable, regardless of the
+setting of the MARK-SYMLINKED-DIRECTORIES Readline variable.
+
 \1f
 File: bashref.info,  Node: Programmable Completion Builtins,  Prev: Programmable Completion,  Up: Command Line Editing
 
@@ -6507,7 +6653,7 @@ completion facilities.
      no matches were generated.
 
 `complete'
-          `complete [-abcdefgjkvu] [-o COMP-OPTION] [-A ACTION] [-G GLOBPAT] [-W WORDLIST]
+          `complete [-abcdefgjksuv] [-o COMP-OPTION] [-A ACTION] [-G GLOBPAT] [-W WORDLIST]
           [-P PREFIX] [-S SUFFIX] [-X FILTERPAT] [-F FUNCTION]
           [-C COMMAND] NAME [NAME ...]'
           `complete -pr [NAME ...]'
@@ -6534,8 +6680,8 @@ completion facilities.
           COMP-OPTION may be one of:
 
          `default'
-               Use readline's default completion if the compspec
-               generates no matches.
+               Use Readline's default filename completion if the
+               compspec generates no matches.
 
          `dirnames'
                Perform directory name completion if the compspec
@@ -6548,6 +6694,10 @@ completion facilities.
                trailing spaces).  This option is intended to be used
                with shell functions specified with `-F'.
 
+         `nospace'
+               Tell Readline not to append a space (the default) to
+               words completed at the end of the line.
+
     `-A ACTION'
           The ACTION may be one of the following to generate a list of
           possible completions:
@@ -6609,6 +6759,9 @@ completion facilities.
          `running'
                Names of running jobs, if job control is active.
 
+         `service'
+               Service names.  May also be specified as `-s'.
+
          `setopt'
                Valid arguments for the `-o' option to the `set' builtin
                (*note The Set Builtin::).
@@ -7295,7 +7448,7 @@ that the Bash `configure' recognizes.
 `--with-installed-readline[=PREFIX]'
      Define this to make Bash link with a locally-installed version of
      Readline rather than the version in `lib/readline'.  This works
-     only with Readline 4.2 and later versions.  If PREFIX is `yes' or
+     only with Readline 4.3 and later versions.  If PREFIX is `yes' or
      not supplied, `configure' uses the values of the make variables
      `includedir' and `libdir', which are subdirectories of `prefix' by
      default, to find the installed version of Readline if it is not in
@@ -7321,7 +7474,8 @@ compiled and linked, rather than changing run-time features.
      Enable support for large files
      (http://www.sas.com/standards/large_file/x_open.20Mar96.html) if
      the operating system requires special compiler options to build
-     programs which can access large files.
+     programs which can access large files.  This is enabled by
+     default, if the operating system provides large file support.
 
 `--enable-profiling'
      This builds a Bash binary that produces profiling information to be
@@ -7715,7 +7869,8 @@ included in SVR4.2 as the baseline reference.
    * The `trap' builtin (*note Bourne Shell Builtins::) allows a
      `DEBUG' pseudo-signal specification, similar to `EXIT'.  Commands
      specified with a `DEBUG' trap are executed after every simple
-     command.  The `DEBUG' trap is not inherited by shell functions.
+     command.  The `DEBUG' trap is not inherited by shell functions
+     unless the function has been given the `trace' attribute.
 
      The `trap' builtin (*note Bourne Shell Builtins::) allows an `ERR'
      pseudo-signal specification, similar to `EXIT' and `DEBUG'.
@@ -7963,8 +8118,8 @@ Parameter and Variable Index
 * LC_ALL:                                Bash Variables.
 * LC_COLLATE:                            Bash Variables.
 * LC_CTYPE:                              Bash Variables.
-* LC_MESSAGES <1>:                       Bash Variables.
-* LC_MESSAGES:                           Locale Translation.
+* LC_MESSAGES <1>:                       Locale Translation.
+* LC_MESSAGES:                           Bash Variables.
 * LC_NUMERIC:                            Bash Variables.
 * LINENO:                                Bash Variables.
 * LINES:                                 Bash Variables.
@@ -7973,6 +8128,7 @@ Parameter and Variable Index
 * MAILCHECK:                             Bash Variables.
 * MAILPATH:                              Bourne Shell Variables.
 * mark-modified-lines:                   Readline Init File Syntax.
+* mark-symlinked-directories:            Readline Init File Syntax.
 * match-hidden-files:                    Readline Init File Syntax.
 * meta-flag:                             Readline Init File Syntax.
 * OLDPWD:                                Bash Variables.
@@ -7981,6 +8137,7 @@ Parameter and Variable Index
 * OPTIND:                                Bourne Shell Variables.
 * OSTYPE:                                Bash Variables.
 * output-meta:                           Readline Init File Syntax.
+* page-completions:                      Readline Init File Syntax.
 * PATH:                                  Bourne Shell Variables.
 * PIPESTATUS:                            Bash Variables.
 * POSIXLY_CORRECT:                       Bash Variables.
@@ -8059,6 +8216,7 @@ Function Index
 * next-history (C-n):                    Commands For History.
 * non-incremental-forward-search-history (M-n): Commands For History.
 * non-incremental-reverse-search-history (M-p): Commands For History.
+* overwrite-mode ():                     Commands For Text.
 * possible-completions (M-?):            Commands For Completion.
 * prefix-meta (<ESC>):                   Miscellaneous Commands.
 * previous-history (C-p):                Commands For History.
@@ -8210,126 +8368,126 @@ Concept Index
 
 \1f
 Tag Table:
-Node: Top\7f1164
-Node: Introduction\7f3300
-Node: What is Bash?\7f3525
-Node: What is a shell?\7f4626
-Node: Definitions\7f6860
-Node: Basic Shell Features\7f9600
-Node: Shell Syntax\7f10824
-Node: Shell Operation\7f11848
-Node: Quoting\7f13133
-Node: Escape Character\7f14392
-Node: Single Quotes\7f14864
-Node: Double Quotes\7f15199
-Node: ANSI-C Quoting\7f16100
-Node: Locale Translation\7f17009
-Node: Comments\7f17892
-Node: Shell Commands\7f18497
-Node: Simple Commands\7f19378
-Node: Pipelines\7f19999
-Node: Lists\7f21535
-Node: Looping Constructs\7f23048
-Node: Conditional Constructs\7f25492
-Node: Command Grouping\7f31416
-Node: Shell Functions\7f32793
-Node: Shell Parameters\7f35329
-Node: Positional Parameters\7f36903
-Node: Special Parameters\7f37794
-Node: Shell Expansions\7f40452
-Node: Brace Expansion\7f42372
-Node: Tilde Expansion\7f44041
-Node: Shell Parameter Expansion\7f46372
-Node: Command Substitution\7f53172
-Node: Arithmetic Expansion\7f54494
-Node: Process Substitution\7f55338
-Node: Word Splitting\7f56375
-Node: Filename Expansion\7f57827
-Node: Pattern Matching\7f59785
-Node: Quote Removal\7f62916
-Node: Redirections\7f63202
-Node: Executing Commands\7f70105
-Node: Simple Command Expansion\7f70772
-Node: Command Search and Execution\7f72693
-Node: Command Execution Environment\7f74690
-Node: Environment\7f77397
-Node: Exit Status\7f79048
-Node: Signals\7f80243
-Node: Shell Scripts\7f82154
-Node: Shell Builtin Commands\7f84665
-Node: Bourne Shell Builtins\7f86095
-Node: Bash Builtins\7f101581
-Node: The Set Builtin\7f125866
-Node: Special Builtins\7f132847
-Node: Shell Variables\7f133819
-Node: Bourne Shell Variables\7f134255
-Node: Bash Variables\7f136034
-Node: Bash Features\7f151763
-Node: Invoking Bash\7f152645
-Node: Bash Startup Files\7f158078
-Node: Interactive Shells\7f162948
-Node: What is an Interactive Shell?\7f163350
-Node: Is this Shell Interactive?\7f163985
-Node: Interactive Shell Behavior\7f164791
-Node: Bash Conditional Expressions\7f168058
-Node: Shell Arithmetic\7f171352
-Node: Aliases\7f173783
-Node: Arrays\7f176286
-Node: The Directory Stack\7f179306
-Node: Directory Stack Builtins\7f180012
-Node: Printing a Prompt\7f182890
-Node: The Restricted Shell\7f185306
-Node: Bash POSIX Mode\7f186784
-Node: Job Control\7f192616
-Node: Job Control Basics\7f193082
-Node: Job Control Builtins\7f197362
-Node: Job Control Variables\7f201657
-Node: Command Line Editing\7f202806
-Node: Introduction and Notation\7f203804
-Node: Readline Interaction\7f205421
-Node: Readline Bare Essentials\7f206607
-Node: Readline Movement Commands\7f208387
-Node: Readline Killing Commands\7f209343
-Node: Readline Arguments\7f211251
-Node: Searching\7f212286
-Node: Readline Init File\7f214463
-Node: Readline Init File Syntax\7f215517
-Node: Conditional Init Constructs\7f226248
-Node: Sample Init File\7f228772
-Node: Bindable Readline Commands\7f231941
-Node: Commands For Moving\7f233140
-Node: Commands For History\7f233988
-Node: Commands For Text\7f236876
-Node: Commands For Killing\7f238913
-Node: Numeric Arguments\7f240863
-Node: Commands For Completion\7f241990
-Node: Keyboard Macros\7f245570
-Node: Miscellaneous Commands\7f246128
-Node: Readline vi Mode\7f250490
-Node: Programmable Completion\7f251399
-Node: Programmable Completion Builtins\7f256447
-Node: Using History Interactively\7f263433
-Node: Bash History Facilities\7f264112
-Node: Bash History Builtins\7f266672
-Node: History Interaction\7f270238
-Node: Event Designators\7f272789
-Node: Word Designators\7f273716
-Node: Modifiers\7f275345
-Node: Installing Bash\7f276662
-Node: Basic Installation\7f277804
-Node: Compilers and Options\7f280489
-Node: Compiling For Multiple Architectures\7f281223
-Node: Installation Names\7f282880
-Node: Specifying the System Type\7f283691
-Node: Sharing Defaults\7f284400
-Node: Operation Controls\7f285065
-Node: Optional Features\7f286016
-Node: Reporting Bugs\7f293871
-Node: Major Differences From The Bourne Shell\7f294968
-Node: Builtin Index\7f309390
-Node: Reserved Word Index\7f312981
-Node: Variable Index\7f314457
-Node: Function Index\7f320619
-Node: Concept Index\7f325109
+Node: Top\7f1160
+Node: Introduction\7f3285
+Node: What is Bash?\7f3510
+Node: What is a shell?\7f4611
+Node: Definitions\7f6845
+Node: Basic Shell Features\7f9585
+Node: Shell Syntax\7f10809
+Node: Shell Operation\7f11833
+Node: Quoting\7f13118
+Node: Escape Character\7f14377
+Node: Single Quotes\7f14849
+Node: Double Quotes\7f15184
+Node: ANSI-C Quoting\7f16085
+Node: Locale Translation\7f17028
+Node: Comments\7f17911
+Node: Shell Commands\7f18516
+Node: Simple Commands\7f19397
+Node: Pipelines\7f20018
+Node: Lists\7f21554
+Node: Looping Constructs\7f23177
+Node: Conditional Constructs\7f25621
+Node: Command Grouping\7f31547
+Node: Shell Functions\7f32924
+Node: Shell Parameters\7f35460
+Node: Positional Parameters\7f37034
+Node: Special Parameters\7f37925
+Node: Shell Expansions\7f40583
+Node: Brace Expansion\7f42503
+Node: Tilde Expansion\7f44172
+Node: Shell Parameter Expansion\7f46503
+Node: Command Substitution\7f53303
+Node: Arithmetic Expansion\7f54625
+Node: Process Substitution\7f55469
+Node: Word Splitting\7f56506
+Node: Filename Expansion\7f57958
+Node: Pattern Matching\7f59916
+Node: Quote Removal\7f63140
+Node: Redirections\7f63426
+Node: Executing Commands\7f70900
+Node: Simple Command Expansion\7f71567
+Node: Command Search and Execution\7f73488
+Node: Command Execution Environment\7f75485
+Node: Environment\7f78192
+Node: Exit Status\7f79843
+Node: Signals\7f81038
+Node: Shell Scripts\7f82949
+Node: Shell Builtin Commands\7f85460
+Node: Bourne Shell Builtins\7f86890
+Node: Bash Builtins\7f102594
+Node: The Set Builtin\7f127866
+Node: Special Builtins\7f134847
+Node: Shell Variables\7f135819
+Node: Bourne Shell Variables\7f136255
+Node: Bash Variables\7f138034
+Node: Bash Features\7f154053
+Node: Invoking Bash\7f154935
+Node: Bash Startup Files\7f160399
+Node: Interactive Shells\7f165269
+Node: What is an Interactive Shell?\7f165671
+Node: Is this Shell Interactive?\7f166306
+Node: Interactive Shell Behavior\7f167112
+Node: Bash Conditional Expressions\7f170379
+Node: Shell Arithmetic\7f173798
+Node: Aliases\7f176236
+Node: Arrays\7f178739
+Node: The Directory Stack\7f181759
+Node: Directory Stack Builtins\7f182465
+Node: Printing a Prompt\7f185343
+Node: The Restricted Shell\7f187969
+Node: Bash POSIX Mode\7f189794
+Node: Job Control\7f195965
+Node: Job Control Basics\7f196431
+Node: Job Control Builtins\7f200711
+Node: Job Control Variables\7f205006
+Node: Command Line Editing\7f206155
+Node: Introduction and Notation\7f207153
+Node: Readline Interaction\7f208770
+Node: Readline Bare Essentials\7f209956
+Node: Readline Movement Commands\7f211736
+Node: Readline Killing Commands\7f212692
+Node: Readline Arguments\7f214600
+Node: Searching\7f215635
+Node: Readline Init File\7f217812
+Node: Readline Init File Syntax\7f218866
+Node: Conditional Init Constructs\7f230030
+Node: Sample Init File\7f232554
+Node: Bindable Readline Commands\7f235737
+Node: Commands For Moving\7f236936
+Node: Commands For History\7f237784
+Node: Commands For Text\7f240672
+Node: Commands For Killing\7f243332
+Node: Numeric Arguments\7f245282
+Node: Commands For Completion\7f246409
+Node: Keyboard Macros\7f249989
+Node: Miscellaneous Commands\7f250547
+Node: Readline vi Mode\7f255845
+Node: Programmable Completion\7f256754
+Node: Programmable Completion Builtins\7f262149
+Node: Using History Interactively\7f269370
+Node: Bash History Facilities\7f270049
+Node: Bash History Builtins\7f272609
+Node: History Interaction\7f276175
+Node: Event Designators\7f278726
+Node: Word Designators\7f279653
+Node: Modifiers\7f281282
+Node: Installing Bash\7f282599
+Node: Basic Installation\7f283741
+Node: Compilers and Options\7f286426
+Node: Compiling For Multiple Architectures\7f287160
+Node: Installation Names\7f288817
+Node: Specifying the System Type\7f289628
+Node: Sharing Defaults\7f290337
+Node: Operation Controls\7f291002
+Node: Optional Features\7f291953
+Node: Reporting Bugs\7f299895
+Node: Major Differences From The Bourne Shell\7f300992
+Node: Builtin Index\7f315476
+Node: Reserved Word Index\7f319067
+Node: Variable Index\7f320543
+Node: Function Index\7f326841
+Node: Concept Index\7f331391
 \1f
 End Tag Table
index 337a2b6a2afa6c34911f0874a2bdf90478613ff8..4a00d54abef365e9e2b0d832fe3f43af044a88d7 100644 (file)
@@ -5,13 +5,13 @@
 @c %**end of header
 
 @ignore
-Last Change: Tue Nov 13 12:48:51 EST 2001
+Last Change: Mon Jul 15 15:21:16 EDT 2002
 @end ignore
 
-@set EDITION 2.5a
-@set VERSION 2.05a
-@set UPDATED 13 November 2001
-@set UPDATE-MONTH November 2001
+@set EDITION 2.5b
+@set VERSION 2.05b
+@set UPDATED 15 July 2002
+@set UPDATE-MONTH July 2002
 
 @iftex
 @finalout
@@ -36,7 +36,7 @@ This is Edition @value{EDITION}, last updated @value{UPDATED},
 of @cite{The GNU Bash Reference Manual},
 for @code{Bash}, Version @value{VERSION}.
 
-Copyright (C) 1991-2001 Free Software Foundation, Inc.
+Copyright (C) 1991-2002 Free Software Foundation, Inc.
 
 Permission is granted to make and distribute verbatim copies of
 this manual provided the copyright notice and this permission notice
@@ -70,7 +70,7 @@ by the Free Software Foundation.
 @author Brian Fox, Free Software Foundation
 @page
 @vskip 0pt plus 1filll
-Copyright @copyright{} 1991-1999 Free Software Foundation, Inc.
+Copyright @copyright{} 1991-2002 Free Software Foundation, Inc.
 
 Permission is granted to make and distribute verbatim copies of
 this manual provided the copyright notice and this permission notice
@@ -100,7 +100,7 @@ This is Edition @value{EDITION}, last updated @value{UPDATED},
 of @cite{The GNU Bash Reference Manual},
 for @code{Bash}, Version @value{VERSION}.
 
-Copyright (C) 1991, 1993, 1996 Free Software Foundation, Inc.
+Copyright (C) 1991-2002 Free Software Foundation, Inc.
 
 Bash contains features that appear in other popular shells, and some
 features that only appear in Bash.  Some of the shells that Bash has
@@ -548,6 +548,8 @@ the eight-bit character whose value is the octal value @var{nnn}
 @item \x@var{HH}
 the eight-bit character whose value is the hexadecimal value @var{HH}
 (one or two hex digits)
+@item \c@var{x}
+a control-@var{x} character
 @end table
 
 @noindent
@@ -688,6 +690,9 @@ 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}.
@@ -972,7 +977,7 @@ True if both @var{expression1} and @var{expression2} are true.
 True if either @var{expression1} or @var{expression2} is true.
 @end table
 @noindent
-The @code{&&} and @code{||} commands do not execute @var{expression2} if the
+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.
 
@@ -1778,10 +1783,12 @@ using the syntax
 following classes defined in the @sc{posix} 1003.2 standard:
 @example
 alnum   alpha   ascii   blank   cntrl   digit   graph   lower
-print   punct   space   upper   xdigit
+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
@@ -1905,20 +1912,20 @@ is not specified.
 
 The general format for redirecting input is:
 @example
-[n]<@var{word}
+[@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 @code{n},
-or the standard output (file descriptor 1) if @code{n}
+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
-[n]>[|]@var{word}
+[@var{n}]>[|]@var{word}
 @end example
 
 If the redirection operator is @samp{>}, and the @code{noclobber}
@@ -1933,13 +1940,13 @@ is attempted even if the file named by @var{word} exists.
 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 @code{n},
-or the standard output (file descriptor 1) if @code{n}
+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
-[n]>>@var{word}
+[@var{n}]>>@var{word}
 @end example
 
 @subsection Redirecting Standard Output and Standard Error
@@ -1973,7 +1980,7 @@ current source until a line containing only @var{word}
 the lines read up to that point are then used as the standard
 input for a command.
 
-The format of here-documents is as follows:
+The format of here-documents is:
 @example
 <<[@minus{}]@var{word}
         @var{here-document}
@@ -1998,45 +2005,71 @@ 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} is expanded and supplied to the command on its standard
+input.
+
 @subsection Duplicating File Descriptors
 The redirection operator
 @example
-[n]<&@var{word}
+[@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 @code{n}
+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 @code{n} is closed.  If
-@code{n} is not specified, the standard input (file descriptor 0) is used.
+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
-[n]>&@var{word}
+[@var{n}]>&@var{word}
 @end example
 @noindent
 is used similarly to duplicate output file descriptors.  If
-@code{n}
-is not specified, the standard output (file descriptor 1) is used.
+@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.
-As a special case, if @code{n} is omitted, and @var{word} does not
+As a special case, if @var{n} is omitted, and @var{word} does not
 expand to one or more digits, 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
-[n]<>@var{word}
+[@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
-@code{n}, or on file descriptor 0 if @code{n}
+@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
@@ -2501,7 +2534,7 @@ The return status is zero unless @var{n} is not greater than or equal to 1.
 @item cd
 @btindex cd
 @example
-cd [-LP] [@var{directory}]
+cd [-L|-P] [@var{directory}]
 @end example
 Change the current working directory to @var{directory}.  If @var{directory}
 is not given, the value of the @env{HOME} shell variable is used.  If the
@@ -2637,7 +2670,7 @@ If @code{getopts} is silent, then a colon (@samp{:}) is placed in
 @item hash
 @btindex hash
 @example
-hash [-r] [-p @var{filename}] [-t] [@var{name}]
+hash [-'r] [-p @var{filename}] [-dt] [@var{name}]
 @end example
 Remember the full pathnames of commands specified as @var{name} arguments,
 so they need not be searched for on subsequent invocations.
@@ -2646,11 +2679,16 @@ The commands are found by searching through the directories listed in
 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.
-If no arguments are given, information about remembered commands is printed.
+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.
 
@@ -2905,14 +2943,16 @@ 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, or
-bind a key sequence to a Readline function or macro.  The
-binding syntax accepted is identical to that of
+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
 a Readline initialization file (@pxref{Readline Init File}),
-but each binding must be passed as a separate argument:  e.g.,
+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:
 
@@ -3019,7 +3059,7 @@ zero if @var{command} is found, and non-zero if not.
 @item declare
 @btindex declare
 @example
-declare [-afFrxi] [-p] [@var{name}[=@var{value}]]
+declare [-afFirtx] [-p] [@var{name}[=@var{value}]]
 @end example
 
 Declare variables and give them attributes.  If no @var{name}s
@@ -3049,6 +3089,11 @@ performed when the variable is assigned a value.
 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} trap from the calling shell.
+The trace attribute has no special meaning for variables.
+
 @item -x
 Mark each @var{name} for export to subsequent commands via
 the environment.
@@ -3106,9 +3151,12 @@ horizontal tab
 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 \@var{nnn}
 the eight-bit character whose value is the octal value @var{nnn}
-(one to three digits)
+(one 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)
@@ -3218,13 +3266,14 @@ non-zero on failure.
 @item read
 @btindex read
 @example
-read [-ers] [-a @var{aname}] [-p @var{prompt}] [-t @var{timeout}] [-n @var{nchars}] [-d @var{delim}] [@var{name} @dots{}]
+read [-ers] [-a @var{aname}] [-d @var{delim}] [-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, and the first word
+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 standard input than names,
+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.
@@ -3232,8 +3281,9 @@ 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 or @code{read}
-times out.
+The return code is zero, unless end-of-file is encountered, @code{read}
+times out, or an invalid file descriptor is supplied as the argument to
+@option{-u}.
 Options, if supplied, have the following meanings:
 
 @table @code
@@ -3275,6 +3325,9 @@ input is not read within @var{timeout} seconds.
 This option has no effect if @code{read} is not reading input from the
 terminal or a pipe.
 
+@item -u @var{fd}
+Read input from file descriptor @var{fd}.
+
 @end table
 
 @item shopt
@@ -3482,7 +3535,7 @@ A synonym for @code{.} (@pxref{Bourne Shell Builtins}).
 @item type
 @btindex type
 @example
-type [-atp] [@var{name} @dots{}]
+type [-afptP] [@var{name} @dots{}]
 @end example
 For each @var{name}, indicate how it would be interpreted if used as a
 command name.
@@ -3499,11 +3552,20 @@ 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,
+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 any of the @var{names} are found, non-zero
 if none are found.
 
@@ -4329,7 +4391,13 @@ 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, the value is interpreted as
+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 interative shell, the value is interpreted as
 the number of seconds to wait for input after issuing the primary
 prompt when the shell is interactive.
 Bash terminates after that number of seconds if input does
@@ -4374,8 +4442,7 @@ bash [long-opt] -s [-abefhkmnptuvxdBCDHP] [-o @var{option}] [-O @var{shopt_optio
 In addition to the single-character shell command-line options
 (@pxref{The Set Builtin}), there are several multi-character
 options that you can use.  These options must appear on the command
-line before the single-character options in order for them
-to be recognized. 
+line before the single-character options to be recognized. 
 
 @table @code
 @item --dump-po-strings
@@ -4396,15 +4463,7 @@ Execute commands from @var{filename} (instead of @file{~/.bashrc})
 in an interactive shell.
 
 @item --login
-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 --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.
+Equivalent to @option{-l}.
 
 @item --noediting
 Do not use the @sc{gnu} Readline library (@pxref{Command Line Editing})
@@ -4453,6 +4512,17 @@ positional parameters, starting with @code{$0}.
 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}).
 
@@ -4860,14 +4930,15 @@ True if @var{file} exists and is a socket.
 True if @var{file} exists and has been modified since it was last read.
 
 @item @var{file1} -nt @var{file2}
-True if @var{file1} is newer (according to
-modification date) than @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}.
+True if @var{file1} is older than @var{file2},
+or if @var{file2} exists and @var{file1} does not.
 
 @item @var{file1} -ef @var{file2}
-True if @var{file1} and @var{file2} have the same device and
+True if @var{file1} and @var{file2} refer to the same device and
 inode numbers.
 
 @item -o @var{optname}
@@ -4884,7 +4955,7 @@ True if the length of @var{string} is non-zero.
 
 @item @var{string1} == @var{string2}
 True if the strings are equal.
-@samp{=} may be used in place of @samp{==}.
+@samp{=} may be used in place of @samp{==} for strict @sc{posix} compliance.
 
 @item @var{string1} != @var{string2}
 True if the strings are not equal.
@@ -4919,7 +4990,7 @@ may be positive or negative integers.
 The shell allows arithmetic expressions to be evaluated, as one of
 the shell expansions or by the @code{let} builtin.
 
-Evaluation is done in long integers with no check for overflow,
+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 and associativity are the same
 as in the C language.
@@ -5277,6 +5348,10 @@ can appear in the prompt variables:
 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
@@ -5347,11 +5422,14 @@ expansion, and quote removal, subject to the value of the
 
 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:
+with the exception that the following are disallowed or not performed:
+
 @itemize @bullet
 @item
 Changing directories with the @code{cd} builtin.
@@ -5379,11 +5457,19 @@ Using the @code{exec} builtin to replace the shell with another command.
 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
@@ -5393,6 +5479,9 @@ Starting Bash with the @option{--posix} command-line option or executing
 closely to the @sc{posix} 1003.2 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
@@ -5538,6 +5627,12 @@ shell function names and definitions.
 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.
 @end enumerate
 
 There is other @sc{posix} 1003.2 behavior that Bash does not implement.
@@ -6129,7 +6224,7 @@ 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 4.2 and later versions.  If @var{PREFIX} is @code{yes} or not
+Readline 4.3 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
@@ -6158,7 +6253,8 @@ compiled and linked, rather than changing run-time features.
 @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.
+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
@@ -6628,7 +6724,8 @@ 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 after every
 simple command.
-The @code{DEBUG} trap is not inherited by shell functions.
+The @code{DEBUG} trap is not inherited by shell functions unless the
+function has been given the @code{trace} attribute.
 
 The @code{trap} builtin (@pxref{Bourne Shell Builtins}) allows an
 @code{ERR} pseudo-signal specification, similar to @code{EXIT} and @code{DEBUG}.
index 3c342b71e13cab9e335368dfbcc3357ca220b88b..800f6f1d7a20920c9dbd9907fcc338e362881928 100644 (file)
@@ -1,14 +1,13 @@
 .\" This is a hack to force bash builtins into the whatis database
 .\" and to get the list of builtins to come up with the man command.
-.TH BASH_BUILTINS 1 "2001 October 29" "GNU Bash-2.05a"
+.TH BASH_BUILTINS 1 "2001 November 27" "GNU Bash-2.05a"
 .SH NAME
-bash, :, ., [, alias, bg, bind, break, builtin, case, cd, command, compgen,
-complete, 
+bash, :, ., [, alias, bg, bind, break, builtin, cd, command, compgen, complete, 
 continue, declare, dirs, disown, echo, enable, eval, exec, exit,
-export, fc, fg, for, getopts, hash, help, history, if, jobs, kill,
+export, fc, fg, getopts, hash, help, history, jobs, kill,
 let, local, logout, popd, printf, pushd, pwd, read, readonly, return, set,
 shift, shopt, source, suspend, test, times, trap, type, typeset,
-ulimit, umask, unalias, unset, until, wait, while \- bash built-in commands, see \fBbash\fR(1)
+ulimit, umask, unalias, unset, wait \- bash built-in commands, see \fBbash\fR(1)
 .SH BASH BUILTIN COMMANDS
 .nr zZ 1
 .so bash.1
diff --git a/error.c b/error.c
index 68ea548a58e1f9f7a7e8cf1325f54b875652582b..837a3e2b4b23d97b2411fa447be907cf92486df2 100644 (file)
--- a/error.c
+++ b/error.c
@@ -29,9 +29,7 @@
 #if defined (PREFER_STDARG)
 #  include <stdarg.h>
 #else
-#  if defined (PREFER_VARARGS)
-#    include <varargs.h>
-#  endif
+#  include <varargs.h>
 #endif
 
 #include <stdio.h>
@@ -53,7 +51,9 @@ extern int errno;
 #  include "bashhist.h"
 #endif
 
-extern int interactive_shell, interactive;
+extern int executing_line_number __P((void));
+
+extern int interactive_shell, interactive, startup_state;
 extern char *dollar_vars[];
 extern char *shell_name;
 #if defined (JOB_CONTROL)
@@ -61,6 +61,8 @@ extern pid_t shell_pgrp;
 extern int give_terminal_to __P((pid_t, int));
 #endif /* JOB_CONTROL */
 
+static void error_prolog __P((int));
+
 /* The current maintainer of the shell.  You change this in the
    Makefile. */
 #if !defined (MAINTAINER)
@@ -69,6 +71,22 @@ extern int give_terminal_to __P((pid_t, int));
 
 char *the_current_maintainer = MAINTAINER;
 
+static void
+error_prolog (print_lineno)
+     int print_lineno;
+{
+  int line;
+
+  fprintf (stderr, "%s: ", get_name_for_error ());
+
+  if (print_lineno && interactive_shell == 0)
+    {
+      line = executing_line_number ();
+      if (line > 0)
+       fprintf (stderr, "line %d: ", line);
+    }
+}
+
 /* Return the name of the shell or the shell script for error reporting. */
 char *
 get_name_for_error ()
@@ -100,120 +118,6 @@ file_error (filename)
   report_error ("%s: %s", filename, strerror (errno));
 }
 
-#if !defined (USE_VARARGS)
-void
-programming_error (reason, arg1, arg2, arg3, arg4, arg5)
-     char *reason;
-{
-  char *h;
-
-#if defined (JOB_CONTROL)
-  give_terminal_to (shell_pgrp);
-#endif /* JOB_CONTROL */
-
-  report_error (reason, arg1, arg2);
-
-#if defined (HISTORY)
-  if (remember_on_history)
-    {
-      h = last_history_line ();
-      fprintf (stderr, "last command: %s\n", h ? h : "(null)");
-    }
-#endif
-
-#if 0
-  fprintf (stderr, "Report this to %s\n", the_current_maintainer);
-#endif
-
-  fprintf (stderr, "Stopping myself...");
-  fflush (stderr);
-
-  abort ();
-}
-
-void
-report_error (format, arg1, arg2, arg3, arg4, arg5)
-     char *format;
-{
-  fprintf (stderr, "%s: ", get_name_for_error ());
-
-  fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
-  fprintf (stderr, "\n");
-  if (exit_immediately_on_error)
-    exit (1);
-}
-
-void
-parser_error (lineno, format, arg1, arg2, arg3, arg4, arg5);
-     int lineno;
-     char *format;
-     va_dcl
-{
-  char *ename, *iname;
-
-  ename = get_name_for_error ();
-  iname = bash_input.name ? bash_input.name : "stdin";
-
-  if (interactive)
-    fprintf (stderr, "%s: ", ename);
-  else if (interactive_shell)
-    fprintf (stderr, "%s: %s: line %d: ", ename, iname, lineno);
-  else if (STREQ (ename, iname))
-    fprintf (stderr, "%s: line %d: ", ename, lineno);
-  else
-    fprintf (stderr, "%s: %s: line %d: ", ename, iname, lineno);
-
-  fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
-  fprintf (stderr, "\n");
-
-  if (exit_immediately_on_error)
-    exit (2);
-}
-
-void
-fatal_error (format, arg1, arg2, arg3, arg4, arg5)
-     char *format;
-{
-  fprintf (stderr, "%s: ", get_name_for_error ());
-
-  fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
-  fprintf (stderr, "\n");
-
-  exit (2);
-}
-
-void
-internal_error (format, arg1, arg2, arg3, arg4, arg5)
-     char *format;
-{
-  fprintf (stderr, "%s: ", get_name_for_error ());
-
-  fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
-  fprintf (stderr, "\n");
-}
-
-void
-internal_warning (format, arg1, arg2, arg3, arg4, arg5)
-     char *format;
-{
-  fprintf (stderr, "%s: warning: ", get_name_for_error ());
-
-  fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
-  fprintf (stderr, "\n");
-}
-
-void
-sys_error (format, arg1, arg2, arg3, arg4, arg5)
-     char *format;
-{
-  fprintf (stderr, "%s: ", get_name_for_error ());
-
-  fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
-  fprintf (stderr, ": %s\n", strerror (errno));
-}
-
-#else /* We have VARARGS support, so use it. */
-
 void
 #if defined (PREFER_STDARG)
 programming_error (const char *format, ...)
@@ -230,11 +134,7 @@ programming_error (format, va_alist)
   give_terminal_to (shell_pgrp, 0);
 #endif /* JOB_CONTROL */
 
-#if defined (PREFER_STDARG)
-  va_start (args, format);
-#else
-  va_start (args);
-#endif
+  SH_VA_START (args, format);
 
   vfprintf (stderr, format, args);
   fprintf (stderr, "\n");
@@ -258,6 +158,10 @@ programming_error (format, va_alist)
   abort ();
 }
 
+/* Print an error message and, if `set -e' has been executed, exit the
+   shell.  Used in this file by file_error and programming_error.  Used
+   outside this file mostly to report substitution and expansion errors,
+   and for bad invocation options. */
 void
 #if defined (PREFER_STDARG)
 report_error (const char *format, ...)
@@ -269,20 +173,16 @@ report_error (format, va_alist)
 {
   va_list args;
 
-  fprintf (stderr, "%s: ", get_name_for_error ());
+  error_prolog (1);
 
-#if defined (PREFER_STDARG)
-  va_start (args, format);
-#else
-  va_start (args);
-#endif
+  SH_VA_START (args, format);
 
   vfprintf (stderr, format, args);
   fprintf (stderr, "\n");
 
   va_end (args);
   if (exit_immediately_on_error)
-    exit (1);
+    sh_exit (1);
 }
 
 void
@@ -296,19 +196,15 @@ fatal_error (format, va_alist)
 {
   va_list args;
 
-  fprintf (stderr, "%s: ", get_name_for_error ());
+  error_prolog (0);
 
-#if defined (PREFER_STDARG)
-  va_start (args, format);
-#else
-  va_start (args);
-#endif
+  SH_VA_START (args, format);
 
   vfprintf (stderr, format, args);
   fprintf (stderr, "\n");
 
   va_end (args);
-  exit (2);
+  sh_exit (2);
 }
 
 void
@@ -322,13 +218,9 @@ internal_error (format, va_alist)
 {
   va_list args;
 
-  fprintf (stderr, "%s: ", get_name_for_error ());
+  error_prolog (1);
 
-#if defined (PREFER_STDARG)
-  va_start (args, format);
-#else
-  va_start (args);
-#endif
+  SH_VA_START (args, format);
 
   vfprintf (stderr, format, args);
   fprintf (stderr, "\n");
@@ -349,11 +241,7 @@ internal_warning (format, va_alist)
 
   fprintf (stderr, "%s: warning: ", get_name_for_error ());
 
-#if defined (PREFER_STDARG)
-  va_start (args, format);
-#else
-  va_start (args);
-#endif
+  SH_VA_START (args, format);
 
   vfprintf (stderr, format, args);
   fprintf (stderr, "\n");
@@ -370,18 +258,16 @@ sys_error (format, va_alist)
      va_dcl
 #endif
 {
+  int e;
   va_list args;
 
-  fprintf (stderr, "%s: ", get_name_for_error ());
+  e = errno;
+  error_prolog (0);
 
-#if defined (PREFER_STDARG)
-  va_start (args, format);
-#else
-  va_start (args);
-#endif
+  SH_VA_START (args, format);
 
   vfprintf (stderr, format, args);
-  fprintf (stderr, ": %s\n", strerror (errno));
+  fprintf (stderr, ": %s\n", strerror (e));
 
   va_end (args);
 }
@@ -408,7 +294,7 @@ parser_error (lineno, format, va_alist)
   char *ename, *iname;
 
   ename = get_name_for_error ();
-  iname = bash_input.name ? bash_input.name : "stdin";
+  iname = yy_input_name ();
 
   if (interactive)
     fprintf (stderr, "%s: ", ename);
@@ -419,11 +305,7 @@ parser_error (lineno, format, va_alist)
   else
     fprintf (stderr, "%s: %s: line %d: ", ename, iname, lineno);
 
-#if defined (PREFER_STDARG)
-  va_start (args, format);
-#else
-  va_start (args);
-#endif
+  SH_VA_START (args, format);
 
   vfprintf (stderr, format, args);
   fprintf (stderr, "\n");
@@ -431,7 +313,7 @@ parser_error (lineno, format, va_alist)
   va_end (args);
 
   if (exit_immediately_on_error)
-    exit (2);
+    sh_exit (2);
 }
 
 #ifdef DEBUG
@@ -448,11 +330,7 @@ itrace (format, va_alist)
 
   fprintf(stderr, "TRACE: pid %ld: ", (long)getpid());
 
-#if defined (PREFER_STDARG)
-  va_start (args, format);
-#else
-  va_start (args);
-#endif
+  SH_VA_START (args, format);
 
   vfprintf (stderr, format, args);
   fprintf (stderr, "\n");
@@ -486,11 +364,7 @@ trace (format, va_alist)
 
   fprintf(tracefp, "TRACE: pid %ld: ", (long)getpid());
 
-#if defined (PREFER_STDARG)
-  va_start (args, format);
-#else
-  va_start (args);
-#endif
+  SH_VA_START (args, format);
 
   vfprintf (tracefp, format, args);
   fprintf (tracefp, "\n");
@@ -500,9 +374,15 @@ trace (format, va_alist)
   fflush(tracefp);
 }
 
-#endif /* USE_VARARGS */
 #endif /* DEBUG */
 
+/* **************************************************************** */
+/*                                                                 */
+/*                 Common error reporting                          */
+/*                                                                 */
+/* **************************************************************** */
+
+
 static char *cmd_error_table[] = {
        "unknown command error",        /* CMDERR_DEFAULT */
        "bad command type",             /* CMDERR_BADTYPE */
@@ -531,3 +411,26 @@ command_errstr (code)
 
   return (cmd_error_table[code]);
 }
+
+#ifdef ARRAY_VARS
+void
+err_badarraysub (s)
+     const char *s;
+{
+  report_error ("%s: bad array subscript", s);
+}
+#endif
+
+void
+err_unboundvar (s)
+     const char *s;
+{
+  report_error ("%s: unbound variable", s);
+}
+
+void
+err_readonly (s)
+     const char *s;
+{
+  report_error ("%s: readonly variable", s);
+}
diff --git a/error.h b/error.h
index 3bdb0d03ed41a4b96db718f31344a6ff8d440580..64dc27e15c9b1e3030d9e586db209941da5a5bcb 100644 (file)
--- a/error.h
+++ b/error.h
@@ -50,12 +50,19 @@ extern void internal_error __P((const char *, ...))  __attribute__((__format__ (
 /* Report an internal warning. */
 extern void internal_warning __P((const char *, ...))  __attribute__((__format__ (printf, 1, 2)));
 
+/* Debugging function, not enabled in released version. */
+extern void itrace __P((const char *, ...)) __attribute__ ((__format__ (printf, 1, 2)));
+
 /* Report an error having to do with command parsing or execution. */
 extern void command_error __P((const char *, int, int, int));
 
 extern char *command_errstr __P((int));
 
-/* Debugging function, not enabled in released version. */
-extern void itrace __P((const char *, ...)) __attribute__ ((__format__ (printf, 1, 2)));
+/* Specific errror message functions that eventually call report_error or
+   internal_error. */
+
+extern void err_badarraysub __P((const char *));
+extern void err_unboundvar __P((const char *));
+extern void err_readonly __P((const char *));
 
 #endif /* !_ERROR_H_ */
diff --git a/eval.c b/eval.c
index b9572b9299f012760493355650db6fb2b061f26a..9908f22d445f7e6b72f533a61eb35a1a6cf3efb8 100644 (file)
--- a/eval.c
+++ b/eval.c
@@ -52,6 +52,9 @@ extern int need_here_doc;
 extern int current_command_number, current_command_line_count, line_number;
 extern int expand_aliases;
 
+static void send_pwd_to_eterm __P((void));
+static sighandler alrm_catcher __P((int));
+
 /* Read and execute commands until EOF is reached.  This assumes that
    the input source has already been initialized. */
 int
@@ -114,7 +117,8 @@ reader_loop ()
        }
 
       executing = 0;
-      dispose_used_env_vars ();
+      if (temporary_env)
+       dispose_used_env_vars ();
 
 #if (defined (ultrix) && defined (mips)) || defined (C_ALLOCA)
       /* Attempt to reclaim memory allocated with alloca (). */
@@ -240,9 +244,9 @@ read_command ()
     {
       tmout_var = find_variable ("TMOUT");
 
-      if (tmout_var && tmout_var->value)
+      if (tmout_var && var_isset (tmout_var))
        {
-         tmout_len = atoi (tmout_var->value);
+         tmout_len = atoi (value_cell (tmout_var));
          if (tmout_len > 0)
            {
              old_alrm = set_signal_handler (SIGALRM, alrm_catcher);
old mode 100644 (file)
new mode 100755 (executable)
index 97d287d..2bca9f9
-# kshdb - Korn Shell Debugger main file
-# adapted from 'Learning the Korn Shell' by Bill Rosenblatt (O'Reilly)
-# by Cigy Cyriac (cigy@felix.tulblr.unisys.com)
-# Main driver: constructs full script (with preamble) and runs it
+#! /bin/bash
+# bashdb - Bash shell debugger
+#
+# Adapted from an idea in O'Reilly's `Learning the Korn Shell'
+# Copyright (C) 1993-1994 O'Reilly and Associates, Inc.
+# Copyright (C) 1998, 1999, 2001 Gary V. Vaughan <gvv@techie.com>>
+#
+# 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 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
 
-echo 'Bourne-Again Shell Debugger version 0.1'
+# NOTE:
+#
+# This program requires bash 2.x.
+# If bash 2.x is installed as "bash2", you can invoke  bashdb like this:
+#
+#   DEBUG_SHELL=/bin/bash2 /bin/bash2 bashdb script.sh
 
-_pname=${0##*/}
+# TODO:
+#
+# break [regexp]
+# cond [break] [condition]
+# tbreak [regexp|+lines]
+# restart
+# Variable watchpoints
+# Instrument `source' and `.' files in $_potbelliedpig
+# be cleverer about lines we allow breakpoints to be set on
+# break [function_name]
 
-[ $# -eq 0 ] && {
-       echo "${_pname}: usage: ${_pname} <script_file>"
-       exit 1
-}
+echo 'Bash Debugger version 1.2.4'
+
+export _dbname=${0##*/}
+
+if test $# -lt 1; then
+  echo "$_dbname: Usage: $_dbname filename" >&2
+  exit 1
+fi
 
 _guineapig=$1
 
-[ -r $_guineapig ] || {
-       echo "${_pname}: cannot read $_guineapig." >&2
-       exit 1
-}
+if test ! -r $1; then
+  echo "$_dbname: Cannot read file '$_guineapig'." >&2
+  exit 1
+fi
+
 shift
 
-_tmpdir=/tmp
-_libdir=.
-_dbgfile=$_tmpdir/bashdb$$             #temp file for script being debugged
+__debug=${TMPDIR-/tmp}/bashdb.$$
+sed -e '/^# bashdb - Bash shell debugger/,/^# -- DO NOT DELETE THIS LINE -- /d' "$0" > $__debug
+cat $_guineapig >> $__debug
+exec ${DEBUG_SHELL-bash} $__debug $_guineapig "$@"
 
-cat $_libdir/bashdb.pre $_guineapig > $_dbgfile
-if [ -f "$BASH" ]; then
-       exec $BASH $_dbgfile $_guineapig $_tmpdir $_libdir "$@"
-else
-       exec bash $_dbgfile $_guineapig $_tmpdir $_libdir "$@"
-fi
-# end of bashdb
+exit 1
+
+# -- DO NOT DELETE THIS LINE -- The program depends on it
+
+#bashdb preamble
+# $1 name of the original guinea pig script
+
+__debug=$0
+_guineapig=$1
+__steptrap_calls=0
+
+shift
+
+shopt -s extglob       # turn on extglob so we can parse the debugger funcs
+
+function _steptrap
+{
+  local i=0
+
+  _curline=$1
+
+  if (( ++__steptrap_calls > 1 && $_curline == 1 )); then
+    return
+  fi
+
+  if [ -n "$_disps" ]; then
+    while (( $i < ${#_disps[@]} ))
+    do
+      if [ -n "${_disps[$i]}" ]; then
+        _msg "${_disps[$i]}: \c"
+        eval _msg ${_disps[$i]}
+      fi
+      let i=$i+1
+    done
+  fi
+
+  if (( $_trace )); then
+    _showline $_curline
+  fi
+
+  if (( $_steps >= 0 )); then
+    let _steps="$_steps - 1"
+  fi
+
+  if _at_linenumbp ; then
+    _msg "Reached breakpoint at line $_curline"
+    _showline $_curline
+    _cmdloop
+  elif [ -n "$_brcond" ] && eval $_brcond; then
+    _msg "Break condition $_brcond true at line $_curline"
+    _showline $_curline
+    _cmdloop
+  elif (( $_steps == 0 )); then
+    # Assuming a real script will have the "#! /bin/sh" at line 1,
+    # assume that when $_curline == 1 we are inside backticks.
+    if (( ! $_trace )); then
+      _msg "Stopped at line $_curline"
+      _showline $_curline
+    fi
+    _cmdloop
+  fi
+}
+
+function _setbp
+{
+  local i f line _x
+
+  if [ -z "$1" ]; then
+    _listbp
+    return
+  fi
+
+  eval "$_seteglob"
+
+  if [[ $1 == *(\+)[1-9]*([0-9]) ]]; then
+    case $1 in
+    +*)
+      # normalize argument, then double it (+2 -> +2 + 2 = 4)
+      _x=${1##*([!1-9])}       # cut off non-numeric prefix
+      _x=${x%%*([!0-9])}       # cut off non-numeric suffix
+      f=$(( $1 + $_x ))
+      ;;
+    *)
+      f=$(( $1 ))
+      ;;
+    esac
+
+    # find the next valid line
+    line="${_lines[$f]}"
+    while _invalidbreakp $f
+    do
+      (( f++ ))
+      line="${_lines[$f]}"
+    done
+
+    if (( $f != $1 ))
+    then
+      _msg "Line $1 is not a valid breakpoint"
+    fi
+
+    if [ -n "${_lines[$f]}" ]; then
+      _linebp[$1]=$1;
+      _msg "Breakpoint set at line $f"
+    else
+      _msg "Breakpoints can only be set on executable lines"
+    fi
+  else
+    _msg "Please specify a numeric line number"
+  fi
+
+  eval "$_resteglob"
+}
+
+function _listbp
+{
+  local i
+  
+  if [ -n "$_linebp" ]; then
+    _msg "Breakpoints:"
+    for i in ${_linebp[*]}; do
+      _showline $i
+    done
+  else
+    _msg "No breakpoints have been set"
+  fi
+}
+
+function _clearbp
+{
+  local i
+
+  if [ -z "$1" ]; then
+    read -e -p "Delete all breakpoints? "
+    case $REPLY in
+    [yY]*)
+      unset _linebp[*]
+      _msg "All breakpoints have been cleared"
+      ;;
+    esac
+    return 0
+  fi
+
+  eval "$_seteglob"
+
+  if [[ $1 == [1-9]*([0-9]) ]]; then
+    unset _linebp[$1]
+    _msg "Breakpoint cleared at line $1"
+  else
+    _msg "Please specify a numeric line number"
+  fi
+
+  eval "$_resteglob"
+}
+
+function _setbc
+{
+  if (( $# > 0 )); then
+    _brcond=$@
+    _msg "Break when true: $_brcond"
+  else
+    _brcond=
+    _msg "Break condition cleared"
+  fi
+}
+
+function _setdisp
+{
+  if [ -z "$1" ]; then
+    _listdisp
+  else
+    _disps[${#_disps[@]}]="$1"
+    if (( ${#_disps[@]} < 10 ))
+    then
+      _msg " ${#_disps[@]}: $1"
+    else
+      _msg "${#_disps[@]}: $1"
+    fi
+  fi
+}
+
+function _listdisp
+{
+  local i=0 j
+  
+  if [ -n "$_disps" ]; then
+    while (( $i < ${#_disps[@]} ))
+    do
+      let j=$i+1
+    if (( ${#_disps[@]} < 10 ))
+    then
+      _msg " $j: ${_disps[$i]}"
+    else
+      _msg "$j: ${_disps[$i]}"
+    fi
+      let i=$j
+    done
+  else
+    _msg "No displays have been set"
+  fi
+}
+
+function _cleardisp
+{
+  if (( $# < 1 )) ; then
+    read -e -p "Delete all display expressions? "
+    case $REPLY in
+    [Yy]*)
+      unset _disps[*]
+      _msg "All breakpoints have been cleared"
+      ;;
+    esac
+    return 0
+  fi
+
+  eval "$_seteglob"
+
+  if [[ $1 == [1-9]*([0-9]) ]]; then
+    unset _disps[$1]
+    _msg "Display $i has been cleared"
+  else
+    _listdisp
+    _msg "Please specify a numeric display number"
+  fi
+
+  eval "$_resteglob"
+}   
+
+# usage _ftrace -u funcname [funcname...]
+function _ftrace
+{
+  local _opt=-t _tmsg="enabled" _func 
+  if [[ $1 == -u ]]; then
+       _opt=+t
+       _tmsg="disabled"
+       shift
+  fi
+  for _func; do
+         declare -f $_opt $_func
+         _msg "Tracing $_tmsg for function $_func"
+  done
+}
+
+function _cmdloop
+{
+  local cmd args
+
+  while read -e -p "bashdb> " cmd args; do
+    test -n "$cmd" && history -s "$cmd $args"  # save on history list
+    test -n "$cmd" || { set $_lastcmd; cmd=$1; shift; args=$*; }
+    if [ -n "$cmd" ]
+    then
+      case $cmd in
+       b|br|bre|brea|break)
+         _setbp $args
+         _lastcmd="break $args"
+         ;;
+       co|con)
+         _msg "ambiguous command: '$cmd', condition, continue?"
+         ;;
+       cond|condi|condit|conditi|conditio|condition)
+         _setbc $args
+         _lastcmd="condition $args"
+         ;;
+       c|cont|conti|contin|continu|continue)
+         _lastcmd="continue"
+         return
+         ;;
+       d)
+         _msg "ambiguous command: '$cmd', delete, display?"
+         ;;
+       de|del|dele|delet|delete)
+         _clearbp $args
+         _lastcmd="delete $args"
+         ;;
+       di|dis|disp|displ|displa|display)
+         _setdisp $args
+         _lastcmd="display $args"
+         ;;
+       f|ft|ftr|ftra|ftrace)
+         _ftrace $args
+         _lastcmd="ftrace $args"
+         ;;
+       \?|h|he|hel|help)
+         _menu
+         _lastcmd="help"
+         ;;
+       l|li|lis|list)
+         _displayscript $args
+         # _lastcmd is set in the _displayscript function
+         ;;
+       p|pr|pri|prin|print)
+         _examine $args
+         _lastcmd="print $args"
+         ;;
+       q|qu|qui|quit)
+         exit
+         ;;
+       s|st|ste|step|n|ne|nex|next)
+         let _steps=${args:-1}
+         _lastcmd="next $args"
+         return
+         ;;
+       t|tr|tra|trac|trace)
+         _xtrace
+         ;;
+       u|un|und|undi|undis|undisp|undispl|undispla|undisplay)
+         _cleardisp $args
+         _lastcmd="undisplay $args"
+         ;;
+       !*)
+         eval ${cmd#!} $args
+         _lastcmd="$cmd $args"
+         ;;
+       *)
+         _msg "Invalid command: '$cmd'"
+         ;;
+      esac
+    fi
+  done
+}
+
+function _at_linenumbp
+{
+  [[ -n ${_linebp[$_curline]} ]]
+}
+
+function _invalidbreakp
+{
+  local line=${_lines[$1]}
+
+  # XXX - should use shell patterns
+  if test -z "$line" \
+      || expr "$line" : '[ \t]*#.*' > /dev/null \
+      || expr "$line" : '[ \t]*;;[ \t]*$' > /dev/null \
+      || expr "$line" : '[ \t]*[^)]*)[ \t]*$' > /dev/null \
+      || expr "$line" : '[ \t]*;;[ \t]*#.**$' > /dev/null \
+      || expr "$line" : '[ \t]*[^)]*)[ \t]*;;[ \t]*$' > /dev/null \
+      || expr "$line" : '[ \t]*[^)]*)[ \t]*;;*[ \t]*#.*$' > /dev/null
+  then
+    return 0
+  fi
+
+  return 1
+}
+
+function _examine
+{
+  if [ -n "$*" ]; then
+    _msg "$args: \c"
+    eval _msg $args
+  else
+    _msg "Nothing to print"
+  fi
+}
+
+function _displayscript
+{
+  local i j start end bp cl
+
+  if (( $# == 1 )); then       # list 5 lines on either side of $1
+    if [ $1 = "%" ]; then
+      let start=1
+      let end=${#_lines[@]}
+    else
+      let start=$1-5
+      let end=$1+5
+    fi
+  elif (( $# > 1 )); then      # list between start and end
+    if [ $1 = "^" ]; then
+      let start=1
+    else
+      let start=$1
+    fi
+
+    if [ $2 = "\$" ]; then
+      let end=${#_lines[@]}
+    else
+      let end=$2
+    fi
+  else                         # list 5 lines on either side of current line
+    let start=$_curline-5
+    let end=$_curline+5
+  fi
+
+  # normalize start and end
+  if (( $start < 1 )); then
+    start=1
+  fi
+  if (( $end > ${#_lines[@]} )); then
+    end=${#_lines[@]}
+  fi
+
+  cl=$(( $end - $start ))
+  if (( $cl > ${LINES-24} )); then
+    pager=${PAGER-more}
+  else
+    pager=cat
+  fi
+  
+  i=$start
+  ( while (( $i <= $end )); do
+      _showline $i
+      let i=$i+1
+    done ) 2>&1 | $pager
+
+  # calculate the next block of lines
+  start=$(( $end + 1 ))
+  end=$(( $start + 11 ))
+  if (( $end > ${#_lines[@]} ))
+  then
+    end=${#_lines[@]}
+  fi
+
+  _lastcmd="list $start $end"
+}
+
+function _xtrace
+{
+  let _trace="! $_trace"
+  if (( $_trace )); then
+    _msg "Execution trace on"
+  else
+    _msg "Execution trace off"
+  fi
+}
+       
+function _msg
+{
+  echo -e "$@" >&2
+}
+
+function _showline
+{
+  local i=0 bp=' ' line=$1 cl=' '
+
+  if [[ -n ${_linebp[$line]} ]]; then
+    bp='*'
+  fi
+
+  if  (( $_curline == $line )); then
+    cl=">"
+  fi
+
+  if (( $line < 100 )); then
+    _msg "$_guineapig:$line   $bp $cl${_lines[$line]}"
+  elif (( $line < 10 )); then
+    _msg "$_guineapig:$line  $bp $cl${_lines[$line]}"
+  elif (( $line > 0 )); then
+    _msg "$_guineapig:$line $bp $cl${_lines[$line]}"
+  fi
+}
+
+function _cleanup
+{
+  rm -f $__debug $_potbelliedpig 2> /dev/null
+}
+
+function _menu
+{
+  _msg 'bashdb commands:
+       break N         set breakpoint at line N
+       break           list breakpoints & break condition
+       condition foo   set break condition to foo
+       condition       clear break condition
+       delete N        clear breakpoint at line N
+       delete          clear all breakpoints
+       display EXP     evaluate and display EXP for each debug step
+       display         show a list of display expressions
+       undisplay N     remove display expression N
+       list N M        display all lines of script between N and M
+       list N          display 5 lines of script either side of line N
+       list            display 5 lines if script either side of current line
+       continue        continue execution upto next breakpoint
+       next [N]        execute [N] statements (default 1)
+       print expr      prints the value of an expression
+       trace           toggle execution trace on/off
+       ftrace [-u] func        make the debugger step into function FUNC
+                       (-u turns off tracing FUNC)
+       help            print this menu
+       ! string        passes string to a shell
+       quit            quit'
+}
+
+shopt -u extglob
+
+HISTFILE=~/.bashdb_history
+set -o history
+set +H
+
+# strings to save and restore the setting of `extglob' in debugger functions
+# that need it
+_seteglob='local __eopt=-u ; shopt -q extglob && __eopt=-s ; shopt -s extglob'
+_resteglob='shopt $__eopt extglob'
+
+_linebp=()
+let _trace=0
+let _i=1
+
+# Be careful about quoted newlines
+_potbelliedpig=${TMPDIR-/tmp}/$_guineapig.$$
+sed 's,\\$,\\\\,' $_guineapig > $_potbelliedpig
+
+_msg "Reading source from file: $_guineapig"
+while read; do
+  _lines[$_i]=$REPLY
+  let _i=$_i+1
+done < $_potbelliedpig
+
+trap _cleanup EXIT
+# Assuming a real script will have the "#! /bin/sh" at line 1,
+# don't stop at line 1 on the first run
+let _steps=1
+LINENO=-1
+trap '_steptrap $LINENO' DEBUG
diff --git a/examples/bashdb/bashdb.el b/examples/bashdb/bashdb.el
new file mode 100644 (file)
index 0000000..40584dd
--- /dev/null
@@ -0,0 +1,177 @@
+;;; bashdb.el --- Grand Unified Debugger mode for running bashdb
+;; Copyright (C) 2000, 2001 Masatake YAMATO 
+
+;; Author: Masatake YAMATO <jet@gyve.org>
+
+;; 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 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, write to the Free Software Foundation,
+;; Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+;; Commentary:
+;; This program may run on Emacs 21.0.91 and XEmacs 21.1. 
+;;
+;; Put 
+;; (autoload 'bashdb "bashdb" "Run bashdb" t nil)
+;;  to your .emacs.
+;; M-x bashdb
+;; Run bashdb (like this): bashdb target.sh
+;;
+;; About bashdb:
+;; You can get bashdb from
+;; http://www.oranda.demon.co.uk/development.html
+;;
+;; bashdb.el is based on perldb in gud.el in XEmacs 21.1.
+
+;; Revision:
+;; $Revision: 1.6 $
+;; $Log: bashdb.el,v $
+;; Revision 1.6  2001/01/06 12:18:06  masata-y
+;; Write note about XEmacs.
+;;
+;;
+
+
+;;; Code: 
+(require 'gud)
+
+;; User customizable variable
+(defcustom gud-bashdb-command-name "bashdb"
+  "File name for executing Bashdb."
+  :type 'string
+  :group 'gud)
+
+;; History of argument lists passed to bashdb.
+(defvar gud-bashdb-history nil)
+
+(defun gud-bashdb-massage-args (file args)
+  (if xemacsp
+      (cons (file-name-nondirectory file) args)        
+    args))
+
+;; There's no guarantee that Emacs will hand the filter the entire
+;; marker at once; it could be broken up across several strings.  We
+;; might even receive a big chunk with several markers in it.  If we
+;; receive a chunk of text which looks like it might contain the
+;; beginning of a marker, we save it here between calls to the
+;; filter.
+(if xemacsp
+    (defvar gud-bashdb-marker-acc ""))
+(defun gud-bashdb-marker-acc ()
+  (if xemacsp
+      gud-bashdb-marker-acc
+    gud-marker-acc))
+(defun gud-bashdb-marker-acc-quote ()
+  (if xemacsp
+      'gud-bashdb-marker-acc
+    'gud-marker-acc))
+
+(defun gud-bashdb-marker-filter (string)
+  (save-match-data
+    (set (gud-bashdb-marker-acc-quote)
+        (concat (gud-bashdb-marker-acc) string))
+    (let ((output ""))
+      ;; Process all the complete markers in this chunk.
+      (while (string-match "^\\([^:\n]+\\):\\([0-9]+\\)[ *]*>.*\n"
+                          (gud-bashdb-marker-acc))
+       (setq
+        ;; Extract the frame position from the marker.
+        gud-last-frame (cons
+                        (substring (gud-bashdb-marker-acc)
+                                   (match-beginning 1)
+                                   (match-end 1))
+                        (string-to-int 
+                         (substring (gud-bashdb-marker-acc)
+                                    (match-beginning 2) 
+                                    (match-end 2))))
+        ;; Append any text before the marker to the output we're going
+        ;; to return - we don't include the marker in this text.
+        output (concat output
+                       (substring (gud-bashdb-marker-acc) 0 (match-beginning 0))))
+        ;; Set the accumulator to the remaining text.
+       (set
+        (gud-bashdb-marker-acc-quote) (substring 
+                                       (gud-bashdb-marker-acc) (match-end 0))))
+
+      ;; Does the remaining text look like it might end with the
+      ;; beginning of another marker?  If it does, then keep it in
+      ;; (gud-bashdb-marker-acc) until we receive the rest of it.  Since we
+      ;; know the full marker regexp above failed, it's pretty simple to
+      ;; test for marker starts.
+      (if (string-match "^\\([^:\n]+\\):\\([0-9]+\\)[ *]*>" (gud-bashdb-marker-acc))
+         (progn
+           ;; Everything before the potential marker start can be output.
+           (setq output (concat output (substring (gud-bashdb-marker-acc)
+                                                  0 (match-beginning 0))))
+           ;; Everything after, we save, to combine with later input.
+           (set (gud-bashdb-marker-acc-quote)
+                (substring (gud-bashdb-marker-acc) (match-beginning 0))))
+       
+       (setq output (concat output (gud-bashdb-marker-acc)))
+       (set (gud-bashdb-marker-acc-quote) ""))
+      
+      output)))
+      
+(defun gud-bashdb-find-file (f)
+  (find-file-noselect f))
+
+;;;###autoload
+(defun bashdb (command-line)
+  "Run bashdb on program FILE in buffer *gud-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger."
+  (interactive
+   (if xemacsp
+       (list (read-from-minibuffer "Run bashdb (like this): "
+                                  (if (consp gud-bashdb-history)
+                                      (car gud-bashdb-history)
+                                    (format "%s " gud-bashdb-command-name))
+                                  nil nil
+                                  '(gud-bashdb-history . 1)))
+     (list (gud-query-cmdline 'bashdb))
+     ))
+  
+  (if xemacsp
+      (progn
+       (gud-overload-functions '((gud-massage-args . gud-bashdb-massage-args)
+                                 (gud-marker-filter . gud-bashdb-marker-filter)
+                                 (gud-find-file . gud-bashdb-find-file)))
+       (gud-common-init command-line gud-bashdb-command-name))
+    (gud-common-init command-line 'gud-bashdb-massage-args
+                    'gud-bashdb-marker-filter 'gud-bashdb-find-file)
+    (set (make-local-variable 'gud-minor-mode) 'bashdb))
+
+;; Unsupported commands
+;;  condition foo      set break condition to foo
+;;  condition  clear break condition
+;;  display EXP        evaluate and display EXP for each debug step
+;;  display            show a list of display expressions
+;;  undisplay N        remove display expression N
+;;  ! string   passes string to a shell
+;;  quit               quit
+
+  (gud-def gud-break       "break %l"     "\C-b" "Set breakpoint at current line.")
+  (gud-def gud-list-break  "break"        "b"    "List breakpoints & break condition.")
+  (gud-def gud-remove      "delete %l"    "\C-d" "Remove breakpoint at current line")
+  (gud-def gud-remove-all  "delete"       "d"    "Clear all breakpoints")
+  (gud-def gud-cont   "continue"          "\C-r" "Continue with display.")
+  (gud-def gud-next   "next"              "\C-n" "Step one line (skip functions).")
+  (gud-def gud-print  "print %e"          "\C-p" "Evaluate bash expression at point.")
+  (gud-def gud-help   "help"              "h"    "Show all commands.")
+  (gud-def gud-trace  "trace"             "t"    "Toggle execution trace on/off")
+
+  (setq comint-prompt-regexp "^bashdb> ")
+  (setq paragraph-start comint-prompt-regexp)
+  (run-hooks 'bashdb-mode-hook))
+
+(provide 'bashdb)
+;; bashdb.el ends here
index 9c0721d731cc658fb99f333f7de1596eb6d8b6bd..baa97e393b8c2924470708380a4bfcc83608d964 100644 (file)
@@ -162,11 +162,11 @@ _declare_func()
 
        COMPREPLY=()
        if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
-               COMPREPLY=(-a -f -F -i -r -x -p)
+               COMPREPLY=(-a -f -F -i -p -r -t -x)
                return 0;
        fi
        if [[ $cur == '+' ]]; then
-               COMPREPLY=(+i +x)
+               COMPREPLY=(+i +t +x)
                return 0;
        fi
        if [[ $prev == '-p' ]]; then
@@ -252,7 +252,7 @@ _hash_func()
        prev=${COMP_WORDS[COMP_CWORD-1]}
 
        if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
-               COMPREPLY=(-p -r)
+               COMPREPLY=(-p -r -t)
                return 0;
        fi
 
@@ -344,8 +344,8 @@ _complete_meta_func()
 
        if (( $COMP_CWORD <= 1 )) || [[ "$cur" == '-' ]]; then
                case "$cmd" in
-               complete) COMPREPLY=(-a -b -c -d -e -f -j -k -v -u -r -p -A -G -W -P -S -X -F -C);;
-               compgen)  COMPREPLY=(-a -b -c -d -e -f -j -k -v -u -A -G -W -P -S -X -F -C);;
+               complete) COMPREPLY=(-a -b -c -d -e -f -j -k -s -v -u -r -p -A -G -W -P -S -X -F -C);;
+               compgen)  COMPREPLY=(-a -b -c -d -e -f -j -k -s -v -u -A -G -W -P -S -X -F -C);;
                esac
                return 0
        fi
@@ -353,7 +353,7 @@ _complete_meta_func()
        if [[ $prev == -A ]]; then
                COMPREPLY=(alias arrayvar binding builtin command directory \
 disabled enabled export file 'function' helptopic hostname job keyword \
-running setopt shopt signal stopped variable)
+running service setopt shopt signal stopped variable)
                return 0
        elif [[ $prev == -F ]]; then
                COMPREPLY=( $( compgen -A function $cur ) )
@@ -466,7 +466,7 @@ complete -f -X '*.bz2' bzip2
 complete -f -X '*.Z' compress
 complete -f -X '!*.+(gz|tgz|Gz)' gunzip gzcat zcat zmore
 complete -f -X '!*.Z' uncompress zmore zcat
-complete -f -X '!*.bz2' bunzip2
+complete -f -X '!*.bz2' bunzip2 bzcat
 complete -f -X '!*.zip' unzip
 complete -f -X '!*.+(gif|jpg|jpeg|GIF|JPG|JPEG|bmp)' xv
 
index 08086aea66af6519abffd15a1f76b8ed3adb948a..f3e228f524892bcc6534c8bdf56fa89b7dd63a23 100644 (file)
@@ -30,7 +30,7 @@ hex2inet ()
        do
                case "$o" in
                r)      rev=true;;
-               *)      echo "hex2inet: usage: hex2inet [0x]XXXXXXXX" >&2 ; exit 2;;
+               *)      echo "hex2inet: usage: hex2inet [-r] [0x]XXXXXXXX" >&2 ; exit 2;;
                esac
        done
        shift $(( $OPTIND - 1 ))
diff --git a/examples/functions/isvalidip b/examples/functions/isvalidip
new file mode 100644 (file)
index 0000000..0b2dafe
--- /dev/null
@@ -0,0 +1,14 @@
+# Thanks to Chris F. A. Johnson <c.f.a.johnson@rogers.com> for this one
+is_validip()
+{
+       case "$*" in
+       ""|*[!0-9.]*|*[!0-9]) return 1 ;;
+       esac
+
+       local IFS=.
+       set -- $*
+
+        [ $# -eq 4 ] &&
+           [ ${1:-666} -le 255 ] && [ ${2:-666} -le 255 ] &&
+           [ ${3:-666} -le 255 ] && [ ${4:-666} -le 254 ]
+}
index 3fdc7acf6a92ad345d7e58511bcd3e7a5b47d7d2..224643e41c7331651108b954fee3a7ee051eb455 100644 (file)
@@ -25,7 +25,7 @@ function manpage ()
     set $file
     file="$1"
     if [ -f "$file" ]; then
-      zot=$(head -1 "$file")
+      zot=$(sed 1q "$file")
       cmd=${MANROFF:-"nroff -man - | col | cat -s"}
       h=${zot##"'"'\"'}
       if [ "$h" != "$zot" ]; then
index a4a5f70e1ebeee2ee5e14d39f3b661383833f190..3c0c743ddf33b64b0cab2f2629aac4688ff4a353 100644 (file)
@@ -7,7 +7,7 @@
 
 mhfold()
 {
-       list=`folders | tail +2 | awk '{print $1}'`
+       list=`folders | awk '{if (1 < NR) print $1}'`
        /bin/ls -lag ~/Mail > /tmp/fold$$
        for i in $list; do
                grep $i /tmp/fold$$
index 4851ff832004e413721a962b92873843b59b6612..ed1721f5852bf7033b329ff2f695eadbb7bbaada 100644 (file)
@@ -42,6 +42,11 @@ host_cpu = @host_cpu@
 host_vendor = @host_vendor@
 
 CFLAGS = @CFLAGS@
+LOCAL_CFLAGS = @LOCAL_CFLAGS@
+DEFS = @DEFS@
+LOCAL_DEFS = @LOCAL_DEFS@
+
+CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) $(CFLAGS)
 
 #
 # These values are generated for configure by ${topdir}/support/shobj-conf.
@@ -62,7 +67,7 @@ INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins \
       -I$(BUILD_DIR)/builtins
 
 .c.o:
-       $(SHOBJ_CC) $(SHOBJ_CFLAGS) $(CFLAGS) $(INC) -c -o $@ $<
+       $(SHOBJ_CC) $(SHOBJ_CFLAGS) $(CCFLAGS) $(INC) -c -o $@ $<
 
 
 ALLPROG = print truefalse sleep pushd finfo logname basename dirname \
index 1c538608ede3744c36e420c628314e1d36d0a47c..b6336296c6af4916ba4c86315cea21233b1b7f46 100644 (file)
@@ -2,6 +2,10 @@
  * finfo - print file info
  */
 
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
 #include <sys/types.h>
 #include "posixstat.h"
 #include <stdio.h>
@@ -127,10 +131,10 @@ char      *f;
 {
        static struct stat st;
        int     fd, r;
-       long    lfd;
+       intmax_t lfd;
 
        if (strncmp(f, "/dev/fd/", 8) == 0) {
-               if (legal_number(f + 8, &lfd) == 0) {
+               if ((legal_number(f + 8, &lfd) == 0) || (int)lfd != lfd) {
                        builtin_error("%s: invalid fd", f + 8);
                        return ((struct stat *)0);
                }
index fc1c1d16ccb05b1f30e025f33576be8daf5a0f1f..5d079b6f03b8c7bf94232e8be2480891a1d5f3aa 100644 (file)
 #endif
 
 #include <stdio.h>
+#ifdef HAVE_LIMITS_H
 #include <limits.h>
+#endif
+#ifdef HAVE_LOCALE_H
 #include <locale.h>
+#endif
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 #include <errno.h>
+
+#include "typemax.h"
+
 #include "bashansi.h"
 #include "shell.h"
 #include "builtins.h"
@@ -857,7 +866,6 @@ static const struct conf_variable conf_table[] =
 static int num_getconf_variables = sizeof(conf_table) / sizeof(struct conf_variable) - 1;
 
 extern char *this_command_name;
-extern char *xmalloc ();
 extern char **make_builtin_argv ();
 
 static void getconf_help ();
index 80943bc759fd66f05a6b877e55f36bca59123061..ad658a7f861af4381c91c8299ca5db2d1f8878e7 100644 (file)
@@ -2,6 +2,10 @@
  * print -- loadable ksh-93 style print builtin
  */
 
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
 #include "bashtypes.h"
 
 #include <errno.h>
@@ -50,6 +54,7 @@ print_builtin (list)
      WORD_LIST *list;
 {
   int c, r, nflag, raw, ofd, sflag;
+  intmax_t lfd;
   char **v, *pfmt, *arg;
   WORD_LIST *l;
 
@@ -83,8 +88,8 @@ print_builtin (list)
        case 'p':
          break;        /* NOP */
        case 'u':
-         if (all_digits (list_optarg))
-           ofd = atoi (list_optarg);
+         if (all_digits (list_optarg) && legal_number (list_optarg, &lfd) && lfd == (int)lfd)
+           ofd = lfd;
          else
            {
              for (l = list; l->next && l->next != lcurrent; l = l->next);
diff --git a/examples/obashdb/PERMISSION b/examples/obashdb/PERMISSION
new file mode 100644 (file)
index 0000000..4e9460c
--- /dev/null
@@ -0,0 +1,27 @@
+From mikel@ora.com Tue Aug  1 12:13:20 1995
+Flags: 10
+Return-Path: mikel@ora.com
+Received: from ruby.ora.com (ruby.ora.com [198.112.208.25]) by odin.INS.CWRU.Edu with ESMTP (8.6.12+cwru/CWRU-2.1-ins)
+       id MAA01565; Tue, 1 Aug 1995 12:13:18 -0400 (from mikel@ora.com for <chet@odin.INS.CWRU.Edu>)
+Received: (from fax@localhost) by ruby.ora.com (8.6.12/8.6.11) with UUCP id MAA23251; Tue, 1 Aug 1995 12:07:51 -0400
+Received: by los.ora.com (4.1/Spike-2.1)
+       id AA00672; Tue, 1 Aug 95 08:57:32 EDT
+Date: Tue, 1 Aug 95 08:57:32 EDT
+From: mikel@ora.com (Michael Loukides)
+Message-Id: <9508011257.AA00672@los.ora.com>
+Subject: Re: Ksh debugger from Rosenblatt's book [for bash]
+To: Chet Ramey <chet@odin.INS.CWRU.Edu>
+Cc: cmarie@ora.com, cam@iinet.com.au, brosenblatt@tm.com
+In-Reply-To: Chet Ramey <chet@odin.INS.CWRU.Edu>, Mon, 31 Jul 1995 16:22:48 -0400
+
+    I've modified a (modified) version of Bill Rosenblatt's ksh debugger
+    to work with bash-2.0.  Does ORA have any problem with me distributing
+    it with bash-2.0?
+    
+That's great!
+
+Go ahead and circulate it; in fact, we should probably grab it and
+stick it in our ftp archive, and put a reference to it in the book.
+(Too late to actually discuss the thing, at least for this edition).
+-------
+
diff --git a/examples/obashdb/bashdb b/examples/obashdb/bashdb
new file mode 100644 (file)
index 0000000..97d287d
--- /dev/null
@@ -0,0 +1,33 @@
+# kshdb - Korn Shell Debugger main file
+# adapted from 'Learning the Korn Shell' by Bill Rosenblatt (O'Reilly)
+# by Cigy Cyriac (cigy@felix.tulblr.unisys.com)
+# Main driver: constructs full script (with preamble) and runs it
+
+echo 'Bourne-Again Shell Debugger version 0.1'
+
+_pname=${0##*/}
+
+[ $# -eq 0 ] && {
+       echo "${_pname}: usage: ${_pname} <script_file>"
+       exit 1
+}
+
+_guineapig=$1
+
+[ -r $_guineapig ] || {
+       echo "${_pname}: cannot read $_guineapig." >&2
+       exit 1
+}
+shift
+
+_tmpdir=/tmp
+_libdir=.
+_dbgfile=$_tmpdir/bashdb$$             #temp file for script being debugged
+
+cat $_libdir/bashdb.pre $_guineapig > $_dbgfile
+if [ -f "$BASH" ]; then
+       exec $BASH $_dbgfile $_guineapig $_tmpdir $_libdir "$@"
+else
+       exec bash $_dbgfile $_guineapig $_tmpdir $_libdir "$@"
+fi
+# end of bashdb
index 9344d90af8f011d2b0e985bae0dec610f7f69fcd..cc419ac0772be4317900ab42bae4679f5656c9d0 100644 (file)
@@ -16,7 +16,7 @@ while :
 do
        $CLEAR
        echo "$HEADER"
-       ps -aux | sort -nr +2 | sed ${SS}q
+       ps -aux | sort -nr -k 3 | sed ${SS}q
        sleep 5
 done
 
diff --git a/examples/scripts.v2/ren b/examples/scripts.v2/ren
new file mode 100644 (file)
index 0000000..da76026
--- /dev/null
@@ -0,0 +1,585 @@
+#!/bin/bash
+#@ This program came from: ftp://ftp.armory.com/pub/scripts/ren
+#@ Look there for the latest version.
+#@ If you don't find it, look through http://www.armory.com/~ftp/
+#
+# @(#) ren 2.1.1 2002-03-17
+# 1990-06-01 John H. DuBois III (john@armory.com)
+# 1991-02-25 Improved help info
+# 1992-06-07 Remove quotes from around shell pattern as required by new ksh
+# 1994-05-10 Exit if no globbing chars given.
+# 1995-01-23 Allow filename set to be given on command line.
+# 1997-09-24 1.4 Let [] be used for globbing.  Added x option.
+# 1997-11-26 1.4.1 Notice if the sequences of globbing chars aren't the same.
+# 1999-05-13 Changed name to ren to avoid conflict with /etc/rename
+# 2000-01-01 1.4.2 Let input patterns that contain whitespace be used.
+# 2001-02-14 1.5 Better test for whether old & new globbing seqs are identical.
+# 2001-02-20 1.6 Added pP options.
+# 2001-02-27 1.7 Added qf options.  Improved interpretation of rename patterns.
+# 2001-05-10 1.8 Allow multiple pP options.  Added Qr options.
+# 2001-07-25 2.0 Added mz options.
+# 2001-11-25 2.1 Allow segment ranges to be given with -m.  Work under ksh93.
+# 2002-03-17 2.1.1 Fixed bug in test for legal expressions.
+
+# todo: It would be nice to be able to escape metacharacters with '\'
+# todo: Should enhance patterns to make ] in a pair of brackets work ([]])
+# todo: Allow use of all ksh globbing patterns.
+# todo: Allow use of extended regexps, with () to enumerate pieces and \num to
+# todo: select them.
+#
+# Modifications for bash made by Chet Ramey <chet@po.cwru.edu>
+
+name=${0##*/}
+Usage="Usage:
+$name [-fhqtv] [-m<segstart[:segend]=operation>] [-z<len>] [-[pP]<pattern>] 
+    oldpattern [newpattern [filename ...]]
+or
+$name -r [same options as above] oldpattern newpattern directory ..."
+tell=false
+verbose=false
+warn=true
+warnNoFiles=true
+debug=false
+recurse=false
+inclPat=
+exclPat=
+declare -i inclCt=0 exclCt=0
+check=true
+declare -i j op_end_seg
+
+# Begin bash additions
+shopt -s extglob
+
+#
+# ksh print emulation
+#
+#      print [-Rnprsu[n]] [-f format] [arg ...]
+#
+#      -       end of options
+#      -R      BSD-style -- only accept -n, no escapes
+#      -n      do not add trailing newline
+#      -p      no-op (no coprocesses)
+#      -r      no escapes
+#      -s      print to the history file
+#      -u n    redirect output to fd n
+#      -f format       printf "$format" "$@"
+#
+
+print()
+{
+       local eflag=-e
+       local nflag= fflag= c
+       local fd=1
+
+       OPTIND=1
+       while getopts "fRnprsu:" c
+       do
+               case $c in
+               R)      eflag= ;;
+               r)      eflag= ;;
+               n)      nflag=-n ;;
+               s)      sflag=y ;;
+               f)      fflag=y ;;
+               u)      fd=$OPTARG ;;
+               p)      ;;
+               esac
+       done
+       shift $(( $OPTIND - 1 ))
+
+       if [ -n "$fflag" ]; then
+               builtin printf "$@" >&$fd
+               return
+       fi
+
+       case "$sflag" in
+       y)      builtin history -s "$*" ;;
+       *)      builtin echo $eflag $nflag "$@" >&$fd
+       esac
+}
+
+# End bash additions
+
+while getopts :htvxp:P:fqQrm:z: opt; do
+    case $opt in
+    h)
+       print -r -- \
+"$name: rename files by changing parts of filenames that match a pattern.
+$Usage
+oldpattern and newpattern are subsets of sh filename patterns; the only
+globbing operators (wildcards) allowed are ?, *, and [].  All filenames that
+match oldpattern will be renamed with the filename characters that match the
+constant (non-globbing) characters of oldpattern changed to the corresponding
+constant characters of newpattern.  The characters of the filename that match
+the globbing operators of oldpattern will be preserved.  Globbing operators
+in oldpattern must occur in the same order in newpattern; for every globbing
+operators in newpattern there must be an identical globbing operators in
+oldpattern in the same sequence.  Both arguments should be quoted since
+globbing operators are special to the shell.  If filenames are given, only
+those named are acted on; if not, all filenames that match oldpattern are acted
+on.  newpattern is required in all cases except when -m is given and no further
+arguments are given.
+If you are unsure whether a $name command will do what you intend, issue it
+with the -t option first to be sure.
+Examples:
+$name \"/tmp/foo*.ba.?\" \"/tmp/new*x?\"
+    All filenames in /tmp that match foo*.ba.? will have the \"foo\" part
+    replaced by \"new\" and the \".ba.\" part replaced by \"x\".
+    For example, /tmp/fooblah.ba.baz would be renamed to /tmp/newblahxbaz.
+$name \* \*- foo bar baz
+    foo, bar, and baz will be renamed to foo-, bar-, and baz-.
+$name '????????' '????-??-??'
+    All filenames that are 8 characters long will be changed such that dashes
+    are inserted after the 4th and 6th characters.
+Options:
+-h: Print this help.
+-r: Recursive operation.  Filenames given on the command line after oldpattern
+    and newpattern are taken to be directories to traverse recursively.  For
+    each subdirectory found, the specified renaming is applied to any matching
+    filenames.  oldpattern and newpattern should not include any directory
+    components.
+-p<pattern>, -P<pattern>: Act only on filenames that do (if -p is given) or do
+    not (if -P is given) match the sh-style filename globbing pattern
+    <pattern>.  This further restricts the filenames that are acted on, beyond
+    the filename selection produced by oldpattern and the filename list (if
+    any).  <pattern> must be quoted to prevent it from being interpreted by the
+    shell.  Multiple instances of these options may be given.  In this case,
+    filenames are acted on only if they match at least one of the patterns
+    given with -p and do not match any of the patterns given with -P.
+-m<segstart[:segend]=operation>: For each file being renamed, perform a
+    mathematical operation on the string that results from concatenating
+    together the filename segments that matched globbing operator numbers
+    segstart through segend, where operators are numbered in order of
+    occurrence from the left.  For example, in the pattern a?b*c[0-9]f, segment
+    1 consists of the character that matched ?, segment 2 consists of the
+    character(s) that matched *, and segment 3 consists of the character that
+    matched [0-9].  The selected segments are replaced with the result of the
+    mathematical operation.
+    The concatenated string must consist of characters that can be interpreted
+    as a decimal integer; if it does not, the filename is not acted on.  This
+    number is assigned to the variable 'i', which can be referenced by the
+    operation.  The operations available are those understood by the ksh
+    interpreter, which includes most of the operators and syntax of the C
+    language.  The original filename segment is replaced by the result of the
+    operation.  If -m is used, newpattern may be an empty string or not given
+    at all (if no directory/file names are given).  In this case, it is taken
+    to be the same as oldpattern.
+    If segend is given, any fixed text that occurs in the pattern between the
+    starting and ending globbing segments is discarded.  If there are fewer
+    globbing segments than segend, no complaint is issued; the string is formed
+    from segment segstart through the last segment that does exist.
+    If segend is not given, the only segment acted on is startseg.
+    Examples:
+    $name -m3=i+6 '??*.ppm'
+       This is equivalent to:
+       $name -m3=i+6 '??*.ppm' '??*.ppm'
+       Since the old pattern and new pattern are identical, this would
+       normally be a no-op.  But in this case, if a filename of ab079.ppm is
+       given, it is changed to ab85.ppm.
+    $name '-m1:2=i*2' 'foo??bar'
+       This will change a file named foo12bar to foo24bar
+    $name '-m1:2=i*2' 'foo?xyz?bar'
+       This will also change a file named foo1xyz2bar to foo24bar
+-z<len>: Set the size of the number fields that result when -m is used.  The
+    field is truncated to the trailing <len> digits or filled out to <len>
+    digits with leading zeroes.  In the above example, if -z3 is given, the
+    output filename will be ab085.ppm.  
+-f: Force rename.  By default, $name will not rename files if a file with the
+    new filename already exists.  If -f is given, $name will carry out the
+    rename anyway.
+-q: Quiet operation.  By default, if -f is given, $name will still notify the
+    user if a rename results in replacement of an already-existing filename. 
+    If -q is given, no notification is issued.
+-Q: Suppress other warnings.  By default, a warning is issued if no files are
+    selected for acting upon.  If -Q is given, no warning is issued.
+-v: Show the rename commands being executed.
+-t: Show what rename commands would be done, but do not carry them out."
+       exit 0
+       ;;
+    f)
+       check=false
+       ;;
+    q)
+       warn=false
+       ;;
+    Q)
+       warnNoFiles=false
+       ;;
+    r)
+       warnNoFiles=false
+       recurse=true
+       ;;
+    t)
+       tell=true
+       ;;
+    v)
+       verbose=true
+       ;;
+    x)
+       verbose=true
+       debug=true
+       ;;
+    p)
+       inclPats[inclCt]=$OPTARG
+       ((inclCt+=1))
+       ;;
+    P)
+       exclPats[exclCt]=$OPTARG
+       ((exclCt+=1))
+       ;;
+    m)
+       # Store operation for each segment number in ops[num]
+       # Store ending segment number in op_end_seg[num]
+       range=${OPTARG%%=*}
+       op=${OPTARG#*=}
+       start=${range%%:*}
+       end=${range#*:}
+       if [[ "$start" != +([0-9]) || "$start" -eq 0 ]]; then
+           print -ru2 -- "$name: Bad starting segment number given with -m: $start"
+           exit 1
+       fi
+       if [[ "$end" != +([0-9]) || "$end" -eq 0 ]]; then
+           print -ru2 -- "$name: Bad ending segment number given with -m: $end"
+           exit 1
+       fi
+       if [[ start -gt end ]]; then
+           print -ru2 -- "$name: Ending segment ($end) is less than starting segment ($start)"
+           exit 1
+       fi
+       if [[ "$op" != @(|*[!_a-zA-Z0-9])i@(|[!_a-zA-Z0-9]*) ]]; then
+           print -ru2 -- \
+           "$name: Operation given with -m does not reference 'i': $op"
+           exit 1
+       fi
+       # Test whether operation is legal.  let returns 1 both for error
+       # indication and when last expression evaluates to 0, so evaluate 1
+       # after test expression.
+       i=1
+       let "$op" 1 2>/dev/null || {
+           print -ru2 -- \
+           "$name: Bad operation given with -m: $op"
+           exit 1
+       }
+       ops[start]=$op
+       op_end_seg[start]=$end
+       ;;
+    z)
+       if [[ "$OPTARG" != +([0-9]) || "$OPTARG" -eq 0 ]]; then
+           print -ru2 -- "$name: Bad length given with -z: $OPTARG"
+           exit 1
+       fi
+       typeset -Z$OPTARG j || exit 1
+       ;;
+    +?)        # no way to tell getopts to not treat +x as an option
+       print -r -u2 "$name: Do not prefix options with '+'."
+       exit 1
+       ;;
+    :) 
+       print -r -u2 \
+"$name: Option -$OPTARG requires a value.
+$Usage
+Use -h for help."
+       exit 1
+       ;;
+    \?) 
+       print -r -u2 \
+"$name: -$OPTARG: no such option.
+$Usage
+Use -h for help."
+       exit 1
+       ;;
+    esac
+done
+# remove args that were options
+let OPTIND=OPTIND-1
+shift $OPTIND
+
+oldpat=$1
+newpat=$2
+
+# If -m is given, a non-existant or null newpat should be set to oldpat
+if [ ${#ops[*]} -gt 0 ]; then
+    case $# in
+    0)
+       ;;
+    1)
+       set -- "$oldpat" "$oldpat"
+       newpat=$oldpat
+       $debug && print -ru2 -- "Set new pattern to: $newpat"
+       ;;
+    *)
+       if [ -z "$newpat" ]; then
+           shift 2
+           set -- "$oldpat" "$oldpat" "$@"
+           newpat=$oldpat
+           $debug && print -ru2 -- "Set new pattern to: $newpat"
+       fi
+       ;;
+    esac
+fi
+
+# Make sure input patterns that contain whitespace can be expanded properly
+IFS=
+
+origPat=$oldpat
+
+# Generate list of filenames to act on.
+case $# in
+[01])
+    print -u2 "$Usage\nUse -h for help."
+    exit 1
+    ;;
+2)
+    if $recurse; then
+       print -r -u2 "$name: No directory names given with -r.  Use -h for help."
+       exit 1
+    fi
+    set -- $oldpat     # Get list of all filenames that match 1st globbing pattern.
+    if [[ ! -a $1 ]]; then
+       $warnNoFiles && print -r -- "$name: No filenames match this pattern: $oldpat"
+       exit
+    fi
+    ;;
+*)
+    shift 2
+    ;;
+esac
+
+integer patSegNum=1 numPatSegs
+
+# For old ksh
+# while [[ "$oldpat" = *'[\*\?]'* ]]; do
+
+# Example oldpat: foo*.a
+# Example newpat: bar*.b
+
+# Build list of non-pattern segments and globbing segments found in arguments.
+# Note the patterns given are used to get the list of filenames to act on,
+# to delimit constant segments, and to determine which parts of filenames are
+# to be replaced.
+# Examples given for first iteration (in the example, the only iteration)
+# The || newpat  is to ensure that new pattern does not have more globbing
+# segments than old pattern
+while [[ "$oldpat" = *@([\*\?]|\[+([!\]])\])* ||
+         "$newpat" = *@([\*\?]|\[+([!\]])\])* ]]; do
+    ## Get leftmost globbing pattern in oldpat
+
+    # Make r be oldpat with smallest left piece that includes a globbing
+    # pattern removed from it
+    r=${oldpat#*@([\*\?]|\[+([!\]])\])}        # r=.a
+    # Make pat be oldpat with the above removed from it, leaving smallest
+    # left piece that includes a globbing pattern
+    pat=${oldpat%%"$r"}                        # pat=foo*
+    # Make l be pat with the globbing pattern removed from the right,
+    # leaving a constant string
+    l=${pat%@([\*\?]|\[+([!\]])\])}    # l=foo
+    # Remove the constant part of pat from the left, leaving the globbing
+    # pattern
+    pat=${pat#"$l"}                    # pat=*
+
+    # Do the same thing for newpat, solely to provide a reliable test that
+    # both oldpat & newpat contain exactly the same sequence of globbing
+    # patterns.
+    r=${newpat#*@([\*\?]|\[+([!\]])\])}        # r=.b
+    npat=${newpat%%"$r"}               # pat=bar*
+    l=${npat%@([\*\?]|\[+([!\]])\])}   # l=bar
+    npat=${npat#"$l"}                  # npat=*
+
+    if [[ "$pat" != "$npat" ]]; then
+       print -ru2 -- \
+"$name: Old-pattern and new-pattern do not have the same sequence of globbing chars.
+Pattern segment $patSegNum: Old pattern: $pat  New pattern: $npat"
+       exit 1
+    fi
+
+    ## Find parts before & after pattern
+    # oldpre[] stores the old constant part before the pattern,
+    # so that it can be removed and replaced with the new constant part.
+    oldpre[patSegNum]=${oldpat%%"$pat"*}       # oldpre[1]=foo
+    # oldsuf stores the part that follows the globbing pattern,
+    # so that it too can be removed.
+    # After oldpre[] & oldsuf[] have been removed from a filename, what remains
+    # is the part matched by the globbing pattern, which is to be retained.
+    oldsuf[patSegNum]=${oldpat#*"$pat"}                # oldsuf[1]=.a
+    # newpre[] stores the new constant part before the pattern,
+    # so that it can be used to replace the old constant part.
+    newpre[patSegNum]=${newpat%%"$pat"*}       # newpre[1]=bar
+    # Get rid of processed part of patterns
+    oldpat=${oldpat#${oldpre[patSegNum]}"$pat"}        # oldpat=.a
+    newpat=${newpat#${newpre[patSegNum]}"$pat"}        # newpat=.b
+    # Store either * or ? in pats[], depending on whether this segment matches 1
+    # or any number of characters.
+    [[ "$pat" = \[* ]] && pat=?
+    pats[patSegNum]=$pat
+    ((patSegNum+=1))
+done
+
+if [ patSegNum -eq 1 ]; then
+    print -u2 "No globbing chars in pattern."
+    exit 1
+fi
+
+oldpre[patSegNum]=${oldpat%%"$pat"*}   # oldpre[2]=.a
+oldsuf[patSegNum]=${oldpat#*"$pat"}    # oldsuf[2]=.a
+newpre[patSegNum]=${newpat%%"$pat"*}   # newpre[2]=.b
+
+numPatSegs=patSegNum
+
+if $debug; then
+    patSegNum=1
+    while [[ patSegNum -le numPatSegs ]]; do
+       print -ru2 -- \
+"Old prefix: <${oldpre[patSegNum]}>   Old suffix: <${oldsuf[patSegNum]}>   New prefix: <${newpre[patSegNum]}>   Pattern: <${pats[patSegNum]}>"
+       ((patSegNum+=1))
+    done
+fi
+
+# Example filename: foox.a
+# Example oldpat: foo*.a
+# Example newpat: bar*.b
+
+integer numFiles=0
+
+# Usage: renameFile filename [dirname]
+# [dirname] is a directory name to prefix filenames with when they are printed
+# for informational purposes.
+# Uses globals:
+#     inclCt exclCt inclPats[] exclPats[] ops[]
+#     numPatSegs oldpre[] oldsuf[] newpre[] pats[]
+#     check warn tell verbose name
+# Modifies globals: numFiles
+function renameFile {
+    typeset file=$1 subdir=$2
+    integer patSegNum patnum
+    typeset origname porigname newfile matchtext pnewfile matchsegs
+    integer startseg endseg
+
+    origname=$file     # origname=foox.a
+    porigname=$subdir$file
+    # Unfortunately, ksh88 does not do a good job of allowing for patterns
+    # stored in variables.  Without the conditional expression being eval'ed,
+    # only sh patterns are recognized.  If the expression is eval'ed, full
+    # ksh expressions can be used, but then expressions that contain whitespace
+    # break unless the user passed a pattern with the whitespace properly
+    # quoted, which is not intuititive.  This is fixed in ksh93; full patterns
+    # work without being eval'ed.
+    if [ inclCt -gt 0 ]; then
+       patnum=0
+       while [ patnum -lt inclCt ]; do
+           [[ "$file" = ${inclPats[patnum]} ]] && break
+           ((patnum+=1))
+       done
+       if [ patnum -eq inclCt ]; then
+           $debug && print -ru2 -- "Skipping not-included filename '$porigname'"
+           return 1
+       fi
+    fi
+    patnum=0
+    while [ patnum -lt exclCt ]; do
+       if [[ "$file" = ${exclPats[patnum]} ]]; then
+           $debug && print -ru2 -- "Skipping excluded filename '$porigname'"
+           return 1
+       fi
+       ((patnum+=1))
+    done
+    # Extract matching segments from filename
+    ((numFiles+=1))
+    patSegNum=1
+    while [[ patSegNum -le numPatSegs ]]; do
+       # Remove a fixed prefix         iteration:      1               2
+       file=${file#${oldpre[patSegNum]}}                       # file=x.a      file=
+       # Save the part of this suffix that is to be retained.  To do this, we
+       # need to know what part of the suffix matched the current globbing
+       # segment.  If the globbing segment is a *, this is done by removing
+       # the minimum part of the suffix that matches oldsuf (since * matches
+       # the longest segment possible).  If the globbing segment is ? or []
+       # (the latter has already been coverted to ?), it is done by taking the
+       # next character.
+       if [ "${pats[patSegNum]}" == \? ]; then
+           matchtext=${file#?}
+           matchtext=${file%$matchtext}
+       else
+           matchtext=${file%${oldsuf[patSegNum]}}              # matchtext=x   matchtext=
+       fi
+       $debug && print -ru2 -- "Matching segment $patSegNum: $matchtext"
+       file=${file#$matchtext}                         # file=.a       file=.a
+
+       matchsegs[patSegNum]=$matchtext
+       ((patSegNum+=1))
+    done
+
+    # Paste fixed and matching segments together to form new filename.
+    patSegNum=0
+    newfile=
+    while [[ patSegNum -le numPatSegs ]]; do
+       matchtext=${matchsegs[patSegNum]}
+       startseg=patSegNum
+       if [ -n "${ops[startseg]}" ]; then
+           endseg=${op_end_seg[startseg]}
+           while [ patSegNum -lt endseg ]; do
+               ((patSegNum+=1))
+               matchtext=$matchtext${matchsegs[patSegNum]}
+           done
+           if [[ "$matchtext" != +([-0-9]) ]]; then
+               print -ru2 -- \
+"Segment(s) $startseg - $endseg ($matchtext) of file '$porigname' do not form an integer; skipping this file."
+               return 2
+           fi
+           i=$matchtext
+           let "j=${ops[startseg]}" || {
+               print -ru2 -- \
+"Operation failed on segment(s) $startseg - $endseg ($matchtext) of file '$file'; skipping this file."
+               return 2
+           }
+           $debug && print -ru2 -- "Converted $matchtext to $j"
+           matchtext=$j
+       fi
+       newfile=$newfile${newpre[startseg]}$matchtext           # newfile=barx  newfile=barx.b
+       ((patSegNum+=1))
+    done
+
+    pnewfile=$subdir$newfile
+    if $check && [ -e "$newfile" ]; then
+       $warn &&
+       print -ru2 -- "$name: Not renaming \"$porigname\"; destination filename \"$pnewfile\" already exists."
+       return 2
+    fi
+    if $tell; then
+       print -n -r -- "Would move: $porigname -> $pnewfile"
+       $warn && [ -e "$newfile" ] && print -n -r " (destination filename already exists; would replace it)"
+       print ""
+    else
+       if $verbose; then
+           print -n -r -- "Moving: $porigname -> $pnewfile"
+           $warn && [ -e "$newfile" ] && print -n -r -- " (replacing old destination filename \"$pnewfile\")"
+           print ""
+       elif $warn && [ -e "$newfile" ]; then
+           print -r -- "$name: Note: Replacing old file \"$pnewfile\""
+       fi
+       mv -f -- "$origname" "$newfile"
+    fi
+}
+
+if $recurse; then
+    oPWD=$PWD
+    find "$@" -depth -type d ! -name '*
+*' -print | while read dir; do
+       cd -- "$oPWD"
+       if cd -- "$dir"; then
+           for file in $origPat; do
+               renameFile "$file" "$dir/"
+           done
+       else
+           print -ru2 -- "$name: Could not access directory '$dir' - skipped."
+       fi
+    done
+else
+    for file; do
+       renameFile "$file"
+    done
+fi
+
+if [ numFiles -eq 0 ]; then
+    $warnNoFiles && print -ru2 -- \
+    "$name: All filenames were excluded by patterns given with -p or -P."
+fi
index 9d93b30556cd6a57fbed66aa295c96188c626a98..509fe88525088a6d767901307586ad238182e134 100755 (executable)
@@ -335,7 +335,7 @@ if test -s "$histfile"
        then
        cmdno="`set - \`wc -l $histfile\`;echo $1`"
        cmdno="`expr \"$cmdno\" + 1`"
-       lastcmd="`tail -1 $histfile`"
+       lastcmd="`sed -n '$p' $histfile`"
        copy=false
        ohist=$histfile
        while test ! -w "$histfile"
@@ -689,7 +689,7 @@ esac/
                                        rest=
                                        ;;
                                esac
-                               i="`grep \"$wanted\" $histfile | tail -1`"
+                               i="`grep \"$wanted\" $histfile | sed -n '$p'`"
                                ;;
                        *)
                                # find which 'start-of-command' match is wanted
@@ -708,7 +708,7 @@ esac/
                                        rest=
                                        ;;
                                esac
-                               i="`grep \"^$wanted\" $histfile | tail -1`"
+                               i="`grep \"^$wanted\" $histfile | sed -n '$p'`"
                                ;;
                        esac
 
diff --git a/examples/scripts/self-repro b/examples/scripts/self-repro
new file mode 100644 (file)
index 0000000..951d4e4
--- /dev/null
@@ -0,0 +1,9 @@
+# self-reproducing script (except for these comment lines -- remove them)
+# i got this from the ksh93 faq:
+#      http://www.kornshell.com/doc/faq.html
+#
+n="
+" q="'" x="cat <<-!" y=! z='n="$n" q="$q" x="$x" y=$y z=$q$z$q$n$x$n$z$n$y'
+cat <<-!
+n="$n" q="$q" x="$x" y=$y z=$q$z$q$n$x$n$z$n$yb
+!
index 62aa94862287241e22da44740fb0e3299985d545..878cbabc26a6c71dae04037093d1fbdae34b6a23 100755 (executable)
@@ -32,7 +32,7 @@ do
        cd "$1" || { shift; [ $# -ge 1 ] && echo >&2; continue; }
        echo -n "$PWD"
 
-       du $andfiles | sort +1f | sed \
+       du $andfiles | sort -k 2f | sed \
                -e 's/\([^      ]*\)    \(.*\)/\2  (\1)/' \
                -e "s#^$1##" \
                -e 's#[^/]*/\([^/]*\)$#|____\1#' \
index d04821cf1852b73337d09ce70ab89fd48d7a0677..23d3399ecb6b6c57cb7d3f76954a6d4592fbbebe 100644 (file)
@@ -24,7 +24,7 @@ ff        () { find . -name ${1} -print ; }
 ll        () { ls -lag "$@" | more ; }
 word      () { fgrep -i "$*" /usr/dict/web2 ; }
 wordcount () { cat "${1}" | tr -s '    .,;:?\!()[]"' '\012' | \
-              cat -n | tail -1 | awk '{print $1}' ; }
+              awk 'END {print NR}' ; }
 
 ##
 # Read user's aliases
index d8bde10b0a1264855e88b8fa34522c732c96a58a..2291c7af80f38e66488b0e54a57f03cc66977ed6 100644 (file)
@@ -1,6 +1,6 @@
 /* execute_command.c -- Execute a COMMAND structure. */
 
-/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -101,7 +101,6 @@ extern int parse_and_execute_level, running_trap, trap_line_number;
 extern int command_string_index, line_number;
 extern int dot_found_in_search;
 extern int already_making_children;
-extern char **temporary_env, **function_env, **builtin_env;
 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;
@@ -133,7 +132,7 @@ static int execute_for_command __P((FOR_COM *));
 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 *));
+static char *select_query __P((WORD_LIST *, int, char *, int));
 static int execute_select_command __P((SELECT_COM *));
 #endif
 #if defined (DPAREN_ARITHMETIC)
@@ -151,7 +150,7 @@ static void print_formatted_time __P((FILE *, char *,
 static int time_command __P((COMMAND *, int, int, int, struct fd_bitmap *));
 #endif
 #if defined (ARITH_FOR_COMMAND)
-static long eval_arith_for_expr __P((WORD_LIST *, int *));
+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 *));
@@ -186,8 +185,6 @@ static int execute_connection __P((COMMAND *, int, int, int, struct fd_bitmap *)
 
 static int execute_intern_function __P((WORD_DESC *, COMMAND *));
 
-
-
 /* The line number that the currently executing function starts on. */
 static int function_line_number;
 
@@ -249,7 +246,7 @@ new_fd_bitmap (size)
   if (size)
     {
       ret->bitmap = (char *)xmalloc (size);
-      bzero (ret->bitmap, size);
+      memset (ret->bitmap, '\0', size);
     }
   else
     ret->bitmap = (char *)NULL;
@@ -285,9 +282,19 @@ close_fd_bitmap (fdbp)
 int
 executing_line_number ()
 {
-  if (executing && variable_context == 0 && currently_executing_command &&
-       currently_executing_command->type == cm_simple)
-    return currently_executing_command->value.Simple->line;
+  if (executing && (variable_context == 0 || interactive_shell == 0) && currently_executing_command)
+    {
+      if (currently_executing_command->type == cm_simple)
+       return currently_executing_command->value.Simple->line;
+      else if (currently_executing_command->type == cm_cond)
+       return currently_executing_command->value.Cond->line;
+      else if (currently_executing_command->type == cm_arith)
+       return currently_executing_command->value.Arith->line;
+      else if (currently_executing_command->type == cm_arith_for)
+       return currently_executing_command->value.ArithFor->line;
+      else
+       return line_number;
+    }
   else if (running_trap)
     return trap_line_number;
   else
@@ -459,7 +466,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
      int pipe_in, pipe_out;
      struct fd_bitmap *fds_to_close;
 {
-  int exec_result, invert, ignore_return, was_debug_trap, was_error_trap;
+  int exec_result, invert, ignore_return, was_error_trap;
   REDIRECT *my_undo_list, *exec_undo_list;
   volatile pid_t last_pid;
 
@@ -613,7 +620,6 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
           call to execute_simple_command if a longjmp occurs as the
           result of a `return' builtin.  This is true for sure with gcc. */
        last_pid = last_made_pid;
-       was_debug_trap = signal_is_trapped (DEBUG_TRAP) && signal_is_ignored (DEBUG_TRAP) == 0;
        was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
 
        if (ignore_return && command->value.Simple)
@@ -668,12 +674,6 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
          }
       }
 
-      if (was_debug_trap)
-       {
-         last_command_exit_value = exec_result;
-         run_debug_trap ();
-       }
-
       if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
        {
          last_command_exit_value = exec_result;
@@ -910,16 +910,16 @@ mkfmt (buf, prec, lng, sec, sec_fraction)
 
 /* Interpret the format string FORMAT, interpolating the following escape
    sequences:
-               %[prec][l][RUS]
+               %[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
+               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
@@ -1392,9 +1392,6 @@ execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close)
      int asynchronous, pipe_in, pipe_out;
      struct fd_bitmap *fds_to_close;
 {
-#if 0
-  REDIRECT *tr, *tl;
-#endif
   REDIRECT *rp;
   COMMAND *tc, *second;
   int ignore_return, exec_result;
@@ -1424,37 +1421,12 @@ execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close)
 #else
       if (!stdin_redir)
 #endif /* JOB_CONTROL */
-       {
-#if 0
-         rd.filename = make_bare_word ("/dev/null");
-         tr = make_redirection (0, r_inputa_direction, rd);
-         tr->next = tc->redirects;
-         tc->redirects = tr;
-#endif
-         tc->flags |= CMD_STDIN_REDIR;
-       }
+       tc->flags |= CMD_STDIN_REDIR;
 
       exec_result = execute_command_internal (tc, 1, pipe_in, pipe_out, fds_to_close);
 
       if (tc->flags & CMD_STDIN_REDIR)
-       {
-#if 0
-         /* Remove the redirection we added above.  It matters,
-            especially for loops, which call execute_command ()
-            multiple times with the same command. */
-         tr = tc->redirects;
-         do
-           {
-             tl = tc->redirects;
-             tc->redirects = tc->redirects->next;
-           }
-         while (tc->redirects && tc->redirects != rp);
-
-         tl->next = (REDIRECT *)NULL;
-         dispose_redirects (tr);
-#endif
-         tc->flags &= ~CMD_STDIN_REDIR;
-       }
+       tc->flags &= ~CMD_STDIN_REDIR;
 
       second = command->value.Connection->second;
       if (second)
@@ -1628,7 +1600,7 @@ execute_for_command (for_command)
   if (lexical_scoping)
     {
       if (!old_value)
-       makunbound (identifier, shell_variables);
+        unbind_variable (identifier);
       else
        {
          SHELL_VAR *new_value;
@@ -1661,19 +1633,22 @@ execute_for_command (for_command)
                eval \(\( step \)\)
        done
 */
-static long
+static intmax_t
 eval_arith_for_expr (l, okp)
      WORD_LIST *l;
      int *okp;
 {
   WORD_LIST *new;
-  long expresult;
+  intmax_t expresult;
 
   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 */
+      if (signal_is_trapped (DEBUG_TRAP) && signal_is_ignored (DEBUG_TRAP) == 0)
+       run_debug_trap ();
       expresult = evalexp (new->word->word, okp);
       dispose_words (new);
     }
@@ -1690,8 +1665,8 @@ static int
 execute_arith_for_command (arith_for_command)
      ARITH_FOR_COM *arith_for_command;
 {
-  long expresult;
-  int expok, body_status;
+  intmax_t expresult;
+  int expok, body_status, arith_lineno, save_lineno;
 
   body_status = EXECUTION_SUCCESS;
   loop_level++;
@@ -1701,8 +1676,12 @@ execute_arith_for_command (arith_for_command)
 
   this_command_name = "((";    /* )) for expression error messages */
 
-  if (variable_context)
-    line_number = arith_for_command->line - function_line_number;
+  /* save the starting line number of the command so we can reset
+     line_number before executing each expression -- for $LINENO
+     and the DEBUG trap. */
+  arith_lineno = arith_for_command->line;
+  if (variable_context && interactive_shell)
+    line_number = arith_lineno -= function_line_number;
 
   /* Evaluate the initialization expression. */
   expresult = eval_arith_for_expr (arith_for_command->init, &expok);
@@ -1712,7 +1691,11 @@ execute_arith_for_command (arith_for_command)
   while (1)
     {
       /* Evaluate the test expression. */
+      save_lineno = line_number;
+      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;
@@ -1742,7 +1725,11 @@ execute_arith_for_command (arith_for_command)
        }
 
       /* Evaluate the step expression. */
+      save_lineno = line_number;
+      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;
@@ -1859,13 +1846,14 @@ print_select_list (list, list_len, max_elem_len, indices_len)
    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)
+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;
-  long reply;
+  intmax_t reply;
   WORD_LIST *l;
   char *repl_string, *t;
 
@@ -1895,7 +1883,8 @@ select_query (list, list_len, prompt)
 
   while (1)
     {
-      print_select_list (list, list_len, max_elem_len, indices_len);
+      if (print_menu)
+       print_select_list (list, list_len, max_elem_len, indices_len);
       fprintf (stderr, "%s", prompt);
       fflush (stderr);
       QUIT;
@@ -1907,7 +1896,10 @@ select_query (list, list_len, prompt)
        }
       repl_string = get_string_value ("REPLY");
       if (*repl_string == 0)
-       continue;
+       {
+         print_menu = 1;
+         continue;
+       }
       if (legal_number (repl_string, &reply) == 0)
        return "";
       if (reply < 1 || reply > list_len)
@@ -1930,8 +1922,8 @@ execute_select_command (select_command)
   WORD_LIST *releaser, *list;
   SHELL_VAR *v;
   char *identifier, *ps3_prompt, *selection;
-  int retval, list_len;
+  int retval, list_len, show_menu;
+
   if (check_identifier (select_command->name, 1) == 0)
     return (EXECUTION_FAILURE);
 
@@ -1956,6 +1948,7 @@ execute_select_command (select_command)
     select_command->action->flags |= CMD_IGNORE_RETURN;
 
   retval = EXECUTION_SUCCESS;
+  show_menu = 1;
 
   while (1)
     {
@@ -1964,10 +1957,15 @@ execute_select_command (select_command)
        ps3_prompt = "#? ";
 
       QUIT;
-      selection = select_query (list, list_len, ps3_prompt);
+      selection = select_query (list, list_len, ps3_prompt, show_menu);
       QUIT;
       if (selection == 0)
-       break;
+       {
+         /* 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);
       if (readonly_p (v) || noassign_p (v))
@@ -2001,6 +1999,13 @@ execute_select_command (select_command)
          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--;
@@ -2027,7 +2032,7 @@ execute_case_command (case_command)
   /* Posix.2 specifies that the WORD is tilde expanded. */
   if (member ('~', case_command->word->word))
     {
-      word = bash_tilde_expand (case_command->word->word);
+      word = bash_tilde_expand (case_command->word->word, 0);
       free (case_command->word->word);
       case_command->word->word = word;
     }
@@ -2053,7 +2058,7 @@ execute_case_command (case_command)
             list. */
          if (member ('~', list->word->word))
            {
-             pattern = bash_tilde_expand (list->word->word);
+             pattern = bash_tilde_expand (list->word->word, 0);
              free (list->word->word);
              list->word->word = pattern;
            }
@@ -2217,16 +2222,22 @@ execute_arith_command (arith_command)
      ARITH_COM *arith_command;
 {
   int expok;
-  long expresult;
+  intmax_t expresult;
   WORD_LIST *new;
 
   expresult = 0;
 
   this_command_name = "((";    /* )) */
   /* If we're in a function, update the line number information. */
-  if (variable_context)
+  if (variable_context && interactive_shell)
     line_number = arith_command->line - function_line_number;
 
+  /* 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. */
+  if (signal_is_trapped (DEBUG_TRAP) && signal_is_ignored (DEBUG_TRAP) == 0)
+    run_debug_trap ();
+
   new = expand_words (arith_command->exp);
 
   /* If we're tracing, make a new word list with `((' at the front and `))'
@@ -2329,9 +2340,14 @@ execute_cond_command (cond_command)
 
   this_command_name = "[[";
   /* If we're in a function, update the line number information. */
-  if (variable_context)
+  if (variable_context && interactive_shell)
     line_number = cond_command->line - function_line_number;
 
+  /* Run the debug trap before each conditional command, but do it after we
+     update the line number information. */
+  if (signal_is_trapped (DEBUG_TRAP) && signal_is_ignored (DEBUG_TRAP) == 0)
+    run_debug_trap ();
+
 #if 0
   debug_print_cond_command (cond_command);
 #endif
@@ -2418,13 +2434,19 @@ fix_assignment_words (words)
   if (words == 0)
     return;
 
-  b = builtin_address_internal (words->word->word, 0);
-  if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
-    return;
+  b = 0;
 
   for (w = words; w; w = w->next)
     if (w->word->flags & W_ASSIGNMENT)
-      w->word->flags |= (W_NOSPLIT|W_NOGLOB);
+      {
+       if (b == 0)
+         {
+           b = builtin_address_internal (words->word->word, 0);
+           if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
+             return;
+         }
+       w->word->flags |= (W_NOSPLIT|W_NOGLOB|W_TILDEEXP);
+      }
 }
 
 /* The meaty part of all the executions.  We have to start hacking the
@@ -2448,9 +2470,14 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
   command_line = (char *)0;
 
   /* If we're in a function, update the line number information. */
-  if (variable_context)
+  if (variable_context && interactive_shell)
     line_number = simple_command->line - function_line_number;
 
+  /* Run the debug trap before each simple command, but do it after we
+     update the line number information. */
+  if (signal_is_trapped (DEBUG_TRAP) && signal_is_ignored (DEBUG_TRAP) == 0)
+    run_debug_trap ();
+
   /* Remember what this command line looks like at invocation. */
   command_string_index = 0;
   print_simple_command (simple_command);
@@ -2607,48 +2634,25 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
        pipe_out == NO_PIPE &&
        (temp = get_string_value ("auto_resume")))
     {
-      char *word;
-      register int i;
-      int wl, cl, exact_p, substring_p, match, started_status;
-      register PROCESS *p;
+      int job, jflags, started_status;
 
-      word = words->word->word;
-      exact_p = STREQ (temp, "exact");
-      substring_p = STREQ (temp, "substring");
-      wl = strlen (word);
-      for (i = job_slots - 1; i > -1; i--)
+      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)
        {
-         if (jobs[i] == 0 || (JOBSTATE (i) != JSTOPPED))
-           continue;
+         run_unwind_frame ("simple-command");
+         this_command_name = "fg";
+         last_shell_builtin = this_shell_builtin;
+         this_shell_builtin = builtin_address ("fg");
 
-         p = jobs[i]->pipe;
-         do
-           {
-             if (exact_p)
-               {
-                 cl = strlen (p->command);
-                 match = STREQN (p->command, word, cl);
-               }
-             else if (substring_p)
-               match = strindex (p->command, word) != (char *)0;
-             else
-               match = STREQN (p->command, word, wl);
-
-             if (match == 0)
-               {
-                 p = p->next;
-                 continue;
-               }
-
-             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 (i, 1);
-             return ((started_status < 0) ? EXECUTION_FAILURE : started_status);
-           }
-         while (p != jobs[i]->pipe);
+         started_status = start_job (job, 1);
+         return ((started_status < 0) ? EXECUTION_FAILURE : started_status);
        }
     }
 #endif /* JOB_CONTROL */
@@ -2771,6 +2775,7 @@ execute_builtin (builtin, words, flags, subshell)
      int flags, subshell;
 {
   int old_e_flag, result, eval_unwind;
+  int isbltinenv;
 
   old_e_flag = exit_immediately_on_error;
   /* The eval builtin calls parse_and_execute, which does not know about
@@ -2792,19 +2797,19 @@ execute_builtin (builtin, words, flags, subshell)
   /* 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 `source' and `eval' builtins. */
-  if (builtin == source_builtin || builtin == eval_builtin)
+  isbltinenv = (builtin == source_builtin || builtin == eval_builtin);
+  if (isbltinenv)
     {
       if (subshell == 0)
        begin_unwind_frame ("builtin_env");
 
       if (temporary_env)
        {
-         builtin_env = copy_array (temporary_env);
+         push_scope (VC_BLTNENV, temporary_env);
          if (subshell == 0)
-           add_unwind_protect (dispose_builtin_env, (char *)NULL);
-         dispose_used_env_vars ();
+           add_unwind_protect (pop_scope, "1");
+          temporary_env = (HASH_TABLE *)NULL;    
        }
-      /* Otherwise we inherit builtin_env from our caller. */
     }
 
   /* `return' does a longjmp() back to a saved environment in execute_function.
@@ -2824,16 +2829,8 @@ execute_builtin (builtin, words, flags, subshell)
   if (posixly_correct && subshell == 0 && builtin == return_builtin && temporary_env)
     discard_unwind_frame ("return_temp_env");
 
-  if (subshell == 0 && (builtin == source_builtin || builtin == eval_builtin))
-    {
-      /* In POSIX mode, if any variable assignments precede the `.' or
-        `eval' builtin, they persist after the builtin completes, since `.'
-        and `eval' are special builtins. */
-      if (posixly_correct && builtin_env)
-       merge_builtin_env ();
-
-      run_unwind_frame ("builtin_env");
-    }
+  if (subshell == 0 && isbltinenv)
+    run_unwind_frame ("builtin_env");
 
   if (eval_unwind)
     {
@@ -2865,7 +2862,7 @@ execute_function (var, words, flags, fds_to_close, async, subshell)
   if (subshell == 0)
     {
       begin_unwind_frame ("function_calling");
-      push_context ();
+      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);
@@ -2874,6 +2871,10 @@ execute_function (var, words, flags, fds_to_close, async, subshell)
       unwind_protect_pointer (this_shell_function);
       unwind_protect_int (loop_level);
     }
+  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);
@@ -2885,7 +2886,7 @@ execute_function (var, words, flags, fds_to_close, async, subshell)
      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. */
-  if (debug_trap)
+  if (debug_trap && (trace_p (var) == 0))
     {
       if (subshell == 0)
        {
@@ -2909,27 +2910,12 @@ execute_function (var, words, flags, fds_to_close, async, subshell)
 
   /* The temporary environment for a function is supposed to apply to
      all commands executed within the function body. */
-  if (temporary_env)
-    {
-      function_env = copy_array (temporary_env);
-      /* In POSIX mode, variable assignments preceding function names are
-        supposed to persist in the environment after the function returns,
-        as if a special builtin command had been executed. */
-      if (subshell == 0)
-       {
-         if (posixly_correct)
-           add_unwind_protect (merge_function_env, (char *)NULL);
-         else
-           add_unwind_protect (dispose_function_env, (char *)NULL);
-       }
-      dispose_used_env_vars ();
-    }
-    /* Otherwise, we inherit function_env from our caller. */
 
   remember_args (words->next, 1);
 
   /* Number of the line on which the function body starts. */
-  line_number = function_line_number = tc->line;
+  if (interactive_shell)
+    line_number = function_line_number = tc->line;
 
   if (subshell)
     {
@@ -2940,8 +2926,6 @@ execute_function (var, words, flags, fds_to_close, async, subshell)
 
       if (fc && (flags & CMD_IGNORE_RETURN))
        fc->flags |= CMD_IGNORE_RETURN;
-
-      variable_context++;
     }
   else
     fc = tc;
@@ -3202,7 +3186,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
   pathname = words->word->word;
 
 #if defined (RESTRICTED_SHELL)
-  if (restricted && strchr (pathname, '/'))
+  if (restricted && xstrchr (pathname, '/'))
     {
       internal_error ("%s: restricted: cannot specify `/' in command names",
                    pathname);
@@ -3293,7 +3277,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
       /* 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 = word_list_to_argv (words, 0, 0, (int *)NULL);
+      args = strvec_from_word_list (words, 0, 0, (int *)NULL);
       exit (shell_execve (command, args, export_env));
     }
   else
@@ -3387,9 +3371,8 @@ execute_shell_script (sample, sample_len, command, args, env)
       size_increment = 2;
     }
 
-  larry = array_len (args) + size_increment;
-
-  args = (char **)xrealloc ((char *)args, (1 + larry) * sizeof (char *));
+  larry = strvec_len (args) + size_increment;
+  args = strvec_resize (args, larry + 1);
 
   for (i = larry - 1; i; i--)
     args[i] = args[i - size_increment];
@@ -3440,8 +3423,10 @@ initialize_subshell ()
   /* 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). */
-  builtin_env = 0;
+     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);
 
@@ -3497,8 +3482,15 @@ shell_execve (command, args, env)
     {
       if ((stat (command, &finfo) == 0) && (S_ISDIR (finfo.st_mode)))
        internal_error ("%s: is a directory", command);
+      else if (executable_file (command) == 0)
+       {
+         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);
          if (sample_len > 2 && sample[0] == '#' && sample[1] == '!')
@@ -3557,8 +3549,8 @@ shell_execve (command, args, env)
   set_sigint_handler ();
 
   /* Insert the name of this shell into the argument list. */
-  larray = array_len (args) + 1;
-  args = (char **)xrealloc ((char *)args, (1 + larray) * sizeof (char *));
+  larray = strvec_len (args) + 1;
+  args = strvec_resize (args, larray + 1);
 
   for (i = larray - 1; i; i--)
     args[i] = args[i - 1];
@@ -3634,7 +3626,7 @@ close_all_files ()
 
   fd_table_size = getdtablesize ();
   if (fd_table_size > 256)     /* clamp to a reasonable value */
-       fd_table_size = 256;
+    fd_table_size = 256;
 
   for (i = 3; i < fd_table_size; i++)
     close (i);
diff --git a/expr.c b/expr.c
index 83c20d988b39b1538fae875b4db9107093f749ff..a4a3ae8ad5aba2d86595be2794ef8c016aecf821 100644 (file)
--- a/expr.c
+++ b/expr.c
@@ -1,6 +1,6 @@
 /* expr.c -- arithmetic expression evaluation. */
 
-/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+/* Copyright (C) 1990-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -19,7 +19,7 @@
    Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
 
 /*
- All arithmetic is done as long integers with no checking for overflow
+ All arithmetic is done as intmax_t integers with no checking for overflow
  (though division by 0 is caught and flagged as an error).
 
  The following operators are handled, grouped into a set of levels in
@@ -142,41 +142,44 @@ static int        curtok;         /* the current token */
 static int     lasttok;        /* the previous token */
 static int     assigntok;      /* the OP in OP= */
 static char    *tokstr;        /* current token string */
-static long    tokval;         /* current token value */
+static intmax_t        tokval;         /* current token value */
 static int     noeval;         /* set to 1 if no assignment to be done */
 static procenv_t evalbuf;
 
 static void    readtok __P((void));    /* lexical analyzer */
-static long    strlong __P((char *));
+
+static intmax_t        expr_streval __P((char *, int));
+static intmax_t        strlong __P((char *));
 static void    evalerror __P((char *));
 
 static void    pushexp __P((void));
 static void    popexp __P((void));
-
-static long    subexpr __P((char *));
-
-static long    expcomma __P((void));
-static long    expassign __P((void));
-static long    expcond __P((void));
-static long    explor __P((void));
-static long    expland __P((void));
-static long    expbor __P((void));
-static long    expbxor __P((void));
-static long    expband __P((void));
-static long    exp5 __P((void));
-static long    exp4 __P((void));
-static long    expshift __P((void));
-static long    exp3 __P((void));
-static long    exp2 __P((void));
-static long    exppower __P((void));
-static long    exp1 __P((void));
-static long    exp0 __P((void));
+static void    expr_unwind __P((void));
+
+static intmax_t subexpr __P((char *));
+
+static intmax_t        expcomma __P((void));
+static intmax_t expassign __P((void));
+static intmax_t        expcond __P((void));
+static intmax_t explor __P((void));
+static intmax_t expland __P((void));
+static intmax_t        expbor __P((void));
+static intmax_t        expbxor __P((void));
+static intmax_t        expband __P((void));
+static intmax_t exp5 __P((void));
+static intmax_t exp4 __P((void));
+static intmax_t expshift __P((void));
+static intmax_t exp3 __P((void));
+static intmax_t exp2 __P((void));
+static intmax_t        exppower __P((void));
+static intmax_t exp1 __P((void));
+static intmax_t exp0 __P((void));
 
 /* A structure defining a single expression context. */
 typedef struct {
   int curtok, lasttok;
   char *expression, *tp, *lasttp;
-  long tokval;
+  intmax_t tokval;
   char *tokstr;
   int noeval;
 } EXPR_CONTEXT;
@@ -185,7 +188,7 @@ typedef struct {
 /* Not used yet. */
 typedef struct {
   char *tokstr;
-  long tokval;
+  intmax_t tokval;
 } LVALUE;
 #endif
 
@@ -195,6 +198,7 @@ static int expr_depth;                 /* Location in the stack. */
 static int expr_stack_size;       /* Number of slots already allocated. */
 
 extern char *this_command_name;
+extern int unbound_vars_is_error;
 
 #define SAVETOK(X) \
   do { \
@@ -260,6 +264,22 @@ popexp ()
   free (context);
 }
 
+static void
+expr_unwind ()
+{
+  while (--expr_depth > 0)
+    {
+      if (expr_stack[expr_depth]->tokstr)
+       free (expr_stack[expr_depth]->tokstr);
+
+      if (expr_stack[expr_depth]->expression)
+       free (expr_stack[expr_depth]->expression);
+
+      free (expr_stack[expr_depth]);
+    }
+  free (expr_stack[expr_depth]);       /* free the allocated EXPR_CONTEXT */
+}
+
 /* Evaluate EXPR, and return the arithmetic result.  If VALIDP is
    non-null, a zero is stored into the location to which it points
    if the expression is invalid, non-zero otherwise.  If a non-zero
@@ -273,41 +293,22 @@ popexp ()
    were assigned at program startup or by the compiler.  Therefore, it is
    safe to let the loop terminate when expr_depth == 0, without freeing up
    any of the expr_depth[0] stuff. */
-long
+intmax_t
 evalexp (expr, validp)
      char *expr;
      int *validp;
 {
-  long val;
-#if 0
-  procenv_t old_evalbuf;
-#endif
+  intmax_t val;
 
   val = 0;
 
-#if 0
-  /* Save the value of evalbuf to protect it around possible recursive
-     calls to evalexp (). */
-  COPY_PROCENV (evalbuf, old_evalbuf);
-#endif
-
   if (setjmp (evalbuf))
     {
       FREE (tokstr);
       FREE (expression);
       tokstr = expression = (char *)NULL;
 
-      while (--expr_depth > 0)
-       {
-         if (expr_stack[expr_depth]->tokstr)
-           free (expr_stack[expr_depth]->tokstr);
-
-         if (expr_stack[expr_depth]->expression)
-           free (expr_stack[expr_depth]->expression);
-
-         free (expr_stack[expr_depth]);
-       }
-      free (expr_stack[expr_depth]);   /* free the allocated EXPR_CONTEXT */
+      expr_unwind ();
 
       if (validp)
        *validp = 0;
@@ -316,23 +317,17 @@ evalexp (expr, validp)
 
   val = subexpr (expr);
 
-#if 0
-  /* Restore the value of evalbuf so that any subsequent longjmp calls
-     will have a valid location to jump to. */
-  COPY_PROCENV (old_evalbuf, evalbuf);
-#endif
-
   if (validp)
     *validp = 1;
 
   return (val);
 }
 
-static long
+static intmax_t
 subexpr (expr)
      char *expr;
 {
-  long val;
+  intmax_t val;
   char *p;
 
   for (p = expr; p && *p && cr_whitespace (*p); p++)
@@ -364,10 +359,10 @@ subexpr (expr)
   return val;
 }
 
-static long
+static intmax_t
 expcomma ()
 {
-  register long value;
+  register intmax_t value;
 
   value = expassign ();
   while (curtok == COMMA)
@@ -379,17 +374,17 @@ expcomma ()
   return value;
 }
   
-static long
+static intmax_t
 expassign ()
 {
-  register long        value;
+  register intmax_t value;
   char *lhs, *rhs;
 
   value = expcond ();
   if (curtok == EQ || curtok == OP_ASSIGN)
     {
       int special, op;
-      long lvalue;
+      intmax_t lvalue;
 
       special = curtok == OP_ASSIGN;
 
@@ -414,9 +409,13 @@ expassign ()
              lvalue *= value;
              break;
            case DIV:
+             if (value == 0)
+               evalerror ("division by 0");
              lvalue /= value;
              break;
            case MOD:
+             if (value == 0)
+               evalerror ("division by 0");
              lvalue %= value;
              break;
            case PLUS:
@@ -460,10 +459,10 @@ expassign ()
 }
 
 /* Conditional expression (expr?expr:expr) */
-static long
+static intmax_t
 expcond ()
 {
-  long cval, val1, val2, rval;
+  intmax_t cval, val1, val2, rval;
   int set_noeval;
 
   set_noeval = 0;
@@ -504,10 +503,10 @@ expcond ()
 }
 
 /* Logical OR. */
-static long
+static intmax_t
 explor ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
   int set_noeval;
 
   val1 = expland ();
@@ -532,10 +531,10 @@ explor ()
 }
 
 /* Logical AND. */
-static long
+static intmax_t
 expland ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
   int set_noeval;
 
   val1 = expbor ();
@@ -560,10 +559,10 @@ expland ()
 }
 
 /* Bitwise OR. */
-static long
+static intmax_t
 expbor ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
 
   val1 = expbxor ();
 
@@ -578,10 +577,10 @@ expbor ()
 }
 
 /* Bitwise XOR. */
-static long
+static intmax_t
 expbxor ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
 
   val1 = expband ();
 
@@ -596,10 +595,10 @@ expbxor ()
 }
 
 /* Bitwise AND. */
-static long
+static intmax_t
 expband ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
 
   val1 = exp5 ();
 
@@ -613,10 +612,10 @@ expband ()
   return (val1);
 }
 
-static long
+static intmax_t
 exp5 ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
 
   val1 = exp4 ();
 
@@ -634,10 +633,10 @@ exp5 ()
   return (val1);
 }
 
-static long
+static intmax_t
 exp4 ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
 
   val1 = expshift ();
   while ((curtok == LEQ) ||
@@ -663,10 +662,10 @@ exp4 ()
 }
 
 /* Left and right shifts. */
-static long
+static intmax_t
 expshift ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
 
   val1 = exp3 ();
 
@@ -686,10 +685,10 @@ expshift ()
   return (val1);
 }
 
-static long
+static intmax_t
 exp3 ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
 
   val1 = exp2 ();
 
@@ -708,10 +707,10 @@ exp3 ()
   return (val1);
 }
 
-static long
+static intmax_t
 exp2 ()
 {
-  register long val1, val2;
+  register intmax_t val1, val2;
 
   val1 = exppower ();
 
@@ -738,10 +737,10 @@ exp2 ()
   return (val1);
 }
 
-static long
+static intmax_t
 exppower ()
 {
-  register long val1, val2, c;
+  register intmax_t val1, val2, c;
 
   val1 = exp1 ();
   if (curtok == POWER)
@@ -759,10 +758,10 @@ exppower ()
   return (val1);
 }
 
-static long
+static intmax_t
 exp1 ()
 {
-  register long val;
+  register intmax_t val;
 
   if (curtok == NOT)
     {
@@ -780,10 +779,10 @@ exp1 ()
   return (val);
 }
 
-static long
+static intmax_t
 exp0 ()
 {
-  register long val = 0, v2;
+  register intmax_t val = 0, v2;
   char *vincdec;
   int stok;
 
@@ -852,6 +851,61 @@ exp0 ()
   return (val);
 }
 
+static intmax_t
+expr_streval (tok, e)
+     char *tok;
+     int e;
+{
+  SHELL_VAR *v;
+  char *value;
+  intmax_t tval;
+
+  /* [[[[[ */
+#if defined (ARRAY_VARS)
+  v = (e == ']') ? array_variable_part (tok, (char **)0, (int *)0) : find_variable (tok);
+#else
+  v = find_variable (tok);
+#endif
+
+  if ((v == 0 || invisible_p (v)) && unbound_vars_is_error)
+    {
+#if defined (ARRAY_VARS)
+      value = (e == ']') ? array_variable_name (tok, (char **)0, (int *)0) : tok;
+#else
+      value = tok;
+#endif
+
+      err_unboundvar (value);
+
+#if defined (ARRAY_VARS)
+      if (e == ']')
+       FREE (value);   /* array_variable_name returns new memory */
+#endif
+
+      if (interactive_shell)
+       {
+         expr_unwind ();
+         jump_to_top_level (DISCARD);
+       }
+      else
+       jump_to_top_level (FORCE_EOF);
+    }
+
+#if defined (ARRAY_VARS)
+  /* Second argument of 0 to get_array_value means that we don't allow
+     references like array[@].  In this case, get_array_value is just
+     like get_variable_value in that it does not return newly-allocated
+     memory or quote the results. */
+  value = (e == ']') ? get_array_value (tok, 0, (int *)NULL) : get_variable_value (v);
+#else
+  value = get_variable_value (v);
+#endif
+
+  tval = (value && *value) ? subexpr (value) : 0;
+
+  return (tval);
+}
+
 /* Lexical analyzer/token reader for the expression evaluator.  Reads the
    next token and puts its value into curtok, while advancing past it.
    Updates value of tp.  May also set tokval (for number) or tokstr (for
@@ -885,7 +939,7 @@ readtok ()
   if (legal_variable_starter (c))
     {
       /* variable names not preceded with a dollar sign are shell variables. */
-      char *value, *savecp;
+      char *savecp;
       EXPR_CONTEXT ec;
       int peektok;
 
@@ -928,20 +982,7 @@ readtok ()
       /* The tests for PREINC and PREDEC aren't strictly correct, but they
         preserve old behavior if a construct like --x=9 is given. */
       if (lasttok == PREINC || lasttok == PREDEC || peektok != EQ)
-       {
-#if defined (ARRAY_VARS)
-         value = (e == ']') ? get_array_value (tokstr, 0) : get_string_value (tokstr);
-#else
-         value = get_string_value (tokstr);
-#endif
-
-         tokval = (value && *value) ? subexpr (value) : 0;
-
-#if defined (ARRAY_VARS)
-         if (e == ']')
-           FREE (value);       /* get_array_value returns newly-allocated memory */
-#endif
-       }
+       tokval = expr_streval (tokstr, e);
       else
        tokval = 0;
 
@@ -1032,7 +1073,7 @@ evalerror (msg)
   longjmp (evalbuf, 1);
 }
 
-/* Convert a string to a long integer, with an arbitrary base.
+/* Convert a string to an intmax_t integer, with an arbitrary base.
    0nnn -> base 8
    0[Xx]nn -> base 16
    Anything else: [base#]number (this is implemented to match ksh93)
@@ -1043,14 +1084,14 @@ evalerror (msg)
    from [0-9][a-z][A-Z]_@ (a = 10, z = 35, A = 36, Z = 61, _ = 62, @ = 63 --
    you get the picture). */
 
-static long
+static intmax_t
 strlong (num)
      char *num;
 {
   register char *s;
   register unsigned char c;
   int base, foundbase;
-  long val;
+  intmax_t val;
 
   s = num;
 
@@ -1142,7 +1183,7 @@ main (argc, argv)
      char **argv;
 {
   register int i;
-  long v;
+  intmax_t v;
   int expok;
 
   if (setjmp (top_level))
@@ -1171,7 +1212,7 @@ builtin_error (format, arg1, arg2, arg3, arg4, arg5)
 
 char *
 itos (n)
-     long n;
+     intmax_t n;
 {
   return ("42");
 }
index 3fcf4004743a494228aa543c5d7cb4a79edd87fc..1da16f74ed92b662da2a18d880e408dfbe49e8ad 100644 (file)
--- a/externs.h
+++ b/externs.h
@@ -1,7 +1,7 @@
 /* externs.h -- extern function declarations which do not appear in their
    own header file. */
 
-/* Copyright (C) 1993 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -27,7 +27,7 @@
 #include "stdc.h"
 
 /* Functions from expr.c. */
-extern long evalexp __P((char *, int *));
+extern intmax_t evalexp __P((char *, int *));
 
 /* Functions from print_cmd.c. */
 extern char *make_command_string __P((COMMAND *));
@@ -35,6 +35,7 @@ extern void print_command __P((COMMAND *));
 extern void print_simple_command __P((SIMPLE_COM *));
 extern char *named_function_string __P((char *, COMMAND *, int));
 extern void print_word_list __P((WORD_LIST *, char *));
+extern char *indirection_level_string __P((void));
 extern void xtrace_print_word_list __P((WORD_LIST *));
 #if defined (DPAREN_ARITHMETIC)
 extern void xtrace_print_arith_cmd __P((WORD_LIST *));
@@ -45,6 +46,7 @@ extern void xtrace_print_cond_term __P((int, int, WORD_DESC *, char *, char *));
 
 /* Functions from shell.c. */
 extern void exit_shell __P((int)) __attribute__((__noreturn__));
+extern void sh_exit __P((int)) __attribute__((__noreturn__));
 extern void disable_priv_mode __P((void));
 extern void unbind_args __P((void));
 
@@ -72,6 +74,8 @@ extern int return_EOF __P((void));
 extern void reset_parser __P((void));
 extern WORD_LIST *parse_string_to_word_list __P((char *, const char *));
 
+extern char *decode_prompt_string __P((char *));
+
 extern int get_current_prompt_level __P((void));
 extern void set_current_prompt_level __P((int));
 
@@ -86,21 +90,23 @@ extern int set_locale_var __P((char *, char *));
 extern int set_lang __P((char *, char *));
 extern char *get_locale_var __P((char *));
 extern char *localetrans __P((char *, int, int *));
+extern char *mk_msgstr __P((char *, int *));
+extern char *localeexpand __P((char *, int, int, int, int *));
 
 /* Declarations for functions defined in list.c. */
-extern void map_over_list __P((GENERIC_LIST *, sh_glist_func_t *));
-extern void map_over_words __P((WORD_LIST *, sh_icpfunc_t *));
-extern GENERIC_LIST *reverse_list ();
+extern void list_walk __P((GENERIC_LIST *, sh_glist_func_t *));
+extern void wlist_walk __P((WORD_LIST *, sh_icpfunc_t *));
+extern GENERIC_LIST *list_reverse ();
 extern int list_length ();
 extern GENERIC_LIST *list_append ();
-extern GENERIC_LIST *delete_element ();
+extern GENERIC_LIST *list_remove ();
 
 /* Declarations for functions defined in stringlib.c */
-extern char **word_list_to_argv __P((WORD_LIST *, int, int, int *));
-extern WORD_LIST *argv_to_word_list __P((char **, int, int));
-
 extern int find_string_in_alist __P((char *, STRING_INT_ALIST *, int));
+extern char *find_token_in_alist __P((int, STRING_INT_ALIST *, int));
+extern int find_index_in_alist __P((char *, STRING_INT_ALIST *, int));
 
+extern char *substring __P((char *, int, int));
 extern char *strsub __P((char *, char *, char *, int));
 extern char *strcreplace __P((char *, int, char *, int));
 extern void strip_leading __P((char *));
@@ -130,16 +136,19 @@ extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
 extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
 #endif
 
+/* Declarations for functions defined in lib/sh/fmtumax.c */
+extern char *fmtumax __P((uintmax_t, int, char *, size_t, int));
+
 /* Declarations for functions defined in lib/sh/getcwd.c */
 #if !defined (HAVE_GETCWD)
 extern char *getcwd __P((char *, size_t));
 #endif
 
 /* Declarations for functions defined in lib/sh/itos.c */
-extern char *inttostr __P((long, char *, size_t));
-extern char *itos __P((long));
-extern char *uinttostr __P((unsigned long, char *, size_t));
-extern char *uitos __P((unsigned long));
+extern char *inttostr __P((intmax_t, char *, size_t));
+extern char *itos __P((intmax_t));
+extern char *uinttostr __P((uintmax_t, char *, size_t));
+extern char *uitos __P((uintmax_t));
 
 /* declarations for functions defined in lib/sh/makepath.c */
 #define MP_DOTILDE     0x01
@@ -148,12 +157,17 @@ extern char *uitos __P((unsigned long));
 
 extern char *sh_makepath __P((const char *, const char *, int));
 
+/* declarations for functions defined in lib/sh/netconn.c */
+extern int isnetconn __P((int));
+
 /* declarations for functions defined in lib/sh/netopen.c */
 extern int netopen __P((char *));
 
 /* Declarations for  functions defined in lib/sh/oslib.c */
 
+#if !defined (HAVE_DUP2) || defined (DUP2_BROKEN)
 extern int dup2 __P((int, int));
+#endif
 
 #if !defined (HAVE_GETDTABLESIZE)
 extern int getdtablesize __P((void));
@@ -163,6 +177,9 @@ extern int getdtablesize __P((void));
 extern int gethostname __P((char *, int));
 #endif /* !HAVE_GETHOSTNAME */
 
+extern int getmaxgroups __P((void));
+extern long getmaxchild __P((void));
+
 /* declarations for functions defined in lib/sh/pathcanon.c */
 #define PATH_CHECKDOTDOT       0x0001
 #define PATH_CHECKEXISTS       0x0002
@@ -202,6 +219,11 @@ extern int strcasecmp __P((const char *, const char *));
 extern char *strerror __P((int));
 #endif
 
+/* declarations for functions defined in lib/sh/strftime.c */
+#if !defined (HAVE_STRFTIME) && defined (NEED_STRFTIME_DECL)
+extern size_t strftime __P((char *, size_t, const char *, const struct tm *));
+#endif
+
 /* declarations for functions defined in lib/sh/strindex.c */
 extern char *strindex __P((const char *, const char *));
 
@@ -214,26 +236,36 @@ typedef struct _list_of_strings {
   int list_len;
 } STRINGLIST;
 
-extern STRINGLIST *alloc_stringlist __P((int));
-extern STRINGLIST *realloc_stringlist __P((STRINGLIST *, int));
-extern void free_stringlist __P((STRINGLIST *));
-extern STRINGLIST *copy_stringlist __P((STRINGLIST *));
-extern STRINGLIST *merge_stringlists __P((STRINGLIST *, STRINGLIST *));
-extern STRINGLIST *append_stringlist __P((STRINGLIST *, STRINGLIST *));
-extern STRINGLIST *prefix_suffix_stringlist __P((STRINGLIST *, char *, char *));
-extern void print_stringlist __P((STRINGLIST *, char *));
-extern void sort_stringlist __P((STRINGLIST *));
+typedef int sh_strlist_map_func_t __P((char *));
+
+extern STRINGLIST *strlist_create __P((int));
+extern STRINGLIST *strlist_resize __P((STRINGLIST *, int));
+extern void strlist_flush __P((STRINGLIST *));
+extern void strlist_dispose __P((STRINGLIST *));
+extern int strlist_remove __P((STRINGLIST *, char *));
+extern STRINGLIST *strlist_copy __P((STRINGLIST *));
+extern STRINGLIST *strlist_merge __P((STRINGLIST *, STRINGLIST *));
+extern STRINGLIST *strlist_append __P((STRINGLIST *, STRINGLIST *));
+extern STRINGLIST *strlist_prefix_suffix __P((STRINGLIST *, char *, char *));
+extern void strlist_print __P((STRINGLIST *, char *));
+extern void strlist_walk __P((STRINGLIST *, sh_strlist_map_func_t *));
+extern void strlist_sort __P((STRINGLIST *));
 
 /* declarations for functions defined in lib/sh/stringvec.c */
 
-extern int find_name_in_array __P((char *, char **));
-extern char **alloc_array __P((int));
-extern int array_len __P((char **));
-extern void free_array_members __P((char **));
-extern void free_array __P((char **));
-extern char **copy_array __P((char **));
-extern int qsort_string_compare __P((char **, char **));
-extern void sort_char_array __P((char **));
+extern char **strvec_create __P((int));
+extern char **strvec_resize __P((char **, int));
+extern void strvec_flush __P((char **));
+extern void strvec_dispose __P((char **));
+extern int strvec_remove __P((char **, char *));
+extern int strvec_len __P((char **));
+extern int strvec_search __P((char **, char *));
+extern char **strvec_copy __P((char **));
+extern int strvec_strcmp __P((char **, char **));
+extern void strvec_sort __P((char **));
+
+extern char **strvec_from_word_list __P((WORD_LIST *, int, int, int *));
+extern WORD_LIST *strvec_to_word_list __P((char **, int, int));
 
 /* declarations for functions defined in lib/sh/strtod.c */
 #if !defined (HAVE_STRTOD)
@@ -261,8 +293,6 @@ extern unsigned long long strtoull __P((const char *, char **, int));
 #endif
 
 /* declarations for functions defined in lib/sh/strimax.c */
-#ifdef NEED_STRTOIMAX_DECL
-
 #if !HAVE_DECL_STRTOIMAX
 extern intmax_t strtoimax __P((const char *, char **, int));
 #endif
@@ -272,12 +302,11 @@ extern intmax_t strtoimax __P((const char *, char **, int));
 extern uintmax_t strtoumax __P((const char *, char **, int));
 #endif
 
-#endif /* NEED_STRTOIMAX_DECL */
-
 /* declarations for functions defined in lib/sh/strtrans.c */
 extern char *ansicstr __P((char *, int, int, int *, int *));
 extern char *ansic_quote __P((char *, int, int *));
 extern int ansic_shouldquote __P((const char *));
+extern char *ansiexpand __P((char *, int, int, int *));
 
 /* declarations for functions defined in lib/sh/timeval.c.  No prototypes
    so we don't have to count on having a definition of struct timeval in
@@ -294,9 +323,13 @@ extern char *sh_mktmpname __P((char *, int));
 extern int sh_mktmpfd __P((char *, int, char **));
 /* extern FILE *sh_mktmpfp __P((char *, int, char **)); */
 
+/* declarations for functions defined in lib/sh/xstrchr.c */
+#undef xstrchr
+extern char *xstrchr __P((const char *, int));
+
 /* declarations for functions defined in lib/sh/zread.c */
 extern ssize_t zread __P((int, char *, size_t));
-extern ssize_t zread1 __P((int, char *, size_t));
+extern ssize_t zreadintr __P((int, char *, size_t));
 extern ssize_t zreadc __P((int, char *));
 extern void zreset __P((void));
 extern void zsyncfd __P((int));
index 5f94863d9e0ee786c0f5ce05ef74b90428b5c784..9c6670a408cac3ea87c9af027d0a36eb79211ede 100644 (file)
--- a/findcmd.c
+++ b/findcmd.c
@@ -203,7 +203,7 @@ _find_user_command_internal (name, flags)
   char *path_list, *cmd;
   SHELL_VAR *var;
 
-  /* Search for the value of PATH in both the temporary environment, and
+  /* Search for the value of PATH in both the temporary environments and
      in the regular list of variables. */
   if (var = find_variable_internal ("PATH", 1))        /* XXX could be array? */
     path_list = value_cell (var);
@@ -215,9 +215,6 @@ _find_user_command_internal (name, flags)
 
   cmd = find_user_command_in_path (name, path_list, flags);
 
-  if (var && tempvar_p (var))
-    dispose_variable (var);
-
   return (cmd);
 }
 
@@ -282,14 +279,16 @@ search_for_command (pathname)
 
   /* If PATH is in the temporary environment for this command, don't use the
      hash table to search for the full pathname. */
-  path = find_tempenv_variable ("PATH");
-  temp_path = path != 0;
+  path = find_variable_internal ("PATH", 1);
+  temp_path = path && tempvar_p (path);
+  if (temp_path == 0 && path)
+    path = (SHELL_VAR *)NULL;
 
   /* Don't waste time trying to find hashed data for a pathname
      that is already completely specified or if we're using a command-
      specific value for PATH. */
   if (path == 0 && absolute_program (pathname) == 0)
-    hashed_file = find_hashed_filename (pathname);
+    hashed_file = phash_search (pathname);
 
   /* If a command found in the hash table no longer exists, we need to
      look for it in $PATH.  Thank you Posix.2.  This forces us to stat
@@ -300,7 +299,7 @@ search_for_command (pathname)
       st = file_status (hashed_file);
       if ((st ^ (FS_EXISTS | FS_EXECABLE)) != 0)
        {
-         remove_hashed_filename (pathname);
+         phash_remove (pathname);
          free (hashed_file);
          hashed_file = (char *)NULL;
        }
@@ -320,13 +319,11 @@ search_for_command (pathname)
        {
          command = find_user_command_in_path (pathname, value_cell (path),
                                               FS_EXEC_PREFERRED|FS_NODIRS);
-         if (tempvar_p (path))
-           dispose_variable (path);
        }
       else
        command = find_user_command (pathname);
       if (command && hashing_enabled && temp_path == 0)
-       remember_filename ((char *)pathname, command, dot_found_in_search, 1);  /* XXX fix const later */
+       phash_insert ((char *)pathname, command, dot_found_in_search, 1);       /* XXX fix const later */
     }
   return (command);
 }
@@ -350,7 +347,7 @@ user_command_matches (name, flags, state)
       if (match_list == 0)
        {
          match_list_size = 5;
-         match_list = alloc_array (match_list_size);
+         match_list = strvec_create (match_list_size);
        }
 
       /* Clear out the old match list. */
@@ -393,7 +390,7 @@ user_command_matches (name, flags, state)
          if (match_index + 1 == match_list_size)
            {
              match_list_size += 10;
-             match_list = (char **)xrealloc (match_list, (match_list_size + 1) * sizeof (char *));
+             match_list = strvec_resize (match_list, (match_list_size + 1));
            }
 
          match_list[match_index++] = match;
@@ -446,7 +443,7 @@ find_in_path_element (name, path, flags, name_len, dotinfop)
   int status;
   char *full_path, *xpath;
 
-  xpath = (*path == '~') ? bash_tilde_expand (path) : path;
+  xpath = (*path == '~') ? bash_tilde_expand (path, 0) : path;
 
   /* Remember the location of "." in the path, in all its forms
      (as long as they begin with a `.', e.g. `./.') */
diff --git a/flags.c b/flags.c
index cdf2aefc8d7d66c8dab91cff0e8ff0f5757587a8..8846ba3077bd03cc1f96f69bd3155034d5665639 100644 (file)
--- a/flags.c
+++ b/flags.c
@@ -203,6 +203,8 @@ struct flags_alist shell_flags[] = {
 
 #define NUM_SHELL_FLAGS (sizeof (shell_flags) / sizeof (struct flags_alist))
 
+char optflags[NUM_SHELL_FLAGS+4] = { '+' };
+
 int *
 find_flag (name)
      int name;
@@ -328,3 +330,15 @@ reset_shell_flags ()
   restricted = 0;
 #endif
 }
+
+void
+initialize_flags ()
+{
+  register int i;
+
+  for (i = 0; shell_flags[i].name; i++)
+    optflags[i+1] = shell_flags[i].name;
+  optflags[++i] = 'o';
+  optflags[++i] = ';';
+  optflags[i+1] = '\0';
+}
diff --git a/flags.h b/flags.h
index 9c93b34d3f66c272886929384bfbdb056e79b841..decfe693dcbc341b27581c09ff5f780d26d7fa5d 100644 (file)
--- a/flags.h
+++ b/flags.h
@@ -38,6 +38,7 @@ struct flags_alist {
 };
 
 extern struct flags_alist shell_flags[];
+extern char optflags[];
 
 extern int
   mark_modified_vars, exit_immediately_on_error, disallow_filename_globbing,
@@ -69,6 +70,8 @@ extern int change_flag __P((int, int));
 extern char *which_set_flags __P((void));
 extern void reset_shell_flags __P((void));
 
+extern void initialize_flags __P((void));
+
 /* A macro for efficiency. */
 #define change_flag_char(flag, on_or_off)  change_flag (flag, on_or_off)
 
index 1d9cda0231b8698d489318c46547bd1305d46d52..446e42f44923099afc94b281a5ecb1a27f581b47 100644 (file)
--- a/general.c
+++ b/general.c
@@ -1,6 +1,6 @@
 /* general.c -- Stuff that is used by all files. */
 
-/* Copyright (C) 1987-1999 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -50,6 +50,10 @@ extern int check_hashed_filenames;
 extern int source_uses_path;
 extern int source_searches_cwd;
 
+static char *bash_special_tilde_expansions __P((char *));
+static int unquoted_tilde_word __P((const char *));
+static void initialize_group_array __P((void));
+
 /* A standard error message to use when getcwd() returns NULL. */
 char *bash_getcwd_errstr = "getcwd: cannot access parent directories";
 
@@ -155,20 +159,20 @@ all_digits (string)
 int
 legal_number (string, result)
      char *string;
-     long *result;
+     intmax_t *result;
 {
-  long value;
+  intmax_t value;
   char *ep;
 
   if (result)
     *result = 0;
 
   errno = 0;
-  value = strtol (string, &ep, 10);
+  value = strtoimax (string, &ep, 10);
   if (errno)
     return 0;  /* errno is set on overflow or underflow */
 
-  /* Skip any trailing whitespace, since strtol does not. */
+  /* Skip any trailing whitespace, since strtoimax does not. */
   while (whitespace (*ep))
     ep++;
 
@@ -232,6 +236,47 @@ check_identifier (word, check_word)
     return (1);
 }
 
+/* Returns non-zero if STRING is an assignment statement.  The returned value
+   is the index of the `=' sign. */
+int
+assignment (string)
+     const char *string;
+{
+  register unsigned char c;
+  register int newi, indx;
+
+  c = string[indx = 0];
+
+  if (legal_variable_starter (c) == 0)
+    return (0);
+
+  while (c = string[indx])
+    {
+      /* The following is safe.  Note that '=' at the start of a word
+        is not an assignment statement. */
+      if (c == '=')
+       return (indx);
+
+#if defined (ARRAY_VARS)
+      if (c == '[')
+       {
+         newi = skipsubscript (string, indx);
+         if (string[newi++] != ']')
+           return (0);
+         return ((string[newi] == '=') ? newi : 0);
+       }
+#endif /* ARRAY_VARS */
+
+      /* Variable names in assignment statements may contain only letters,
+        digits, and `_'. */
+      if (legal_variable_char (c) == 0)
+       return (0);
+
+      indx++;
+    }
+  return (0);
+}
+
 /* **************************************************************** */
 /*                                                                 */
 /*          Functions to manage files and file descriptors         */
@@ -279,6 +324,14 @@ sh_unset_nodelay_mode (fd)
   return 0;
 }
 
+/* Return 1 if file descriptor FD is valid; 0 otherwise. */
+int
+sh_validfd (fd)
+     int fd;
+{
+  return (fcntl (fd, F_GETFD, 0) >= 0);
+}
+
 /* There is a bug in the NeXT 2.1 rlogind that causes opens
    of /dev/tty to fail. */
 
@@ -352,8 +405,8 @@ move_to_high_fd (fd, check_new, maxfd)
       nfds = getdtablesize ();
       if (nfds <= 0)
        nfds = 20;
-      if (nfds > 256)
-       nfds = 256;
+      if (nfds > HIGH_FD_MAX)
+       nfds = HIGH_FD_MAX;             /* reasonable maximum */
     }
   else
     nfds = maxfd;
@@ -362,13 +415,15 @@ move_to_high_fd (fd, check_new, maxfd)
     if (fcntl (nfds, F_GETFD, &ignore) == -1)
       break;
 
-  if (nfds && fd != nfds && (script_fd = dup2 (fd, nfds)) != -1)
+  if (nfds > 3 && fd != nfds && (script_fd = dup2 (fd, nfds)) != -1)
     {
       if (check_new == 0 || fd != fileno (stderr))     /* don't close stderr */
        close (fd);
       return (script_fd);
     }
 
+  /* OK, we didn't find one less than our artificial maximum; return the
+     original file descriptor. */
   return (fd);
 }
  
@@ -450,7 +505,7 @@ int
 absolute_program (string)
      const char *string;
 {
-  return ((char *)strchr (string, '/') != (char *)NULL);
+  return ((char *)xstrchr (string, '/') != (char *)NULL);
 }
 
 /* Return the `basename' of the pathname in STRING (the stuff after the
@@ -478,7 +533,7 @@ full_pathname (file)
 {
   char *ret;
 
-  file = (*file == '~') ? bash_tilde_expand (file) : savestring (file);
+  file = (*file == '~') ? bash_tilde_expand (file, 0) : savestring (file);
 
   if (ABSPATH(file))
     return (file);
@@ -572,7 +627,6 @@ extract_colon_unit (string, p_index)
 extern char *get_dirstack_from_string __P((char *));
 #endif
 
-/* Reserved for post-bash-2.05a */
 static char **bash_tilde_prefixes;
 static char **bash_tilde_suffixes;
 
@@ -617,14 +671,14 @@ tilde_initialize ()
      tilde_initialize () is called from within bashline_reinitialize (). */
   if (times_called++ == 0)
     {
-      bash_tilde_prefixes = alloc_array (3);
+      bash_tilde_prefixes = strvec_create (3);
       bash_tilde_prefixes[0] = "=~";
       bash_tilde_prefixes[1] = ":~";
       bash_tilde_prefixes[2] = (char *)NULL;
 
       tilde_additional_prefixes = bash_tilde_prefixes;
 
-      bash_tilde_suffixes = alloc_array (3);
+      bash_tilde_suffixes = strvec_create (3);
       bash_tilde_suffixes[0] = ":";
       bash_tilde_suffixes[1] = "=~";   /* XXX - ?? */
       bash_tilde_suffixes[2] = (char *)NULL;
@@ -661,16 +715,20 @@ unquoted_tilde_word (s)
   return 1;
 }
 
-/* Tilde-expand S by running it through the tilde expansion library. */
+/* Tilde-expand S by running it through the tilde expansion library.
+   ASSIGN_P is 1 if this is a variable assignment, so the alternate
+   tilde prefixes should be enabled (`=~' and `:~', see above). */
 char *
-bash_tilde_expand (s)
+bash_tilde_expand (s, assign_p)
      const char *s;
+     int assign_p;
 {
   int old_immed, r;
   char *ret;
 
   old_immed = interrupt_immediately;
   interrupt_immediately = 1;
+  tilde_additional_prefixes = assign_p ? bash_tilde_prefixes : (char **)0;
   r = (*s == '~') ? unquoted_tilde_word (s) : 1;
   ret = r ? tilde_expand (s) : savestring (s);
   interrupt_immediately = old_immed;
@@ -692,20 +750,6 @@ static GETGROUPS_T *group_array = (GETGROUPS_T *)NULL;
 #  define NOGROUP (gid_t) -1
 #endif
 
-#if defined (HAVE_SYSCONF) && defined (_SC_NGROUPS_MAX)
-#  define getmaxgroups() sysconf(_SC_NGROUPS_MAX)
-#else
-#  if defined (NGROUPS_MAX)
-#    define getmaxgroups() NGROUPS_MAX
-#  else /* !NGROUPS_MAX */
-#    if defined (NGROUPS)
-#      define getmaxgroups() NGROUPS
-#    else /* !NGROUPS */
-#      define getmaxgroups() 64
-#    endif /* !NGROUPS */
-#  endif /* !NGROUPS_MAX */
-#endif /* !HAVE_SYSCONF || !SC_NGROUPS_MAX */
-
 static void
 initialize_group_array ()
 {
@@ -798,7 +842,6 @@ get_group_list (ngp)
 {
   static char **group_vector = (char **)NULL;
   register int i;
-  char *nbuf;
 
   if (group_vector)
     {
@@ -817,12 +860,9 @@ get_group_list (ngp)
       return (char **)NULL;
     }
 
-  group_vector = alloc_array (ngroups);
+  group_vector = strvec_create (ngroups);
   for (i = 0; i < ngroups; i++)
-    {
-      nbuf = itos (group_array[i]);
-      group_vector[i] = nbuf;
-    }
+    group_vector[i] = itos (group_array[i]);
 
   if (ngp)
     *ngp = ngroups;
index 64a671be9c96283e913191d01a629f4abd0343e5..71f787c651e0f0f2bbde910608d1002ccc0784e1 100644 (file)
--- a/general.h
+++ b/general.h
@@ -1,6 +1,6 @@
 /* general.h -- defines that everybody likes to use. */
 
-/* Copyright (C) 1993 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 #  endif /* !__STDC__ */
 #endif /* !NULL */
 
-#define pointer_to_int(x) (int)((long)(x))
+/* Hardly used anymore */
+#define pointer_to_int(x)      (int)((char *)x - (char *)0)
 
 #if defined (alpha) && defined (__GNUC__) && !defined (strchr) && !defined (__STDC__)
 extern char *strchr (), *strrchr ();
 #endif
 
-#if !defined (strcpy)
+#if !defined (strcpy) && (defined (HAVE_DECL_STRCPY) && !HAVE_DECL_STRCPY)
 extern char *strcpy __P((char *, const char *));
 #endif
 
@@ -68,7 +69,7 @@ extern char *strcpy __P((char *, const char *));
 #endif
 
 #ifndef member
-#  define member(c, s) ((c) ? ((char *)strchr ((s), (c)) != (char *)NULL) : 0)
+#  define member(c, s) ((c) ? ((char *)xstrchr ((s), (c)) != (char *)NULL) : 0)
 #endif
 
 #ifndef whitespace
@@ -124,7 +125,7 @@ typedef struct {
 
 /* A macro to avoid making an uneccessary function call. */
 #define REVERSE_LIST(list, type) \
-  ((list && list->next) ? (type)reverse_list ((GENERIC_LIST *)list) \
+  ((list && list->next) ? (type)list_reverse ((GENERIC_LIST *)list) \
                        : (type)(list))
 
 #if __GNUC__ > 1
@@ -230,6 +231,9 @@ typedef int sh_builtin_func_t __P((WORD_LIST *)); /* sh_wlist_func_t */
 #define FS_DIRECTORY     0x10
 #define FS_NODIRS        0x20
 
+/* Default maximum for move_to_high_fd */
+#define HIGH_FD_MAX    256
+
 /* The type of function passed as the fourth argument to qsort(3). */
 #ifdef __STDC__
 typedef int QSFUNC (const void *, const void *);
@@ -270,11 +274,13 @@ extern void print_rlimtype __P((RLIMTYPE, int));
 #endif
 
 extern int all_digits __P((char *));
-extern int legal_number __P((char *, long *));
+extern int legal_number __P((char *, intmax_t *));
 extern int legal_identifier __P((char *));
 extern int check_identifier __P((WORD_DESC *, int));
+extern int assignment __P((const char *));
 
 extern int sh_unset_nodelay_mode __P((int));
+extern int sh_validfd __P((int));
 extern void check_dev_tty __P((void));
 extern int move_to_high_fd __P((int, int, int));
 extern int check_binary_file __P((char *, int));
@@ -293,7 +299,7 @@ extern char *polite_directory_format __P((char *));
 extern char *extract_colon_unit __P((char *, int *));
 
 extern void tilde_initialize __P((void));
-extern char *bash_tilde_expand __P((const char *));
+extern char *bash_tilde_expand __P((const char *, int));
 
 extern int group_member __P((gid_t));
 extern char **get_group_list __P((int *));
index 594d688cc14e5b5856594a996bf1c59aa2f66e7e..895b485065ff7f6f2eef4f76b875be991fcb5c90 100644 (file)
--- a/hashcmd.c
+++ b/hashcmd.c
@@ -1,7 +1,7 @@
 /* hashcmd.c - functions for managing a hash table mapping command names to
               full pathnames. */
 
-/* Copyright (C) 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1997-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 
 extern int hashing_enabled;
 
-static int hashing_initialized = 0;
+HASH_TABLE *hashed_filenames = (HASH_TABLE *)NULL;
 
-HASH_TABLE *hashed_filenames;
+static void phash_freedata __P((PTR_T));
 
 void
-initialize_filename_hashing ()
+phash_create ()
 {
-  if (hashing_initialized == 0)
-    {
-      hashed_filenames = make_hash_table (FILENAME_HASH_BUCKETS);
-      hashing_initialized = 1;
-    }
+  if (hashed_filenames == 0)
+    hashed_filenames = hash_create (FILENAME_HASH_BUCKETS);
 }
 
 static void
-free_filename_data (data)
+phash_freedata (data)
      PTR_T data;
 {
   free (((PATH_DATA *)data)->path);
@@ -59,39 +56,41 @@ free_filename_data (data)
 }
 
 void
-flush_hashed_filenames ()
+phash_flush ()
 {
   if (hashed_filenames)
-    flush_hash_table (hashed_filenames, free_filename_data);
+    hash_flush (hashed_filenames, phash_freedata);
 }
 
 /* Remove FILENAME from the table of hashed commands. */
-void
-remove_hashed_filename (filename)
+int
+phash_remove (filename)
      const char *filename;
 {
   register BUCKET_CONTENTS *item;
 
   if (hashing_enabled == 0 || hashed_filenames == 0)
-    return;
+    return 0;
 
-  item = remove_hash_item (filename, hashed_filenames);
+  item = hash_remove (filename, hashed_filenames, 0);
   if (item)
     {
       if (item->data)
-       free_filename_data (item->data);
+       phash_freedata (item->data);
       free (item->key);
       free (item);
+      return 0;
     }
+  return 1;
 }
 
 /* Place FILENAME (key) and FULL_PATH (data->path) into the
    hash table.  CHECK_DOT if non-null is for future calls to
-   find_hashed_filename (); it means that this file was found
+   phash_search (); it means that this file was found
    in a directory in $PATH that is not an absolute pathname.
    FOUND is the initial value for times_found. */
 void
-remember_filename (filename, full_path, check_dot, found)
+phash_insert (filename, full_path, check_dot, found)
      char *filename, *full_path;
      int check_dot, found;
 {
@@ -100,16 +99,16 @@ remember_filename (filename, full_path, check_dot, found)
   if (hashing_enabled == 0)
     return;
 
-  if (hashed_filenames == 0 || hashing_initialized == 0)
-    initialize_filename_hashing ();
+  if (hashed_filenames == 0)
+    phash_create ();
 
-  item = add_hash_item (filename, hashed_filenames);
+  item = hash_insert (filename, hashed_filenames, 0);
   if (item->data)
     free (pathdata(item)->path);
   else
     {
       item->key = savestring (filename);
-      item->data = (char *)xmalloc (sizeof (PATH_DATA));
+      item->data = xmalloc (sizeof (PATH_DATA));
     }
   pathdata(item)->path = savestring (full_path);
   pathdata(item)->flags = 0;
@@ -126,7 +125,7 @@ remember_filename (filename, full_path, check_dot, found)
    returns a newly-allocated string; the caller is responsible
    for freeing it. */
 char *
-find_hashed_filename (filename)
+phash_search (filename)
      const char *filename;
 {
   register BUCKET_CONTENTS *item;
@@ -136,7 +135,7 @@ find_hashed_filename (filename)
   if (hashing_enabled == 0 || hashed_filenames == 0)
     return ((char *)NULL);
 
-  item = find_hash_item (filename, hashed_filenames);
+  item = hash_search (filename, hashed_filenames, 0);
 
   if (item == NULL)
     return ((char *)NULL);
index 56a66deed0d521439eb71cde874cecb11cf6e696..3d47c1c95f91b118ddcb1bbc243d76c4bb8fdd6f 100644 (file)
--- a/hashcmd.h
+++ b/hashcmd.h
@@ -21,7 +21,7 @@
 #include "stdc.h"
 #include "hashlib.h"
 
-#define FILENAME_HASH_BUCKETS 107
+#define FILENAME_HASH_BUCKETS 64       /* must be power of two */
 
 extern HASH_TABLE *hashed_filenames;
 
@@ -35,8 +35,9 @@ typedef struct {
 
 #define pathdata(x) ((PATH_DATA *)(x)->data)
 
-extern void initialize_filename_hashing __P((void));
-extern void flush_hashed_filenames __P((void));
-extern void remove_hashed_filename __P((const char *));
-extern void remember_filename __P((char *, char *, int, int));
-extern char *find_hashed_filename __P((const char *));
+extern void phash_create __P((void));
+extern void phash_flush __P((void));
+
+extern void phash_insert __P((char *, char *, int, int));
+extern int phash_remove __P((const char *));
+extern char *phash_search __P((const char *));
index dd5a6c24e5c975f94deeb2a347170ff14a9c3683..456272ac1adfa04c1dfe1d7e7ca9437995a85de9 100644 (file)
--- a/hashlib.c
+++ b/hashlib.c
@@ -34,26 +34,20 @@ Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
 #include "shell.h"
 #include "hashlib.h"
 
-static void initialize_hash_table __P((HASH_TABLE *));
-static BUCKET_CONTENTS *copy_bucket_array __P((BUCKET_CONTENTS *, sh_string_func_t *));
+/* Rely on properties of unsigned division (unsigned/int -> unsigned) and
+   don't discard the upper 32 bits of the value, if present. */
+#define HASH_BUCKET(s, t, h) (((h) = hash_string (s)) & ((t)->nbuckets - 1))
 
-/* Zero the buckets in TABLE. */
-static void
-initialize_hash_table (table)
-     HASH_TABLE *table;
-{
-  register int i;
-  for (i = 0; i < table->nbuckets; i++)
-    table->bucket_array[i] = (BUCKET_CONTENTS *)NULL;
-}
+static BUCKET_CONTENTS *copy_bucket_array __P((BUCKET_CONTENTS *, sh_string_func_t *));
 
 /* Make a new hash table with BUCKETS number of buckets.  Initialize
    each slot in the table to NULL. */
 HASH_TABLE *
-make_hash_table (buckets)
+hash_create (buckets)
      int buckets;
 {
   HASH_TABLE *new_table;
+  register int i;
 
   new_table = (HASH_TABLE *)xmalloc (sizeof (HASH_TABLE));
   if (buckets == 0)
@@ -63,12 +57,15 @@ make_hash_table (buckets)
     (BUCKET_CONTENTS **)xmalloc (buckets * sizeof (BUCKET_CONTENTS *));
   new_table->nbuckets = buckets;
   new_table->nentries = 0;
-  initialize_hash_table (new_table);
+
+  for (i = 0; i < buckets; i++)
+    new_table->bucket_array[i] = (BUCKET_CONTENTS *)NULL;
+
   return (new_table);
 }
 
 int
-hash_table_nentries (table)
+hash_size (table)
      HASH_TABLE *table;
 {
   return (HASH_ENTRIES(table));
@@ -99,7 +96,8 @@ copy_bucket_array (ba, cpdata)
 
       n->key = savestring (e->key);
       n->data = e->data ? (cpdata ? (*cpdata) (e->data) : savestring (e->data))
-                       : (char *)NULL;
+                       : NULL;
+      n->khash = e->khash;
       n->times_found = e->times_found;
       n->next = (BUCKET_CONTENTS *)NULL;
     }
@@ -108,7 +106,7 @@ copy_bucket_array (ba, cpdata)
 }
 
 HASH_TABLE *
-copy_hash_table (table, cpdata)
+hash_copy (table, cpdata)
      HASH_TABLE *table;
      sh_string_func_t *cpdata;
 {
@@ -118,7 +116,7 @@ copy_hash_table (table, cpdata)
   if (table == 0)
     return ((HASH_TABLE *)NULL);
 
-  new_table = make_hash_table (table->nbuckets);
+  new_table = hash_create (table->nbuckets);
 
   for (i = 0; i < table->nbuckets; i++)
     new_table->bucket_array[i] = copy_bucket_array (table->bucket_array[i], cpdata);
@@ -127,59 +125,82 @@ copy_hash_table (table, cpdata)
   return new_table;
 }
 
-/* Return the location of the bucket which should contain the data
-   for STRING.  TABLE is a pointer to a HASH_TABLE. */
+/* The `khash' check below requires that strings that compare equally with
+   strcmp hash to the same value. */
+unsigned int
+hash_string (s)
+     const char *s;
+{
+  register unsigned int i;
 
-#if 0
-/* A possibly better distribution may be obtained by initializing i to
-   ~0UL and using i = (i * 31) + *string++ as the step */
+  /* This is the best string hash function I found.
 
-#define ALL_ONES (~((unsigned long) 0))
-#define BITS(h, n) ((unsigned long)(h) & ~(ALL_ONES << (n)))
-#endif
+     The magic is in the interesting relationship between the special prime
+     16777619 (2^24 + 403) and 2^32 and 2^8. */
+  for (i = 0; *s; s++)
+    {
+      i *= 16777619;
+      i ^= *s;
+    }
+
+  return i;
+}
+
+/* Return the location of the bucket which should contain the data
+   for STRING.  TABLE is a pointer to a HASH_TABLE. */
 
 int
-hash_string (string, table)
+hash_bucket (string, table)
      const char *string;
      HASH_TABLE *table;
 {
-  register unsigned int i = 0;
+  unsigned int h;
 
-  while (*string)
-    i = (i << 2) + *string++;
-
-#if 0
-  return (BITS (i, 31) % table->nbuckets);
-#else
-  /* Rely on properties of unsigned division (unsigned/int -> unsigned) and
-     don't discard the upper 32 bits of the value, if present. */
-  return (i % table->nbuckets);
-#endif
+  return (HASH_BUCKET (string, table, h));
 }
 
-/* Return a pointer to the hashed item, or NULL if the item
-   can't be found. */
+/* Return a pointer to the hashed item.  If the HASH_CREATE flag is passed,
+   create a new hash table entry for STRING, otherwise return NULL. */
 BUCKET_CONTENTS *
-find_hash_item (string, table)
+hash_search (string, table, flags)
      const char *string;
      HASH_TABLE *table;
+     int flags;
 {
   BUCKET_CONTENTS *list;
-  int which_bucket;
+  int bucket;
+  unsigned int hv;
 
-  if (table == 0)
+  if (table == 0 || ((flags & HASH_CREATE) == 0 && HASH_ENTRIES (table) == 0))
     return (BUCKET_CONTENTS *)NULL;
 
-  which_bucket = hash_string (string, table);
+  bucket = HASH_BUCKET (string, table, hv);
 
-  for (list = table->bucket_array[which_bucket]; list; list = list->next)
+  for (list = table->bucket_array[bucket]; list; list = list->next)
     {
-      if (STREQ (list->key, string))
+      if (hv == list->khash && STREQ (list->key, string))
        {
          list->times_found++;
          return (list);
        }
     }
+
+  if (flags & HASH_CREATE)
+    {
+      list = (BUCKET_CONTENTS *)xmalloc (sizeof (BUCKET_CONTENTS));
+      list->next = table->bucket_array[bucket];
+      table->bucket_array[bucket] = list;
+
+      list->data = NULL;
+      list->key = (char *)string;      /* XXX fix later */
+      list->khash = hv;
+      list->times_found = 0;
+
+      table->nentries++;
+      return (list);
+    }
+      
   return (BUCKET_CONTENTS *)NULL;
 }
 
@@ -187,26 +208,28 @@ find_hash_item (string, table)
    The item removed is returned, so you can free its contents.  If
    the item isn't in this table NULL is returned. */
 BUCKET_CONTENTS *
-remove_hash_item (string, table)
+hash_remove (string, table, flags)
      const char *string;
      HASH_TABLE *table;
+     int flags;
 {
-  int the_bucket;
+  int bucket;
   BUCKET_CONTENTS *prev, *temp;
+  unsigned int hv;
 
-  if (table == 0)
+  if (table == 0 || HASH_ENTRIES (table) == 0)
     return (BUCKET_CONTENTS *)NULL;
 
-  the_bucket = hash_string (string, table);
+  bucket = HASH_BUCKET (string, table, hv);
   prev = (BUCKET_CONTENTS *)NULL;
-  for (temp = table->bucket_array[the_bucket]; temp; temp = temp->next)
+  for (temp = table->bucket_array[bucket]; temp; temp = temp->next)
     {
-      if (STREQ (temp->key, string))
+      if (hv == temp->khash && STREQ (temp->key, string))
        {
          if (prev)
            prev->next = temp->next;
          else
-           table->bucket_array[the_bucket] = temp->next;
+           table->bucket_array[bucket] = temp->next;
 
          table->nentries--;
          return (temp);
@@ -217,43 +240,37 @@ remove_hash_item (string, table)
 }
 
 /* Create an entry for STRING, in TABLE.  If the entry already
-   exists, then return it. */
+   exists, then return it (unless the HASH_NOSRCH flag is set). */
 BUCKET_CONTENTS *
-add_hash_item (string, table)
+hash_insert (string, table, flags)
      char *string;
      HASH_TABLE *table;
+     int flags;
 {
   BUCKET_CONTENTS *item;
   int bucket;
+  unsigned int hv;
 
   if (table == 0)
-    table = make_hash_table (0);
+    table = hash_create (0);
 
-  if ((item = find_hash_item (string, table)) == 0)
+  item = (flags & HASH_NOSRCH) ? (BUCKET_CONTENTS *)NULL
+                              : hash_search (string, table, 0);
+
+  if (item == 0)
     {
-      bucket = hash_string (string, table);
-      item = table->bucket_array[bucket];
+      bucket = HASH_BUCKET (string, table, hv);
 
-      while (item && item->next)
-       item = item->next;
+      item = (BUCKET_CONTENTS *)xmalloc (sizeof (BUCKET_CONTENTS));
+      item->next = table->bucket_array[bucket];
+      table->bucket_array[bucket] = item;
 
-      if (item)
-       {
-         item->next = (BUCKET_CONTENTS *)xmalloc (sizeof (BUCKET_CONTENTS));
-         item = item->next;
-       }
-      else
-       {
-         table->bucket_array[bucket] =
-           (BUCKET_CONTENTS *)xmalloc (sizeof (BUCKET_CONTENTS));
-         item = table->bucket_array[bucket];
-       }
-
-      item->data = (char *)NULL;
-      item->next = (BUCKET_CONTENTS *)NULL;
+      item->data = NULL;
       item->key = string;
-      table->nentries++;
+      item->khash = hv;
       item->times_found = 0;
+
+      table->nentries++;
     }
 
   return (item);
@@ -263,14 +280,14 @@ add_hash_item (string, table)
    is a function to call to dispose of a hash item's data.  Otherwise,
    free() is called. */
 void
-flush_hash_table (table, free_data)
+hash_flush (table, free_data)
      HASH_TABLE *table;
      sh_free_func_t *free_data;
 {
   int i;
   register BUCKET_CONTENTS *bucket, *item;
 
-  if (table == 0)
+  if (table == 0 || HASH_ENTRIES (table) == 0)
     return;
 
   for (i = 0; i < table->nbuckets; i++)
@@ -291,37 +308,41 @@ flush_hash_table (table, free_data)
        }
       table->bucket_array[i] = (BUCKET_CONTENTS *)NULL;
     }
+
+  table->nentries = 0;
 }
 
 /* Free the hash table pointed to by TABLE. */
 void
-dispose_hash_table (table)
+hash_dispose (table)
      HASH_TABLE *table;
 {
   free (table->bucket_array);
   free (table);
 }
 
-/* No longer necessary; everything uses the macro */
-#if 0
-/* Return the bucket_contents list of bucket BUCKET in TABLE.  If
-   TABLE doesn't have BUCKET buckets, return NULL. */
-#undef get_hash_bucket
-BUCKET_CONTENTS *
-get_hash_bucket (bucket, table)
-     int bucket;
+void
+hash_walk (table, func)
      HASH_TABLE *table;
+     hash_wfunc *func;
 {
-  if (table && bucket < table->nbuckets)
-    return (table->bucket_array[bucket]);
-  else
-    return (BUCKET_CONTENTS *)NULL;
+  register int i;
+  BUCKET_CONTENTS *item;
+
+  if (table == 0 || HASH_ENTRIES (table) == 0)
+    return;
+
+  for (i = 0; i < table->nbuckets; i++)
+    {
+      for (item = hash_items (i, table); item; item = item->next)
+       if ((*func) (item) < 0)
+         return;
+    }
 }
-#endif
 
-#ifdef DEBUG
+#if defined (DEBUG) || defined (TEST_HASHING)
 void
-print_table_stats (table, name)
+hash_pstats (table, name)
      HASH_TABLE *table;
      char *name;
 {
@@ -337,7 +358,7 @@ print_table_stats (table, name)
      see how even the distribution is. */
   for (slot = 0; slot < table->nbuckets; slot++)
     {
-      bc = get_hash_bucket (slot, table);
+      bc = hash_items (slot, table);
 
       fprintf (stderr, "\tslot %3d: ", slot);
       for (bcount = 0; bc; bc = bc->next)
@@ -350,6 +371,7 @@ print_table_stats (table, name)
 
 #ifdef TEST_HASHING
 
+/* link with xmalloc.o and lib/malloc/libmalloc.a */
 #undef NULL
 #include <stdio.h>
 
@@ -358,19 +380,26 @@ print_table_stats (table, name)
 #endif
 
 HASH_TABLE *table, *ntable;
-#define NBUCKETS 107
 
-void *
-xmalloc (bytes)
-     size_t bytes;
+int interrupt_immediately = 0;
+
+int
+signal_is_trapped (s)
+     int s;
 {
-  void *result = malloc (bytes);
-  if (!result)
-    {
-      fprintf (stderr, "hash: out of virtual memory\n");
-      abort ();
-    }
-  return (result);
+  return (0);
+}
+
+void
+programming_error (const char *format, ...)
+{
+  abort();
+}
+
+void
+fatal_error (const char *format, ...)
+{
+  abort();
 }
 
 main ()
@@ -379,7 +408,7 @@ main ()
   int count = 0;
   BUCKET_CONTENTS *tt;
 
-  table = make_hash_table (NBUCKETS);
+  table = hash_create (0);
 
   for (;;)
     {
@@ -389,7 +418,7 @@ main ()
       if (!*string)
        break;
       temp_string = savestring (string);
-      tt = add_hash_item (temp_string, table);
+      tt = hash_insert (temp_string, table, 0);
       if (tt->times_found)
        {
          fprintf (stderr, "You have already added item `%s'\n", string);
@@ -401,11 +430,11 @@ main ()
        }
     }
 
-  print_table_stats (table, "hash test");
+  hash_pstats (table, "hash test");
 
-  ntable = copy_hash_table (table, (sh_string_func_t *)NULL);
-  flush_hash_table (table, (sh_free_func_t *)NULL);
-  print_table_stats (ntable, "hash copy test");
+  ntable = hash_copy (table, (sh_string_func_t *)NULL);
+  hash_flush (table, (sh_free_func_t *)NULL);
+  hash_pstats (ntable, "hash copy test");
 
   exit (0);
 }
index 9c3dee09eaad2416a1d5c371efcbdd9257473acb..bb7120be10de7d7534340ef880664ef9937446d5 100644 (file)
--- a/hashlib.h
+++ b/hashlib.h
 
 #include "stdc.h"
 
+#ifndef PTR_T
+#  ifdef __STDC__
+#    define PTR_T void *
+#  else
+#    define PTR_T char *
+#  endif
+#endif
+
 typedef struct bucket_contents {
   struct bucket_contents *next;        /* Link to next hashed key in this bucket. */
   char *key;                   /* What we look up. */
-  char *data;                  /* What we really want. */
+  PTR_T data;                  /* What we really want. */
+  unsigned int khash;          /* What key hashes to */
   int times_found;             /* Number of times this item has been found. */
 } BUCKET_CONTENTS;
 
@@ -36,27 +45,42 @@ typedef struct hash_table {
   int nentries;                        /* How many entries does this table have. */
 } HASH_TABLE;
 
-extern int hash_string __P((const char *, HASH_TABLE *));
-extern int hash_table_nentries __P((HASH_TABLE *));
-extern HASH_TABLE *make_hash_table __P((int));
-extern HASH_TABLE *copy_hash_table __P((HASH_TABLE *, sh_string_func_t *));
-extern BUCKET_CONTENTS *find_hash_item __P((const char *, HASH_TABLE *));
-extern BUCKET_CONTENTS *remove_hash_item __P((const char *, HASH_TABLE *));
-extern BUCKET_CONTENTS *add_hash_item __P((char *, HASH_TABLE *));
-extern void flush_hash_table __P((HASH_TABLE *, sh_free_func_t *));
-extern void dispose_hash_table __P((HASH_TABLE *));
+typedef int hash_wfunc __P((BUCKET_CONTENTS *));
+
+/* Operations on tables as a whole */
+extern HASH_TABLE *hash_create __P((int));
+extern HASH_TABLE *hash_copy __P((HASH_TABLE *, sh_string_func_t *));
+extern void hash_flush __P((HASH_TABLE *, sh_free_func_t *));
+extern void hash_dispose __P((HASH_TABLE *));
+extern void hash_walk __P((HASH_TABLE *, hash_wfunc *));
+
+/* Operations to extract information from or pieces of tables */
+extern int hash_bucket __P((const char *, HASH_TABLE *));
+extern int hash_size __P((HASH_TABLE *));
+
+/* Operations on hash table entries */
+extern BUCKET_CONTENTS *hash_search __P((const char *, HASH_TABLE *, int));
+extern BUCKET_CONTENTS *hash_insert __P((char *, HASH_TABLE *, int));
+extern BUCKET_CONTENTS *hash_remove __P((const char *, HASH_TABLE *, int));
+
+/* Miscellaneous */
+extern unsigned int hash_string __P((const char *));
 
 /* Redefine the function as a macro for speed. */
-#define get_hash_bucket(bucket, table) \
+#define hash_items(bucket, table) \
        ((table && (bucket < table->nbuckets)) ?  \
                table->bucket_array[bucket] : \
                (BUCKET_CONTENTS *)NULL)
 
 /* Default number of buckets in the hash table. */
-#define DEFAULT_HASH_BUCKETS 53        /* was 107 */
+#define DEFAULT_HASH_BUCKETS 64        /* was 107, then 53, must be power of two now */
 
 #define HASH_ENTRIES(ht)       ((ht) ? (ht)->nentries : 0)
 
+/* flags for hash_search and hash_insert */
+#define HASH_NOSRCH    0x01
+#define HASH_CREATE    0x02
+
 #if !defined (NULL)
 #  if defined (__STDC__)
 #    define NULL ((void *) 0)
index d19b7f6ac303b0e3f704fdd5009201b971327384..4f47b994d2b79d14dda30095602acea347bb1972 100644 (file)
@@ -82,6 +82,8 @@
 
 #define DIGIT(c)       ((c) >= '0' && (c) <= '9')
 
+#define ISWORD(c)      (ISLETTER(c) || DIGIT(c) || ((c) == '_'))
+
 #define HEXVALUE(c) \
   (((c) >= 'a' && (c) <= 'f') \
        ? (c)-'a'+10 \
 #define TOLOWER(c)     (ISUPPER(c) ? tolower(c) : (c))
 #define TOUPPER(c)     (ISLOWER(c) ? toupper(c) : (c))
 
-#ifdef toascii
-#  define TOASCII(c)   (toascii(c))
-#else
-#  define TOASCII(c)   ((c) & 0x7F)
+#ifndef TOCTRL
+   /* letter to control char -- ASCII.  The TOUPPER is in there so \ce and
+      \cE will map to the same character in $'...' expansions. */
+#  define TOCTRL(x)    (TOUPPER(x) & 037)
 #endif
-
-/* We remove any previous definition of `SIGN_EXTEND_CHAR',
-   since ours (we hope) works properly with all combinations of
-   machines, compilers, `char' and `unsigned char' argument types.
-   (Per Bothner suggested the basic approach.)  */
-#undef SIGN_EXTEND_CHAR
-#if __STDC__
-#  define SIGN_EXTEND_CHAR(c) ((signed char) (c))
-#else  /* not __STDC__ */
-   /* As in Harbison and Steele.  */
-#  define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
+#ifndef UNCTRL
+   /* control char to letter -- ASCII */
+#  define UNCTRL(x)    (TOUPPER((x) | 0x40))
 #endif
 
 #endif /* _SH_CHARTYPES_H */
diff --git a/include/ocache.h b/include/ocache.h
new file mode 100644 (file)
index 0000000..67448c3
--- /dev/null
@@ -0,0 +1,133 @@
+/* ocache.h -- a minimal object caching implementation. */
+
+/* Copyright (C) 2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_OCACHE_H_)
+#define        _OCACHE_H_ 1
+
+#ifndef PTR_T
+
+#if defined (__STDC__)
+#  define PTR_T void *
+#else
+#  define PTR_T char *
+#endif
+
+#endif /* PTR_T */
+
+#define OC_MEMSET(memp, xch, nbytes)                                   \
+do {                                                                   \
+  if ((nbytes) <= 32) {                                                        \
+    register char * mzp = (char *)(memp);                              \
+    unsigned long mctmp = (nbytes);                                    \
+    register long mcn;                                                 \
+    if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp &= 7; }    \
+    switch (mctmp) {                                                   \
+      case 0: for(;;) { *mzp++ = xch;                                  \
+      case 7:     *mzp++ = xch;                                        \
+      case 6:     *mzp++ = xch;                                        \
+      case 5:     *mzp++ = xch;                                        \
+      case 4:     *mzp++ = xch;                                        \
+      case 3:     *mzp++ = xch;                                        \
+      case 2:     *mzp++ = xch;                                        \
+      case 1:     *mzp++ = xch; if(mcn <= 0) break; mcn--; }           \
+    }                                                                  \
+  } else                                                               \
+    memset ((memp), (xch), (nbytes));                                  \
+} while(0)
+
+typedef struct objcache {
+       PTR_T   data;
+       int     cs;             /* cache size, number of objects */
+       int     nc;             /* number of cache entries */
+} sh_obj_cache_t;
+
+/* Create an object cache C of N pointers to OTYPE. */
+#define ocache_create(c, otype, n) \
+       do { \
+               (c).data = xmalloc((n) * sizeof (otype *)); \
+               (c).cs = (n); \
+               (c).nc = 0; \
+       } while (0)
+
+/* Destroy an object cache C. */
+#define ocache_destroy(c) \
+       do { \
+               if ((c).data) \
+                       xfree ((c).data); \
+               (c).data = 0; \
+               (c).cs = (c).nc = 0; \
+       } while (0)
+
+/* Free all cached items, which are pointers to OTYPE, in object cache C. */
+#define ocache_flush(c, otype) \
+       do { \
+               while ((c).nc > 0) \
+                       xfree (((otype **)((c).data))[--(c).nc]); \
+       } while (0)
+
+/*
+ * Allocate a new item of type pointer to OTYPE, using data from object
+ * cache C if any cached items exist, otherwise calling xmalloc.  Return
+ * the object in R.
+ */
+#define ocache_alloc(c, otype, r) \
+       do { \
+               if ((c).nc > 0) { \
+                       (r) = (otype *)((otype **)((c).data))[--(c).nc]; \
+               } else \
+                       (r) = (otype *)xmalloc (sizeof (otype)); \
+       } while (0)
+
+/*
+ * Free an item R of type pointer to OTYPE, adding to object cache C if
+ * there is room and calling xfree if the cache is full.  If R is added
+ * to the object cache, the contents are scrambled.
+ */
+#define ocache_free(c, otype, r) \
+       do { \
+               if ((c).nc < (c).cs) { \
+                       OC_MEMSET ((r), 0xdf, sizeof(otype)); \
+                       ((otype **)((c).data))[(c).nc++] = (r); \
+               } else \
+                       xfree (r); \
+       } while (0)
+
+/*
+ * One may declare and use an object cache as (for instance):
+ *
+ *     sh_obj_cache_t wdcache = {0, 0, 0};
+ *     sh_obj_cache_t wlcache = {0, 0, 0};
+ *
+ *     ocache_create(wdcache, WORD_DESC, 30);
+ *     ocache_create(wlcache, WORD_LIST, 30);
+ *
+ *     WORD_DESC *wd;
+ *     ocache_alloc (wdcache, WORD_DESC, wd);
+ *
+ *     WORD_LIST *wl;
+ *     ocache_alloc (wlcache, WORD_LIST, wl);
+ *
+ *     ocache_free(wdcache, WORD_DESC, wd);
+ *     ocache_free(wlcache, WORD_LIST, wl);
+ *
+ * The use is almost arbitrary.
+ */
+
+#endif /* _OCACHE_H  */
index 98ced75b346b2654b9b3356b77823d26e66757ea..505e27954f1683671ed12b7e1a140fb9ae9e7ba4 100644 (file)
 #  define d_fileno d_ino
 #endif
 
+#if defined (_POSIX_SOURCE) && (!defined (STRUCT_DIRENT_HAS_D_INO) || defined (BROKEN_DIRENT_D_INO))
+/* Posix does not require that the d_ino field be present, and some
+   systems do not provide it. */
+#  define REAL_DIR_ENTRY(dp) 1
+#else
+#  define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+#endif /* _POSIX_SOURCE */
+
 #endif /* !_POSIXDIR_H_ */
diff --git a/include/shmbutil.h b/include/shmbutil.h
new file mode 100644 (file)
index 0000000..7fe2f8e
--- /dev/null
@@ -0,0 +1,347 @@
+/* shmbutil.h -- utility functions for multibyte characters. */
+
+/* Copyright (C) 2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+                                 
+#if !defined (_SH_MBUTIL_H_)
+#define _SH_MBUTIL_H_
+
+#include "stdc.h"
+
+/************************************************/
+/* check multibyte capability for I18N code     */
+/************************************************/
+
+/* For platforms which support the ISO C amendement 1 functionality we
+   support user defined character classes.  */
+   /* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
+#if defined (HAVE_WCTYPE_H) && defined (HAVE_WCHAR_H)
+#  include <wchar.h>
+#  include <wctype.h>
+#  if defined (HAVE_MBSRTOWCS) /* system is supposed to support XPG5 */
+#    define HANDLE_MULTIBYTE      1
+#  endif
+#endif /* HAVE_WCTYPE_H && HAVE_WCHAR_H */
+
+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
+#if HANDLE_MULTIBYTE && !defined (HAVE_MBSTATE_T)
+#  define wcsrtombs(dest, src, len, ps) (wcsrtombs) (dest, src, len, 0)
+#  define mbsrtowcs(dest, src, len, ps) (mbsrtowcs) (dest, src, len, 0)
+#  define wcrtomb(s, wc, ps) (wcrtomb) (s, wc, 0)
+#  define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
+#  define mbrlen(s, n, ps) (mbrlen) (s, n, 0)
+#  define mbstate_t int
+#endif /* HANDLE_MULTIBYTE && !HAVE_MBSTATE_T */
+
+/* Make sure MB_LEN_MAX is at least 16 on systems that claim to be able to
+   handle multibyte chars (some systems define MB_LEN_MAX as 1) */
+#ifdef HANDLE_MULTIBYTE
+#  include <limits.h>
+#  if defined(MB_LEN_MAX) && (MB_LEN_MAX < 16)
+#    undef MB_LEN_MAX
+#  endif
+#  if !defined (MB_LEN_MAX)
+#    define MB_LEN_MAX 16
+#  endif
+#endif /* HANDLE_MULTIBYTE */
+
+/************************************************/
+/* end of multibyte capability checks for I18N  */
+/************************************************/
+
+#if defined (HANDLE_MULTIBYTE)
+
+extern size_t xmbsrtowcs __P((wchar_t *, const char **, size_t, mbstate_t *));
+
+extern char *xstrchr __P((const char *, int));
+
+#else /* !HANDLE_MULTIBYTE */
+
+#undef MB_LEN_MAX
+#undef MB_CUR_MAX
+
+#define MB_LEN_MAX     1
+#define MB_CUR_MAX     1
+
+#undef xstrchr
+#define xstrchr(s, c)  strchr(s, c)
+
+#endif /* !HANDLE_MULTIBYTE */
+
+/* Declare and initialize a multibyte state.  Call must be terminated
+   with `;'. */
+#if defined (HANDLE_MULTIBYTE)
+#  define DECLARE_MBSTATE \
+       mbstate_t state; \
+       memset (&state, '\0', sizeof (mbstate_t))
+#else
+#  define DECLARE_MBSTATE
+#endif  /* !HANDLE_MULTIBYTE */
+
+/* Initialize or reinitialize a multibyte state named `state'.  Call must be
+   terminated with `;'. */
+#if defined (HANDLE_MULTIBYTE)
+#  define INITIALIZE_MBSTATE memset (&state, '\0', sizeof (mbstate_t))
+#else
+#  define INITIALIZE_MBSTATE
+#endif  /* !HANDLE_MULTIBYTE */
+
+/* Advance one (possibly multi-byte) character in string _STR of length
+   _STRSIZE, starting at index _I.  STATE must have already been declared. */
+#if defined (HANDLE_MULTIBYTE)
+#  define ADVANCE_CHAR(_str, _strsize, _i) \
+    do \
+      { \
+       if (MB_CUR_MAX > 1) \
+         { \
+           mbstate_t state_bak; \
+           size_t mblength; \
+\
+           state_bak = state; \
+           mblength = mbrlen ((_str) + (_i), (_strsize) - (_i), &state); \
+\
+           if (mblength == (size_t)-2 || mblength == (size_t)-1) \
+             { \
+               state = state_bak; \
+               (_i)++; \
+             } \
+           else \
+             (_i) += mblength; \
+         } \
+       else \
+         (_i)++; \
+      } \
+    while (0)
+#else
+#  define ADVANCE_CHAR(_str, _strsize, _i)     (_i)++
+#endif  /* !HANDLE_MULTIBYTE */
+
+/* Advance one (possibly multibyte) character in the string _STR of length
+   _STRSIZE.
+   SPECIAL:  assume that _STR will be incremented by 1 after this call. */
+#if defined (HANDLE_MULTIBYTE)
+#  define ADVANCE_CHAR_P(_str, _strsize) \
+    do \
+      { \
+       if (MB_CUR_MAX > 1) \
+         { \
+           mbstate_t state_bak; \
+           size_t mblength; \
+\
+           state_bak = state; \
+           mblength = mbrlen ((_str), (_strsize), &state); \
+\
+           if (mblength == (size_t)-2 || mblength == (size_t)-1) \
+             { \
+               state = state_bak; \
+               mblength = 1; \
+             } \
+           else \
+             (_str) += (mblength < 1) ? 0 : (mblength - 1); \
+         } \
+      } \
+    while (0)
+#else
+#  define ADVANCE_CHAR_P(_str, _strsize)
+#endif  /* !HANDLE_MULTIBYTE */
+
+/* Copy a single character from the string _SRC to the string _DST.
+   _SRCEND is a pointer to the end of _SRC. */
+#if defined (HANDLE_MULTIBYTE)
+#  define COPY_CHAR_P(_dst, _src, _srcend) \
+    do \
+      { \
+       if (MB_CUR_MAX > 1) \
+         { \
+           mbstate_t state_bak; \
+           size_t mblength; \
+           int _k; \
+\
+           state_bak = state; \
+           mblength = mbrlen ((_src), (_srcend) - (_src), &state); \
+           if (mblength == (size_t)-2 || mblength == (size_t)-1) \
+             { \
+               state = state_bak; \
+               mblength = 1; \
+             } \
+           else \
+             mblength = (mblength < 1) ? 1 : mblength; \
+\
+           for (_k = 0; _k < mblength; _k++) \
+             *(_dst)++ = *(_src)++; \
+         } \
+       else \
+         *(_dst)++ = *(_src)++; \
+      } \
+    while (0)
+#else
+#  define COPY_CHAR_P(_dst, _src, _srcend)     *(_dst)++ = *(_src)++
+#endif  /* !HANDLE_MULTIBYTE */
+
+/* Copy a single character from the string _SRC at index _SI to the string
+   _DST at index _DI.  _SRCEND is a pointer to the end of _SRC. */
+#if defined (HANDLE_MULTIBYTE)
+#  define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) \
+    do \
+      { \
+       if (MB_CUR_MAX > 1) \
+         { \
+           mbstate_t state_bak; \
+           size_t mblength; \
+           int _k; \
+\
+           state_bak = state; \
+           mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src)+(_si)), &state); \
+           if (mblength == (size_t)-2 || mblength == (size_t)-1) \
+             { \
+               state = state_bak; \
+               mblength = 1; \
+             } \
+           else \
+             mblength = (mblength < 1) ? 1 : mblength; \
+\
+           for (_k = 0; _k < mblength; _k++) \
+             _dst[_di++] = _src[_si++]; \
+         } \
+       else \
+         _dst[_di++] = _src[_si++]; \
+      } \
+    while (0)
+#else
+#  define COPY_CHAR_I(_dst, _di, _src, _srcend, _si)   _dst[_di++] = _src[_si++]
+#endif  /* !HANDLE_MULTIBYTE */
+
+/****************************************************************
+ *                                                             *
+ * The following are only guaranteed to work in subst.c                *
+ *                                                             *
+ ****************************************************************/
+
+#if defined (HANDLE_MULTIBYTE)
+#  define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
+    do \
+      { \
+       if (MB_CUR_MAX > 1) \
+         { \
+           mbstate_t state_bak; \
+           size_t mblength; \
+           int _i; \
+\
+           state_bak = state; \
+           mblength = mbrlen ((_src) + (_si), (_slen) - (_si), &state); \
+           if (mblength == (size_t)-2 || mblength == (size_t)-1) \
+             { \
+               state = state_bak; \
+               mblength = 1; \
+             } \
+           else \
+             mblength = (mblength < 1) ? 1 : mblength; \
+\
+           temp = xmalloc (mblength + 2); \
+           temp[0] = _escchar; \
+           for (_i = 0; _i < mblength; _i++) \
+             temp[_i + 1] = _src[_si++]; \
+           temp[mblength + 1] = '\0'; \
+\
+           goto add_string; \
+         } \
+       else \
+         { \
+           _dst[0] = _escchar; \
+           _dst[1] = _sc; \
+         } \
+      } \
+    while (0)
+#else
+#  define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
+    _dst[0] = _escchar; \
+    _dst[1] = _sc
+#endif  /* !HANDLE_MULTIBYTE */
+
+#if defined (HANDLE_MULTIBYTE)
+#  define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
+    do \
+      { \
+       if (MB_CUR_MAX > 1) \
+         { \
+           mbstate_t state_bak; \
+           size_t mblength; \
+\
+           state_bak = state; \
+           mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src) + (_si)), &state); \
+           if (mblength == (size_t)-2 || mblength == (size_t)-1) \
+             { \
+               state = state_bak; \
+               mblength = 1; \
+             } \
+           else \
+             mblength = (mblength < 1) ? 1 : mblength; \
+\
+           FASTCOPY(((_src) + (_si)), (_dst), mblength); \
+\
+           (_dst) += mblength; \
+           (_si) += mblength; \
+         } \
+       else \
+         { \
+           *(_dst)++ = _src[(_si)]; \
+           (_si)++; \
+         } \
+      } \
+    while (0)
+#else
+#  define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
+       *(_dst)++ = _src[(_si)]; \
+       (_si)++
+#endif  /* !HANDLE_MULTIBYTE */
+
+#if HANDLE_MULTIBYTE
+#  define SADD_MBCHAR(_dst, _src, _si, _srcsize) \
+    do \
+      { \
+       if (MB_CUR_MAX > 1) \
+         { \
+           int i; \
+           mbstate_t state_bak; \
+           size_t mblength; \
+\
+           state_bak = state; \
+           mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
+           if (mblength == (size_t)-1 || mblength == (size_t)-2) \
+             { \
+               state = state_bak; \
+               mblength = 1; \
+             } \
+           if (mblength < 1) \
+             mblength = 1; \
+\
+           _dst = (char *)xmalloc (mblength + 1); \
+           for (i = 0; i < mblength; i++) \
+             (_dst)[i] = (_src)[(_si)++]; \
+           (_dst)[mblength] = '\0'; \
+\
+           goto add_string; \
+         } \
+      } \
+    while (0)
+
+#else
+#  define SADD_MBCHAR(_dst, _src, _si, _srcsize)
+#endif
+
+#endif /* _SH_MBUTIL_H_ */
index 3106a90ad1903fac64f7915b69411b061b487ae1..05b743e5cfab2602c8d50f1daaa221b0d840146b 100644 (file)
@@ -29,7 +29,7 @@
        extern char *func __P((char *, char *, int)); */
 
 #if !defined (__P)
-#  if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus)
+#  if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus) || defined (PROTOTYPES)
 #    define __P(protos) protos
 #  else 
 #    define __P(protos) ()
 #  endif
 #endif
 
+/* For those situations when gcc handles inlining a particular function but
+   other compilers complain. */
+#ifdef __GNUC__
+#  define INLINE inline
+#else
+#  define INLINE
+#endif
+
+#if defined (PREFER_STDARG)
+#  define SH_VA_START(va, arg)  va_start(va, arg)
+#else
+#  define SH_VA_START(va, arg)  va_start(va)
+#endif
+
 #endif /* !_STDC_H_ */
diff --git a/input.h b/input.h
index 59e06cba0e54f3cedf3ecf6eabb94b5642c6e633..b024abc6b3ab7fb1490523b75f9fdcd0dd406f80 100644 (file)
--- a/input.h
+++ b/input.h
@@ -86,9 +86,11 @@ typedef struct {
 
 extern BASH_INPUT bash_input;
 
-/* Functions from parse.y. */
+/* Functions from parse.y whose use directly or indirectly depends on the
+   definitions in this file. */
 extern void initialize_bash_input __P((void));
 extern void init_yy_io __P((sh_cget_func_t *, sh_cunget_func_t *, enum stream_type, const char *, INPUT_STREAM));
+extern char *yy_input_name __P((void));
 extern void with_input_from_stdin __P((void));
 extern void with_input_from_string __P((char *, const char *));
 extern void with_input_from_stream __P((FILE *, const char *));
@@ -97,7 +99,6 @@ extern void pop_stream __P((void));
 extern int stream_on_stack __P((enum stream_type));
 extern char *read_secondary_line __P((int));
 extern int find_reserved_word __P((char *));
-extern char *decode_prompt_string __P((char *));
 extern void gather_here_documents __P((void));
 extern void execute_prompt_command __P((char *));
 
diff --git a/jobs.c b/jobs.c
index d50db68f12300fb83ef5b9aa645c934a7e61119f..2bcb3ac9efdbd0e68574c1ed3767ff4da4b0c1a5 100644 (file)
--- a/jobs.c
+++ b/jobs.c
@@ -83,9 +83,8 @@
 extern int errno;
 #endif /* !errno */
 
-#if !defined (CHILD_MAX)
-#  define CHILD_MAX 32
-#endif
+#define DEFAULT_CHILD_MAX 32
+#define MAX_JOBS_IN_ARRAY 4096         /* testing */
 
 /* Take care of system dependencies that must be handled when waiting for
    children.  The arguments to the WAITPID macro match those to the Posix.1
@@ -141,7 +140,7 @@ extern void rl_set_screen_size __P((int, int));
 #endif
 
 /* Variables used here but defined in other files. */
-extern int startup_state, subshell_environment, line_number;
+extern int subshell_environment, line_number;
 extern int posixly_correct, shell_level;
 extern int interrupt_immediately, last_command_exit_value;
 extern int loop_level, breaking;
@@ -150,13 +149,9 @@ extern sh_builtin_func_t *this_shell_builtin;
 extern char *shell_name, *this_command_name;
 extern sigset_t top_level_mask;
 extern procenv_t wait_intr_buf;
+extern int wait_signal_received;
 extern WORD_LIST *subst_assign_varlist;
 
-#if defined (ARRAY_VARS)
-static int *pstatuses;         /* list of pipeline statuses */
-static int statsize;
-#endif
-
 /* The array of known jobs. */
 JOB **jobs = (JOB **)NULL;
 
@@ -224,21 +219,20 @@ static sighandler sigstop_sighandler __P((int));
 
 static int waitchld __P((pid_t, int));
 
-static PROCESS *find_pipeline __P((pid_t));
+static PROCESS *find_pipeline __P((pid_t, int, int *));
 
 static char *current_working_directory __P((void));
 static char *job_working_directory __P((void));
 static char *printable_job_status __P((int, PROCESS *, int));
 
-static pid_t find_last_pid __P((int));
-static pid_t last_pid __P((int));
+static pid_t find_last_pid __P((int, int));
 
 static int set_new_line_discipline __P((int));
 static int map_over_jobs __P((sh_job_map_func_t *, int, int));
 static int job_last_stopped __P((int));
 static int job_last_running __P((int));
 static int most_recent_job_in_state __P((int, JOB_STATE));
-static int find_job __P((pid_t));
+static int find_job __P((pid_t, int));
 static int print_job __P((JOB *, int, int, int));
 static int process_exit_status __P((WAIT));
 static int job_exit_status __P((int));
@@ -248,6 +242,7 @@ static WAIT raw_job_exit_status __P((int));
 
 static void notify_of_job_status __P((void));
 static void cleanup_dead_jobs __P((void));
+static int compact_jobs_list __P((int));
 static void discard_pipeline __P((PROCESS *));
 static void add_process __P((char *, pid_t));
 static void print_pipeline __P((PROCESS *, int, int, FILE *));
@@ -264,9 +259,31 @@ static void pipe_read __P((int *));
 static void pipe_close __P((int *));
 #endif
 
-/* Used to synchronize between wait_for and the SIGCHLD signal handler. */
+#if defined (ARRAY_VARS)
+static int *pstatuses;         /* list of pipeline statuses */
+static int statsize;
+#endif
+
+/* Used to synchronize between wait_for and other functions and the SIGCHLD
+   signal handler. */
 static int sigchld;
-static int waiting_for_job;
+static int queue_sigchld;
+
+#define QUEUE_SIGCHLD(os)      (os) = sigchld, queue_sigchld++
+
+#define UNQUEUE_SIGCHLD(os) \
+       do { \
+         queue_sigchld--; \
+         if (queue_sigchld == 0 && os != sigchld) \
+           waitchld (-1, 0); \
+       } while (0)
+
+static SigHandler *old_tstp, *old_ttou, *old_ttin;
+static SigHandler *old_cont = (SigHandler *)SIG_DFL;
+
+#if defined (TIOCGWINSZ) && defined (SIGWINCH)
+static SigHandler *old_winch = (SigHandler *)SIG_DFL;
+#endif
 
 /* A place to temporarily save the current pipeline. */
 static PROCESS *saved_pipeline;
@@ -280,6 +297,8 @@ static int jobs_list_frozen;
 
 static char retcode_name_buffer[64];
 
+static long child_max = -1L;
+
 #if !defined (_POSIX_VERSION)
 
 /* These are definitions to map POSIX 1003.1 functions onto existing BSD
@@ -466,6 +485,12 @@ stop_pipeline (async, deferred)
     }
 
   /* Do we need more room? */
+
+  /* First try compaction */
+  if (subshell_environment && interactive_shell && i == job_slots && job_slots >= MAX_JOBS_IN_ARRAY)
+    i = compact_jobs_list (0);
+
+  /* If we can't compact, reallocate */
   if (i == job_slots)
     {
       job_slots += JOB_SLOTS;
@@ -561,18 +586,86 @@ static void
 cleanup_dead_jobs ()
 {
   register int i;
-  sigset_t set, oset;
+  int os;
 
   if (job_slots == 0 || jobs_list_frozen)
     return;
 
-  BLOCK_CHILD (set, oset);
+  QUEUE_SIGCHLD(os);
 
   for (i = 0; i < job_slots; i++)
     if (jobs[i] && DEADJOB (i) && IS_NOTIFIED (i))
       delete_job (i, 0);
 
+  UNQUEUE_SIGCHLD(os);
+}
+
+/* Compact the jobs list by removing dead jobs.  Assumed that we have filled
+   the jobs array to some predefined maximum.  Called when the shell is not
+   the foreground process (subshell_environment != 0).  Returns the first
+   available slot in the compacted list.  If that value is job_slots, then
+   the list needs to be reallocated.  The jobs array is in new memory if
+   this returns > 0 and < job_slots.  FLAGS is reserved for future use. */
+static int
+compact_jobs_list (flags)
+     int flags;
+{
+  sigset_t set, oset;
+  register int i, j;
+  int nremove, ndel;
+  JOB **newlist;
+
+  if (job_slots == 0 || jobs_list_frozen)
+    return job_slots;
+
+  if (child_max < 0)
+    child_max = getmaxchild ();
+
+  /* Take out at most a quarter of the jobs in the jobs array, but leave at
+     least child_max */
+  nremove = job_slots >> 2;
+  if ((job_slots - nremove) < child_max)
+    nremove = job_slots - child_max;
+
+  /* need to increase jobs list to at least CHILD_MAX entries */
+  if (nremove < 0)
+    return job_slots;
+
+  BLOCK_CHILD (set, oset);  
+
+  for (ndel = i = 0; i < job_slots; i++)
+    if (jobs[i])
+      {
+       if (DEADJOB (i) && (find_last_pid (i, 0) != last_asynchronous_pid))
+         {
+           delete_job (i, 0);
+           ndel++;
+           if (ndel == nremove)
+             break;
+         }
+      }
+
+  if (ndel == 0)
+    {
+      UNBLOCK_CHILD (oset);
+      return job_slots;
+    }
+
+  newlist = (JOB **)xmalloc ((1 + job_slots) * sizeof (JOB *));
+  for (i = j = 0; i < job_slots; i++)
+    if (jobs[i])
+      newlist[j++] = jobs[i];
+
+  ndel = j;
+  for ( ; j < job_slots; j++)
+    newlist[j] = (JOB *)NULL;
+
+  free (jobs);
+  jobs = newlist;
+
   UNBLOCK_CHILD (oset);
+
+  return ndel;
 }
 
 /* Delete the job at INDEX from the job list.  Must be called
@@ -650,7 +743,7 @@ add_process (name, pid)
   t->next = the_pipeline;
   t->pid = pid;
   WSTATUS (t->status) = 0;
-  t->running = 1;
+  t->running = PS_RUNNING;
   t->command = name;
   the_pipeline = t;
 
@@ -792,13 +885,17 @@ kill_current_pipeline ()
 /* Return the pipeline that PID belongs to.  Note that the pipeline
    doesn't have to belong to a job.  Must be called with SIGCHLD blocked. */
 static PROCESS *
-find_pipeline (pid)
+find_pipeline (pid, running_only, jobp)
      pid_t pid;
+     int running_only;
+     int *jobp;                /* index into jobs list or NO_JOB */
 {
   int job;
   register PROCESS *p;
 
   /* See if this process is in the pipeline that we are building. */
+  if (jobp)
+    *jobp = NO_JOB;
   if (the_pipeline)
     {
       p = the_pipeline;
@@ -806,23 +903,28 @@ find_pipeline (pid)
        {
          /* Return it if we found it. */
          if (p->pid == pid)
-           return (p);
+           {
+             if ((running_only && PRUNNING(p)) || (running_only == 0))
+               return (p);
+           }
 
          p = p->next;
        }
       while (p != the_pipeline);
     }
 
-  job = find_job (pid);
-
+  job = find_job (pid, running_only);
+  if (jobp)
+    *jobp = job;
   return (job == NO_JOB) ? (PROCESS *)NULL : jobs[job]->pipe;
 }
 
 /* Return the job index that PID belongs to, or NO_JOB if it doesn't
    belong to any job.  Must be called with SIGCHLD blocked. */
 static int
-find_job (pid)
+find_job (pid, running_only)
      pid_t pid;
+     int running_only;
 {
   register int i;
   register PROCESS *p;
@@ -836,7 +938,10 @@ find_job (pid)
          do
            {
              if (p->pid == pid)
-               return (i);
+               {
+                 if ((running_only && PRUNNING(p)) || (running_only == 0))
+                   return (i);
+               }
 
              p = p->next;
            }
@@ -859,7 +964,9 @@ get_job_by_pid (pid, block)
 
   if (block)
     BLOCK_CHILD (set, oset);
-  job = find_job (pid);
+
+  job = find_job (pid, 0);
+
   if (block)
     UNBLOCK_CHILD (oset);
 
@@ -876,7 +983,7 @@ describe_pid (pid)
 
   BLOCK_CHILD (set, oset);
 
-  job = find_job (pid);
+  job = find_job (pid, 0);
 
   if (job != NO_JOB)
     printf ("[%d] %ld\n", job + 1, (long)pid);
@@ -1056,31 +1163,26 @@ print_pipeline (p, job_index, format, stream)
   fflush (stream);
 }
 
+/* Print information to STREAM about jobs[JOB_INDEX] according to FORMAT.
+   Must be called with SIGCHLD blocked or queued with queue_sigchld */
 static void
 pretty_print_job (job_index, format, stream)
      int job_index, format;
      FILE *stream;
 {
   register PROCESS *p;
-  sigset_t set, oset;
-
-  BLOCK_CHILD (set, oset);
 
   /* Format only pid information about the process group leader? */
   if (format == JLIST_PID_ONLY)
     {
       fprintf (stream, "%ld\n", (long)jobs[job_index]->pipe->pid);
-      UNBLOCK_CHILD (oset);
       return;
     }
 
   if (format == JLIST_CHANGED_ONLY)
     {
       if (IS_NOTIFIED (job_index))
-       {
-         UNBLOCK_CHILD (oset);
-         return;
-       }
+       return;
       format = JLIST_STANDARD;
     }
 
@@ -1099,8 +1201,6 @@ pretty_print_job (job_index, format, stream)
   /* We have printed information about this job.  When the job's
      status changes, waitchld () sets the notification flag to 0. */
   jobs[job_index]->flags |= J_NOTIFIED;
-
-  UNBLOCK_CHILD (oset);
 }
 
 static int
@@ -1118,7 +1218,7 @@ list_one_job (job, format, ignore, job_index)
      JOB *job;
      int format, ignore, job_index;
 {
-  print_job (job, format, -1, job_index);
+  pretty_print_job (job_index, format, stdout);
 }
 
 void
@@ -1317,6 +1417,7 @@ make_child (command, async_p)
   return (pid);
 }
 
+/* These two functions are called only in child processes. */
 void
 ignore_tty_job_signals ()
 {
@@ -1465,38 +1566,32 @@ set_tty_state ()
 
 /* Given an index into the jobs array JOB, return the pid of the last
    process in that job's pipeline.  This is the one whose exit status
-   counts. */
+   counts.  Must be called with SIGCHLD blocked or queued. */
 static pid_t
-find_last_pid (job)
+find_last_pid (job, block)
      int job;
+     int block;
 {
   register PROCESS *p;
+  sigset_t set, oset;
+
+  if (block)
+    BLOCK_CHILD (set, oset);
 
   p = jobs[job]->pipe;
   while (p->next != jobs[job]->pipe)
     p = p->next;
 
-  return (p->pid);
-}
-
-static pid_t
-last_pid (job)
-     int job;
-{
-  pid_t pid;
-  sigset_t set, oset;
-
-  BLOCK_CHILD (set, oset);
-  pid = find_last_pid (job);
-  UNBLOCK_CHILD (oset);
+  if (block)
+    UNBLOCK_CHILD (oset);
 
-  return (pid);
+  return (p->pid);
 }
 
 /* Wait for a particular child of the shell to finish executing.
    This low-level function prints an error message if PID is not
-   a child of this shell.  It returns -1 if it fails, or 0 if not
-   (whatever wait_for returns).  If the child is not found in the
+   a child of this shell.  It returns -1 if it fails, or whatever
+   wait_for returns otherwise.  If the child is not found in the
    jobs table, it returns 127. */
 int
 wait_for_single_pid (pid)
@@ -1507,7 +1602,7 @@ wait_for_single_pid (pid)
   int r, job;
 
   BLOCK_CHILD (set, oset);
-  child = find_pipeline (pid);
+  child = find_pipeline (pid, 0, (int *)NULL);
   UNBLOCK_CHILD (oset);
 
   if (child == 0)
@@ -1521,7 +1616,7 @@ wait_for_single_pid (pid)
   /* POSIX.2: if we just waited for a job, we can remove it from the jobs
      table. */
   BLOCK_CHILD (set, oset);
-  job = find_job (pid);
+  job = find_job (pid, 0);
   if (job != NO_JOB && jobs[job] && DEADJOB (job))
     jobs[job]->flags |= J_NOTIFIED;
   UNBLOCK_CHILD (oset);
@@ -1533,7 +1628,7 @@ wait_for_single_pid (pid)
 void
 wait_for_background_pids ()
 {
-  register int i, count, r, waited_for;
+  register int i, r, waited_for;
   sigset_t set, oset;
   pid_t pid;
 
@@ -1541,37 +1636,31 @@ wait_for_background_pids ()
     {
       BLOCK_CHILD (set, oset);
 
-      count = 0;
+      /* find first running job; if none running in foreground, break */
       for (i = 0; i < job_slots; i++)
        if (jobs[i] && RUNNING (i) && IS_FOREGROUND (i) == 0)
-         {
-           count++;
-           break;
-         }
+         break;
 
-      if (count == 0)
+      if (i == job_slots)
        {
          UNBLOCK_CHILD (oset);
          break;
        }
 
-      for (i = 0; i < job_slots; i++)
-       if (jobs[i] && RUNNING (i) && IS_FOREGROUND (i) == 0)
-         {
-           pid = last_pid (i);
-           UNBLOCK_CHILD (oset);
-           QUIT;
-           errno = 0;          /* XXX */
-           r = wait_for_single_pid (pid);
-           if (r == -1)
-             {
-               if (errno == ECHILD)
-                 mark_all_jobs_as_dead ();
-             }
-           else
-             waited_for++;
-           break;
-         }
+      /* now wait for the last pid in that job. */
+      pid = find_last_pid (i, 0);
+      UNBLOCK_CHILD (oset);
+      QUIT;
+      errno = 0;               /* XXX */
+      r = wait_for_single_pid (pid);
+      if (r == -1)
+       {
+         /* If we're mistaken about job state, compensate. */
+         if (errno == ECHILD)
+           mark_all_jobs_as_dead ();
+       }
+      else
+       waited_for++;
     }
 
   /* POSIX.2 says the shell can discard the statuses of all completed jobs if
@@ -1618,6 +1707,7 @@ wait_sigint_handler (sig)
        {
          interrupt_immediately = 0;
          trap_handler (SIGINT);        /* set pending_traps[SIGINT] */
+         wait_signal_received = SIGINT;
          longjmp (wait_intr_buf, 1);
        }
       
@@ -1671,7 +1761,7 @@ job_exit_status (job)
 #define FIND_CHILD(pid, child) \
   do \
     { \
-      child = find_pipeline (pid); \
+      child = find_pipeline (pid, 0, (int *)NULL); \
       if (child == 0) \
        { \
          give_terminal_to (shell_pgrp, 0); \
@@ -1731,7 +1821,7 @@ wait_for (pid)
         We check for JDEAD in case the job state has been set by waitchld
         after receipt of a SIGCHLD. */
       if (job == NO_JOB)
-       job = find_job (pid);
+       job = find_job (pid, 0);
 
       /* waitchld() takes care of setting the state of the job.  If the job
         has already exited before this is called, sigchld_handler will have
@@ -1757,13 +1847,13 @@ wait_for (pid)
          act.sa_flags = 0;
          sigaction (SIGCHLD, &act, &oact);
 #  endif
-         waiting_for_job = 1;
+         queue_sigchld = 1;
          r = waitchld (pid, 1);
 #  if defined (MUST_UNBLOCK_CHLD)
          sigaction (SIGCHLD, &oact, (struct sigaction *)NULL);
          sigprocmask (SIG_SETMASK, &chldset, (sigset_t *)NULL);
 #  endif
-         waiting_for_job = 0;
+         queue_sigchld = 0;
          if (r == -1 && errno == ECHILD && this_shell_builtin == wait_builtin)
            {
              termination_state = -1;
@@ -1776,8 +1866,8 @@ wait_for (pid)
             if it exists, as JDEAD. */
          if (r == -1 && errno == ECHILD)
            {
-             child->running = 0;
-             child->status = 0;        /* XXX */
+             child->running = PS_DONE;
+             child->status = 0;        /* XXX -- can't find true status */
              if (job != NO_JOB)
                jobs[job]->state = JDEAD;
            }
@@ -1886,6 +1976,11 @@ if (job == NO_JOB)
            }
        }
 
+      /* Moved here from set_job_status_and_cleanup, which is in the SIGCHLD
+         signal handler path */
+      if (DEADJOB (job) && IS_FOREGROUND (job) /*&& subshell_environment == 0*/)
+       setjstatus (job);
+
       /* If this job is dead, notify the user of the status.  If the shell
         is interactive, this will display a message on the terminal.  If
         the shell is not interactive, make sure we turn on the notify bit
@@ -1918,9 +2013,9 @@ wait_for_job (job)
   BLOCK_CHILD(set, oset);
   if (JOBSTATE (job) == JSTOPPED)
     internal_warning ("wait_for_job: job %d is stopped", job+1);
-  UNBLOCK_CHILD(oset);
 
-  pid = last_pid (job);
+  pid = find_last_pid (job, 0);
+  UNBLOCK_CHILD(oset);
   r = wait_for (pid);
 
   /* POSIX.2: we can remove the job from the jobs table if we just waited
@@ -1970,6 +2065,7 @@ most_recent_job_in_state (job, state)
   sigset_t set, oset;
 
   BLOCK_CHILD (set, oset);
+
   for (result = NO_JOB, i = job - 1; i >= 0; i--)
     {
       if (jobs[i] && (JOBSTATE (i) == state))
@@ -1978,6 +2074,7 @@ most_recent_job_in_state (job, state)
          break;
        }
     }
+
   UNBLOCK_CHILD (oset);
 
   return (result);
@@ -2110,7 +2207,7 @@ set_job_running (job)
   do
     {
       if (WIFSTOPPED (p->status))
-       p->running = 1;
+       p->running = PS_RUNNING;        /* XXX - could be PS_STOPPED */
       p = p->next;
     }
   while (p != jobs[job]->pipe);
@@ -2209,14 +2306,13 @@ start_job (job, foreground)
       killpg (jobs[job]->pgrp, SIGCONT);
     }
 
-  UNBLOCK_CHILD (oset);
-
   if (foreground)
     {
       pid_t pid;
       int s;
 
-      pid = last_pid (job);
+      pid = find_last_pid (job, 0);
+      UNBLOCK_CHILD (oset);
       s = wait_for (pid);
       shell_tty_info = save_stty;
       set_tty_state ();
@@ -2224,7 +2320,6 @@ start_job (job, foreground)
     }
   else
     {
-      BLOCK_CHILD (set, oset);
       reset_current ();
       UNBLOCK_CHILD (oset);
       return (0);
@@ -2248,8 +2343,7 @@ kill_pid (pid, sig, group)
   if (group)
     {
       BLOCK_CHILD (set, oset);
-      p = find_pipeline (pid);
-      job = find_job (pid);
+      p = find_pipeline (pid, 0, &job);
 
       if (job != NO_JOB)
        {
@@ -2263,7 +2357,7 @@ kill_pid (pid, sig, group)
              do
                {
                  kill (p->pid, sig);
-                 if (p->running == 0 && (sig == SIGTERM || sig == SIGHUP))
+                 if (p->running == PS_DONE && (sig == SIGTERM || sig == SIGHUP))
                    kill (p->pid, SIGCONT);
                  p = p->next;
                }
@@ -2307,7 +2401,7 @@ sigchld_handler (sig)
   REINSTALL_SIGCHLD_HANDLER;
   sigchld++;
   n = 0;
-  if (waiting_for_job == 0)
+  if (queue_sigchld == 0)
     n = waitchld (-1, 0);
   errno = oerrno;
   SIGRETURN (n);
@@ -2370,7 +2464,7 @@ waitchld (wpid, block)
        children_exited++;
 
       /* Locate our PROCESS for this pid. */
-      child = find_pipeline (pid);
+      child = find_pipeline (pid, 1, &job);    /* want running procs only */
 
       /* It is not an error to have a child terminate that we did
         not have a record of.  This child could have been part of
@@ -2384,10 +2478,8 @@ waitchld (wpid, block)
 
       /* Remember status, and whether or not the process is running. */
       child->status = status;
-      child->running = WIFCONTINUED(status) ? 1 : 0;
+      child->running = WIFCONTINUED(status) ? PS_RUNNING : PS_DONE;
 
-      job = find_job (pid);
-  
       if (job == NO_JOB)
        continue;
 
@@ -2453,7 +2545,7 @@ set_job_status_and_cleanup (job)
   do
     {
       job_state |= child->running;
-      if (child->running == 0 && (WIFSTOPPED (child->status)))
+      if (child->running == PS_DONE && (WIFSTOPPED (child->status)))
        {
          any_stopped = 1;
          any_tstped |= interactive && job_control &&
@@ -2492,8 +2584,10 @@ set_job_status_and_cleanup (job)
     {
       jobs[job]->state = JDEAD;
 
+#if 0
       if (IS_FOREGROUND (job))
        setjstatus (job);
+#endif
 
       /* If this job has a cleanup function associated with it, call it
         with `cleanarg' as the single argument, then set the function
@@ -2523,12 +2617,14 @@ set_job_status_and_cleanup (job)
          WIFSIGNALED (child->status) == 0 && IS_FOREGROUND (job) &&
          signal_is_trapped (SIGINT))
        {
+         int old_frozen;
          wait_sigint_received = 0;
          last_command_exit_value = process_exit_status (child->status);
 
+         old_frozen = jobs_list_frozen;
          jobs_list_frozen = 1;
          tstatus = maybe_call_trap_handler (SIGINT);
-         jobs_list_frozen = 0;
+         jobs_list_frozen = old_frozen;
        }
 
       /* If the foreground job is killed by SIGINT when job control is not
@@ -2543,6 +2639,8 @@ set_job_status_and_cleanup (job)
       else if (wait_sigint_received && (WTERMSIG (child->status) == SIGINT) &&
              IS_FOREGROUND (job) && IS_JOBCONTROL (job) == 0)
        {
+         int old_frozen;
+
          wait_sigint_received = 0;
 
          /* If SIGINT is trapped, set the exit status so that the trap
@@ -2555,9 +2653,10 @@ set_job_status_and_cleanup (job)
            maybe_call_trap_handler() may cause dead jobs to be removed from
            the job table because of a call to execute_command.  We work
            around this by setting JOBS_LIST_FROZEN. */
+         old_frozen = jobs_list_frozen;
          jobs_list_frozen = 1;
          tstatus = maybe_call_trap_handler (SIGINT);
-         jobs_list_frozen = 0;
+         jobs_list_frozen = old_frozen;
          if (tstatus == 0 && old_sigint_handler != INVALID_SIGNAL_HANDLER)
            {
              /* wait_sigint_handler () has already seen SIGINT and
@@ -2600,7 +2699,7 @@ setjstatus (j)
   for (i = 1, p = jobs[j]->pipe; p->next != jobs[j]->pipe; p = p->next, i++)
     ;
   i++;
-  if (statsize <= i)
+  if (statsize < i)
     {
       pstatuses = (int *)xrealloc (pstatuses, i * sizeof (int));
       statsize = i;
@@ -2615,7 +2714,7 @@ setjstatus (j)
   while (p != jobs[j]->pipe);
 
   pstatuses[i] = -1;   /* sentinel */
-  set_pipestatus_array (pstatuses);
+  set_pipestatus_array (pstatuses, i);
 #endif
 }
 
@@ -2675,11 +2774,16 @@ notify_of_job_status ()
   if (jobs == 0 || job_slots == 0)
     return;
 
-  sigemptyset (&set);
-  sigaddset (&set, SIGCHLD);
-  sigaddset (&set, SIGTTOU);
-  sigemptyset (&oset);
-  sigprocmask (SIG_BLOCK, &set, &oset);
+  if (old_ttou != 0)
+    {
+      sigemptyset (&set);
+      sigaddset (&set, SIGCHLD);
+      sigaddset (&set, SIGTTOU);
+      sigemptyset (&oset);
+      sigprocmask (SIG_BLOCK, &set, &oset);
+    }
+  else
+    queue_sigchld++;
 
   for (job = 0, dir = (char *)NULL; job < job_slots; job++)
     {
@@ -2706,7 +2810,7 @@ notify_of_job_status ()
                 hang onto the job corresponding to the last asynchronous
                 pid until the user has been notified of its status or does
                 a `wait'. */
-             if (DEADJOB (job) && (interactive_shell || (find_last_pid (job) != last_asynchronous_pid)))
+             if (DEADJOB (job) && (interactive_shell || (find_last_pid (job, 0) != last_asynchronous_pid)))
                jobs[job]->flags |= J_NOTIFIED;
              continue;
            }
@@ -2776,7 +2880,10 @@ notify_of_job_status ()
            }
        }
     }
-  sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+  if (old_ttou != 0)
+    sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+  else
+    queue_sigchld--;
 }
 
 /* Initialize the job control mechanism, and set up the tty stuff. */
@@ -2821,11 +2928,11 @@ initialize_job_control (force)
        {
          if (shell_pgrp != terminal_pgrp)
            {
-             SigHandler *old_ttin;
+             SigHandler *ottin;
 
-             old_ttin = set_signal_handler(SIGTTIN, SIG_DFL);
+             ottin = set_signal_handler(SIGTTIN, SIG_DFL);
              kill (0, SIGTTIN);
-             set_signal_handler (SIGTTIN, old_ttin);
+             set_signal_handler (SIGTTIN, ottin);
              continue;
            }
          break;
@@ -2952,12 +3059,7 @@ set_new_line_discipline (tty)
 #endif
 }
 
-static SigHandler *old_tstp, *old_ttou, *old_ttin;
-static SigHandler *old_cont = (SigHandler *)SIG_DFL;
-
 #if defined (TIOCGWINSZ) && defined (SIGWINCH)
-static SigHandler *old_winch = (SigHandler *)SIG_DFL;
-
 static void
 get_new_window_size (from_sig)
      int from_sig;
@@ -3026,8 +3128,8 @@ initialize_job_signals ()
   else if (job_control)
     {
       old_tstp = set_signal_handler (SIGTSTP, sigstop_sighandler);
-      old_ttou = set_signal_handler (SIGTTOU, sigstop_sighandler);
       old_ttin = set_signal_handler (SIGTTIN, sigstop_sighandler);
+      old_ttou = set_signal_handler (SIGTTOU, sigstop_sighandler);
     }
   /* Leave these things alone for non-interactive shells without job
      control. */
@@ -3173,16 +3275,16 @@ mark_all_jobs_as_dead ()
   register int i;
   sigset_t set, oset;
 
-  if (job_slots)
-    {
-      BLOCK_CHILD (set, oset);
+  if (job_slots == 0)
+    return;
 
-      for (i = 0; i < job_slots; i++)
-       if (jobs[i])
-         jobs[i]->state = JDEAD;
+  BLOCK_CHILD (set, oset);
 
-      UNBLOCK_CHILD (oset);
-    }
+  for (i = 0; i < job_slots; i++)
+    if (jobs[i])
+      jobs[i]->state = JDEAD;
+
+  UNBLOCK_CHILD (oset);
 }
 
 /* Mark all dead jobs as notified, so delete_job () cleans them out
@@ -3196,41 +3298,62 @@ mark_dead_jobs_as_notified (force)
   register int i, ndead;
   sigset_t set, oset;
 
-  if (job_slots)
-    {
-      BLOCK_CHILD (set, oset);
-
-      /* Count the number of dead jobs */
-      for (i = ndead = 0; force == 0 && i < job_slots; i++)
-       {
-         if (jobs[i] && DEADJOB (i))
-           ndead++;
-       }
+  if (job_slots == 0)
+    return;
 
-      /* Don't do anything if the number of jobs is less than CHILD_MAX and
-        we're not forcing a cleanup. */
-      if (force == 0 && ndead <= CHILD_MAX)
-       {
-         UNBLOCK_CHILD (oset);
-         return;
-       }
+  BLOCK_CHILD (set, oset);
 
-      /* Mark enough dead jobs as notified that we keep CHILD_MAX jobs in
-        the list.  This isn't exactly right yet; changes need to be made
-        to stop_pipeline so we don't mark the newer jobs after we've
-        created CHILD_MAX slots in the jobs array. */
+  /* If FORCE is non-zero, we don't have to keep CHILD_MAX statuses
+     around; just run through the array. */
+  if (force)
+    {
       for (i = 0; i < job_slots; i++)
        {
-         if (jobs[i] && DEADJOB (i) && (interactive_shell || (find_last_pid (i) != last_asynchronous_pid)))
-           {
-             jobs[i]->flags |= J_NOTIFIED;
-             if (force == 0 && --ndead <= CHILD_MAX)
-               break;
-           }
+         if (jobs[i] && DEADJOB (i) && (interactive_shell || (find_last_pid (i, 0) != last_asynchronous_pid)))
+           jobs[i]->flags |= J_NOTIFIED;
        }
+      UNBLOCK_CHILD (oset);
+      return;
+    }
+
+  /* Mark enough dead jobs as notified to keep CHILD_MAX jobs left in the
+     array not marked as notified. */
+          
+  /* Count the number of dead jobs */
+  for (i = ndead = 0; i < job_slots; i++)
+    {
+      if (jobs[i] && DEADJOB (i))
+       ndead++;
+    }
+
+  if (child_max < 0)
+    child_max = getmaxchild ();
+  if (child_max < 0)
+    child_max = DEFAULT_CHILD_MAX;
 
+  /* Don't do anything if the number of dead jobs is less than CHILD_MAX and
+     we're not forcing a cleanup. */
+  if (ndead <= child_max)
+    {
       UNBLOCK_CHILD (oset);
+      return;
     }
+
+  /* Mark enough dead jobs as notified that we keep CHILD_MAX jobs in
+     the list.  This isn't exactly right yet; changes need to be made
+     to stop_pipeline so we don't mark the newer jobs after we've
+     created CHILD_MAX slots in the jobs array. */
+  for (i = 0; i < job_slots; i++)
+    {
+      if (jobs[i] && DEADJOB (i) && (interactive_shell || (find_last_pid (i, 0) != last_asynchronous_pid)))
+       {
+         jobs[i]->flags |= J_NOTIFIED;
+         if (--ndead <= child_max)
+           break;
+       }
+    }
+
+  UNBLOCK_CHILD (oset);
 }
 
 /* Here to allow other parts of the shell (like the trap stuff) to
diff --git a/jobs.h b/jobs.h
index fe004ca143b8c64b8d561517d232d0b11849384d..1e21f8cb76bddf395f4ad8324bed6b5a2cd9791b 100644 (file)
--- a/jobs.h
+++ b/jobs.h
@@ -57,6 +57,11 @@ typedef struct process {
   char *command;       /* The particular program that is running. */
 } PROCESS;
 
+/* PRUNNING really means `not exited' */
+#define PRUNNING(p)    ((p)->running || WIFSTOPPED((p)->status))
+#define PSTOPPED(p)    (WIFSTOPPED((p)->status))
+#define PDEADPROC(p)   ((p)->running == PS_DONE)
+
 /* A description of a pipeline's state. */
 typedef enum { JRUNNING, JSTOPPED, JDEAD, JMIXED } JOB_STATE;
 #define JOBSTATE(job) (jobs[(job)]->state)
index a229f997305794c41e4c245c692b55f1877db88b..cddfd3f7cf286207e3d4ee561d519c0102ab5ca2 100644 (file)
@@ -39,6 +39,8 @@ MV = mv
 
 SHELL = @MAKE_SHELL@
 
+PROFILE_FLAGS = @PROFILE_FLAGS@
+
 CFLAGS = @CFLAGS@
 LOCAL_CFLAGS = @LOCAL_CFLAGS@
 CPPFLAGS = @CPPFLAGS@
@@ -51,7 +53,8 @@ BASHINCDIR = ${topdir}/include
 
 INCLUDES = -I. -I../.. -I$(topdir) -I$(BASHINCDIR) -I$(topdir)/lib
 
-CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(CPPFLAGS) ${INCLUDES} $(LOCAL_CFLAGS) $(CFLAGS)
+CCFLAGS = $(PROFILE_FLAGS) $(DEFS) $(LOCAL_DEFS) $(CPPFLAGS) ${INCLUDES} \
+         $(LOCAL_CFLAGS) $(CFLAGS)
 
 # Here is a rule for making .o files from .c files that doesn't force
 # the type of the machine (like -sun3) into the flags.
@@ -62,12 +65,13 @@ CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(CPPFLAGS) ${INCLUDES} $(LOCAL_CFLAGS) $(CFLAGS
 LIBRARY_NAME = libglob.a
 
 # The C code source files for this library.
-CSOURCES = $(srcdir)/glob.c $(srcdir)/strmatch.c
+CSOURCES = $(srcdir)/glob.c $(srcdir)/strmatch.c $(srcdir)/smatch.c \
+          $(srcdir)/xmbsrtowcs.c
 
 # The header files for this library.
 HSOURCES = $(srcdir)/strmatch.h
 
-OBJECTS = glob.o strmatch.o
+OBJECTS = glob.o strmatch.o smatch.o xmbsrtowcs.o
 
 # The texinfo files which document this library.
 DOCSOURCE = doc/glob.texi
@@ -121,15 +125,34 @@ mostlyclean: clean
 #                                                                   #
 ######################################################################
 
+smatch.o: strmatch.h
+smatch.o: $(BUILD_DIR)/config.h
+smatch.o: $(BASHINCDIR)/chartypes.h
+smatch.o: $(BASHINCDIR)/ansi_stdlib.h $(topdir)/bashansi.h
+smatch.o: $(BASHINCDIR)/shmbutil.h
+smatch.o: $(topdir)/xmalloc.h
+
 strmatch.o: strmatch.h
 strmatch.o: $(BUILD_DIR)/config.h
-strmatch.o: $(BASHINCDIR)/chartypes.h
+strmatch.o: $(BASHINCDIR)/stdc.h
 
 glob.o: $(BUILD_DIR)/config.h
 glob.o: $(topdir)/bashtypes.h $(BASHINCDIR)/ansi_stdlib.h $(topdir)/bashansi.h
 glob.o: $(BASHINCDIR)/posixstat.h $(BASHINCDIR)/memalloc.h
-glob.o: strmatch.h
+glob.o: strmatch.h glob.h
+glob.o: $(BASHINCDIR)/shmbutil.h
+glob.o: $(topdir)/xmalloc.h
+
+xmbsrtowcs.o: ${BUILD_DIR}/config.h
+xmbsrtowcs.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+xmbsrtowcs.o: ${BASHINCDIR}/shmbutil.h
 
 # Rules for deficient makes, like SunOS and Solaris
-strmatch.o: strmatch.c
 glob.o: glob.c
+strmatch.o: strmatch.c
+smatch.o: smatch.c
+xmbsrtowcs.o: xmbsrtowcs.c
+
+# dependencies for C files that include other C files
+glob.o: glob_loop.c
+smatch.o: sm_loop.c
index 1dbca3cdd0801d495a3e79181f987323a70d8ec1..ccd9f43ae0985a54904eab9824fc127c4e85b1d7 100644 (file)
 /* collsyms.h -- collating symbol names and their corresponding characters
                 (in ascii) as given by POSIX.2 in table 2.8. */
 
-/* Copyright (C) 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1997-2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
 
-#ifndef _COLLSYMS_H_
-#  define _COLLSYSMS_H_
-
 /* The upper-case letters, lower-case letters, and digits are omitted from
    this table.  The digits are not included in the table in the POSIX.2
    spec.  The upper and lower case letters are translated by the code
-   in fnmatch.c:collsym(). */
+   in smatch.c:collsym(). */
 
-typedef struct _collsym {
-  char *name;
-  char code;
-} COLLSYM;
+typedef struct _COLLSYM {
+  XCHAR *name;
+  CHAR code;
+} __COLLSYM;
 
-static COLLSYM posix_collsyms[] =
+static __COLLSYM POSIXCOLL [] =
 {
-       {  "NUL",               '\0' },
-       {  "SOH",               '\001' },
-       {  "STX",               '\002' },
-       {  "ETX",               '\003' },
-       {  "EOT",               '\004' },
-       {  "ENQ",               '\005' },
-       {  "ACK",               '\006' },
+       {  L("NUL"),                    L('\0') },
+       {  L("SOH"),                    L('\001') },
+       {  L("STX"),                    L('\002') },
+       {  L("ETX"),                    L('\003') },
+       {  L("EOT"),                    L('\004') },
+       {  L("ENQ"),                    L('\005') },
+       {  L("ACK"),                    L('\006') },
 #ifdef __STDC__
-       {  "alert",             '\a' },
+       {  L("alert"),                  L('\a') },
 #else
-       {  "alert",             '\007' },
+       {  L("alert"),                  L('\007') },
 #endif
-       {  "BS",                '\010' },
-       {  "backspace",         '\b' },
-       {  "HT",                '\011' },
-       {  "tab",               '\t' },
-       {  "LF",                '\012' },
-       {  "newline",           '\n' },
-       {  "VT",                '\013' },
-       {  "vertical-tab",      '\v' },
-       {  "FF",                '\014' },
-       {  "form-feed",         '\f' },
-       {  "CR",                '\015' },
-       {  "carriage-return",   '\r' },
-       {  "SO",                '\016' },
-       {  "SI",                '\017' },
-       {  "DLE",               '\020' },
-       {  "DC1",               '\021' },
-       {  "DC2",               '\022' },
-       {  "DC3",               '\023' },
-       {  "DC4",               '\024' },
-       {  "NAK",               '\025' },
-       {  "SYN",               '\026' },
-       {  "ETB",               '\027' },
-       {  "CAN",               '\030' },
-       {  "EM",                '\031' },
-       {  "SUB",               '\032' },
-       {  "ESC",               '\033' },
-       {  "IS4",               '\034' },
-       {  "FS",                '\034' },
-       {  "IS3",               '\035' },
-       {  "GS",                '\035' },
-       {  "IS2",               '\036' },
-       {  "RS",                '\036' },
-       {  "IS1",               '\037' },
-       {  "US",                '\037' },
-       {  "space",             ' ' },
-       {  "exclamation-mark",  '!' },
-       {  "quotation-mark",    '"' },
-       {  "number-sign",       '#' },
-       {  "dollar-sign",       '$' },
-       {  "percent-sign",      '%' },
-       {  "ampersand",         '&' },
-       {  "apostrophe",        '\'' },
-       {  "left-parenthesis",  '(' },
-       {  "right-parenthesis", ')' },
-       {  "asterisk",          '*' },
-       {  "plus-sign",         '+' },
-       {  "comma",             ',' },
-       {  "hyphen",            '-' },
-       {  "hyphen-minus",      '-' },
-       {  "minus",             '-' },          /* extension from POSIX.2 */
-       {  "dash",              '-' },          /* extension from POSIX.2 */
-       {  "period",            '.' },
-       {  "full-stop",         '.' },
-       {  "slash",             '/' },
-       {  "solidus",           '/' },          /* extension from POSIX.2 */
-       {  "zero",              '0' },
-       {  "one",               '1' },
-       {  "two",               '2' },
-       {  "three",             '3' },
-       {  "four",              '4' },
-       {  "five",              '5' },
-       {  "six",               '6' },
-       {  "seven",             '7' },
-       {  "eight",             '8' },
-       {  "nine",              '9' },
-       {  "colon",             ':' },
-       {  "semicolon",         ';' },
-       {  "less-than-sign",    '<' },
-       {  "equals-sign",       '=' },
-       {  "greater-than-sign", '>' },
-       {  "question-mark",     '?' },
-       {  "commercial-at",     '@' },
+       {  L("BS"),                     L('\010') },
+       {  L("backspace"),              L('\b') },
+       {  L("HT"),                     L('\011') },
+       {  L("tab"),                    L('\t') },
+       {  L("LF"),                     L('\012') },
+       {  L("newline"),                L('\n') },
+       {  L("VT"),                     L('\013') },
+       {  L("vertical-tab"),           L('\v') },
+       {  L("FF"),                     L('\014') },
+       {  L("form-feed"),              L('\f') },
+       {  L("CR"),                     L('\015') },
+       {  L("carriage-return"),        L('\r') },
+       {  L("SO"),                     L('\016') },
+       {  L("SI"),                     L('\017') },
+       {  L("DLE"),                    L('\020') },
+       {  L("DC1"),                    L('\021') },
+       {  L("DC2"),                    L('\022') },
+       {  L("DC3"),                    L('\023') },
+       {  L("DC4"),                    L('\024') },
+       {  L("NAK"),                    L('\025') },
+       {  L("SYN"),                    L('\026') },
+       {  L("ETB"),                    L('\027') },
+       {  L("CAN"),                    L('\030') },
+       {  L("EM"),                     L('\031') },
+       {  L("SUB"),                    L('\032') },
+       {  L("ESC"),                    L('\033') },
+       {  L("IS4"),                    L('\034') },
+       {  L("FS"),                     L('\034') },
+       {  L("IS3"),                    L('\035') },
+       {  L("GS"),                     L('\035') },
+       {  L("IS2"),                    L('\036') },
+       {  L("RS"),                     L('\036') },
+       {  L("IS1"),                    L('\037') },
+       {  L("US"),                     L('\037') },
+       {  L("space"),                  L(' ') },
+       {  L("exclamation-mark"),       L('!') },
+       {  L("quotation-mark"),         L('"') },
+       {  L("number-sign"),            L('#') },
+       {  L("dollar-sign"),            L('$') },
+       {  L("percent-sign"),           L('%') },
+       {  L("ampersand"),              L('&') },
+       {  L("apostrophe"),             L('\'') },
+       {  L("left-parenthesis"),       L('(') },
+       {  L("right-parenthesis"),      L(')') },
+       {  L("asterisk"),               L('*') },
+       {  L("plus-sign"),              L('+') },
+       {  L("comma"),                  L(',') },
+       {  L("hyphen"),                 L('-') },
+       {  L("hyphen-minus"),           L('-') },
+       {  L("minus"),                  L('-') },       /* extension from POSIX.2 */
+       {  L("dash"),                   L('-') },       /* extension from POSIX.2 */
+       {  L("period"),                 L('.') },
+       {  L("full-stop"),              L('.') },
+       {  L("slash"),                  L('/') },
+       {  L("solidus"),                L('/') },       /* extension from POSIX.2 */
+       {  L("zero"),                   L('0') },
+       {  L("one"),                    L('1') },
+       {  L("two"),                    L('2') },
+       {  L("three"),                  L('3') },
+       {  L("four"),                   L('4') },
+       {  L("five"),                   L('5') },
+       {  L("six"),                    L('6') },
+       {  L("seven"),                  L('7') },
+       {  L("eight"),                  L('8') },
+       {  L("nine"),                   L('9') },
+       {  L("colon"),                  L(':') },
+       {  L("semicolon"),              L(';') },
+       {  L("less-than-sign"),         L('<') },
+       {  L("equals-sign"),            L('=') },
+       {  L("greater-than-sign"),      L('>') },
+       {  L("question-mark"),          L('?') },
+       {  L("commercial-at"),          L('@') },
        /* upper-case letters omitted */
-       {  "left-square-bracket",'[' },
-       {  "backslash",         '\\' },
-       {  "reverse-solidus",   '\\' },
-       {  "right-square-bracket",']' },
-       {  "circumflex",        '^' },
-       {  "circumflex-accent", '^' },          /* extension from POSIX.2 */
-       {  "underscore",        '_' },
-       {  "grave-accent",      '`' },
+       {  L("left-square-bracket"),    L('[') },
+       {  L("backslash"),              L('\\') },
+       {  L("reverse-solidus"),        L('\\') },
+       {  L("right-square-bracket"),   L(']') },
+       {  L("circumflex"),             L('^') },
+       {  L("circumflex-accent"),      L('^') },       /* extension from POSIX.2 */
+       {  L("underscore"),             L('_') },
+       {  L("grave-accent"),           L('`') },
        /* lower-case letters omitted */
-       {  "left-brace",        '{' },          /* extension from POSIX.2 */
-       {  "left-curly-bracket",'{' },
-       {  "vertical-line",     '|' },
-       {  "right-brace",       '}' },  /* extension from POSIX.2 */
-       {  "right-curly-bracket",'}' },
-       {  "tilde",             '~' },
-       {  "DEL",               '\177' },
+       {  L("left-brace"),             L('{') },       /* extension from POSIX.2 */
+       {  L("left-curly-bracket"),     L('{') },
+       {  L("vertical-line"),          L('|') },
+       {  L("right-brace"),            L('}') },       /* extension from POSIX.2 */
+       {  L("right-curly-bracket"),    L('}') },
+       {  L("tilde"),                  L('~') },
+       {  L("DEL"),                    L('\177') },
        {  0,   0 },
 };
 
-#endif
+#undef _COLLSYM
+#undef __COLLSYM
+#undef POSIXCOLL
index 22f293120f0c6d79419bab19ee9efc8b98c219e3..27099f76a93b7b6c778b9df9d95a2b27d15e8ec8 100644 (file)
@@ -1,5 +1,6 @@
-/* File-name wildcard pattern matching for GNU.
-   Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
+/* glob.c -- file-name wildcard pattern matching for Bash.
+
+   Copyright (C) 1985-2002 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
   #pragma alloca
 #endif /* _AIX && RISC6000 && !__GNUC__ */
 
-#if defined (SHELL)
-#  include "bashtypes.h"
-#else
-#  include <sys/types.h>
-#endif
+#include "bashtypes.h"
 
 #if defined (HAVE_UNISTD_H)
 #  include <unistd.h>
 #endif
 
-#if defined (SHELL)
-#  include "bashansi.h"
-#else
-#  if defined (HAVE_STDLIB_H)
-#    include <stdlib.h>
-#  endif
-#  if defined (HAVE_STRING_H)
-#    include <string.h>
-#  else /* !HAVE_STRING_H */
-#    include <strings.h>
-#  endif /* !HAVE_STRING_H */
-#endif
-
-#if defined (HAVE_DIRENT_H)
-#  include <dirent.h>
-#  define D_NAMLEN(d) strlen ((d)->d_name)
-#else /* !HAVE_DIRENT_H */
-#  define D_NAMLEN(d) ((d)->d_namlen)
-#  if defined (HAVE_SYS_NDIR_H)
-#    include <sys/ndir.h>
-#  endif
-#  if defined (HAVE_SYS_DIR_H)
-#    include <sys/dir.h>
-#  endif /* HAVE_SYS_DIR_H */
-#  if defined (HAVE_NDIR_H)
-#    include <ndir.h>
-#  endif
-#  if !defined (dirent)
-#    define dirent direct
-#  endif
-#endif /* !HAVE_DIRENT_H */
-
-#if defined (_POSIX_SOURCE) && !defined (STRUCT_DIRENT_HAS_D_INO) || defined (BROKEN_DIRENT_D_INO)
-/* Posix does not require that the d_ino field be present, and some
-   systems do not provide it. */
-#  define REAL_DIR_ENTRY(dp) 1
-#else
-#  define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
-#endif /* _POSIX_SOURCE */
-
-#if !defined (HAVE_BCOPY) && !defined (bcopy)
-#  define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
-#endif /* !HAVE_BCOPY && !bcopy */
-
-#if defined (SHELL)
-#  include "posixstat.h"
-#else /* !SHELL */
-#  include <sys/stat.h>
-#endif /* !SHELL */
+#include "bashansi.h"
+#include "posixdir.h"
+#include "posixstat.h"
+#include "shmbutil.h"
+#include "xmalloc.h"
 
 #include "filecntl.h"
 #if !defined (F_OK)
 #  define F_OK 0
 #endif
 
-#if defined (SHELL)
-#  include "memalloc.h"
-#endif
+#include "stdc.h"
+#include "memalloc.h"
+#include "quit.h"
 
+#include "glob.h"
 #include "strmatch.h"
 
-#if !defined (HAVE_STDLIB_H) && !defined (SHELL)
-extern char *malloc (), *realloc ();
-extern void free ();
-#endif /* !HAVE_STDLIB_H */
+#if !defined (HAVE_BCOPY) && !defined (bcopy)
+#  define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
+#endif /* !HAVE_BCOPY && !bcopy */
 
 #if !defined (NULL)
 #  if defined (__STDC__)
@@ -109,13 +62,10 @@ extern void free ();
 #  endif /* __STDC__ */
 #endif /* !NULL */
 
-#if defined (SHELL)
-extern void throw_to_top_level ();
-extern int test_eaccess ();
+extern void throw_to_top_level __P((void));
+extern int test_eaccess __P((char *, int));
 
-extern int interrupt_state;
 extern int extended_glob;
-#endif /* SHELL */
 
 /* Global variable which controls whether or not * matches .*.
    Non-zero means don't match .*.  */
@@ -128,51 +78,152 @@ int glob_ignore_case = 0;
 /* Global variable to return to signify an error in globbing. */
 char *glob_error_return;
 
-/* Return nonzero if PATTERN has any special globbing chars in it.  */
+/* Some forward declarations. */
+static int skipname __P((char *, char *));
+#if HANDLE_MULTIBYTE
+static int mbskipname __P((char *, char *));
+#endif
+#if HANDLE_MULTIBYTE
+static void udequote_pathname __P((char *));
+static void wdequote_pathname __P((char *));
+#else
+#  define dequote_pathname udequote_pathname
+#endif
+static void dequote_pathname __P((char *));
+static int glob_testdir __P((char *));
+static char **glob_dir_to_array __P((char *, char **, int));
+
+/* Compile `glob_loop.c' for single-byte characters. */
+#define CHAR   unsigned char
+#define INT    int
+#define L(CS)  CS
+#define INTERNAL_GLOB_PATTERN_P internal_glob_pattern_p
+#include "glob_loop.c"
+
+/* Compile `glob_loop.c' again for multibyte characters. */
+#if HANDLE_MULTIBYTE
+
+#define CHAR   wchar_t
+#define INT    wint_t
+#define L(CS)  L##CS
+#define INTERNAL_GLOB_PATTERN_P internal_glob_wpattern_p
+#include "glob_loop.c"
+
+#endif /* HANDLE_MULTIBYTE */
+
+/* And now a function that calls either the single-byte or multibyte version
+   of internal_glob_pattern_p. */
 int
 glob_pattern_p (pattern)
      const char *pattern;
 {
-  register const char *p;
-  register char c;
-  int bopen;
-
-  p = pattern;
-  bopen = 0;
-
-  while ((c = *p++) != '\0')
-    switch (c)
-      {
-      case '?':
-      case '*':
-       return (1);
-
-      case '[':                /* Only accept an open brace if there is a close */
-       bopen++;        /* brace to match it.  Bracket expressions must be */
-       continue;       /* complete, according to Posix.2 */
-      case ']':
-       if (bopen)
-         return (1);
-       continue;      
-
-      case '+':                /* extended matching operators */
-      case '@':
-      case '!':
-       if (*p == '(')  /*) */
-         return (1);
-       continue;
-
-      case '\\':
-       if (*p++ == '\0')
-         return (0);
-      }
+#if HANDLE_MULTIBYTE
+  mbstate_t ps;
+  size_t n;
+  wchar_t *wpattern;
+  int r;
+
+  if (MB_CUR_MAX == 1)
+    return (internal_glob_pattern_p (pattern));
+
+  /* Convert strings to wide chars, and call the multibyte version. */
+  memset (&ps, '\0', sizeof (ps));
+  n = xmbsrtowcs (NULL, (const char **)&pattern, 0, &ps);
+  if (n == (size_t)-1)
+    /* Oops.  Invalid multibyte sequence.  Try it as single-byte sequence. */
+    return (internal_glob_pattern_p (pattern));
+  wpattern = (wchar_t *)xmalloc ((n + 1) * sizeof (wchar_t));
+  (void) xmbsrtowcs (wpattern, (const char **)&pattern, n + 1, &ps);
+  r = internal_glob_wpattern_p (wpattern);
+  free (wpattern);
+  return r;
+#else
+  return (internal_glob_pattern_p (pattern));
+#endif
+}
 
-  return (0);
+/* Return 1 if DNAME should be skipped according to PAT.  Mostly concerned
+   with matching leading `.'. */
+
+static int
+skipname (pat, dname)
+     char *pat;
+     char *dname;
+{
+  /* If a leading dot need not be explicitly matched, and the pattern
+     doesn't start with a `.', don't match `.' or `..' */
+  if (noglob_dot_filenames == 0 && pat[0] != '.' &&
+       (pat[0] != '\\' || pat[1] != '.') &&
+       (dname[0] == '.' &&
+         (dname[1] == '\0' || (dname[1] == '.' && dname[2] == '\0'))))
+    return 1;
+
+  /* If a dot must be explicity matched, check to see if they do. */
+  else if (noglob_dot_filenames && dname[0] == '.' && pat[0] != '.' &&
+       (pat[0] != '\\' || pat[1] != '.'))
+    return 1;
+
+  return 0;
+}
+
+#if HANDLE_MULTIBYTE
+/* Return 1 if DNAME should be skipped according to PAT.  Handles multibyte
+   characters in PAT and DNAME.  Mostly concerned with matching leading `.'. */
+
+static int
+mbskipname (pat, dname)
+     char *pat, *dname;
+{
+  char *pat_bak, *dn_bak;
+  wchar_t *pat_wc, *dn_wc;
+  mbstate_t pat_ps, dn_ps;
+  size_t pat_n, dn_n, n;
+
+  n = strlen(pat);
+  pat_bak = (char *) alloca (n + 1);
+  memcpy (pat_bak, pat, n + 1);
+
+  n = strlen(dname);
+  dn_bak = (char *) alloca (n + 1);
+  memcpy (dn_bak, dname,  n + 1);
+
+  memset(&pat_ps, '\0', sizeof(mbstate_t));
+  memset(&dn_ps, '\0', sizeof(mbstate_t));
+
+  pat_n = xmbsrtowcs (NULL, (const char **)&pat_bak, 0, &pat_ps);
+  dn_n = xmbsrtowcs (NULL, (const char **)&dn_bak, 0, &dn_ps);
+
+  if (pat_n != (size_t)-1 && dn_n !=(size_t)-1)
+    {
+      pat_wc = (wchar_t *) alloca ((pat_n + 1) * sizeof(wchar_t));
+      dn_wc = (wchar_t *) alloca ((dn_n + 1) * sizeof(wchar_t));
+
+      (void) xmbsrtowcs (pat_wc, (const char **)&pat_bak, pat_n + 1, &pat_ps);
+      (void) xmbsrtowcs (dn_wc, (const char **)&dn_bak, dn_n + 1, &dn_ps);
+
+      /* If a leading dot need not be explicitly matched, and the
+        pattern doesn't start with a `.', don't match `.' or `..' */
+      if (noglob_dot_filenames == 0 && pat_wc[0] != L'.' &&
+           (pat_wc[0] != L'\\' || pat_wc[1] != L'.') &&
+           (dn_wc[0] == L'.' &&
+             (dn_wc[1] == L'\0' || (dn_wc[1] == L'.' && dn_wc[2] == L'\0'))))
+       return 1;
+
+      /* If a leading dot must be explicity matched, check to see if the
+        pattern and dirname both have one. */
+     else if (noglob_dot_filenames && dn_wc[0] == L'.' &&
+          pat_wc[0] != L'.' &&
+          (pat_wc[0] != L'\\' || pat_wc[1] != L'.'))
+       return 1;
+    }
+
+  return 0;
 }
+#endif /* HANDLE_MULTIBYTE */
 
 /* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
 static void
-dequote_pathname (pathname)
+udequote_pathname (pathname)
      char *pathname;
 {
   register int i, j;
@@ -190,18 +241,71 @@ dequote_pathname (pathname)
   pathname[j] = '\0';
 }
 
-\f
+#if HANDLE_MULTIBYTE
+/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
+static void
+wdequote_pathname (pathname)
+     char *pathname;
+{
+  mbstate_t ps;
+  size_t len, n;
+  wchar_t *wpathname;
+  char *pathname_bak;
+  int i, j;
+
+  len = strlen (pathname);
+  pathname_bak = (char *) alloca (len + 1);
+  memcpy (pathname_bak, pathname , len + 1);
+
+  /* Convert the strings into wide characters.  */
+  memset (&ps, '\0', sizeof (ps));
+  n = xmbsrtowcs (NULL, (const char **)&pathname_bak, 0, &ps);
+  if (n == (size_t) -1)
+    /* Something wrong. */
+    return;
+
+  wpathname = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
+  (void) xmbsrtowcs (wpathname, (const char **)&pathname_bak, n + 1, &ps);
+
+  for (i = j = 0; wpathname && wpathname[i]; )
+    {
+      if (wpathname[i] == L'\\')
+       i++;
+
+      wpathname[j++] = wpathname[i++];
+
+      if (!wpathname[i - 1])
+       break;
+    }
+  wpathname[j] = L'\0';
+
+  /* Convert the wide character string into unibyte character set. */
+  memset (&ps, '\0', sizeof(mbstate_t));
+  n = wcsrtombs(pathname, (const wchar_t **)&wpathname, len, &ps);
+  pathname[len] = '\0';
+}
+
+static void
+dequote_pathname (pathname)
+     char *pathname;
+{
+  if (MB_CUR_MAX > 1)
+    wdequote_pathname (pathname);
+  else
+    udequote_pathname (pathname);
+}
+#endif /* HANDLE_MULTIBYTE */
 
 /* Test whether NAME exists. */
 
 #if defined (HAVE_LSTAT)
 #  define GLOB_TESTNAME(name)  (lstat (name, &finfo))
 #else /* !HAVE_LSTAT */
-#  if defined (SHELL) && !defined (AFS)
+#  if !defined (AFS)
 #    define GLOB_TESTNAME(name)  (test_eaccess (nextname, F_OK))
-#  else /* !SHELL || AFS */
+#  else /* AFS */
 #    define GLOB_TESTNAME(name)  (access (nextname, F_OK))
-#  endif /* !SHELL || AFS */
+#  endif /* AFS */
 #endif /* !HAVE_LSTAT */
 
 /* Return 0 if DIR is a directory, -1 otherwise. */
@@ -237,9 +341,10 @@ glob_testdir (dir)
    Look in errno for more information.  */
 
 char **
-glob_vector (pat, dir)
+glob_vector (pat, dir, flags)
      char *pat;
      char *dir;
+     int flags;
 {
   struct globval
     {
@@ -256,7 +361,7 @@ glob_vector (pat, dir)
   int lose, skip;
   register char **name_vector;
   register unsigned int i;
-  int flags;           /* Flags passed to strmatch (). */
+  int mflags;          /* Flags passed to strmatch (). */
 
   lastlink = 0;
   count = lose = skip = 0;
@@ -344,17 +449,15 @@ glob_vector (pat, dir)
 
       /* Compute the flags that will be passed to strmatch().  We don't
         need to do this every time through the loop. */
-      flags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
+      mflags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
 
 #ifdef FNM_CASEFOLD
       if (glob_ignore_case)
-       flags |= FNM_CASEFOLD;
+       mflags |= FNM_CASEFOLD;
 #endif
 
-#ifdef SHELL
       if (extended_glob)
-       flags |= FNM_EXTMATCH;
-#endif
+       mflags |= FNM_EXTMATCH;
 
       /* Scan the directory, finding all names that match.
         For each name that matches, allocate a struct globval
@@ -362,14 +465,12 @@ glob_vector (pat, dir)
         Chain those structs together; lastlink is the front of the chain.  */
       while (1)
        {
-#if defined (SHELL)
          /* Make globbing interruptible in the shell. */
          if (interrupt_state)
            {
              lose = 1;
              break;
            }
-#endif /* SHELL */
          
          dp = readdir (d);
          if (dp == NULL)
@@ -379,22 +480,15 @@ glob_vector (pat, dir)
          if (REAL_DIR_ENTRY (dp) == 0)
            continue;
 
-         /* If a leading dot need not be explicitly matched, and the pattern
-            doesn't start with a `.', don't match `.' or `..' */
-#define dname dp->d_name
-         if (noglob_dot_filenames == 0 && pat[0] != '.' &&
-               (pat[0] != '\\' || pat[1] != '.') &&
-               (dname[0] == '.' &&
-                 (dname[1] == '\0' || (dname[1] == '.' && dname[2] == '\0'))))
-#undef dname
+#if HANDLE_MULTIBYTE
+         if (MB_CUR_MAX > 1 && mbskipname (pat, dp->d_name))
            continue;
-
-         /* If a dot must be explicity matched, check to see if they do. */
-         if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.' &&
-               (pat[0] != '\\' || pat[1] != '.'))
+         else
+#endif
+         if (skipname (pat, dp->d_name))
            continue;
 
-         if (strmatch (pat, dp->d_name, flags) != FNM_NOMATCH)
+         if (strmatch (pat, dp->d_name, mflags) != FNM_NOMATCH)
            {
              nextlink = (struct globval *) alloca (sizeof (struct globval));
              nextlink->next = lastlink;
@@ -429,10 +523,8 @@ glob_vector (pat, dir)
          free (lastlink->name);
          lastlink = lastlink->next;
        }
-#if defined (SHELL)
-      if (interrupt_state)
-       throw_to_top_level ();
-#endif /* SHELL */
+
+      QUIT;
 
       return ((char **)NULL);
     }
@@ -447,22 +539,40 @@ glob_vector (pat, dir)
   name_vector[count] = NULL;
   return (name_vector);
 }
-\f
+
 /* Return a new array which is the concatenation of each string in ARRAY
    to DIR.  This function expects you to pass in an allocated ARRAY, and
    it takes care of free()ing that array.  Thus, you might think of this
-   function as side-effecting ARRAY. */
+   function as side-effecting ARRAY.  This should handle GX_MARKDIRS. */
 static char **
-glob_dir_to_array (dir, array)
+glob_dir_to_array (dir, array, flags)
      char *dir, **array;
+     int flags;
 {
   register unsigned int i, l;
   int add_slash;
-  char **result;
+  char **result, *new;
+  struct stat sb;
 
   l = strlen (dir);
   if (l == 0)
-    return (array);
+    {
+      if (flags & GX_MARKDIRS)
+       for (i = 0; array[i]; i++)
+         {
+           if ((stat (array[i], &sb) == 0) && S_ISDIR (sb.st_mode))
+             {
+               l = strlen (array[i]);
+               new = (char *)realloc (array[i], l + 2);
+               if (new == 0)
+                 return NULL;
+               new[l] = '/';
+               new[l+1] = '\0';
+               array[i] = new;
+             }
+         }
+      return (array);
+    }
 
   add_slash = dir[l - 1] != '/';
 
@@ -476,8 +586,9 @@ glob_dir_to_array (dir, array)
 
   for (i = 0; array[i] != NULL; i++)
     {
-      result[i] = (char *) malloc (l + (add_slash ? 1 : 0)
-                                  + strlen (array[i]) + 1);
+      /* 3 == 1 for NUL, 1 for slash at end of DIR, 1 for GX_MARKDIRS */
+      result[i] = (char *) malloc (l + strlen (array[i]) + 3);
+
       if (result[i] == NULL)
        return (NULL);
 
@@ -485,6 +596,16 @@ glob_dir_to_array (dir, array)
       if (add_slash)
        result[i][l] = '/';
       strcpy (result[i] + l + add_slash, array[i]);
+      if (flags & GX_MARKDIRS)
+       {
+         if ((stat (result[i], &sb) == 0) && S_ISDIR (sb.st_mode))
+           {
+             size_t rlen;
+             rlen = strlen (result[i]);
+             result[i][rlen] = '/';
+             result[i][rlen+1] = '\0';
+           }
+       }
     }
   result[i] = NULL;
 
@@ -495,15 +616,16 @@ glob_dir_to_array (dir, array)
 
   return (result);
 }
-\f
+
 /* Do globbing on PATHNAME.  Return an array of pathnames that match,
    marking the end of the array with a null-pointer as an element.
    If no pathnames match, then the array is empty (first element is null).
    If there isn't enough memory, then return NULL.
    If a file system error occurs, return -1; `errno' has the error code.  */
 char **
-glob_filename (pathname)
+glob_filename (pathname, flags)
      char *pathname;
+     int flags;
 {
   char **result;
   unsigned int result_size;
@@ -545,7 +667,7 @@ glob_filename (pathname)
       if (directory_name[directory_len - 1] == '/')
        directory_name[directory_len - 1] = '\0';
 
-      directories = glob_filename (directory_name);
+      directories = glob_filename (directory_name, flags & ~GX_MARKDIRS);
 
       if (directories == NULL)
        goto memory_error;
@@ -571,7 +693,7 @@ glob_filename (pathname)
          /* Scan directory even on a NULL pathname.  That way, `*h/'
             returns only directories ending in `h', instead of all
             files ending in `h' with a `/' appended. */
-         temp_results = glob_vector (filename, directories[i]);
+         temp_results = glob_vector (filename, directories[i], flags & ~GX_MARKDIRS);
 
          /* Handle error cases. */
          if (temp_results == NULL)
@@ -584,7 +706,7 @@ glob_filename (pathname)
              char **array;
              register unsigned int l;
 
-             array = glob_dir_to_array (directories[i], temp_results);
+             array = glob_dir_to_array (directories[i], temp_results, flags);
              l = 0;
              while (array[l] != NULL)
                ++l;
@@ -619,6 +741,7 @@ glob_filename (pathname)
       result = (char **) realloc ((char *) result, 2 * sizeof (char *));
       if (result == NULL)
        return (NULL);
+      /* Handle GX_MARKDIRS here. */
       result[0] = (char *) malloc (directory_len + 1);
       if (result[0] == NULL)
        goto memory_error;
@@ -642,13 +765,14 @@ glob_filename (pathname)
 
       /* Just return what glob_vector () returns appended to the
         directory name. */
-      temp_results =
-       glob_vector (filename, (directory_len == 0 ? "." : directory_name));
+      temp_results = glob_vector (filename,
+                                 (directory_len == 0 ? "." : directory_name),
+                                 flags & ~GX_MARKDIRS);
 
       if (temp_results == NULL || temp_results == (char **)&glob_error_return)
        return (temp_results);
 
-      return (glob_dir_to_array (directory_name, temp_results));
+      return (glob_dir_to_array (directory_name, temp_results, flags));
     }
 
   /* We get to memory_error if the program has run out of memory, or
@@ -661,13 +785,12 @@ glob_filename (pathname)
        free (result[i]);
       free ((char *) result);
     }
-#if defined (SHELL)
-  if (interrupt_state)
-    throw_to_top_level ();
-#endif /* SHELL */
+
+  QUIT;
+
   return (NULL);
 }
-\f
+
 #if defined (TEST)
 
 main (argc, argv)
@@ -678,7 +801,7 @@ main (argc, argv)
 
   for (i = 1; i < argc; ++i)
     {
-      char **value = glob_filename (argv[i]);
+      char **value = glob_filename (argv[i], 0);
       if (value == NULL)
        puts ("Out of memory.");
       else if (value == &glob_error_return)
index fbfa9f739b28b9e5939cf025fc6a2b5ff9beea06..95108a44dc20c50fa055e4f12989865740c1f83f 100644 (file)
 
 #include "stdc.h"
 
+#define GX_MARKDIRS    0x01    /* mark directory names with trailing `/' */
+#define GX_NOCASE      0x02    /* ignore case */
+#define GX_MATCHDOT    0x04    /* match `.' literally */
+
 extern int glob_pattern_p __P((const char *));
-extern char **glob_vector __P((char *, char *));
-extern char **glob_filename __P((char *));
+extern char **glob_vector __P((char *, char *, int));
+extern char **glob_filename __P((char *, int));
 
 extern char *glob_error_return;
 extern int noglob_dot_filenames;
diff --git a/lib/glob/glob_loop.c b/lib/glob/glob_loop.c
new file mode 100644 (file)
index 0000000..8010df7
--- /dev/null
@@ -0,0 +1,67 @@
+/* Copyright (C) 1991-2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+static int INTERNAL_GLOB_PATTERN_P __P((const CHAR *));
+
+/* Return nonzero if PATTERN has any special globbing chars in it.
+   Compiled twice, once each for single-byte and multibyte characters. */
+static int
+INTERNAL_GLOB_PATTERN_P (pattern)
+     const CHAR *pattern;
+{
+  register const CHAR *p;
+  register CHAR c;
+  int bopen;
+
+  p = pattern;
+  bopen = 0;
+
+  while ((c = *p++) != L('\0'))
+    switch (c)
+      {
+      case L('?'):
+      case L('*'):
+       return 1;
+
+      case L('['):      /* Only accept an open brace if there is a close */
+       bopen++;        /* brace to match it.  Bracket expressions must be */
+       continue;       /* complete, according to Posix.2 */
+      case L(']'):
+       if (bopen)
+         return 1;
+       continue;
+
+      case L('+'):         /* extended matching operators */
+      case L('@'):
+      case L('!'):
+       if (*p == L('('))  /*) */
+         return 1;
+       continue;
+
+      case L('\\'):
+       if (*p++ == L('\0'))
+         return 0;
+      }
+
+  return 0;
+}
+
+#undef INTERNAL_GLOB_PATTERN_P
+#undef L
+#undef INT
+#undef CHAR
diff --git a/lib/glob/sm_loop.c b/lib/glob/sm_loop.c
new file mode 100644 (file)
index 0000000..3760fb2
--- /dev/null
@@ -0,0 +1,737 @@
+/* Copyright (C) 1991-2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+static int FCT __P((CHAR *, CHAR *, int));
+static int GMATCH __P((CHAR *, CHAR *, CHAR *, CHAR *, int));
+static CHAR *PARSE_COLLSYM __P((CHAR *, INT *));
+static CHAR *BRACKMATCH __P((CHAR *, U_CHAR, int));
+static int EXTMATCH __P((INT, CHAR *, CHAR *, CHAR *, CHAR *, int));
+static CHAR *PATSCAN __P((CHAR *, CHAR *, INT));
+
+static int
+FCT (pattern, string, flags)
+     CHAR *pattern;
+     CHAR *string;
+     int flags;
+{
+  CHAR *se, *pe;
+
+  if (string == 0 || pattern == 0)
+    return FNM_NOMATCH;
+
+  se = string + STRLEN ((XCHAR *)string);
+  pe = pattern + STRLEN ((XCHAR *)pattern);
+
+  return (GMATCH (string, se, pattern, pe, flags));
+}
+
+/* Match STRING against the filename pattern PATTERN, returning zero if
+   it matches, FNM_NOMATCH if not.  */
+static int
+GMATCH (string, se, pattern, pe, flags)
+     CHAR *string, *se;
+     CHAR *pattern, *pe;
+     int flags;
+{
+  CHAR *p, *n;         /* pattern, string */
+  INT c;               /* current pattern character - XXX U_CHAR? */
+  INT sc;              /* current string character - XXX U_CHAR? */
+
+  p = pattern;
+  n = string;
+
+  if (string == 0 || pattern == 0)
+    return FNM_NOMATCH;
+
+#if DEBUG_MATCHING
+fprintf(stderr, "gmatch: string = %s; se = %s\n", string, se);
+fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
+#endif
+
+  while (p < pe)
+    {
+      c = *p++;
+      c = FOLD (c);
+
+      sc = n < se ? *n : '\0';
+
+#ifdef EXTENDED_GLOB
+      /* EXTMATCH () will handle recursively calling GMATCH, so we can
+        just return what EXTMATCH() returns. */
+      if ((flags & FNM_EXTMATCH) && *p == L('(') &&
+         (c == L('+') || c == L('*') || c == L('?') || c == L('@') || c == L('!'))) /* ) */
+       {
+         int lflags;
+         /* If we're not matching the start of the string, we're not
+            concerned about the special cases for matching `.' */
+         lflags = (n == string) ? flags : (flags & ~FNM_PERIOD);
+         return (EXTMATCH (c, n, se, p, pe, lflags));
+       }
+#endif /* EXTENDED_GLOB */
+
+      switch (c)
+       {
+       case L('?'):            /* Match single character */
+         if (sc == '\0')
+           return FNM_NOMATCH;
+         else if ((flags & FNM_PATHNAME) && sc == L('/'))
+           /* If we are matching a pathname, `?' can never match a `/'. */
+           return FNM_NOMATCH;
+         else if ((flags & FNM_PERIOD) && sc == L('.') &&
+                  (n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/'))))
+           /* `?' cannot match a `.' if it is the first character of the
+              string or if it is the first character following a slash and
+              we are matching a pathname. */
+           return FNM_NOMATCH;
+         break;
+
+       case L('\\'):           /* backslash escape removes special meaning */
+         if (p == pe)
+           return FNM_NOMATCH;
+
+         if ((flags & FNM_NOESCAPE) == 0)
+           {
+             c = *p++;
+             /* A trailing `\' cannot match. */
+             if (p > pe)
+               return FNM_NOMATCH;
+             c = FOLD (c);
+           }
+         if (FOLD (sc) != (U_CHAR)c)
+           return FNM_NOMATCH;
+         break;
+
+       case '*':               /* Match zero or more characters */
+         if (p == pe)
+           return 0;
+         
+         if ((flags & FNM_PERIOD) && sc == L('.') &&
+             (n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/'))))
+           /* `*' cannot match a `.' if it is the first character of the
+              string or if it is the first character following a slash and
+              we are matching a pathname. */
+           return FNM_NOMATCH;
+
+         /* Collapse multiple consecutive `*' and `?', but make sure that
+            one character of the string is consumed for each `?'. */
+         for (c = *p++; (c == L('?') || c == L('*')); c = *p++)
+           {
+             if ((flags & FNM_PATHNAME) && sc == L('/'))
+               /* A slash does not match a wildcard under FNM_PATHNAME. */
+               return FNM_NOMATCH;
+             else if (c == L('?'))
+               {
+                 if (sc == L('\0'))
+                   return FNM_NOMATCH;
+                 /* One character of the string is consumed in matching
+                    this ? wildcard, so *??? won't match if there are
+                    fewer than three characters. */
+                 n++;
+                 sc = n < se ? *n : '\0';
+               }
+
+#ifdef EXTENDED_GLOB
+             /* Handle ******(patlist) */
+             if ((flags & FNM_EXTMATCH) && c == L('*') && *p == L('('))  /*)*/
+               {
+                 CHAR *newn;
+                 /* We need to check whether or not the extended glob
+                    pattern matches the remainder of the string.
+                    If it does, we match the entire pattern. */
+                 for (newn = n; newn < se; ++newn)
+                   {
+                     if (EXTMATCH (c, newn, se, p, pe, flags) == 0)
+                       return (0);
+                   }
+                 /* We didn't match the extended glob pattern, but
+                    that's OK, since we can match 0 or more occurrences.
+                    We need to skip the glob pattern and see if we
+                    match the rest of the string. */
+                 newn = PATSCAN (p + 1, pe, 0);
+                 /* If NEWN is 0, we have an ill-formed pattern. */
+                 p = newn ? newn : pe;
+               }
+#endif
+             if (p == pe)
+               break;
+           }
+
+         /* If we've hit the end of the pattern and the last character of
+            the pattern was handled by the loop above, we've succeeded.
+            Otherwise, we need to match that last character. */
+         if (p == pe && (c == L('?') || c == L('*')))
+           return (0);
+
+         /* General case, use recursion. */
+         {
+           U_CHAR c1;
+
+           c1 = ((flags & FNM_NOESCAPE) == 0 && c == L('\\')) ? *p : c;
+           c1 = FOLD (c1);
+           for (--p; n < se; ++n)
+             {
+               /* Only call strmatch if the first character indicates a
+                  possible match.  We can check the first character if
+                  we're not doing an extended glob match. */
+               if ((flags & FNM_EXTMATCH) == 0 && c != L('[') && FOLD (*n) != c1) /*]*/
+                 continue;
+
+               /* If we're doing an extended glob match and the pattern is not
+                  one of the extended glob patterns, we can check the first
+                  character. */
+               if ((flags & FNM_EXTMATCH) && p[1] != L('(') && /*)*/
+                   STRCHR (L("?*+@!"), *p) == 0 && c != L('[') && FOLD (*n) != c1) /*]*/
+                 continue;
+
+               /* Otherwise, we just recurse. */
+               if (GMATCH (n, se, p, pe, flags & ~FNM_PERIOD) == 0)
+                 return (0);
+             }
+           return FNM_NOMATCH;
+         }
+
+       case L('['):
+         {
+           if (sc == L('\0') || n == se)
+             return FNM_NOMATCH;
+
+           /* A character class cannot match a `.' if it is the first
+              character of the string or if it is the first character
+              following a slash and we are matching a pathname. */
+           if ((flags & FNM_PERIOD) && sc == L('.') &&
+               (n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/'))))
+             return (FNM_NOMATCH);
+
+           p = BRACKMATCH (p, sc, flags);
+           if (p == 0)
+             return FNM_NOMATCH;
+         }
+         break;
+
+       default:
+         if ((U_CHAR)c != FOLD (sc))
+           return (FNM_NOMATCH);
+       }
+
+      ++n;
+    }
+
+  if (n == se)
+    return (0);
+
+  if ((flags & FNM_LEADING_DIR) && *n == L('/'))
+    /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
+    return 0;
+         
+  return (FNM_NOMATCH);
+}
+
+/* Parse a bracket expression collating symbol ([.sym.]) starting at P, find
+   the value of the symbol, and move P past the collating symbol expression.
+   The value is returned in *VP, if VP is not null. */
+static CHAR *
+PARSE_COLLSYM (p, vp)
+     CHAR *p;
+     INT *vp;
+{
+  register int pc;
+  INT val;
+
+  p++;                         /* move past the `.' */
+         
+  for (pc = 0; p[pc]; pc++)
+    if (p[pc] == L('.') && p[pc+1] == L(']'))
+      break;
+   val = COLLSYM (p, pc);
+   if (vp)
+     *vp = val;
+   return (p + pc + 2);
+}
+
+/* Use prototype definition here because of type promotion. */
+static CHAR *
+#if defined (PROTOTYPES)
+BRACKMATCH (CHAR *p, U_CHAR test, int flags)
+#else
+BRACKMATCH (p, test, flags)
+     CHAR *p;
+     U_CHAR test;
+     int flags;
+#endif
+{
+  register CHAR cstart, cend, c;
+  register int not;    /* Nonzero if the sense of the character class is inverted.  */
+  int brcnt;
+  INT pc;
+  CHAR *savep;
+
+  test = FOLD (test);
+
+  savep = p;
+
+  /* POSIX.2 3.13.1 says that an exclamation mark (`!') shall replace the
+     circumflex (`^') in its role in a `nonmatching list'.  A bracket
+     expression starting with an unquoted circumflex character produces
+     unspecified results.  This implementation treats the two identically. */
+  if (not = (*p == L('!') || *p == L('^')))
+    ++p;
+
+  c = *p++;
+  for (;;)
+    {
+      /* Initialize cstart and cend in case `-' is the last
+        character of the pattern. */
+      cstart = cend = c;
+
+      /* POSIX.2 equivalence class:  [=c=].  See POSIX.2 2.8.3.2.  Find
+        the end of the equivalence class, move the pattern pointer past
+        it, and check for equivalence.  XXX - this handles only
+        single-character equivalence classes, which is wrong, or at
+        least incomplete. */
+      if (c == L('[') && *p == L('=') && p[2] == L('=') && p[3] == L(']'))
+       {
+         pc = FOLD (p[1]);
+         p += 4;
+         if (COLLEQUIV (test, pc))
+           {
+/*[*/        /* Move past the closing `]', since the first thing we do at
+                the `matched:' label is back p up one. */
+             p++;
+             goto matched;
+           }
+         else
+           {
+             c = *p++;
+             if (c == L('\0'))
+               return ((test == L('[')) ? savep : (CHAR *)0); /*]*/
+             c = FOLD (c);
+             continue;
+           }
+       }
+
+      /* POSIX.2 character class expression.  See POSIX.2 2.8.3.2. */
+      if (c == L('[') && *p == L(':'))
+       {
+         CHAR *close, *ccname;
+
+         pc = 0;       /* make sure invalid char classes don't match. */
+         /* Find end of character class name */
+         for (close = p + 1; *close != '\0'; close++)
+           if (*close == L(':') && *(close+1) == L(']'))
+             break;
+
+         if (*close != L('\0'))
+           {
+             ccname = (CHAR *)malloc ((close - p) * sizeof (CHAR));
+             if (ccname == 0)
+               pc = 0;
+             else
+               {
+                 bcopy (p + 1, ccname, (close - p - 1) * sizeof (CHAR));
+                 *(ccname + (close - p - 1)) = L('\0');
+                 pc = IS_CCLASS (test, ccname);
+               }
+             if (pc == -1)
+               pc = 0;
+             else
+               p = close + 2;
+
+             free (ccname);
+           }
+           
+         if (pc)
+           {
+/*[*/        /* Move past the closing `]', since the first thing we do at
+                the `matched:' label is back p up one. */
+             p++;
+             goto matched;
+           }
+         else
+           {
+             /* continue the loop here, since this expression can't be
+                the first part of a range expression. */
+             c = *p++;
+             if (c == L('\0'))
+               return ((test == L('[')) ? savep : (CHAR *)0);
+             else if (c == L(']'))
+               break;
+             c = FOLD (c);
+             continue;
+           }
+       }
+      /* POSIX.2 collating symbols.  See POSIX.2 2.8.3.2.  Find the end of
+        the symbol name, make sure it is terminated by `.]', translate
+        the name to a character using the external table, and do the
+        comparison. */
+      if (c == L('[') && *p == L('.'))
+       {
+         p = PARSE_COLLSYM (p, &pc);
+         /* An invalid collating symbol cannot be the first point of a
+            range.  If it is, we set cstart to one greater than `test',
+            so any comparisons later will fail. */
+         cstart = (pc == INVALID) ? test + 1 : pc;
+       }
+
+      if (!(flags & FNM_NOESCAPE) && c == L('\\'))
+       {
+         if (*p == '\0')
+           return (CHAR *)0;
+         cstart = cend = *p++;
+       }
+
+      cstart = cend = FOLD (cstart);
+
+      /* POSIX.2 2.8.3.1.2 says: `An expression containing a `[' that
+        is not preceded by a backslash and is not part of a bracket
+        expression produces undefined results.'  This implementation
+        treats the `[' as just a character to be matched if there is
+        not a closing `]'. */
+      if (c == L('\0'))
+       return ((test == L('[')) ? savep : (CHAR *)0);
+
+      c = *p++;
+      c = FOLD (c);
+
+      if ((flags & FNM_PATHNAME) && c == L('/'))
+       /* [/] can never match when matching a pathname.  */
+       return (CHAR *)0;
+
+      /* This introduces a range, unless the `-' is the last
+        character of the class.  Find the end of the range
+        and move past it. */
+      if (c == L('-') && *p != L(']'))
+       {
+         cend = *p++;
+         if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
+           cend = *p++;
+         if (cend == L('\0'))
+           return (CHAR *)0;
+         if (cend == L('[') && *p == L('.'))
+           {
+             p = PARSE_COLLSYM (p, &pc);
+             /* An invalid collating symbol cannot be the second part of a
+                range expression.  If we get one, we set cend to one fewer
+                than the test character to make sure the range test fails. */
+             cend = (pc == INVALID) ? test - 1 : pc;
+           }
+         cend = FOLD (cend);
+
+         c = *p++;
+
+         /* POSIX.2 2.8.3.2:  ``The ending range point shall collate
+            equal to or higher than the starting range point; otherwise
+            the expression shall be treated as invalid.''  Note that this
+            applies to only the range expression; the rest of the bracket
+            expression is still checked for matches. */
+         if (RANGECMP (cstart, cend) > 0)
+           {
+             if (c == L(']'))
+               break;
+             c = FOLD (c);
+             continue;
+           }
+       }
+
+      if (RANGECMP (test, cstart) >= 0 && RANGECMP (test, cend) <= 0)
+       goto matched;
+
+      if (c == L(']'))
+       break;
+    }
+  /* No match. */
+  return (!not ? (CHAR *)0 : p);
+
+matched:
+  /* Skip the rest of the [...] that already matched.  */
+  c = *--p;
+  brcnt = 1;
+  while (brcnt > 0)
+    {
+      /* A `[' without a matching `]' is just another character to match. */
+      if (c == L('\0'))
+       return ((test == L('[')) ? savep : (CHAR *)0);
+
+      c = *p++;
+      if (c == L('[') && (*p == L('=') || *p == L(':') || *p == L('.')))
+       brcnt++;
+      else if (c == L(']'))
+       brcnt--;
+      else if (!(flags & FNM_NOESCAPE) && c == L('\\'))
+       {
+         if (*p == '\0')
+           return (CHAR *)0;
+         /* XXX 1003.2d11 is unclear if this is right. */
+         ++p;
+       }
+    }
+  return (not ? (CHAR *)0 : p);
+}
+
+#if defined (EXTENDED_GLOB)
+/* ksh-like extended pattern matching:
+
+       [?*+@!](pat-list)
+
+   where pat-list is a list of one or patterns separated by `|'.  Operation
+   is as follows:
+
+       ?(patlist)      match zero or one of the given patterns
+       *(patlist)      match zero or more of the given patterns
+       +(patlist)      match one or more of the given patterns
+       @(patlist)      match exactly one of the given patterns
+       !(patlist)      match anything except one of the given patterns
+*/
+
+/* Scan a pattern starting at STRING and ending at END, keeping track of
+   embedded () and [].  If DELIM is 0, we scan until a matching `)'
+   because we're scanning a `patlist'.  Otherwise, we scan until we see
+   DELIM.  In all cases, we never scan past END.  The return value is the
+   first character after the matching DELIM. */
+static CHAR *
+PATSCAN (string, end, delim)
+     CHAR *string, *end;
+     INT delim;
+{
+  int pnest, bnest;
+  INT cchar;
+  CHAR *s, c, *bfirst;
+
+  pnest = bnest = 0;
+  cchar = 0;
+  bfirst = NULL;
+
+  for (s = string; c = *s; s++)
+    {
+      if (s >= end)
+       return (s);
+      switch (c)
+       {
+       case L('\0'):
+         return ((CHAR *)NULL);
+
+       /* `[' is not special inside a bracket expression, but it may
+          introduce one of the special POSIX bracket expressions
+          ([.SYM.], [=c=], [: ... :]) that needs special handling. */
+       case L('['):
+         if (bnest == 0)
+           {
+             bfirst = s + 1;
+             if (*bfirst == L('!') || *bfirst == L('^'))
+               bfirst++;
+             bnest++;
+           }
+         else if (s[1] == L(':') || s[1] == L('.') || s[1] == L('='))
+           cchar = s[1];
+         break;
+
+       /* `]' is not special if it's the first char (after a leading `!'
+          or `^') in a bracket expression or if it's part of one of the
+          special POSIX bracket expressions ([.SYM.], [=c=], [: ... :]) */
+       case L(']'):
+         if (bnest)
+           {
+             if (cchar && s[-1] == cchar)
+               cchar = 0;
+             else if (s != bfirst)
+               {
+                 bnest--;
+                 bfirst = 0;
+               }
+           }
+         break;
+
+       case L('('):
+         if (bnest == 0)
+           pnest++;
+         break;
+
+       case L(')'):
+         if (bnest == 0 && pnest-- <= 0)
+           return ++s;
+         break;
+
+       case L('|'):
+         if (bnest == 0 && pnest == 0 && delim == L('|'))
+           return ++s;
+         break;
+       }
+    }
+
+  return (NULL);
+}
+
+/* Return 0 if dequoted pattern matches S in the current locale. */
+static int
+STRCOMPARE (p, pe, s, se)
+     CHAR *p, *pe, *s, *se;
+{
+  int ret;
+  CHAR c1, c2;
+
+  c1 = *pe;
+  c2 = *se;
+
+  *pe = *se = '\0';
+#if HAVE_MULTIBYTE || defined (HAVE_STRCOLL)
+  ret = STRCOLL ((XCHAR *)p, (XCHAR *)s);
+#else
+  ret = STRCMP ((XCHAR *)p, (XCHAR *)s);
+#endif
+
+  *pe = c1;
+  *se = c2;
+
+  return (ret == 0 ? ret : FNM_NOMATCH);
+}
+
+/* Match a ksh extended pattern specifier.  Return FNM_NOMATCH on failure or
+   0 on success.  This is handed the entire rest of the pattern and string
+   the first time an extended pattern specifier is encountered, so it calls
+   gmatch recursively. */
+static int
+EXTMATCH (xc, s, se, p, pe, flags)
+     INT xc;           /* select which operation */
+     CHAR *s, *se;
+     CHAR *p, *pe;
+     int flags;
+{
+  CHAR *prest;                 /* pointer to rest of pattern */
+  CHAR *psub;                  /* pointer to sub-pattern */
+  CHAR *pnext;                 /* pointer to next sub-pattern */
+  CHAR *srest;                 /* pointer to rest of string */
+  int m1, m2;
+
+#if DEBUG_MATCHING
+fprintf(stderr, "extmatch: xc = %c\n", xc);
+fprintf(stderr, "extmatch: s = %s; se = %s\n", s, se);
+fprintf(stderr, "extmatch: p = %s; pe = %s\n", p, pe);
+#endif
+
+  prest = PATSCAN (p + (*p == L('(')), pe, 0); /* ) */
+  if (prest == 0)
+    /* If PREST is 0, we failed to scan a valid pattern.  In this
+       case, we just want to compare the two as strings. */
+    return (STRCOMPARE (p - 1, pe, s, se));
+
+  switch (xc)
+    {
+    case L('+'):               /* match one or more occurrences */
+    case L('*'):               /* match zero or more occurrences */
+      /* If we can get away with no matches, don't even bother.  Just
+        call GMATCH on the rest of the pattern and return success if
+        it succeeds. */
+      if (xc == L('*') && (GMATCH (s, se, prest, pe, flags) == 0))
+       return 0;
+
+      /* OK, we have to do this the hard way.  First, we make sure one of
+        the subpatterns matches, then we try to match the rest of the
+        string. */
+      for (psub = p + 1; ; psub = pnext)
+       {
+         pnext = PATSCAN (psub, pe, L('|'));
+         for (srest = s; srest <= se; srest++)
+           {
+             /* Match this substring (S -> SREST) against this
+                subpattern (psub -> pnext - 1) */
+             m1 = GMATCH (s, srest, psub, pnext - 1, flags) == 0;
+             /* OK, we matched a subpattern, so make sure the rest of the
+                string matches the rest of the pattern.  Also handle
+                multiple matches of the pattern. */
+             if (m1)
+               m2 = (GMATCH (srest, se, prest, pe, flags) == 0) ||
+                     (s != srest && GMATCH (srest, se, p - 1, pe, flags) == 0);
+             if (m1 && m2)
+               return (0);
+           }
+         if (pnext == prest)
+           break;
+       }
+      return (FNM_NOMATCH);
+
+    case L('?'):               /* match zero or one of the patterns */
+    case L('@'):               /* match exactly one of the patterns */
+      /* If we can get away with no matches, don't even bother.  Just
+        call gmatch on the rest of the pattern and return success if
+        it succeeds. */
+      if (xc == L('?') && (GMATCH (s, se, prest, pe, flags) == 0))
+       return 0;
+
+      /* OK, we have to do this the hard way.  First, we see if one of
+        the subpatterns matches, then, if it does, we try to match the
+        rest of the string. */
+      for (psub = p + 1; ; psub = pnext)
+       {
+         pnext = PATSCAN (psub, pe, L('|'));
+         srest = (prest == pe) ? se : s;
+         for ( ; srest <= se; srest++)
+           {
+             if (GMATCH (s, srest, psub, pnext - 1, flags) == 0 &&
+                 GMATCH (srest, se, prest, pe, flags) == 0)
+               return (0);
+           }
+         if (pnext == prest)
+           break;
+       }
+      return (FNM_NOMATCH);
+
+    case '!':          /* match anything *except* one of the patterns */
+      for (srest = s; srest <= se; srest++)
+       {
+         m1 = 0;
+         for (psub = p + 1; ; psub = pnext)
+           {
+             pnext = PATSCAN (psub, pe, L('|'));
+             /* If one of the patterns matches, just bail immediately. */
+             if (m1 = (GMATCH (s, srest, psub, pnext - 1, flags) == 0))
+               break;
+             if (pnext == prest)
+               break;
+           }
+         if (m1 == 0 && GMATCH (srest, se, prest, pe, flags) == 0)
+           return (0);
+       }
+      return (FNM_NOMATCH);
+    }
+
+  return (FNM_NOMATCH);
+}
+#endif /* EXTENDED_GLOB */
+
+#undef IS_CCLASS
+#undef FOLD
+#undef CHAR
+#undef U_CHAR
+#undef XCHAR
+#undef INT
+#undef INVALID
+#undef FCT
+#undef GMATCH
+#undef COLLSYM
+#undef PARSE_COLLSYM
+#undef PATSCAN
+#undef STRCOMPARE
+#undef EXTMATCH
+#undef BRACKMATCH
+#undef STRCHR
+#undef STRCOLL
+#undef STRLEN
+#undef STRCMP
+#undef COLLEQUIV
+#undef RANGECMP
+#undef L
diff --git a/lib/glob/smatch.c b/lib/glob/smatch.c
new file mode 100644 (file)
index 0000000..8c54702
--- /dev/null
@@ -0,0 +1,410 @@
+/* strmatch.c -- ksh-like extended pattern matching for the shell and filename
+               globbing. */
+
+/* Copyright (C) 1991-2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#include <config.h>
+
+#include <stdio.h>     /* for debugging */
+                               
+#include "strmatch.h"
+#include <chartypes.h>
+
+#include "bashansi.h"
+#include "shmbutil.h"
+#include "xmalloc.h"
+
+/* First, compile `sm_loop.c' for single-byte characters. */
+#define CHAR   unsigned char
+#define U_CHAR unsigned char
+#define XCHAR  char
+#define INT    int
+#define L(CS)  CS
+#define INVALID        -1
+
+#undef STREQ
+#undef STREQN
+#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp(a, b) == 0)
+#define STREQN(a, b, n) ((a)[0] == (b)[0] && strncmp(a, b, n) == 0)
+
+/* We use strcoll(3) for range comparisons in bracket expressions,
+   even though it can have unwanted side effects in locales
+   other than POSIX or US.  For instance, in the de locale, [A-Z] matches
+   all characters. */
+
+#if defined (HAVE_STRCOLL)
+/* Helper function for collating symbol equivalence. */
+static int rangecmp (c1, c2)
+     int c1, c2;
+{
+  static char s1[2] = { ' ', '\0' };
+  static char s2[2] = { ' ', '\0' };
+  int ret;
+
+  /* Eight bits only.  Period. */
+  c1 &= 0xFF;
+  c2 &= 0xFF;
+
+  if (c1 == c2)
+    return (0);
+
+  s1[0] = c1;
+  s2[0] = c2;
+
+  if ((ret = strcoll (s1, s2)) != 0)
+    return ret;
+  return (c1 - c2);
+}
+#else /* !HAVE_STRCOLL */
+#  define rangecmp(c1, c2)     ((int)(c1) - (int)(c2))
+#endif /* !HAVE_STRCOLL */
+
+#if defined (HAVE_STRCOLL)
+static int
+collequiv (c1, c2)
+     int c1, c2;
+{
+  return (rangecmp (c1, c2) == 0);
+}
+#else
+#  define collequiv(c1, c2)    ((c1) == (c2))
+#endif
+
+#define _COLLSYM       _collsym
+#define __COLLSYM      __collsym
+#define POSIXCOLL      posix_collsyms
+#include "collsyms.h"
+
+static int
+collsym (s, len)
+     char *s;
+     int len;
+{
+  register struct _collsym *csp;
+
+  for (csp = posix_collsyms; csp->name; csp++)
+    {
+      if (STREQN(csp->name, s, len) && csp->name[len] == '\0')
+       return (csp->code);
+    }
+  if (len == 1)
+    return s[0];
+  return INVALID;
+}
+
+/* unibyte character classification */
+#if !defined (isascii) && !defined (HAVE_ISASCII)
+#  define isascii(c)   ((unsigned int)(c) <= 0177)
+#endif
+
+enum char_class
+  {
+    CC_NO_CLASS = 0,
+    CC_ASCII, CC_ALNUM, CC_ALPHA, CC_BLANK, CC_CNTRL, CC_DIGIT, CC_GRAPH,
+    CC_LOWER, CC_PRINT, CC_PUNCT, CC_SPACE, CC_UPPER, CC_WORD, CC_XDIGIT
+  };
+
+static char const *const cclass_name[] =
+  {
+    "",
+    "ascii", "alnum", "alpha", "blank", "cntrl", "digit", "graph",
+    "lower", "print", "punct", "space", "upper", "word", "xdigit"
+  };
+
+#define N_CHAR_CLASS (sizeof(cclass_name) / sizeof (cclass_name[0]))
+
+static int
+is_cclass (c, name)
+     int c;
+     const char *name;
+{
+  enum char_class char_class = CC_NO_CLASS;
+  int i, result;
+
+  for (i = 1; i < N_CHAR_CLASS; i++)
+    {
+      if (STREQ (name, cclass_name[i]))
+       {
+         char_class = (enum char_class)i;
+         break;
+       }
+    }
+
+  if (char_class == 0)
+    return -1;
+
+  switch (char_class)
+    {
+      case CC_ASCII:
+       result = isascii (c);
+       break;
+      case CC_ALNUM:
+       result = ISALNUM (c);
+       break;
+      case CC_ALPHA:
+       result = ISALPHA (c);
+       break;
+      case CC_BLANK:  
+       result = ISBLANK (c);
+       break;
+      case CC_CNTRL:
+       result = ISCNTRL (c);
+       break;
+      case CC_DIGIT:
+       result = ISDIGIT (c);
+       break;
+      case CC_GRAPH:
+       result = ISGRAPH (c);
+       break;
+      case CC_LOWER:
+       result = ISLOWER (c);
+       break;
+      case CC_PRINT: 
+       result = ISPRINT (c);
+       break;
+      case CC_PUNCT:
+       result = ISPUNCT (c);
+       break;
+      case CC_SPACE:
+       result = ISSPACE (c);
+       break;
+      case CC_UPPER:
+       result = ISUPPER (c);
+       break;
+      case CC_WORD:
+        result = (ISALNUM (c) || c == '_');
+       break;
+      case CC_XDIGIT:
+       result = ISXDIGIT (c);
+       break;
+      default:
+       result = -1;
+       break;
+    }
+
+  return result;  
+}
+
+/* Now include `sm_loop.c' for single-byte characters. */
+/* The result of FOLD is an `unsigned char' */
+# define FOLD(c) ((flags & FNM_CASEFOLD) \
+       ? TOLOWER ((unsigned char)c) \
+       : ((unsigned char)c))
+
+#define FCT                    internal_strmatch
+#define GMATCH                 gmatch
+#define COLLSYM                        collsym
+#define PARSE_COLLSYM          parse_collsym
+#define BRACKMATCH             brackmatch
+#define PATSCAN                        patscan
+#define STRCOMPARE             strcompare
+#define EXTMATCH               extmatch
+#define STRCHR(S, C)           strchr((S), (C))
+#define STRCOLL(S1, S2)                strcoll((S1), (S2))
+#define STRLEN(S)              strlen(S)
+#define STRCMP(S1, S2)         strcmp((S1), (S2))
+#define RANGECMP(C1, C2)       rangecmp((C1), (C2))
+#define COLLEQUIV(C1, C2)      collequiv((C1), (C2))
+#define CTYPE_T                        enum char_class
+#define IS_CCLASS(C, S)                is_cclass((C), (S))
+#include "sm_loop.c"
+
+#if HANDLE_MULTIBYTE
+
+#  define CHAR         wchar_t
+#  define U_CHAR       wint_t
+#  define XCHAR                wchar_t
+#  define INT          wint_t
+#  define L(CS)                L##CS
+#  define INVALID      WEOF
+
+#  undef STREQ
+#  undef STREQN
+#  define STREQ(s1, s2) ((wcscmp (s1, s2) == 0))
+#  define STREQN(a, b, n) ((a)[0] == (b)[0] && wcsncmp(a, b, n) == 0)
+
+static int
+rangecmp_wc (c1, c2)
+     wint_t c1, c2;
+{
+  static wchar_t s1[2] = { L' ', L'\0' };
+  static wchar_t s2[2] = { L' ', L'\0' };
+  int ret;
+
+  if (c1 == c2)
+    return 0;
+
+  s1[0] = c1;
+  s2[0] = c2;
+
+  return (wcscoll (s1, s2));
+}
+
+static int
+collequiv_wc (c, equiv)
+     wint_t c, equiv;
+{
+  return (!(c - equiv));
+}
+
+/* Helper function for collating symbol. */
+#  define _COLLSYM     _collwcsym
+#  define __COLLSYM    __collwcsym
+#  define POSIXCOLL    posix_collwcsyms
+#  include "collsyms.h"
+
+static wint_t
+collwcsym (s, len)
+     wchar_t *s;
+     int len;
+{
+  register struct _collwcsym *csp;
+
+  for (csp = posix_collwcsyms; csp->name; csp++)
+    {
+      if (STREQN(csp->name, s, len) && csp->name[len] == L'\0')
+       return (csp->code);
+    }
+  if (len == 1)
+    return s[0];
+  return INVALID;
+}
+
+static int
+is_wcclass (wc, name)
+     wint_t wc;
+     wchar_t *name;
+{
+  char *mbs;
+  mbstate_t state;
+  size_t mbslength;
+  wctype_t desc;
+  int want_word;
+
+  if ((wctype ("ascii") == (wctype_t)0) && (wcscmp (name, L"ascii") == 0))
+    {
+      int c;
+
+      if ((c = wctob (wc)) == EOF)
+       return 0;
+      else
+        return (c <= 0x7F);
+    }
+
+  want_word = (wcscmp (name, L"word") == 0);
+  if (want_word)
+    name = L"alnum";
+
+  memset (&state, '\0', sizeof (mbstate_t));
+  mbs = (char *) malloc (wcslen(name) * MB_CUR_MAX + 1);
+  mbslength = wcsrtombs(mbs, (const wchar_t **)&name, (wcslen(name) * MB_CUR_MAX + 1), &state);
+
+  if (mbslength == (size_t)-1 || mbslength == (size_t)-2)
+    {
+      free (mbs);
+      return -1;
+    }
+  desc = wctype (mbs);
+  free (mbs);
+
+  if (desc == (wctype_t)0)
+    return -1;
+
+  if (want_word)
+    return (iswctype (wc, desc) || wc == L'_');
+  else
+    return (iswctype (wc, desc));
+}
+
+/* Now include `sm_loop.c' for multibyte characters. */
+#define FOLD(c) ((flags & FNM_CASEFOLD) && iswupper (c) ? towlower (c) : (c))
+#define FCT                    internal_wstrmatch
+#define GMATCH                 gmatch_wc
+#define COLLSYM                        collwcsym
+#define PARSE_COLLSYM          parse_collwcsym
+#define BRACKMATCH             brackmatch_wc
+#define PATSCAN                        patscan_wc
+#define STRCOMPARE             wscompare
+#define EXTMATCH               extmatch_wc
+#define STRCHR(S, C)           wcschr((S), (C))
+#define STRCOLL(S1, S2)                wcscoll((S1), (S2))
+#define STRLEN(S)              wcslen(S)
+#define STRCMP(S1, S2)         wcscmp((S1), (S2))
+#define RANGECMP(C1, C2)       rangecmp_wc((C1), (C2))
+#define COLLEQUIV(C1, C2)      collequiv_wc((C1), (C2))
+#define CTYPE_T                        enum char_class
+#define IS_CCLASS(C, S)                is_wcclass((C), (S))
+#include "sm_loop.c"
+
+#endif /* HAVE_MULTIBYTE */
+
+int
+xstrmatch (pattern, string, flags)
+     char *pattern;
+     char *string;
+     int flags;
+{
+#if HANDLE_MULTIBYTE
+  int ret;
+  mbstate_t ps;
+  size_t n;
+  char *pattern_bak;
+  wchar_t *wpattern, *wstring;
+
+  if (MB_CUR_MAX == 1)
+    return (internal_strmatch (pattern, string, flags));
+
+  pattern_bak = (char *)xmalloc (strlen (pattern) + 1);
+  strcpy (pattern_bak, pattern);
+
+  memset (&ps, '\0', sizeof (mbstate_t));
+  n = xmbsrtowcs (NULL, (const char **)&pattern, 0, &ps);
+  if (n == (size_t)-1 || n == (size_t)-2)
+    {
+      free (pattern_bak);
+      return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
+    }
+
+  wpattern = (wchar_t *)xmalloc ((n + 1) * sizeof (wchar_t));
+  (void) xmbsrtowcs (wpattern, (const char **)&pattern, n + 1, &ps);
+
+  memset (&ps, '\0', sizeof (mbstate_t));
+  n = xmbsrtowcs (NULL, (const char **)&string, 0, &ps);
+  if (n == (size_t)-1 || n == (size_t)-2)
+    {
+      free (wpattern);
+      ret = internal_strmatch (pattern_bak, string, flags);
+      free (pattern_bak);
+      return ret;
+    }
+
+  wstring = (wchar_t *)xmalloc ((n + 1) * sizeof (wchar_t));
+  (void) xmbsrtowcs (wstring, (const char **)&string, n + 1, &ps);
+
+  ret = internal_wstrmatch (wpattern, wstring, flags);
+
+  free (pattern_bak);
+  free (wpattern);
+  free (wstring);
+
+  return ret;
+#else
+  return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
+#endif /* !HANDLE_MULTIBYTE */
+}
index c0645ad09db8e517b1267d4bfbd1f4985ce248f4..b72fb7dbc245f31a49c5b38c573bbc45aae80361 100644 (file)
@@ -1,7 +1,7 @@
 /* strmatch.c -- ksh-like extended pattern matching for the shell and filename
                globbing. */
 
-/* Copyright (C) 1991, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
    
 
 #include <config.h>
 
-#include <stdio.h>     /* for debugging */
-                               
+#include "stdc.h"
 #include "strmatch.h"
-#include "collsyms.h"
-#include <chartypes.h>
 
-#if defined (HAVE_STRING_H)
-#  include <string.h>
-#else
-#  include <strings.h>
-#endif /* HAVE_STRING_H */
-
-static int gmatch ();
-static char *brackmatch ();
-#ifdef EXTENDED_GLOB
-static int extmatch ();
-static char *patscan ();
-#endif
-  
-#if !defined (isascii) && !defined (HAVE_ISASCII)
-#  define isascii(c)   ((unsigned int)(c) <= 0177)
-#endif
-
-/* The result of FOLD is an `unsigned char' */
-# define FOLD(c) ((flags & FNM_CASEFOLD) \
-       ? TOLOWER ((unsigned char)c) \
-       : ((unsigned char)c))
-
-#ifndef STREQ
-#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp(a, b) == 0)
-#define STREQN(a, b, n) ((a)[0] == (b)[0] && strncmp(a, b, n) == 0)
-#endif
-
-/* We use strcoll(3) for range comparisons in bracket expressions,
-   even though it can have unwanted side effects in locales
-   other than POSIX or US.  For instance, in the de locale, [A-Z] matches
-   all characters. */
-
-#if defined (HAVE_STRCOLL)
-/* Helper function for collating symbol equivalence. */
-static int rangecmp (c1, c2)
-     int c1, c2;
-{
-  static char s1[2] = { ' ', '\0' };
-  static char s2[2] = { ' ', '\0' };
-  int ret;
+/* Structured this way so that if HAVE_LIBC_FNM_EXTMATCH is defined, the
+   matching portion of the library (smatch.c) is not linked into the shell. */
 
-  /* Eight bits only.  Period. */
-  c1 &= 0xFF;
-  c2 &= 0xFF;
-
-  if (c1 == c2)
-    return (0);
-
-  s1[0] = c1;
-  s2[0] = c2;
-
-  if ((ret = strcoll (s1, s2)) != 0)
-    return ret;
-  return (c1 - c2);
-}
-#else /* !HAVE_STRCOLL */
-#  define rangecmp(c1, c2)     ((int)(c1) - (int)(c2))
-#endif /* !HAVE_STRCOLL */
-
-#if defined (HAVE_STRCOLL)
-static int collequiv (c1, c2)
-     int c1, c2;
-{
-  return (rangecmp (c1, c2) == 0);
-}
+#ifndef HAVE_LIBC_FNM_EXTMATCH
+extern int xstrmatch __P((char *, char *, int));
 #else
-#  define collequiv(c1, c2)    ((c1) == (c2))
+#  define xstrmatch fnmatch
 #endif
 
-static int
-collsym (s, len)
-     char *s;
-     int len;
-{
-  register struct _collsym *csp;
-
-  for (csp = posix_collsyms; csp->name; csp++)
-    {
-      if (STREQN(csp->name, s, len) && csp->name[len] == '\0')
-       return (csp->code);
-    }
-  if (len == 1)
-    return s[0];
-  return -1;
-}
-
-#ifdef HAVE_LIBC_FNM_EXTMATCH
-int
-strmatch (pattern, string, flags)
-     char *pattern;
-     char *string;
-     int flags;
-{
-  char *se, *pe;
-
-  if (string == 0 || pattern == 0)
-    return FNM_NOMATCH;
-
-  return (fnmatch (pattern, string, flags));
-}
-#else /* !HAVE_LIBC_FNM_EXTMATCH */
 int
 strmatch (pattern, string, flags)
      char *pattern;
      char *string;
      int flags;
 {
-  char *se, *pe;
-
   if (string == 0 || pattern == 0)
     return FNM_NOMATCH;
 
-  se = string + strlen (string);
-  pe = pattern + strlen (pattern);
-
-  return (gmatch (string, se, pattern, pe, flags));
-}
-#endif /* !HAVE_LIBC_FNM_EXTMATCH */
-
-/* Match STRING against the filename pattern PATTERN, returning zero if
-   it matches, FNM_NOMATCH if not.  */
-static int
-gmatch (string, se, pattern, pe, flags)
-     char *string, *se;
-     char *pattern, *pe;
-     int flags;
-{
-  register char *p, *n;                /* pattern, string */
-  register char c;             /* current pattern character */
-  register char sc;            /* current string character */
-
-  p = pattern;
-  n = string;
-
-  if (string == 0 || pattern == 0)
-    return FNM_NOMATCH;
-
-#if DEBUG_MATCHING
-fprintf(stderr, "gmatch: string = %s; se = %s\n", string, se);
-fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
-#endif
-
-  while (p < pe)
-    {
-      c = *p++;
-      c = FOLD (c);
-
-      sc = n < se ? *n : '\0';
-
-#ifdef EXTENDED_GLOB
-      /* extmatch () will handle recursively calling gmatch, so we can
-        just return what extmatch() returns. */
-      if ((flags & FNM_EXTMATCH) && *p == '(' &&
-         (c == '+' || c == '*' || c == '?' || c == '@' || c == '!')) /* ) */
-       {
-         int lflags;
-         /* If we're not matching the start of the string, we're not
-            concerned about the special cases for matching `.' */
-         lflags = (n == string) ? flags : (flags & ~FNM_PERIOD);
-         return (extmatch (c, n, se, p, pe, lflags));
-       }
-#endif
-
-      switch (c)
-       {
-       case '?':               /* Match single character */
-         if (sc == '\0')
-           return FNM_NOMATCH;
-         else if ((flags & FNM_PATHNAME) && sc == '/')
-           /* If we are matching a pathname, `?' can never match a `/'. */
-           return FNM_NOMATCH;
-         else if ((flags & FNM_PERIOD) && sc == '.' &&
-                  (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
-           /* `?' cannot match a `.' if it is the first character of the
-              string or if it is the first character following a slash and
-              we are matching a pathname. */
-           return FNM_NOMATCH;
-         break;
-
-       case '\\':              /* backslash escape removes special meaning */
-         if (p == pe)
-           return FNM_NOMATCH;
-
-         if ((flags & FNM_NOESCAPE) == 0)
-           {
-             c = *p++;
-             /* A trailing `\' cannot match. */
-             if (p > pe)
-               return FNM_NOMATCH;
-             c = FOLD (c);
-           }
-         if (FOLD (sc) != (unsigned char)c)
-           return FNM_NOMATCH;
-         break;
-
-       case '*':               /* Match zero or more characters */
-         if (p == pe)
-           return 0;
-         
-         if ((flags & FNM_PERIOD) && sc == '.' &&
-             (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
-           /* `*' cannot match a `.' if it is the first character of the
-              string or if it is the first character following a slash and
-              we are matching a pathname. */
-           return FNM_NOMATCH;
-
-         /* Collapse multiple consecutive `*' and `?', but make sure that
-            one character of the string is consumed for each `?'. */
-         for (c = *p++; (c == '?' || c == '*'); c = *p++)
-           {
-             if ((flags & FNM_PATHNAME) && sc == '/')
-               /* A slash does not match a wildcard under FNM_PATHNAME. */
-               return FNM_NOMATCH;
-             else if (c == '?')
-               {
-                 if (sc == '\0')
-                   return FNM_NOMATCH;
-                 /* One character of the string is consumed in matching
-                    this ? wildcard, so *??? won't match if there are
-                    fewer than three characters. */
-                 n++;
-                 sc = n < se ? *n : '\0';
-               }
-
-#ifdef EXTENDED_GLOB
-             /* Handle ******(patlist) */
-             if ((flags & FNM_EXTMATCH) && c == '*' && *p == '(')  /*)*/
-               {
-                 char *newn;
-                 /* We need to check whether or not the extended glob
-                    pattern matches the remainder of the string.
-                    If it does, we match the entire pattern. */
-                 for (newn = n; newn < se; ++newn)
-                   {
-                     if (extmatch (c, newn, se, p, pe, flags) == 0)
-                       return (0);
-                   }
-                 /* We didn't match the extended glob pattern, but
-                    that's OK, since we can match 0 or more occurrences.
-                    We need to skip the glob pattern and see if we
-                    match the rest of the string. */
-                 newn = patscan (p + 1, pe, 0);
-                 /* If NEWN is 0, we have an ill-formed pattern. */
-                 p = newn ? newn : pe;
-               }
-#endif
-             if (p == pe)
-               break;
-           }
-
-         /* If we've hit the end of the pattern and the last character of
-            the pattern was handled by the loop above, we've succeeded.
-            Otherwise, we need to match that last character. */
-         if (p == pe && (c == '?' || c == '*'))
-           return (0);
-
-         /* General case, use recursion. */
-         {
-           unsigned char c1;
-
-           c1 = (unsigned char)((flags & FNM_NOESCAPE) == 0 && c == '\\') ? *p : c;
-           c1 = FOLD (c1);
-           for (--p; n < se; ++n)
-             {
-               /* Only call strmatch if the first character indicates a
-                  possible match.  We can check the first character if
-                  we're not doing an extended glob match. */
-               if ((flags & FNM_EXTMATCH) == 0 && c != '[' && FOLD (*n) != c1) /*]*/
-                 continue;
-
-               /* If we're doing an extended glob match and the pattern is not
-                  one of the extended glob patterns, we can check the first
-                  character. */
-               if ((flags & FNM_EXTMATCH) && p[1] != '(' && /*)*/
-                   strchr ("?*+@!", *p) == 0 && c != '[' && FOLD (*n) != c1) /*]*/
-                 continue;
-
-               /* Otherwise, we just recurse. */
-               if (gmatch (n, se, p, pe, flags & ~FNM_PERIOD) == 0)
-                 return (0);
-             }
-           return FNM_NOMATCH;
-         }
-
-       case '[':
-         {
-           if (sc == '\0' || n == se)
-             return FNM_NOMATCH;
-
-           /* A character class cannot match a `.' if it is the first
-              character of the string or if it is the first character
-              following a slash and we are matching a pathname. */
-           if ((flags & FNM_PERIOD) && sc == '.' &&
-               (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
-             return (FNM_NOMATCH);
-
-           p = brackmatch (p, sc, flags);
-           if (p == 0)
-             return FNM_NOMATCH;
-         }
-         break;
-
-       default:
-         if ((unsigned char)c != FOLD (sc))
-           return (FNM_NOMATCH);
-       }
-
-      ++n;
-    }
-
-  if (n == se)
-    return (0);
-
-  if ((flags & FNM_LEADING_DIR) && *n == '/')
-    /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
-    return 0;
-         
-  return (FNM_NOMATCH);
-}
-
-/* Parse a bracket expression collating symbol ([.sym.]) starting at P, find
-   the value of the symbol, and move P past the collating symbol expression.
-   The value is returned in *VP, if VP is not null. */
-static char *
-parse_collsym (p, vp)
-     char *p;
-     int *vp;
-{
-  register int pc;
-  int val;
-
-  p++;                         /* move past the `.' */
-         
-  for (pc = 0; p[pc]; pc++)
-    if (p[pc] == '.' && p[pc+1] == ']')
-      break;
-   val = collsym (p, pc);
-   if (vp)
-     *vp = val;
-   return (p + pc + 2);
-}
-
-static char *
-brackmatch (p, test, flags)
-     char *p;
-     unsigned char test;
-     int flags;
-{
-  register char cstart, cend, c;
-  register int not;    /* Nonzero if the sense of the character class is inverted.  */
-  int pc, brcnt;
-  char *savep;
-
-  test = FOLD (test);
-
-  savep = p;
-
-  /* POSIX.2 3.13.1 says that an exclamation mark (`!') shall replace the
-     circumflex (`^') in its role in a `nonmatching list'.  A bracket
-     expression starting with an unquoted circumflex character produces
-     unspecified results.  This implementation treats the two identically. */
-  if (not = (*p == '!' || *p == '^'))
-    ++p;
-
-  c = *p++;
-  for (;;)
-    {
-      /* Initialize cstart and cend in case `-' is the last
-        character of the pattern. */
-      cstart = cend = c;
-
-      /* POSIX.2 equivalence class:  [=c=].  See POSIX.2 2.8.3.2.  Find
-        the end of the equivalence class, move the pattern pointer past
-        it, and check for equivalence.  XXX - this handles only
-        single-character equivalence classes, which is wrong, or at
-        least incomplete. */
-      if (c == '[' && *p == '=' && p[2] == '=' && p[3] == ']')
-       {
-         pc = FOLD (p[1]);
-         p += 4;
-         if (collequiv (test, pc))
-           {
-/*[*/        /* Move past the closing `]', since the first thing we do at
-                the `matched:' label is back p up one. */
-             p++;
-             goto matched;
-           }
-         else
-           {
-             c = *p++;
-             if (c == '\0')
-               return ((test == '[') ? savep : (char *)0); /*]*/
-             c = FOLD (c);
-             continue;
-           }
-       }
-
-      /* POSIX.2 character class expression.  See POSIX.2 2.8.3.2. */
-      if (c == '[' && *p == ':')       /*]*/
-       {
-         pc = 0;       /* make sure invalid char classes don't match. */
-         if (STREQN (p+1, "alnum:]", 7))
-           { pc = ISALNUM (test); p += 8; }
-         else if (STREQN (p+1, "alpha:]", 7))
-           { pc = ISALPHA (test); p += 8; }
-         else if (STREQN (p+1, "blank:]", 7))
-           { pc = ISBLANK (test); p += 8; }
-         else if (STREQN (p+1, "cntrl:]", 7))
-           { pc = ISCNTRL (test); p += 8; }
-         else if (STREQN (p+1, "digit:]", 7))
-           { pc = ISDIGIT (test); p += 8; }
-         else if (STREQN (p+1, "graph:]", 7))
-           { pc = ISGRAPH (test); p += 8; }
-         else if (STREQN (p+1, "lower:]", 7))
-           { pc = ISLOWER (test); p += 8; }
-         else if (STREQN (p+1, "print:]", 7))
-           { pc = ISPRINT (test); p += 8; }
-         else if (STREQN (p+1, "punct:]", 7))
-           { pc = ISPUNCT (test); p += 8; }
-         else if (STREQN (p+1, "space:]", 7))
-           { pc = ISSPACE (test); p += 8; }
-         else if (STREQN (p+1, "upper:]", 7))
-           { pc = ISUPPER (test); p += 8; }
-         else if (STREQN (p+1, "xdigit:]", 8))
-           { pc = ISXDIGIT (test); p += 9; }
-         else if (STREQN (p+1, "ascii:]", 7))
-           { pc = isascii (test); p += 8; }
-         if (pc)
-           {
-/*[*/        /* Move past the closing `]', since the first thing we do at
-                the `matched:' label is back p up one. */
-             p++;
-             goto matched;
-           }
-         else
-           {
-             /* continue the loop here, since this expression can't be
-                the first part of a range expression. */
-             c = *p++;
-             if (c == '\0')
-               return ((test == '[') ? savep : (char *)0);
-             else if (c == ']')
-               break;
-             c = FOLD (c);
-             continue;
-           }
-       }
-      /* POSIX.2 collating symbols.  See POSIX.2 2.8.3.2.  Find the end of
-        the symbol name, make sure it is terminated by `.]', translate
-        the name to a character using the external table, and do the
-        comparison. */
-      if (c == '[' && *p == '.')
-       {
-         p = parse_collsym (p, &pc);
-         /* An invalid collating symbol cannot be the first point of a
-            range.  If it is, we set cstart to one greater than `test',
-            so any comparisons later will fail. */
-         cstart = (pc == -1) ? test + 1 : pc;
-       }
-
-      if (!(flags & FNM_NOESCAPE) && c == '\\')
-       {
-         if (*p == '\0')
-           return (char *)0;
-         cstart = cend = *p++;
-       }
-
-      cstart = cend = FOLD (cstart);
-
-      /* POSIX.2 2.8.3.1.2 says: `An expression containing a `[' that
-        is not preceded by a backslash and is not part of a bracket
-        expression produces undefined results.'  This implementation
-        treats the `[' as just a character to be matched if there is
-        not a closing `]'. */
-      if (c == '\0')
-       return ((test == '[') ? savep : (char *)0);
-
-      c = *p++;
-      c = FOLD (c);
-
-      if ((flags & FNM_PATHNAME) && c == '/')
-       /* [/] can never match when matching a pathname.  */
-       return (char *)0;
-
-      /* This introduces a range, unless the `-' is the last
-        character of the class.  Find the end of the range
-        and move past it. */
-      if (c == '-' && *p != ']')
-       {
-         cend = *p++;
-         if (!(flags & FNM_NOESCAPE) && cend == '\\')
-           cend = *p++;
-         if (cend == '\0')
-           return (char *)0;
-         if (cend == '[' && *p == '.')
-           {
-             p = parse_collsym (p, &pc);
-             /* An invalid collating symbol cannot be the second part of a
-                range expression.  If we get one, we set cend to one fewer
-                than the test character to make sure the range test fails. */
-             cend = (pc == -1) ? test - 1 : pc;
-           }
-         cend = FOLD (cend);
-
-         c = *p++;
-
-         /* POSIX.2 2.8.3.2:  ``The ending range point shall collate
-            equal to or higher than the starting range point; otherwise
-            the expression shall be treated as invalid.''  Note that this
-            applies to only the range expression; the rest of the bracket
-            expression is still checked for matches. */
-         if (rangecmp (cstart, cend) > 0)
-           {
-             if (c == ']')
-               break;
-             c = FOLD (c);
-             continue;
-           }
-       }
-
-      if (rangecmp (test, cstart) >= 0 && rangecmp (test, cend) <= 0)
-       goto matched;
-
-      if (c == ']')
-       break;
-    }
-  /* No match. */
-  return (!not ? (char *)0 : p);
-
-matched:
-  /* Skip the rest of the [...] that already matched.  */
-#if 0
-  brcnt = (c != ']') + (c == '[' && (*p == '=' || *p == ':' || *p == '.'));
-#else
-  c = *--p;
-  brcnt = 1;
-#endif
-  while (brcnt > 0)
-    {
-      /* A `[' without a matching `]' is just another character to match. */
-      if (c == '\0')
-       return ((test == '[') ? savep : (char *)0);
-
-      c = *p++;
-      if (c == '[' && (*p == '=' || *p == ':' || *p == '.'))
-       brcnt++;
-      else if (c == ']')
-       brcnt--;
-      else if (!(flags & FNM_NOESCAPE) && c == '\\')
-       {
-         if (*p == '\0')
-           return (char *)0;
-         /* XXX 1003.2d11 is unclear if this is right. */
-         ++p;
-       }
-    }
-  return (not ? (char *)0 : p);
-}
-
-#if defined (EXTENDED_GLOB)
-/* ksh-like extended pattern matching:
-
-       [?*+@!](pat-list)
-
-   where pat-list is a list of one or patterns separated by `|'.  Operation
-   is as follows:
-
-       ?(patlist)      match zero or one of the given patterns
-       *(patlist)      match zero or more of the given patterns
-       +(patlist)      match one or more of the given patterns
-       @(patlist)      match exactly one of the given patterns
-       !(patlist)      match anything except one of the given patterns
-*/
-
-/* Scan a pattern starting at STRING and ending at END, keeping track of
-   embedded () and [].  If DELIM is 0, we scan until a matching `)'
-   because we're scanning a `patlist'.  Otherwise, we scan until we see
-   DELIM.  In all cases, we never scan past END.  The return value is the
-   first character after the matching DELIM. */
-static char *
-patscan (string, end, delim)
-     char *string, *end;
-     int delim;
-{
-  int pnest, bnest, cchar;
-  char *s, c, *bfirst;
-
-  pnest = bnest = cchar = 0;
-  bfirst = 0;
-  for (s = string; c = *s; s++)
-    {
-      if (s >= end)
-       return (s);
-      switch (c)
-       {
-       case '\0':
-         return ((char *)0);
-
-       /* `[' is not special inside a bracket expression, but it may
-          introduce one of the special POSIX bracket expressions
-          ([.SYM.], [=c=], [: ... :]) that needs special handling. */
-       case '[':
-         if (bnest == 0)
-           {
-             bfirst = s + 1;
-             if (*bfirst == '!' || *bfirst == '^')
-               bfirst++;
-             bnest++;
-           }
-         else if (s[1] == ':' || s[1] == '.' || s[1] == '=')
-           cchar = s[1];
-         break;
-
-       /* `]' is not special if it's the first char (after a leading `!'
-          or `^') in a bracket expression or if it's part of one of the
-          special POSIX bracket expressions ([.SYM.], [=c=], [: ... :]) */
-       case ']':
-         if (bnest)
-           {
-             if (cchar && s[-1] == cchar)
-               cchar = 0;
-             else if (s != bfirst)
-               {
-                 bnest--;
-                 bfirst = 0;
-               }
-           }
-         break;
-
-       case '(':
-         if (bnest == 0)
-           pnest++;
-         break;
-
-       case ')':
-#if 0
-         if (bnest == 0)
-           pnest--;
-         if (pnest <= 0)
-           return ++s;
-#else
-         if (bnest == 0 && pnest-- <= 0)
-           return ++s;
-#endif
-         break;
-
-       case '|':
-         if (bnest == 0 && pnest == 0 && delim == '|')
-           return ++s;
-         break;
-       }
-    }
-
-  return (char *)0;
-}
-
-/* Return 0 if dequoted pattern matches S in the current locale. */
-static int
-strcompare (p, pe, s, se)
-     char *p, *pe, *s, *se;
-{
-  int ret;
-  char c1, c2;
-
-  c1 = *pe;
-  c2 = *se;
-
-  *pe = *se = '\0';
-#if defined (HAVE_STRCOLL)
-  ret = strcoll (p, s);
-#else
-  ret = strcmp (p, s);
-#endif
-
-  *pe = c1;
-  *se = c2;
-
-  return (ret == 0 ? ret : FNM_NOMATCH);
-}
-
-/* Match a ksh extended pattern specifier.  Return FNM_NOMATCH on failure or
-   0 on success.  This is handed the entire rest of the pattern and string
-   the first time an extended pattern specifier is encountered, so it calls
-   gmatch recursively. */
-static int
-extmatch (xc, s, se, p, pe, flags)
-     int xc;           /* select which operation */
-     char *s, *se;
-     char *p, *pe;
-     int flags;
-{
-  char *prest;                 /* pointer to rest of pattern */
-  char *psub;                  /* pointer to sub-pattern */
-  char *pnext;                 /* pointer to next sub-pattern */
-  char *srest;                 /* pointer to rest of string */
-  int m1, m2;
-
-#if DEBUG_MATCHING
-fprintf(stderr, "extmatch: xc = %c\n", xc);
-fprintf(stderr, "extmatch: s = %s; se = %s\n", s, se);
-fprintf(stderr, "extmatch: p = %s; pe = %s\n", p, pe);
-#endif
-
-  prest = patscan (p + (*p == '('), pe, 0); /* ) */
-  if (prest == 0)
-    /* If PREST is 0, we failed to scan a valid pattern.  In this
-       case, we just want to compare the two as strings. */
-    return (strcompare (p - 1, pe, s, se));
-
-  switch (xc)
-    {
-    case '+':                  /* match one or more occurrences */
-    case '*':                  /* match zero or more occurrences */
-      /* If we can get away with no matches, don't even bother.  Just
-        call gmatch on the rest of the pattern and return success if
-        it succeeds. */
-      if (xc == '*' && (gmatch (s, se, prest, pe, flags) == 0))
-       return 0;
-
-      /* OK, we have to do this the hard way.  First, we make sure one of
-        the subpatterns matches, then we try to match the rest of the
-        string. */
-      for (psub = p + 1; ; psub = pnext)
-       {
-         pnext = patscan (psub, pe, '|');
-         for (srest = s; srest <= se; srest++)
-           {
-             /* Match this substring (S -> SREST) against this
-                subpattern (psub -> pnext - 1) */
-             m1 = gmatch (s, srest, psub, pnext - 1, flags) == 0;
-             /* OK, we matched a subpattern, so make sure the rest of the
-                string matches the rest of the pattern.  Also handle
-                multiple matches of the pattern. */
-             if (m1)
-               m2 = (gmatch (srest, se, prest, pe, flags) == 0) ||
-                     (s != srest && gmatch (srest, se, p - 1, pe, flags) == 0);
-             if (m1 && m2)
-               return (0);
-           }
-         if (pnext == prest)
-           break;
-       }
-      return (FNM_NOMATCH);
-
-    case '?':          /* match zero or one of the patterns */
-    case '@':          /* match exactly one of the patterns */
-      /* If we can get away with no matches, don't even bother.  Just
-        call gmatch on the rest of the pattern and return success if
-        it succeeds. */
-      if (xc == '?' && (gmatch (s, se, prest, pe, flags) == 0))
-       return 0;
-
-      /* OK, we have to do this the hard way.  First, we see if one of
-        the subpatterns matches, then, if it does, we try to match the
-        rest of the string. */
-      for (psub = p + 1; ; psub = pnext)
-       {
-         pnext = patscan (psub, pe, '|');
-         srest = (prest == pe) ? se : s;
-         for ( ; srest <= se; srest++)
-           {
-             if (gmatch (s, srest, psub, pnext - 1, flags) == 0 &&
-                 gmatch (srest, se, prest, pe, flags) == 0)
-               return (0);
-           }
-         if (pnext == prest)
-           break;
-       }
-      return (FNM_NOMATCH);
-
-    case '!':          /* match anything *except* one of the patterns */
-      for (srest = s; srest <= se; srest++)
-       {
-         m1 = 0;
-         for (psub = p + 1; ; psub = pnext)
-           {
-             pnext = patscan (psub, pe, '|');
-             /* If one of the patterns matches, just bail immediately. */
-             if (m1 = (gmatch (s, srest, psub, pnext - 1, flags) == 0))
-               break;
-             if (pnext == prest)
-               break;
-           }
-         if (m1 == 0 && gmatch (srest, se, prest, pe, flags) == 0)
-           return (0);
-       }
-      return (FNM_NOMATCH);
-    }
-
-  return (FNM_NOMATCH);
+  return (xstrmatch (pattern, string, flags));
 }
-#endif /* EXTENDED_GLOB */
 
 #ifdef TEST
 main (c, v)
diff --git a/lib/glob/xmbsrtowcs.c b/lib/glob/xmbsrtowcs.c
new file mode 100644 (file)
index 0000000..abd2093
--- /dev/null
@@ -0,0 +1,116 @@
+/* xmbsrtowcs.c -- replacement function for mbsrtowcs */
+
+/* Copyright (C) 2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#include <config.h>
+
+#include <bashansi.h>
+
+/* <wchar.h>, <wctype.h> and <stdlib.h> are included in "shmbutil.h".
+   If <wchar.h>, <wctype.h>, mbsrtowcs(), exist, HANDLE_MULTIBYTE
+   is defined as 1. */
+#include <shmbutil.h>
+
+#if HANDLE_MULTIBYTE
+/* On some locales (ex. ja_JP.sjis), mbsrtowc doesn't convert 0x5c to U<0x5c>.
+   So, this function is made for converting 0x5c to U<0x5c>. */
+
+static mbstate_t local_state;
+static int local_state_use = 0;
+
+size_t
+xmbsrtowcs (dest, src, len, pstate)
+    wchar_t *dest;
+    const char **src;
+    size_t len;
+    mbstate_t *pstate;
+{
+  mbstate_t *ps;
+  size_t mblength, wclength, n;
+
+  ps = pstate;
+  if (pstate == NULL)
+    {
+      if (!local_state_use)
+       {
+         memset (&local_state, '\0', sizeof(mbstate_t));
+         local_state_use = 1;
+       }
+      ps = &local_state;
+    }
+
+  n = strlen(*src) + 1;
+
+  if (dest == NULL)
+    {
+      wchar_t *wsbuf;
+      char *mbsbuf, *mbsbuf_top;
+      mbstate_t psbuf;
+
+      wsbuf = (wchar_t *) malloc ((n + 1) * sizeof(wchar_t));
+      mbsbuf_top = mbsbuf = (char *) malloc (n + 1);
+      memcpy(mbsbuf, *src, n + 1);
+      psbuf = *ps;
+
+      wclength = mbsrtowcs (wsbuf, (const char **)&mbsbuf, n, &psbuf);
+
+      free (wsbuf);
+      free (mbsbuf_top);
+      return wclength;
+    }
+      
+  for(wclength = 0; wclength < len; wclength++, dest++)
+    {
+      if(mbsinit(ps))
+       {
+         if (**src == '\0')
+           {
+             *dest = L'\0';
+             *src = NULL;
+             return (wclength);
+           }
+         else if (**src == '\\')
+           {
+             *dest = L'\\';
+             mblength = 1;
+           }
+         else
+           mblength = mbrtowc(dest, *src, n, ps);
+       }
+      else
+       mblength = mbrtowc(dest, *src, n, ps);
+
+      /* Cannot convert multibyte character to wide character. */
+      if (mblength == (size_t)-1 || mblength == (size_t)-2)
+       return (size_t)-1;
+
+      *src += mblength;
+      n -= mblength;
+
+      /* The multibyte string  has  been  completely  converted,
+        including  the terminating '\0'. */
+      if (*dest == L'\0')
+       {
+         *src = NULL;
+         break;
+       }
+    }
+
+    return (wclength);
+}
+#endif /* HANDLE_MULTIBYTE */
index cbc6dbfccddcb92a9240dd791cd777e0a30aa8af..91549c9c7e3be02c5a5929c4e226daf7cb301123 100644 (file)
@@ -36,7 +36,7 @@ MV = mv
 
 SHELL = @MAKE_SHELL@
 
-PROFILE_FLAGS = 
+PROFILE_FLAGS = @PROFILE_FLAGS@
 
 CFLAGS = @CFLAGS@
 LOCAL_CFLAGS = @LOCAL_CFLAGS@
@@ -69,7 +69,7 @@ MALLOC_SRC = @MALLOC_SRC@
 MALLOC = @MALLOC@
 ALLOCA = @ALLOCA@
 
-MALLOC_OBJS = malloc.o $(ALLOCA) trace.o stats.o table.o
+MALLOC_OBJS = malloc.o $(ALLOCA) trace.o stats.o table.o watch.o
 STUB_OBJS = $(ALLOCA) stub.o
 
 .PHONY:                malloc stubmalloc
@@ -110,9 +110,11 @@ trace.o: ${BUILD_DIR}/config.h
 table.o: ${BUILD_DIR}/config.h
 
 malloc.o: ${srcdir}/imalloc.h ${srcdir}/mstats.h
+malloc.o: ${srcdir}/table.h ${srcdir}/watch.h
 stats.o: ${srcdir}/imalloc.h ${srcdir}/mstats.h
 trace.o: ${srcdir}/imalloc.h
 table.o: ${srcdir}/imalloc.h ${srcdir}/table.h
+watch.o: ${srcdir}/imalloc.h ${srcdir}/watch.h
 
 # Rules for deficient makes, like SunOS and Solaris
 stub.o: stub.c
@@ -120,3 +122,4 @@ malloc.o: malloc.c
 table.o: table.c
 trace.o: trace.c
 stats.o: stats.c
+watch.o: watch.c
index ef0886814c5a17470b355f64884c2e28422a7453..3920ce99d1a6af1ee6482705f3628435aa8322a2 100644 (file)
 
 /* Must be included *after* config.h */
 
-#ifndef _IMALLOC_H_
+#ifndef _IMALLOC_H
 #define _IMALLOC_H
 
 #ifdef MALLOC_DEBUG
 #define MALLOC_STATS
 #define MALLOC_TRACE
 #define MALLOC_REGISTER
+#define MALLOC_WATCH
 #endif
 
+#define MALLOC_WRAPFUNCS
+
 /* Generic pointer type. */
 #ifndef PTR_T
 #  if defined (__STDC__)
 #  endif /* HAVE_BCOPY */
 #endif /* !__GNUC__ */
 
+#if !defined (__P)
+#  if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus) || defined (PROTOTYPES)
+#    define __P(protos) protos
+#  else 
+#    define __P(protos) ()
+#  endif
 #endif
+
+/* Use Duff's device for good zeroing/copying performance.  DO NOT call the
+   Duff's device macros with NBYTES == 0. */
+
+#define MALLOC_BZERO(charp, nbytes)                                    \
+do {                                                                   \
+  if ((nbytes) <= 32) {                                                        \
+    size_t * mzp = (size_t *)(charp);                                  \
+    unsigned long mctmp = (nbytes)/sizeof(size_t);                     \
+    long mcn;                                                          \
+    if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp &= 7; }    \
+    switch (mctmp) {                                                   \
+      case 0: for(;;) { *mzp++ = 0;                                    \
+      case 7:     *mzp++ = 0;                                          \
+      case 6:     *mzp++ = 0;                                          \
+      case 5:     *mzp++ = 0;                                          \
+      case 4:     *mzp++ = 0;                                          \
+      case 3:     *mzp++ = 0;                                          \
+      case 2:     *mzp++ = 0;                                          \
+      case 1:     *mzp++ = 0; if(mcn <= 0) break; mcn--; }             \
+    }                                                                  \
+  else                                                                 \
+    memset ((charp), 0, (nbytes));                                     \
+} while(0)
+
+#define MALLOC_ZERO(charp, nbytes) \
+do {                                                           \
+  size_t mzsz = (nbytes);                                      \
+  if (mzsz <= 9 * sizeof(mzsz) {                               \
+    size_t *mz = (size_t *)(charp);                            \
+    if(mzsz >= 5*sizeof(mzsz)) {       *mz++ = 0;              \
+                                       *mz++ = 0;              \
+      if(mzsz >= 7*sizeof(mzsz)) {     *mz++ = 0;              \
+                                       *mz++ = 0;              \
+       if(mzsz >= 9*sizeof(mzsz)) {    *mz++ = 0;              \
+                                       *mz++ = 0; }}}          \
+                                       *mz++ = 0;              \
+                                       *mz++ = 0;              \
+                                       *mz = 0;                \
+  } else                                                       \
+    memset ((charp), 0, mzsz);                                 \
+} while (0)
+
+#define MALLOC_MEMSET(charp, xch, nbytes)                              \
+do {                                                                   \
+  if ((nbytes) <= 32) {                                                        \
+    register char * mzp = (charp);                                     \
+    unsigned long mctmp = (nbytes);                                    \
+    register long mcn;                                                 \
+    if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp &= 7; }    \
+    switch (mctmp) {                                                   \
+      case 0: for(;;) { *mzp++ = xch;                                  \
+      case 7:     *mzp++ = xch;                                        \
+      case 6:     *mzp++ = xch;                                        \
+      case 5:     *mzp++ = xch;                                        \
+      case 4:     *mzp++ = xch;                                        \
+      case 3:     *mzp++ = xch;                                        \
+      case 2:     *mzp++ = xch;                                        \
+      case 1:     *mzp++ = xch; if(mcn <= 0) break; mcn--; }           \
+    }                                                                  \
+  } else                                                               \
+    memset ((charp), (xch), (nbytes));                                 \
+} while(0)
+
+#define MALLOC_MEMCPY(dest,src,nbytes)                                 \
+do {                                                                   \
+  if ((nbytes) <= 32) {                                                        \
+    size_t* mcsrc = (size_t*) src;                                     \
+    size_t* mcdst = (size_t*) dest;                                    \
+    unsigned long mctmp = (nbytes)/sizeof(size_t);                     \
+    long mcn;                                                          \
+    if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp &= 7; }    \
+    switch (mctmp) {                                                   \
+      case 0: for(;;) { *mcdst++ = *mcsrc++;                           \
+      case 7:     *mcdst++ = *mcsrc++;                                 \
+      case 6:     *mcdst++ = *mcsrc++;                                 \
+      case 5:     *mcdst++ = *mcsrc++;                                 \
+      case 4:     *mcdst++ = *mcsrc++;                                 \
+      case 3:     *mcdst++ = *mcsrc++;                                 \
+      case 2:     *mcdst++ = *mcsrc++;                                 \
+      case 1:     *mcdst++ = *mcsrc++; if(mcn <= 0) break; mcn--; }    \
+  } else                                                               \
+    memcpy ((dest), (src), (nbytes))                                   \
+} while(0)
+
+#endif /* _IMALLOC_H */
index 03b8f0882b8ddf8de84cc603006e1d206f21502d..0b4c84700492459377847e61ec66147ca7d34ec2 100644 (file)
@@ -53,12 +53,12 @@ what you give them.   Help stamp out software-hoarding!  */
  * to the second.
  */
 
-/* Define this to have free() write 0xcf into memory as it's freed, to
-   uncover callers that refer to freed memory. */
-/* SCO 3.2v4 getcwd and possibly other libc routines fail with MEMSCRAMBLE */
-#if !defined (NO_MEMSCRAMBLE)
-#  define MEMSCRAMBLE
-#endif
+/* Define MEMSCRAMBLE to have free() write 0xcf into memory as it's freed, to
+   uncover callers that refer to freed memory, and to have malloc() write 0xdf
+   into memory as it's allocated to avoid referring to previous contents. */
+
+/* SCO 3.2v4 getcwd and possibly other libc routines fail with MEMSCRAMBLE;
+   handled by configure. */
 
 #if defined (HAVE_CONFIG_H)
 #  include <config.h>
@@ -69,15 +69,6 @@ what you give them.   Help stamp out software-hoarding!  */
 #  include "stdc.h"
 #else
 #  include <sys/types.h>
-
-#  ifndef __P
-#    if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus)
-#      define __P(protos) protos
-#    else
-#      define __P(protos) ()
-#    endif
-#  endif
-
 #endif
 
 #if defined (HAVE_UNISTD_H)
@@ -107,6 +98,9 @@ what you give them.   Help stamp out software-hoarding!  */
 #ifdef MALLOC_REGISTER
 #  include "table.h"
 #endif
+#ifdef MALLOC_WATCH
+#  include "watch.h"
+#endif
 
 /* System-specific omissions. */
 #ifdef HPUX
@@ -145,6 +139,14 @@ union mhead {
 #define mh_nbytes      minfo.mi_nbytes
 #define mh_magic2      minfo.mi_magic2
 
+#define MOVERHEAD      sizeof(union mhead)
+#define MALIGN_MASK    7       /* one less than desired alignment */
+
+typedef union _malloc_guard {
+  char s[4];
+  u_bits32_t i;
+} mguard_t;
+
 /* Access free-list pointer of a block.
    It is stored at block + sizeof (char *).
    This is not a field in the minfo structure member of union mhead
@@ -159,16 +161,15 @@ union mhead {
    and end of each allocated block, and make sure they are undisturbed
    whenever a free or a realloc occurs. */
 
-/* Written in each of the 4 bytes following the block's real space */
-#define MAGIC1 0x55
 /* Written in the 2 bytes before the block's real space (-4 bytes) */
 #define MAGIC2 0x5555
-#define MSLOP  4               /* 4 bytes extra for MAGIC1s */
+#define MSLOP  4               /* 4 bytes extra for u_bits32_t size */
 
 /* How many bytes are actually allocated for a request of size N --
    rounded up to nearest multiple of 8 after accounting for malloc
    overhead. */
-#define ALLOCATED_BYTES(n)  (((n) + sizeof (union mhead) + MSLOP + 7) & ~7)
+#define ALLOCATED_BYTES(n) \
+       (((n) + MOVERHEAD + MSLOP + MALIGN_MASK) & ~MALIGN_MASK)
 
 #define ASSERT(p) \
   do \
@@ -179,15 +180,18 @@ union mhead {
 
 /* Minimum and maximum bucket indices for block splitting (and to bound
    the search for a block to split). */
-#define SPLIT_MIN      3
-#define SPLIT_MID      11      /* XXX - was 9 */
-#define SPLIT_MAX      14      /* XXX - was 12 */
+#define SPLIT_MIN      2       /* XXX - was 3 */
+#define SPLIT_MID      11
+#define SPLIT_MAX      14
 
 /* Minimum and maximum bucket indices for block coalescing. */
-#define COMBINE_MIN    6
-#define COMBINE_MAX    (pagebucket - 1)
+#define COMBINE_MIN    2
+#define COMBINE_MAX    (pagebucket - 1)        /* XXX */
 
-#define MIN_COMBINE_FREE       4
+#define LESSCORE_MIN   10
+#define LESSCORE_FRC   13
+
+#define STARTBUCK      1
 
 /* Flags for the internal functions. */
 #define MALLOC_WRAPPER 0x01    /* wrapper function */
@@ -202,9 +206,16 @@ union mhead {
 #define ERR_ASSERT_FAILED      0x08
 
 /* Evaluates to true if NB is appropriate for bucket NU.  NB is adjusted
-   appropriately by the caller to account for malloc overhead. */
-#define IN_BUCKET(nb, nu) \
-  ((nb) > (4 << (nu)) && ((nb) <= (8 << (nu))))
+   appropriately by the caller to account for malloc overhead.  This only
+   checks that the recorded size is not too big for the bucket.  We
+   can't check whether or not it's in between NU and NU-1 because we
+   might have encountered a busy bucket when allocating and moved up to
+   the next size. */
+#define IN_BUCKET(nb, nu)      ((nb) <= binsizes[(nu)])
+
+/* Use this when we want to be sure that NB is in bucket NU. */
+#define RIGHT_BUCKET(nb, nu) \
+       (((nb) > binsizes[(nu)-1]) && ((nb) <= binsizes[(nu)]))
 
 /* nextf[i] is free list of blocks of size 2**(i + 3)  */
 
@@ -218,6 +229,19 @@ static int pagesz; /* system page size. */
 static int pagebucket; /* bucket for requests a page in size */
 static int maxbuck;    /* highest bucket receiving allocation request. */
 
+static char *memtop;   /* top of heap */
+
+static unsigned long binsizes[NBUCKETS] = {
+       8UL, 16UL, 32UL, 64UL, 128UL, 256UL, 512UL, 1024UL, 2048UL, 4096UL,
+       8192UL, 16384UL, 32768UL, 65536UL, 131072UL, 262144UL, 524288UL,
+       1048576UL, 2097152UL, 4194304UL, 8388608UL, 16777216UL, 33554432UL,
+       67108864UL, 134217728UL, 268435456UL, 536870912UL, 1073741824UL,
+       2147483648UL, 4294967296UL-1
+};
+
+/* binsizes[x] == (1 << ((x) + 3)) */
+#define binsize(x)     binsizes[(x)]
+
 /* Declarations for internal functions */
 static PTR_T internal_malloc __P((size_t, const char *, int, int));
 static PTR_T internal_realloc __P((PTR_T, size_t, const char *, int, int));
@@ -238,10 +262,6 @@ static void botch __P((const char *, const char *, int));
 #endif
 static void xbotch __P((PTR_T, int, const char *, const char *, int));
 
-#ifdef MALLOC_STATS
-extern struct _malstats _mstats;
-#endif /* MALLOC_STATS */
-
 #if !HAVE_DECL_SBRK
 extern char *sbrk ();
 #endif /* !HAVE_DECL_SBRK */
@@ -251,11 +271,23 @@ extern int interrupt_immediately;
 extern int signal_is_trapped __P((int));
 #endif
 
+#ifdef MALLOC_STATS
+struct _malstats _mstats;
+#endif /* MALLOC_STATS */
+
 /* Debugging variables available to applications. */
 int malloc_flags = 0;  /* future use */
 int malloc_trace = 0;  /* trace allocations and frees to stderr */
 int malloc_register = 0;       /* future use */
 
+#ifdef MALLOC_TRACE
+char _malloc_trace_buckets[NBUCKETS];
+
+/* These should really go into a header file. */
+extern void mtrace_alloc __P((const char *, PTR_T, size_t, const char *, int));
+extern void mtrace_free __P((PTR_T, int, const char *, int));
+#endif
+
 #if !defined (botch)
 static void
 botch (s, file, line)
@@ -286,53 +318,54 @@ xbotch (mem, e, s, file, line)
   botch(s, file, line);
 }
 
-#if 0
 /* Coalesce two adjacent free blocks off the free list for size NU - 1,
-   as long as there are at least MIN_COMBINE_FREE free blocks and we
-   can find two adjacent free blocks.  nextf[NU -1] is assumed to not
-   be busy; the caller (morecore()) checks for this. */
+   as long as we can find two adjacent free blocks.  nextf[NU -1] is
+   assumed to not be busy; the caller (morecore()) checks for this. */
 static void
 bcoalesce (nu)
      register int nu;
 {
   register union mhead *mp, *mp1, *mp2;
-  register int nfree, nbuck;
+  register int nbuck;
   unsigned long siz;
 
   nbuck = nu - 1;
   if (nextf[nbuck] == 0)
     return;
 
-  nfree = 1;
-  mp1 = nextf[nbuck];
+  siz = binsize (nbuck);
+
+  mp2 = mp1 = nextf[nbuck];
   mp = CHAIN (mp1);
-  mp2 = (union mhead *)0;
-  while (CHAIN (mp))
+  while (mp && mp != (union mhead *)((char *)mp1 + siz))
     {
       mp2 = mp1;
       mp1 = mp;
       mp = CHAIN (mp);
-      nfree++;
-      /* We may not want to run all the way through the free list here;
-        if we do not, we need to check a threshold value here and break
-        if nfree exceeds it. */
     }
-  if (nfree < MIN_COMBINE_FREE)
+  if (mp == 0)
     return;
+
   /* OK, now we have mp1 pointing to the block we want to add to nextf[NU].
      CHAIN(mp2) must equal mp1.  Check that mp1 and mp are adjacent. */
-  if (CHAIN(mp2) != mp1)
+  if (mp2 != mp1 && CHAIN(mp2) != mp1)
     xbotch ((PTR_T)0, 0, "bcoalesce: CHAIN(mp2) != mp1", (char *)NULL, 0);
-  siz = 1 << (nbuck + 3);
+
+#ifdef MALLOC_DEBUG
   if (CHAIN (mp1) != (union mhead *)((char *)mp1 + siz))
     return;    /* not adjacent */
+#endif
 
 #ifdef MALLOC_STATS
   _mstats.tbcoalesce++;
+  _mstats.ncoalesce[nbuck]++;
 #endif
 
   /* Since they are adjacent, remove them from the free list */
-  CHAIN (mp2) = CHAIN (mp);
+  if (mp1 == nextf[nbuck])
+    nextf[nbuck] = CHAIN (mp);
+  else
+    CHAIN (mp2) = CHAIN (mp);
 
   /* And add the combined two blocks to nextf[NU]. */
   mp1->mh_alloc = ISFREE;
@@ -340,7 +373,6 @@ bcoalesce (nu)
   CHAIN (mp1) = nextf[nu];
   nextf[nu] = mp1;
 }
-#endif
 
 /* Split a block at index > NU (but less than SPLIT_MAX) into a set of
    blocks of the correct size, and attach them to nextf[NU].  nextf[NU]
@@ -387,8 +419,8 @@ bsplit (nu)
 #endif
 
   /* Figure out how many blocks we'll get. */
-  siz = (1 << (nu + 3));
-  nblks = (1 << (nbuck + 3)) / siz;
+  siz = binsize (nu);
+  nblks = binsize (nbuck) / siz;
 
   /* Remove the block from the chain of larger blocks. */
   mp = nextf[nbuck];
@@ -434,6 +466,27 @@ unblock_signals (setp, osetp)
 #  endif
 #endif
 }
+
+/* Return some memory to the system by reducing the break.  This is only
+   called with NU > pagebucket, so we're always assured of giving back
+   more than one page of memory. */  
+static void
+lesscore (nu)                  /* give system back some memory */
+     register int nu;          /* size index we're discarding  */
+{
+  long siz;
+
+  siz = binsize (nu);
+  /* Should check for errors here, I guess. */
+  sbrk (-siz);
+  memtop -= siz;
+
+#ifdef MALLOC_STATS
+  _mstats.nsbrk++;
+  _mstats.tsbrk -= siz;
+  _mstats.nlesscore[nu]++;
+#endif
+}
   
 static void
 morecore (nu)                  /* ask system for more memory */
@@ -456,7 +509,7 @@ morecore (nu)                       /* ask system for more memory */
       blocked_sigs = 1;
     }
 
-  siz = 1 << (nu + 3); /* size of desired block for nextf[nu] */
+  siz = binsize (nu);  /* size of desired block for nextf[nu] */
 
   if (siz < 0)
     goto morecore_done;                /* oops */
@@ -474,7 +527,6 @@ morecore (nu)                       /* ask system for more memory */
        goto morecore_done;
     }
 
-#if 0
   /* Try to coalesce two adjacent blocks from the free list on nextf[nu - 1],
      if we can, and we're withing the range of the block coalescing limits. */
   if (nu >= COMBINE_MIN && nu < COMBINE_MAX && busy[nu - 1] == 0 && nextf[nu - 1])
@@ -483,7 +535,6 @@ morecore (nu)                       /* ask system for more memory */
       if (nextf[nu] != 0)
        goto morecore_done;
     }
-#endif
 
   /* Take at least a page, and figure out how many blocks of the requested
      size we're getting. */
@@ -499,7 +550,7 @@ morecore (nu)                       /* ask system for more memory */
         an amount.  If it is, we can just request it.  If not, we want
         the smallest integral multiple of pagesize that is larger than
         `siz' and will satisfy the request. */
-      sbrk_amt = siz % pagesz;
+      sbrk_amt = siz & (pagesz - 1);
       if (sbrk_amt == 0)
        sbrk_amt = siz;
       else
@@ -518,10 +569,12 @@ morecore (nu)                     /* ask system for more memory */
   if ((long)mp == -1)
     goto morecore_done;
 
+  memtop += sbrk_amt;
+
   /* shouldn't happen, but just in case -- require 8-byte alignment */
-  if ((long)mp & 7)
+  if ((long)mp & MALIGN_MASK)
     {
-      mp = (union mhead *) (((long)mp + 7) & ~7);
+      mp = (union mhead *) (((long)mp + MALIGN_MASK) & ~MALIGN_MASK);
       nblks--;
     }
 
@@ -542,28 +595,82 @@ morecore_done:
     unblock_signals (&set, &oset);
 }
 
-#if defined (MEMSCRAMBLE) || !defined (NO_CALLOC)
-static char *
-zmemset (s, c, n)
-     char *s;
-     int c;
-     register int n;
-{
-  register char *sp;
-
-  sp = s;
-  while (--n >= 0)
-    *sp++ = c;
-  return (s);
-}
-#endif /* MEMSCRAMBLE || !NO_CALLOC */
-
 static void
 malloc_debug_dummy ()
 {
   write (1, "malloc_debug_dummy\n", 19);
 }
 
+#define PREPOP_BIN     2
+#define PREPOP_SIZE    32
+
+static int
+pagealign ()
+{
+  register int nunits;
+  register union mhead *mp;
+  long sbrk_needed;
+  char *curbrk;
+
+  pagesz = getpagesize ();
+  if (pagesz < 1024)
+    pagesz = 1024;
+
+  /* OK, how much do we need to allocate to make things page-aligned?
+     Some of this partial page will be wasted space, but we'll use as
+     much as we can.  Once we figure out how much to advance the break
+     pointer, go ahead and do it. */
+  memtop = curbrk = sbrk (0);
+  sbrk_needed = pagesz - ((long)curbrk & (pagesz - 1));        /* sbrk(0) % pagesz */
+  if (sbrk_needed < 0)
+    sbrk_needed += pagesz;
+
+  /* Now allocate the wasted space. */
+  if (sbrk_needed)
+    {
+#ifdef MALLOC_STATS
+      _mstats.nsbrk++;
+      _mstats.tsbrk += sbrk_needed;
+#endif
+      curbrk = sbrk (sbrk_needed);
+      if ((long)curbrk == -1)
+       return -1;
+      memtop += sbrk_needed;
+
+      /* Take the memory which would otherwise be wasted and populate the most
+        popular bin (2 == 32 bytes) with it.  Add whatever we need to curbrk
+        to make things 32-byte aligned, compute how many 32-byte chunks we're
+        going to get, and set up the bin. */
+      curbrk += sbrk_needed & (PREPOP_SIZE - 1);
+      sbrk_needed -= sbrk_needed & (PREPOP_SIZE - 1);
+      nunits = sbrk_needed / PREPOP_SIZE;
+
+      if (nunits > 0)
+       {
+         mp = (union mhead *)curbrk;
+
+         nextf[PREPOP_BIN] = mp;
+         while (1)
+           {
+             mp->mh_alloc = ISFREE;
+             mp->mh_index = PREPOP_BIN;
+             if (--nunits <= 0) break;
+             CHAIN(mp) = (union mhead *)((char *)mp + PREPOP_SIZE);
+             mp = (union mhead *)((char *)mp + PREPOP_SIZE);
+           }
+         CHAIN(mp) = 0;
+       }
+    }
+
+  /* compute which bin corresponds to the page size. */
+  for (nunits = 7; nunits < NBUCKETS; nunits++)
+    if (pagesz <= binsize(nunits))
+      break;
+  pagebucket = nunits;
+
+  return 0;
+}
+    
 static PTR_T
 internal_malloc (n, file, line, flags)         /* get a block */
      size_t n;
@@ -571,71 +678,27 @@ internal_malloc (n, file, line, flags)            /* get a block */
      int line, flags;
 {
   register union mhead *p;
-  register long nbytes;
   register int nunits;
+  register char *m, *z;
+  long nbytes;
+  mguard_t mg;
 
-  /* Get the system page size and align break pointer so everything will
+  /* Get the system page size and align break pointer so future sbrks will
      be page-aligned.  The page size must be at least 1K -- anything
      smaller is increased. */
   if (pagesz == 0)
-    {
-      register long sbrk_needed;
-
-      pagesz = getpagesize ();
-      if (pagesz < 1024)
-       pagesz = 1024;
-      /* OK, how much do we need to allocate to make things page-aligned?
-        This partial page is wasted space.  Once we figure out how much
-        to advance the break pointer, go ahead and do it. */
-      sbrk_needed = pagesz - ((long)sbrk (0) & (pagesz - 1));  /* sbrk(0) % pagesz */
-      if (sbrk_needed < 0)
-       sbrk_needed += pagesz;
-      /* Now allocate the wasted space. */
-      if (sbrk_needed)
-       {
-#ifdef MALLOC_STATS
-         _mstats.nsbrk++;
-         _mstats.tsbrk += sbrk_needed;
-#endif
-         if ((long)sbrk (sbrk_needed) == -1)
-           return (NULL);
-       }
-      nunits = 0;
-      nbytes = 8;
-      while (pagesz > nbytes)
-       {
-         nbytes <<= 1;
-         nunits++;
-       }
-      pagebucket = nunits;
-    }
+    if (pagealign () < 0)
+      return ((PTR_T)NULL);
  
   /* Figure out how many bytes are required, rounding up to the nearest
      multiple of 8, then figure out which nextf[] area to use.  Try to
      be smart about where to start searching -- if the number of bytes
      needed is greater than the page size, we can start at pagebucket. */
   nbytes = ALLOCATED_BYTES(n);
-  nunits = 0;
-  if (nbytes <= (pagesz >> 1))
-    {
-      register unsigned int shiftr;
-
-      shiftr = (nbytes - 1) >> 2;      /* == (nbytes - 1) / 4 */
-      while (shiftr >>= 1)             /* == (nbytes - 1) / {8,16,32,...} */
-       nunits++;
-    }
-  else
-    {
-      register u_bits32_t amt;
-
-      nunits = pagebucket;
-      amt = pagesz;
-      while (nbytes > amt)
-       {
-         amt <<= 1;
-         nunits++;
-       }
-    }
+  nunits = (nbytes <= (pagesz >> 1)) ? STARTBUCK : pagebucket;
+  for ( ; nunits < NBUCKETS; nunits++)
+    if (nbytes <= binsize(nunits))
+      break;
 
   /* Silently reject too-large requests. */
   if (nunits >= NBUCKETS)
@@ -671,30 +734,35 @@ internal_malloc (n, file, line, flags)            /* get a block */
   /* If not for this check, we would gobble a clobbered free chain ptr
      and bomb out on the NEXT allocate of this size block */
   if (p->mh_alloc != ISFREE || p->mh_index != nunits)
-    xbotch ((PTR_T)0, 0, "malloc: block on free list clobbered", file, line);
+    xbotch ((PTR_T)(p+1), 0, "malloc: block on free list clobbered", file, line);
 
   /* Fill in the info, and set up the magic numbers for range checking. */
   p->mh_alloc = ISALLOC;
   p->mh_magic2 = MAGIC2;
   p->mh_nbytes = n;
-  {
-    register char  *m = (char *) (p + 1) + n;
 
-    *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1;
-  }
+  /* End guard */
+  mg.i = n;
+  z = mg.s;
+  m = (char *) (p + 1) + n;
+  *m++ = *z++, *m++ = *z++, *m++ = *z++, *m++ = *z++;
 
 #ifdef MEMSCRAMBLE
-  zmemset ((char *)(p + 1), 0xdf, n);  /* scramble previous contents */
+  if (n)
+    MALLOC_MEMSET ((char *)(p + 1), 0xdf, n);  /* scramble previous contents */
 #endif
 #ifdef MALLOC_STATS
   _mstats.nmalloc[nunits]++;
   _mstats.tmalloc[nunits]++;
   _mstats.nmal++;
+  _mstats.bytesreq += n;
 #endif /* MALLOC_STATS */
 
 #ifdef MALLOC_TRACE
   if (malloc_trace && (flags & MALLOC_NOTRACE) == 0)
     mtrace_alloc ("malloc", p + 1, n, file, line);
+  else if (_malloc_trace_buckets[nunits])
+    mtrace_alloc ("malloc", p + 1, n, file, line);
 #endif
 
 #ifdef MALLOC_REGISTER
@@ -702,7 +770,12 @@ internal_malloc (n, file, line, flags)             /* get a block */
     mregister_alloc ("malloc", p + 1, n, file, line);
 #endif
 
-  return (char *) (p + 1);     /* XXX - should be cast to PTR_T? */
+#ifdef MALLOC_WATCH
+  if (_malloc_nwatch > 0)
+    _malloc_ckwatch (p + 1, file, line, W_ALLOC, n);
+#endif
+
+  return (PTR_T) (p + 1);
 }
 
 static void
@@ -712,10 +785,11 @@ internal_free (mem, file, line, flags)
      int line, flags;
 {
   register union mhead *p;
-  register char *ap;
+  register char *ap, *z;
   register int nunits;
   register unsigned int nbytes;
   int ubytes;          /* caller-requested size */
+  mguard_t mg;
 
   if ((ap = (char *)mem) == 0)
     return;
@@ -753,18 +827,42 @@ internal_free (mem, file, line, flags)
      We sanity-check the value of mh_nbytes against the size of the blocks
      in the appropriate bucket before we use it.  This can still cause problems
      and obscure errors if mh_nbytes is wrong but still within range; the
-     checks against MAGIC1 will probably fail then.  Using MALLOC_REGISTER
-     will help here, since it saves the original number of bytes requested. */
+     checks against the size recorded at the end of the chunk will probably
+     fail then.  Using MALLOC_REGISTER will help here, since it saves the
+     original number of bytes requested. */
+
   if (IN_BUCKET(nbytes, nunits) == 0)
     xbotch (mem, ERR_UNDERFLOW,
            "free: underflow detected; mh_nbytes out of range", file, line);
 
   ap += p->mh_nbytes;
-  ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1);
-  ASSERT (*ap++ == MAGIC1); ASSERT (*ap   == MAGIC1);
+  z = mg.s;
+  *z++ = *ap++, *z++ = *ap++, *z++ = *ap++, *z++ = *ap++;  
+  if (mg.i != p->mh_nbytes)
+    xbotch (mem, ERR_ASSERT_FAILED, "free: start and end chunk sizes differ", file, line);
+
+#if 1
+  if (nunits >= LESSCORE_MIN && ((char *)p + binsize(nunits) == memtop))
+#else
+  if (((char *)p + binsize(nunits) == memtop) && nunits >= LESSCORE_MIN)
+#endif
+    {
+      /* If above LESSCORE_FRC, give back unconditionally.  This should be set
+        high enough to be infrequently encountered.  If between LESSCORE_MIN
+        and LESSCORE_FRC, call lesscore if the bucket is marked as busy (in
+        which case we would punt below and leak memory) or if there's already
+        a block on the free list. */
+      if ((nunits >= LESSCORE_FRC) || busy[nunits] || nextf[nunits] != 0)
+       {
+         lesscore (nunits);
+         /* keeps the tracing and registering code in one place */
+         goto free_return;
+       }
+    }
 
 #ifdef MEMSCRAMBLE
-  zmemset (mem, 0xcf, p->mh_nbytes);
+  if (p->mh_nbytes)
+    MALLOC_MEMSET (mem, 0xcf, p->mh_nbytes);
 #endif
 
   ASSERT (nunits < NBUCKETS);
@@ -780,6 +878,8 @@ internal_free (mem, file, line, flags)
   nextf[nunits] = p;
   busy[nunits] = 0;
 
+free_return:
+
 #ifdef MALLOC_STATS
   _mstats.nmalloc[nunits]--;
   _mstats.nfre++;
@@ -788,12 +888,19 @@ internal_free (mem, file, line, flags)
 #ifdef MALLOC_TRACE
   if (malloc_trace && (flags & MALLOC_NOTRACE) == 0)
     mtrace_free (mem, ubytes, file, line);
+  else if (_malloc_trace_buckets[nunits])
+    mtrace_free (mem, ubytes, file, line);
 #endif
 
 #ifdef MALLOC_REGISTER
   if (malloc_register && (flags & MALLOC_NOREG) == 0)
     mregister_free (mem, ubytes, file, line);
 #endif
+
+#ifdef MALLOC_WATCH
+  if (_malloc_nwatch > 0)
+    _malloc_ckwatch (mem, file, line, W_FREE, ubytes);
+#endif
 }
 
 static PTR_T
@@ -807,7 +914,8 @@ internal_realloc (mem, n, file, line, flags)
   register u_bits32_t tocopy;
   register unsigned int nbytes;
   register int nunits;
-  register char *m;
+  register char *m, *z;
+  mguard_t mg;
 
 #ifdef MALLOC_STATS
   _mstats.nrealloc++;
@@ -837,37 +945,56 @@ internal_realloc (mem, n, file, line, flags)
      We sanity-check the value of mh_nbytes against the size of the blocks
      in the appropriate bucket before we use it.  This can still cause problems
      and obscure errors if mh_nbytes is wrong but still within range; the
-     checks against MAGIC1 will probably fail then.  Using MALLOC_REGISTER
-     will help here, since it saves the original number of bytes requested. */
+     checks against the size recorded at the end of the chunk will probably
+     fail then.  Using MALLOC_REGISTER will help here, since it saves the
+     original number of bytes requested. */
   if (IN_BUCKET(nbytes, nunits) == 0)
     xbotch (mem, ERR_UNDERFLOW,
            "realloc: underflow detected; mh_nbytes out of range", file, line);
 
   m = (char *)mem + (tocopy = p->mh_nbytes);
-  ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1);
-  ASSERT (*m++ == MAGIC1); ASSERT (*m   == MAGIC1);
+  z = mg.s;
+  *z++ = *m++, *z++ = *m++, *z++ = *m++, *z++ = *m++;
+  if (mg.i != p->mh_nbytes)
+    xbotch (mem, ERR_ASSERT_FAILED, "realloc: start and end chunk sizes differ", file, line);
+
+#ifdef MALLOC_WATCH
+  if (_malloc_nwatch > 0)
+    _malloc_ckwatch (p + 1, file, line, W_REALLOC, n);
+#endif
+#ifdef MALLOC_STATS
+  _mstats.bytesreq += (n < tocopy) ? 0 : n - tocopy;
+#endif
 
   /* See if desired size rounds to same power of 2 as actual size. */
   nbytes = ALLOCATED_BYTES(n);
 
   /* If ok, use the same block, just marking its size as changed.  */
-  if (IN_BUCKET(nbytes, nunits))
+  if (RIGHT_BUCKET(nbytes, nunits))
     {
-      m = (char *)mem + tocopy;
+#if 0
+      m = (char *)mem + p->mh_nbytes;
+#else
+      /* Compensate for increment above. */
+      m -= 4;
+#endif
       *m++ = 0;  *m++ = 0;  *m++ = 0;  *m++ = 0;
-      p->mh_nbytes = n;
-      m = (char *)mem + n;
-      *m++ = MAGIC1;  *m++ = MAGIC1;  *m++ = MAGIC1;  *m++ = MAGIC1;
+      m = (char *)mem + (p->mh_nbytes = n);
+
+      mg.i = n;
+      z = mg.s;
+      *m++ = *z++, *m++ = *z++, *m++ = *z++, *m++ = *z++;      
+
       return mem;
     }
 
+  if (n < tocopy)
+    tocopy = n;
+
 #ifdef MALLOC_STATS
   _mstats.nrcopy++;
 #endif
 
-  if (n < tocopy)
-    tocopy = n;
-
   if ((m = internal_malloc (n, file, line, MALLOC_INTERNAL|MALLOC_NOTRACE|MALLOC_NOREG)) == 0)
     return 0;
   FASTCOPY (mem, m, tocopy);
@@ -876,6 +1003,8 @@ internal_realloc (mem, n, file, line, flags)
 #ifdef MALLOC_TRACE
   if (malloc_trace && (flags & MALLOC_NOTRACE) == 0)
     mtrace_alloc ("realloc", m, n, file, line);
+  else if (_malloc_trace_buckets[nunits])
+    mtrace_alloc ("realloc", m, n, file, line);
 #endif
 
 #ifdef MALLOC_REGISTER
@@ -883,6 +1012,11 @@ internal_realloc (mem, n, file, line, flags)
     mregister_alloc ("realloc", m, n, file, line);
 #endif
 
+#ifdef MALLOC_WATCH
+  if (_malloc_nwatch > 0)
+    _malloc_ckwatch (m, file, line, W_RESIZED, n);
+#endif
+
   return m;
 }
 
@@ -946,7 +1080,7 @@ internal_calloc (n, s, file, line, flags)
   total = n * s;
   result = internal_malloc (total, file, line, flags|MALLOC_INTERNAL);
   if (result)
-    zmemset (result, 0, total);
+    memset (result, 0, total);
   return result;  
 }
 
@@ -961,7 +1095,6 @@ internal_cfree (p, file, line, flags)
 #endif /* !NO_CALLOC */
 
 #ifdef MALLOC_STATS
-
 int
 malloc_free_blocks (size)
      int size;
@@ -977,7 +1110,7 @@ malloc_free_blocks (size)
 }
 #endif
 
-#if defined (SHELL)
+#if defined (MALLOC_WRAPFUNCS)
 PTR_T
 sh_malloc (bytes, file, line)
      size_t bytes;
@@ -1045,9 +1178,9 @@ sh_valloc (size, file, line)
 {
   return internal_valloc (size, file, line, MALLOC_WRAPPER);
 }
-#endif
+#endif /* !NO_VALLOC */
 
-#endif
+#endif /* MALLOC_WRAPFUNCS */
 
 /* Externally-available functions that call their internal counterparts. */
 
index df51485d0918befa43f7c829356ce18371584fc9..d23763551286c12d4f757bf3b519e6da00a936de 100644 (file)
  * NMALLOC[i] is the difference between the number of mallocs and frees
  * for a given block size.  TMALLOC[i] is the total number of mallocs for
  * a given block size.  NMORECORE[i] is the total number of calls to
- * morecore(i).  NMAL and NFRE are counts of the number of calls to malloc()
- * and free(), respectively.  NREALLOC is the total number of calls to
- * realloc(); NRCOPY is the number of times realloc() had to allocate new
- * memory and copy to it.  NRECURSE is a count of the number of recursive
- * calls to malloc() for the same bucket size, which can be caused by calls
- * to malloc() from a signal handler.  NSBRK is the number of calls to sbrk()
- * (whether by morecore() or for alignment); TSBRK is the total number of
- * bytes requested from the kernel with sbrk().  BYTESUSED is the total
- * number of bytes consumed by blocks currently in use; BYTESFREE is the
- * total number of bytes currently on all of the free lists.  TBSPLIT is
- * the number of times a larger block was split to satisfy a smaller request.
- * NSPLIT[i] is the number of times a block of size I was split.
+ * morecore(i).  NLESSCORE[i] is the total number of calls to lesscore(i).
+ *
+ * NMAL and NFRE are counts of the number of calls to malloc() and free(),
+ * respectively.  NREALLOC is the total number of calls to realloc();
+ * NRCOPY is the number of times realloc() had to allocate new memory and
+ * copy to it.  NRECURSE is a count of the number of recursive calls to
+ * malloc() for the same bucket size, which can be caused by calls to
+ * malloc() from a signal handler.
+ *
+ * NSBRK is the number of calls to sbrk() (whether by morecore() or for
+ * alignment); TSBRK is the total number of bytes requested from the kernel
+ * with sbrk().
+ *
+ * BYTESUSED is the total number of bytes consumed by blocks currently in
+ * use; BYTESFREE is the total number of bytes currently on all of the free
+ * lists.  BYTESREQ is the total number of bytes requested by the caller
+ * via calls to malloc() and realloc().
+ *
+ * TBSPLIT is the number of times a larger block was split to satisfy a
+ * smaller request. NSPLIT[i] is the number of times a block of size I was
+ * split.
+ *
  * TBCOALESCE is the number of times two adjacent smaller blocks off the free
  * list were combined to satisfy a larger request.
  */
@@ -50,6 +60,7 @@ struct _malstats {
   int nmalloc[NBUCKETS];
   int tmalloc[NBUCKETS];
   int nmorecore[NBUCKETS];
+  int nlesscore[NBUCKETS];
   int nmal;
   int nfre;
   int nrealloc;
@@ -59,31 +70,38 @@ struct _malstats {
   bits32_t tsbrk;
   bits32_t bytesused;
   bits32_t bytesfree;
+  u_bits32_t bytesreq;
   int tbsplit;
   int nsplit[NBUCKETS];
   int tbcoalesce;
+  int ncoalesce[NBUCKETS];
 };
 
 /* Return statistics describing allocation of blocks of size BLOCKSIZE.
    NFREE is the number of free blocks for this allocation size.  NUSED
    is the number of blocks in use.  NMAL is the number of requests for
    blocks of size BLOCKSIZE.  NMORECORE is the number of times we had
-   to call MORECORE to repopulate the free list for this bucket.  NSPLIT
-   is the number of times a block of this size was split to satisfy a
-   smaller request. */
+   to call MORECORE to repopulate the free list for this bucket.
+   NLESSCORE is the number of times we gave memory back to the system
+   from this bucket.  NSPLIT is the number of times a block of this size
+   was split to satisfy a smaller request.  NCOALESCE is the number of
+   times two blocks of this size were combined to satisfy a larger
+   request. */
 struct bucket_stats {
   u_bits32_t blocksize;
   int nfree;
   int nused;
   int nmal;
   int nmorecore;
+  int nlesscore;
   int nsplit;
+  int ncoalesce;
 };
 
-extern struct bucket_stats malloc_bucket_stats ();
-extern struct _malstats malloc_stats ();
-extern void print_malloc_stats ();
-extern void trace_malloc_stats ();
+extern struct bucket_stats malloc_bucket_stats __P((int));
+extern struct _malstats malloc_stats __P((void));
+extern void print_malloc_stats __P((char *));
+extern void trace_malloc_stats __P((char *, char *));
 
 #endif /* MALLOC_STATS */
 
index 7143803d4f3b22c124c8f5ee6f713676561302fa..85cb5cef6fac14c0e148ea75671fd28e2a84ec26 100644 (file)
@@ -62,6 +62,6 @@ extern int malloc_set_register __P((int));
 /* stats.c */
 extern void print_malloc_stats __P((char *));
 extern void fprint_malloc_stats ();    /* full prototype requires stdio.h */
-extern void trace_malloc_stats __P((char *));
+extern void trace_malloc_stats __P((char *, char *));
 
 #endif
index 48fba1bad48e6404caff5810c97b09df55ed5031..52b23aef5e89849a7031d3729c9ea38ca363754b 100644 (file)
 #ifdef MALLOC_STATS
 
 #include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
 #include "mstats.h"
 
-struct _malstats _mstats;
+extern int malloc_free_blocks __P((int));
+
+extern struct _malstats _mstats;
 
 struct bucket_stats
 malloc_bucket_stats (size)
@@ -40,7 +46,7 @@ malloc_bucket_stats (size)
   if (size < 0 || size >= NBUCKETS)
     {
       v.blocksize = 0;
-      v.nused = v.nmal = v.nmorecore = v.nsplit = 0;
+      v.nused = v.nmal = v.nmorecore = v.nlesscore = v.nsplit = 0;
       return v;
     }
 
@@ -48,7 +54,9 @@ malloc_bucket_stats (size)
   v.nused = _mstats.nmalloc[size];
   v.nmal = _mstats.tmalloc[size];
   v.nmorecore = _mstats.nmorecore[size];
+  v.nlesscore = _mstats.nlesscore[size];
   v.nsplit = _mstats.nsplit[size];
+  v.ncoalesce = _mstats.ncoalesce[size];
 
   v.nfree = malloc_free_blocks (size); /* call back to malloc.c */
 
@@ -86,16 +94,18 @@ _print_malloc_stats (s, fp)
   unsigned long totused, totfree;
   struct bucket_stats v;
 
-  fprintf (fp, "Memory allocation statistics: %s\n\tsize\tfree\tin use\ttotal\tmorecore\tsplit\n", s ? s : "");
+  fprintf (fp, "Memory allocation statistics: %s\n    size\tfree\tin use\ttotal\tmorecore lesscore split\tcoalesce\n", s ? s : "");
   for (i = totused = totfree = 0; i < NBUCKETS; i++)
     {
       v = malloc_bucket_stats (i);
-      fprintf (fp, "%12lu\t%4d\t%6d\t%5d\t%8d\t%5d\n", (unsigned long)v.blocksize, v.nfree, v.nused, v.nmal, v.nmorecore, v.nsplit);
+      if (v.nmal > 0)
+       fprintf (fp, "%8lu\t%4d\t%6d\t%5d\t%8d\t%d %5d %8d\n", (unsigned long)v.blocksize, v.nfree, v.nused, v.nmal, v.nmorecore, v.nlesscore, v.nsplit, v.ncoalesce);
       totfree += v.nfree * v.blocksize;
       totused += v.nused * v.blocksize;
     }
   fprintf (fp, "\nTotal bytes in use: %lu, total bytes free: %lu\n",
           totused, totfree);
+  fprintf (fp, "\nTotal bytes requested by application: %lu\n", _mstats.bytesreq);
   fprintf (fp, "Total mallocs: %d, total frees: %d, total reallocs: %d (%d copies)\n",
           _mstats.nmal, _mstats.nfre, _mstats.nrealloc, _mstats.nrcopy);
   fprintf (fp, "Total sbrks: %d, total bytes via sbrk: %d\n",
@@ -120,24 +130,51 @@ fprint_malloc_stats (s, fp)
 }
 
 #define TRACEROOT "/var/tmp/maltrace/trace."
-extern char *inttostr ();
+static char mallbuf[1024];
 
 void
-trace_malloc_stats (s)
-     char *s;
+trace_malloc_stats (s, fn)
+     char *s, *fn;
 {
-  char ibuf[32], *ip;
-  char fname[64];
-  long p;
+  char defname[sizeof (TRACEROOT) + 64];
+  char fname[1024];
+  long l;
   FILE *fp;
 
-  p = getpid();
-  ip = inttostr(p, ibuf, sizeof(ibuf));
-  strcpy (fname, TRACEROOT);
-  strcat (fname, ip);
-  fp = fopen(fname, "w");
+  l = (long)getpid ();
+  if (fn == 0)
+    {
+      sprintf (defname, "%s%ld", TRACEROOT, l);  
+      fp = fopen(defname, "w");
+    }
+  else
+    {
+      char *p, *q, *r;
+      char pidbuf[32];
+      int sp;
+
+      sprintf (pidbuf, "%ld", l);
+      if ((strlen (pidbuf) + strlen (fn) + 2) >= sizeof (fname))
+       return;
+      for (sp = 0, p = fname, q = fn; *q; )
+       {
+         if (sp == 0 && *q == '%' && q[1] == 'p')
+           {
+             sp = 1;
+             for (r = pidbuf; *r; )
+               *p++ = *r++;
+             q += 2;
+           }
+         else
+           *p++ = *q++;
+       }
+      *p = '\0';
+      fp = fopen (fname, "w");
+    }
+        
   if (fp)
     {
+      setvbuf (fp, mallbuf, _IOFBF, sizeof (mallbuf));
       _print_malloc_stats (s, fp);
       fflush(fp);
       fclose(fp);
index d297c65903ee17a7243280a6cf0db65cda03eaf7..94693d8ea2c461c642859b129f9a361430b7573b 100644 (file)
@@ -1,3 +1,21 @@
+/* Copyright (C) 1993-2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 void
 bash_malloc_stub()
 {
index d7c48c5c8616f4a1240a8e8448b87b7c0a51a9d5..051b57382ed81c2120e4ff11cd2e3e8045aa6b96 100644 (file)
@@ -34,7 +34,9 @@ extern int malloc_register;
 #define FIND_EXIST     0x02    /* find existing entry */
 
 static int table_count = 0;
+static int table_allocated = 0;
 static mr_table_t mem_table[REG_TABLE_SIZE];
+static mr_table_t mem_overflow;
 
 /*
  * NOTE: taken from dmalloc (http://dmalloc.com) and modified.
@@ -43,7 +45,7 @@ static unsigned int
 mt_hash (key)
      const PTR_T key;
 {
-  unsigned int a, b, c, len;
+  unsigned int a, b, c;
   unsigned long x;
 
   /* set up the internal state */
@@ -61,10 +63,10 @@ static unsigned int
 which_bucket (mem)
      PTR_T mem;
 {
-  return (mt_hash ((unsigned char *)mem) % REG_TABLE_SIZE);
+  return (mt_hash ((unsigned char *)mem) & (REG_TABLE_SIZE-1));
 }
 #else
-#define which_bucket(mem) (mt_hash ((unsigned char *)(mem)) % REG_TABLE_SIZE);
+#define which_bucket(mem) (mt_hash ((unsigned char *)(mem)) & (REG_TABLE_SIZE-1));
 #endif
 
 static mr_table_t *
@@ -76,6 +78,9 @@ find_entry (mem, flags)
   register mr_table_t *tp;
   mr_table_t *endp, *lastp;
 
+  if (mem_overflow.mem == mem)
+    return (&mem_overflow);
+
   bucket = which_bucket (mem); /* get initial hash */
   tp = endp = mem_table + bucket;
   lastp = mem_table + REG_TABLE_SIZE;
@@ -105,17 +110,26 @@ find_entry (mem, flags)
   /* oops.  table is full.  replace an existing free entry. */
   do
     {
+      /* If there are no free entries, punt right away without searching. */
+      if (table_allocated == REG_TABLE_SIZE)
+       break;
+
       if (tp->flags & MT_FREE)
        {
          memset(tp, 0, sizeof (mr_table_t));
          return (tp);
        }
       tp++;
+
+      if (tp == lastp)
+       tp = mem_table;
     }
   while (tp != endp);
 
-  /* wow. entirely full.  return NULL. */
-  return ((mr_table_t *)NULL);
+  /* wow. entirely full.  return mem_overflow dummy entry. */
+  tp = &mem_overflow;
+  memset (tp, 0, sizeof (mr_table_t));
+  return tp;
 }
 
 mr_table_t *
@@ -158,7 +172,7 @@ mregister_alloc (tag, mem, size, file, line)
   if (tentry == 0)
     {
       /* oops.  table is full.  punt. */
-      fprintf (stderr, "register_alloc: alloc table is full?\n");
+      fprintf (stderr, "register_alloc: alloc table is full with FIND_ALLOC?\n");
       return;
     }
   
@@ -175,6 +189,9 @@ mregister_alloc (tag, mem, size, file, line)
   tentry->file = file;
   tentry->line = line;
   tentry->nalloc++;
+
+  if (tentry != &mem_overflow)
+    table_allocated++;
 }
 
 void
@@ -190,7 +207,9 @@ mregister_free (mem, size, file, line)
   if (tentry == 0)
     {
       /* oops.  not found. */
+#if 0
       fprintf (stderr, "register_free: %p not in allocation table?\n", mem);
+#endif
       return;
     }
   if (tentry->flags & MT_FREE)
@@ -204,6 +223,9 @@ mregister_free (mem, size, file, line)
   tentry->file = file;
   tentry->line = line;
   tentry->nfree++;
+
+  if (tentry != &mem_overflow)
+    table_allocated--;
 }
 
 /* If we ever add more flags, this will require changes. */
@@ -250,6 +272,7 @@ void
 mregister_table_init ()
 {
   memset (mem_table, 0, sizeof(mr_table_t) * REG_TABLE_SIZE);
+  memset (&mem_overflow, 0, sizeof (mr_table_t));
   table_count = 0;
 }
 
index f39beb8783960c956d93fa843f5f00caf42a4868..9b2cddd655278b8ce6c31c57f1cd919a9f43f7e8 100644 (file)
@@ -55,12 +55,12 @@ typedef struct mr_table {
 
 #define REG_TABLE_SIZE 8192
 
-extern mr_table_t *mr_table_entry ();
-extern void mregister_alloc ();
-extern void mregister_free ();
+extern mr_table_t *mr_table_entry __P((PTR_T));
+extern void mregister_alloc __P((const char *, PTR_T, size_t, const char *, int));
+extern void mregister_free __P((PTR_T, int, const char *, int));
 extern void mregister_describe_mem ();
-extern void mregister_dump_table ();
-extern void mregister_table_init ();
+extern void mregister_dump_table __P((void));
+extern void mregister_table_init __P((void));
 
 /* NOTE:  HASH_MIX taken from dmalloc (http://dmalloc.com) */
 
index 418509e97a0f750fb34bcfad04259b49b1e58a81..ddd62f0ebb8903606618dafd5ae20b9d6d4845b3 100644 (file)
@@ -32,6 +32,7 @@ static int _mtrace_verbose = 0;
 #ifdef MALLOC_TRACE
 
 FILE *_mtrace_fp = NULL;
+extern char _malloc_trace_buckets[];
 
 void
 mtrace_alloc (tag, mem, size, file, line)
@@ -72,7 +73,7 @@ mtrace_free (mem, size, file, line)
 #endif /* MALLOC_TRACE */
 
 int
-malloc_set_trace(n)
+malloc_set_trace (n)
      int n;
 {
   int old;
@@ -84,10 +85,19 @@ malloc_set_trace(n)
 }
 
 void
-malloc_set_tracefp(fp)
+malloc_set_tracefp (fp)
      FILE *fp;
 {
 #ifdef MALLOC_TRACE
   _mtrace_fp = fp ? fp : stderr;
 #endif
 }
+
+void
+malloc_trace_bin (n)
+     int n;
+{
+#ifdef MALLOC_TRACE
+  _malloc_trace_buckets[n] = 1;
+#endif
+}
diff --git a/lib/malloc/watch.c b/lib/malloc/watch.c
new file mode 100644 (file)
index 0000000..6594a3f
--- /dev/null
@@ -0,0 +1,150 @@
+/* watch.c - watchpoint functions for malloc */
+
+/* Copyright (C) 2001 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include "imalloc.h"
+
+#ifdef MALLOC_WATCH
+#include "watch.h"
+
+#define WATCH_MAX      32
+
+int            _malloc_nwatch;
+static PTR_T   _malloc_watch_list[WATCH_MAX];
+
+static void
+watch_warn (addr, file, line, type, data)
+     PTR_T addr;
+     const char *file;
+     int line, type;
+     unsigned long data;
+{
+  char *tag;
+
+  if (type == W_ALLOC)
+    tag = "allocated";
+  else if (type == W_FREE)
+    tag = "freed";
+  else if (type == W_REALLOC)
+    tag = "requesting resize";
+  else if (type == W_RESIZED)
+    tag = "just resized";
+  else
+    tag = "bug: unknown operation";
+
+  fprintf (stderr, "malloc: watch alert: %p %s ", addr, tag);
+  if (data != (unsigned long)-1)
+    fprintf (stderr, "(size %lu) ", data);
+  fprintf (stderr, "from '%s:%d'\n", file ? file : "unknown", line);
+}
+
+void
+_malloc_ckwatch (addr, file, line, type, data)
+     PTR_T addr;
+     const char *file;
+     int line, type;
+     unsigned long data;
+{
+  register int i;
+
+  for (i = _malloc_nwatch - 1; i >= 0; i--)
+    {
+      if (_malloc_watch_list[i] == addr)
+       {
+         watch_warn (addr, file, line, type, data);
+         return;
+       }
+    }
+}
+#endif /* MALLOC_WATCH */
+
+PTR_T
+malloc_watch (addr)
+     PTR_T addr;
+{
+  register int i;
+  PTR_T ret;
+
+  if (addr == 0)
+    return addr;
+  ret = (PTR_T)0;
+
+#ifdef MALLOC_WATCH
+  for (i = _malloc_nwatch - 1; i >= 0; i--)
+    {
+      if (_malloc_watch_list[i] == addr)
+        break;
+    }
+  if (i < 0)
+    {
+      if (_malloc_nwatch == WATCH_MAX) /* full, take out first */
+       {
+         ret = _malloc_watch_list[0];
+         _malloc_nwatch--;
+         for (i = 0; i < _malloc_nwatch; i++)
+           _malloc_watch_list[i] = _malloc_watch_list[i+1];
+       }
+      _malloc_watch_list[_malloc_nwatch++] = addr;
+    }
+#endif
+
+  return ret;  
+}
+
+/* Remove a watchpoint set on ADDR.  If ADDR is NULL, remove all
+   watchpoints.  Returns ADDR if everything went OK, NULL if ADDR was
+   not being watched. */
+PTR_T
+malloc_unwatch (addr)
+     PTR_T addr;
+{
+#ifdef MALLOC_WATCH
+  register int i;
+
+  if (addr == 0)
+    {
+      for (i = 0; i < _malloc_nwatch; i++)
+        _malloc_watch_list[i] = (PTR_T)0;
+      _malloc_nwatch = 0;
+      return ((PTR_T)0);
+    }
+  else
+    {
+      for (i = 0; i < _malloc_nwatch; i++)
+       {
+         if (_malloc_watch_list[i] == addr)
+           break;
+       }
+      if (i == _malloc_nwatch)
+        return ((PTR_T)0);             /* not found */
+      /* shuffle everything from i+1 to end down 1 */
+      _malloc_nwatch--;
+      for ( ; i < _malloc_nwatch; i++)
+        _malloc_watch_list[i] = _malloc_watch_list[i+1];
+      return addr;
+    }
+#else
+  return ((PTR_T)0);
+#endif
+}
diff --git a/lib/malloc/watch.h b/lib/malloc/watch.h
new file mode 100644 (file)
index 0000000..d66d80e
--- /dev/null
@@ -0,0 +1,39 @@
+/* watch.h - definitions for tables for keeping track of allocated memory */
+
+/*  Copyright (C) 2001 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. */
+
+#ifndef _MWATCH_H
+#define _MWATCH_H
+
+#include "imalloc.h"
+
+#ifdef MALLOC_WATCH
+
+/* `Events' for watchpoints */
+
+#define W_ALLOC                0x01
+#define W_FREE         0x02
+#define W_REALLOC      0x04
+#define W_RESIZED      0x08
+
+extern int _malloc_nwatch;
+
+extern void _malloc_ckwatch __P((PTR_T, const char *, int, int, unsigned long));
+                    
+#endif /* MALLOC_WATCH */
+
+#endif /* _MWATCH_H */
index 2f47e3a51dafe00e787f9fabad8657b7d579cfdb..2caa69a313e445c7a8b121461dbc0b5291262339 100644 (file)
@@ -73,20 +73,22 @@ CSOURCES = $(srcdir)/readline.c $(srcdir)/funmap.c $(srcdir)/keymaps.c \
           $(srcdir)/history.c $(srcdir)/histsearch.c $(srcdir)/histexpand.c \
           $(srcdir)/histfile.c $(srcdir)/nls.c $(srcdir)/search.c \
           $(srcdir)/shell.c $(srcdir)/tilde.c $(srcdir)/savestring.c \
-          $(srcdir)/compat.c
+          $(srcdir)/text.c $(srcdir)/misc.c $(srcdir)/compat.c \
+          $(srcdir)/mbutil.c
 
 # The header files for this library.
 HSOURCES = readline.h rldefs.h chardefs.h keymaps.h history.h histlib.h \
           posixstat.h posixdir.h posixjmp.h tilde.h rlconf.h rltty.h \
           ansi_stdlib.h rlstdc.h tcap.h xmalloc.h rlprivate.h rlshell.h \
-          rltypedefs.h
+          rltypedefs.h rlmbutil.h
 
-HISTOBJ = history.o histexpand.o histfile.o histsearch.o shell.o savestring.o
+HISTOBJ = history.o histexpand.o histfile.o histsearch.o shell.o savestring.o \
+         mbutil.o
 TILDEOBJ = tilde.o
 OBJECTS = readline.o vi_mode.o funmap.o keymaps.o parens.o search.o \
          rltty.o complete.o bind.o isearch.o display.o signals.o \
          util.o kill.o undo.o macro.o input.o callback.o terminal.o \
-         nls.o $(HISTOBJ) $(TILDEOBJ) xmalloc.o compat.o
+         text.o nls.o misc.o $(HISTOBJ) $(TILDEOBJ) xmalloc.o compat.o
 
 # The texinfo files which document this library.
 DOCSOURCE = doc/rlman.texinfo doc/rltech.texinfo doc/rluser.texinfo
@@ -203,6 +205,11 @@ macro.o: ansi_stdlib.h
 macro.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
 macro.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
 macro.o: history.h rlstdc.h
+mbutil.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h rlmbutil.h
+mbutil.o: readline.h keymaps.h rltypedefs.h chardefs.h rlstdc.h
+misc.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
+misc.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
+misc.o: history.h rlstdc.h ansi_stdlib.h
 nls.o: ansi_stdlib.h
 nls.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
 nls.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
@@ -228,6 +235,10 @@ terminal.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
 terminal.o: tcap.h
 terminal.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
 terminal.o: history.h rlstdc.h
+text.o: readline.h keymaps.h rltypedefs.h chardefs.h tilde.h
+text.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
+text.o: history.h rlstdc.h ansi_stdlib.h
+rltty.o: rldefs.h ${BUILD_DIR}/config.h rlconf.h
 tilde.o: ansi_stdlib.h
 tilde.o: ${BUILD_DIR}/config.h
 tilde.o: tilde.h
@@ -259,6 +270,8 @@ input.o: rlprivate.h
 isearch.o: rlprivate.h
 kill.o: rlprivate.h
 macro.o: rlprivate.h
+mbutil.o: rlprivate.h
+misc.o: rlprivate.h
 nls.o: rlprivate.h
 parens.o: rlprivate.h
 readline.o: rlprivate.h
@@ -266,6 +279,7 @@ rltty.o: rlprivate.h
 search.o: rlprivate.h
 signals.o: rlprivate.h
 terminal.o: rlprivate.h
+text.o: rlprivate.h
 undo.o: rlprivate.h
 util.o: rlprivate.h
 vi_mode.o: rlprivate.h
@@ -282,14 +296,31 @@ isearch.o: xmalloc.h
 keymaps.o: xmalloc.h
 kill.o: xmalloc.h
 macro.o: xmalloc.h
+mbutil.o: xmalloc.h
+misc.o: xmalloc.h  
 readline.o: xmalloc.h   
 savestring.o: xmalloc.h
 search.o: xmalloc.h
 shell.o: xmalloc.h   
-tilde.o: xmalloc.h  
+terminal.o: xmalloc.h  
+text.o: xmalloc.h
 tilde.o: xmalloc.h 
+undo.o: xmalloc.h
 util.o: xmalloc.h
 vi_mode.o: xmalloc.h 
+xmalloc.o: xmalloc.h
+
+complete.o: rlmbutil.h
+display.o: rlmbutil.h
+histexpand.o: rlmbutil.h
+input.o: rlmbutil.h
+isearch.o: rlmbutil.h
+mbutil.o: rlmbutil.h
+misc.o: rlmbutil.h
+readline.o: rlmbutil.h
+search.o: rlmbutil.h
+text.o: rlmbutil.h
+vi_mode.o: rlmbutil.h
 
 # Rules for deficient makes, like SunOS and Solaris
 bind.o: bind.c
@@ -298,15 +329,13 @@ compat.o: compat.c
 complete.o: complete.c
 display.o: display.c
 funmap.o: funmap.c
-histexpand.o: histexpand.c
-histfile.o: histfile.c
-history.o: history.c
-histsearch.o: histsearch.c
 input.o: input.c
 isearch.o: isearch.c
 keymaps.o: keymaps.c emacs_keymap.c vi_keymap.c
 kill.o: kill.c
 macro.o: macro.c
+mbutil.o: mbutil.c
+misc.o: misc.c
 nls.o: nls.c
 parens.o: parens.c
 readline.o: readline.c
@@ -316,8 +345,14 @@ search.o: search.c
 shell.o: shell.c
 signals.o: signals.c
 terminal.o: terminal.c
+text.o: terminal.c
 tilde.o: tilde.c
 undo.o: undo.c
 util.o: util.c
 vi_mode.o: vi_mode.c
 xmalloc.o: xmalloc.c
+
+histexpand.o: histexpand.c
+histfile.o: histfile.c
+history.o: history.c
+histsearch.o: histsearch.c
index d429177d1a906a1e45bfa844ca7997543419de64..65ef401e207b34eb2405c52b097e11c9a6f2cc3c 100644 (file)
@@ -68,6 +68,8 @@ extern char *strchr (), *strrchr ();
 /* Variables exported by this file. */
 Keymap rl_binding_keymap;
 
+static char *_rl_read_file PARAMS((char *, size_t *));
+static void _rl_init_file_error PARAMS((const char *));
 static int _rl_read_init_file PARAMS((const char *, int));
 static int glean_key_from_name PARAMS((char *));
 static int substring_member_of_array PARAMS((char *, const char **));
@@ -246,6 +248,9 @@ rl_generic_bind (type, keyseq, data, map)
   char *keys;
   int keys_len;
   register int i;
+  KEYMAP_ENTRY k;
+
+  k.function = 0;
 
   /* If no keys to bind to, exit right away. */
   if (!keyseq || !*keyseq)
@@ -269,7 +274,12 @@ rl_generic_bind (type, keyseq, data, map)
   /* Bind keys, making new keymaps as necessary. */
   for (i = 0; i < keys_len; i++)
     {
-      unsigned char ic = keys[i];
+      unsigned char uc = keys[i];
+      int ic;
+
+      ic = uc;
+      if (ic < 0 || ic >= KEYMAP_SIZE)
+       return -1;
 
       if (_rl_convert_meta_chars_to_ascii && META_CHAR (ic))
        {
@@ -282,18 +292,40 @@ rl_generic_bind (type, keyseq, data, map)
        {
          if (map[ic].type != ISKMAP)
            {
-             if (map[ic].type == ISMACR)
-               free ((char *)map[ic].function);
+             /* We allow subsequences of keys.  If a keymap is being
+                created that will `shadow' an existing function or macro
+                key binding, we save that keybinding into the ANYOTHERKEY
+                index in the new map.  The dispatch code will look there
+                to find the function to execute if the subsequence is not
+                matched.  ANYOTHERKEY was chosen to be greater than
+                UCHAR_MAX. */
+             k = map[ic];
 
              map[ic].type = ISKMAP;
              map[ic].function = KEYMAP_TO_FUNCTION (rl_make_bare_keymap());
            }
          map = FUNCTION_TO_KEYMAP (map, ic);
+         /* The dispatch code will return this function if no matching
+            key sequence is found in the keymap.  This (with a little
+            help from the dispatch code in readline.c) allows `a' to be
+            mapped to something, `abc' to be mapped to something else,
+            and the function bound  to `a' to be executed when the user
+            types `abx', leaving `bx' in the input queue. */
+         if (k.function /* && k.type == ISFUNC */)
+           {
+             map[ANYOTHERKEY] = k;
+             k.function = 0;
+           }
        }
       else
        {
          if (map[ic].type == ISMACR)
            free ((char *)map[ic].function);
+         else if (map[ic].type == ISKMAP)
+           {
+             map = FUNCTION_TO_KEYMAP (map, ic);
+             ic = ANYOTHERKEY;
+           }
 
          map[ic].function = KEYMAP_TO_FUNCTION (data);
          map[ic].type = type;
@@ -331,7 +363,7 @@ rl_translate_keyseq (seq, array, len)
              /* Handle special case of backwards define. */
              if (strncmp (&seq[i], "C-\\M-", 5) == 0)
                {
-                 array[l++] = ESC;
+                 array[l++] = ESC;     /* ESC is meta-prefix */
                  i += 5;
                  array[l++] = CTRL (_rl_to_upper (seq[i]));
                  if (seq[i] == '\0')
@@ -340,7 +372,7 @@ rl_translate_keyseq (seq, array, len)
              else if (c == 'M')
                {
                  i++;
-                 array[l++] = ESC;     /* XXX */
+                 array[l++] = ESC;     /* ESC is meta-prefix */
                }
              else if (c == 'C')
                {
@@ -632,25 +664,15 @@ _rl_read_file (filename, sizep)
   i = read (file, buffer, file_size);
   close (file);
 
-#if 0
-  if (i < file_size)
-#else
   if (i < 0)
-#endif
     {
       free (buffer);
       return ((char *)NULL);
     }
 
-#if 0
-  buffer[file_size] = '\0';
-  if (sizep)
-    *sizep = file_size;
-#else
   buffer[i] = '\0';
   if (sizep)
     *sizep = i;
-#endif
 
   return (buffer);
 }
@@ -767,7 +789,7 @@ _rl_read_init_file (filename, include_level)
 
 static void
 _rl_init_file_error (msg)
-     char *msg;
+     const char *msg;
 {
   if (currently_reading_init_file)
     fprintf (stderr, "readline: %s: line %d: %s\n", current_readline_init_file,
@@ -1075,7 +1097,7 @@ rl_parse_and_bind (string)
       /* Make VAR point to start of variable name. */
       while (*var && whitespace (*var)) var++;
 
-      /* Make value point to start of value string. */
+      /* Make VALUE point to start of value string. */
       value = var;
       while (*value && !whitespace (*value)) value++;
       if (*value)
@@ -1240,6 +1262,7 @@ static struct {
   int flags;
 } boolean_varlist [] = {
   { "blink-matching-paren",    &rl_blink_matching_paren,       V_SPECIAL },
+  { "byte-oriented",           &rl_byte_oriented,              0 },
   { "completion-ignore-case",  &_rl_completion_case_fold,      0 },
   { "convert-meta",            &_rl_convert_meta_chars_to_ascii, 0 },
   { "disable-completion",      &rl_inhibit_completion,         0 },
@@ -1250,9 +1273,11 @@ static struct {
   { "input-meta",              &_rl_meta_flag,                 0 },
   { "mark-directories",                &_rl_complete_mark_directories, 0 },
   { "mark-modified-lines",     &_rl_mark_modified_lines,       0 },
+  { "mark-symlinked-directories", &_rl_complete_mark_symlink_dirs, 0 },
   { "match-hidden-files",      &_rl_match_hidden_files,        0 },
   { "meta-flag",               &_rl_meta_flag,                 0 },
   { "output-meta",             &_rl_output_meta_chars,         0 },
+  { "page-completions",                &_rl_page_completions,          0 },
   { "prefer-visible-bell",     &_rl_prefer_visible_bell,       V_SPECIAL },
   { "print-completions-horizontally", &_rl_print_completions_horizontally, 0 },
   { "show-all-if-ambiguous",   &_rl_complete_show_all,         0 },
@@ -1264,7 +1289,7 @@ static struct {
 
 static int
 find_boolean_var (name)
-     char *name;
+     const char *name;
 {
   register int i;
 
@@ -1333,7 +1358,7 @@ static struct {
 
 static int
 find_string_var (name)
-     char *name;
+     const char *name;
 {
   register int i;
 
@@ -1659,17 +1684,18 @@ _rl_get_keyname (key)
      pairs for possible inclusion in an inputrc file, we don't want to
      do any special meta processing on KEY. */
 
-#if 0
+#if 1
+  /* XXX - Experimental */
   /* We might want to do this, but the old version of the code did not. */
 
   /* If this is an escape character, we don't want to do any more processing.
      Just add the special ESC key sequence and return. */
   if (c == ESC)
     {
-      keyseq[0] = '\\';
-      keyseq[1] = 'e';
-      keyseq[2] = '\0';
-      return keyseq;
+      keyname[0] = '\\';
+      keyname[1] = 'e';
+      keyname[2] = '\0';
+      return keyname;
     }
 #endif
 
@@ -1780,7 +1806,12 @@ rl_invoking_keyseqs_in_map (function, map)
                char *keyname = (char *)xmalloc (6 + strlen (seqs[i]));
 
                if (key == ESC)
+#if 0
                  sprintf (keyname, "\\e");
+#else
+               /* XXX - experimental */
+                 sprintf (keyname, "\\M-");
+#endif
                else if (CTRL_CHAR (key))
                  sprintf (keyname, "\\C-%c", _rl_to_lower (UNCTRL (key)));
                else if (key == RUBOUT)
@@ -1927,11 +1958,8 @@ _rl_macro_dumper_internal (print_readably, map, prefix)
        {
        case ISMACR:
          keyname = _rl_get_keyname (key);
-#if 0
-         out = (char *)map[key].function;
-#else
          out = _rl_untranslate_macro_value ((char *)map[key].function);
-#endif
+
          if (print_readably)
            fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "",
                                                         keyname,
@@ -1941,9 +1969,7 @@ _rl_macro_dumper_internal (print_readably, map, prefix)
                                                        keyname,
                                                        out ? out : "");
          free (keyname);
-#if 1
          free (out);
-#endif
          break;
        case ISFUNC:
          break;
@@ -2033,7 +2059,7 @@ rl_variable_dumper (print_readably)
   if (print_readably)
     fprintf (rl_outstream, "set comment-begin %s\n", _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT);
   else
-    fprintf (rl_outstream, "comment-begin is set to `%s'\n", _rl_comment_begin ? _rl_comment_begin : "");
+    fprintf (rl_outstream, "comment-begin is set to `%s'\n", _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT);
 
   /* completion-query-items */
   if (print_readably)
@@ -2047,15 +2073,6 @@ rl_variable_dumper (print_readably)
   else
     fprintf (rl_outstream, "editing-mode is set to `%s'\n", (rl_editing_mode == emacs_mode) ? "emacs" : "vi");
 
-  /* keymap */
-  kname = rl_get_keymap_name (_rl_keymap);
-  if (kname == 0)
-    kname = rl_get_keymap_name_from_edit_mode ();
-  if (print_readably)
-    fprintf (rl_outstream, "set keymap %s\n", kname ? kname : "none");
-  else
-    fprintf (rl_outstream, "keymap is set to `%s'\n", kname ? kname : "none");
-
   /* isearch-terminators */
   if (_rl_isearch_terminators)
     {
@@ -2070,6 +2087,15 @@ rl_variable_dumper (print_readably)
 
       free (disp);
     }
+
+  /* keymap */
+  kname = rl_get_keymap_name (_rl_keymap);
+  if (kname == 0)
+    kname = rl_get_keymap_name_from_edit_mode ();
+  if (print_readably)
+    fprintf (rl_outstream, "set keymap %s\n", kname ? kname : "none");
+  else
+    fprintf (rl_outstream, "keymap is set to `%s'\n", kname ? kname : "none");
 }
 
 /* Print all of the current variables and their values to
@@ -2086,7 +2112,9 @@ rl_dump_variables (count, key)
   return (0);
 }
 
-/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. */
+/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound.  Right
+   now, this is always used to attempt to bind the arrow keys, hence the
+   check for rl_vi_movement_mode. */
 void
 _rl_bind_if_unbound (keyseq, default_func)
      const char *keyseq;
@@ -2097,7 +2125,11 @@ _rl_bind_if_unbound (keyseq, default_func)
   if (keyseq)
     {
       func = rl_function_of_keyseq (keyseq, _rl_keymap, (int *)NULL);
+#if defined (VI_MODE)
+      if (!func || func == rl_do_lowercase_version || func == rl_vi_movement_mode)
+#else
       if (!func || func == rl_do_lowercase_version)
+#endif
        rl_set_key (keyseq, default_func, _rl_keymap);
     }
 }
index 33ee512f37ceb47be0f5ca96c24b4447591583fb..a537be220b0bcb37ec05a46ebb1399adad23f31a 100644 (file)
 #endif
 
 #ifdef CTRL
-#undef CTRL
+#  undef CTRL
+#endif
+#ifdef UNCTRL
+#  undef UNCTRL
 #endif
 
 /* Some character stuff. */
@@ -76,6 +79,9 @@
 
 #define NON_NEGATIVE(c)        ((unsigned char)(c) == (c))
 
+/* Some systems define these; we want our definitions. */
+#undef ISPRINT
+
 #define ISALNUM(c)     (IN_CTYPE_DOMAIN (c) && isalnum (c))
 #define ISALPHA(c)     (IN_CTYPE_DOMAIN (c) && isalpha (c))
 #define ISDIGIT(c)     (IN_CTYPE_DOMAIN (c) && isdigit (c))
index cbcee28f823867af768e1c70a6c4cc1faaf6dd92..21a9d70859b38882b9edb0eb77f49377052e20f1 100644 (file)
@@ -55,6 +55,7 @@ extern int errno;
 
 /* System-specific feature definitions and include files. */
 #include "rldefs.h"
+#include "rlmbutil.h"
 
 /* Some standard library routines. */
 #include "readline.h"
@@ -100,10 +101,11 @@ static int stat_char PARAMS((char *));
 
 static char *rl_quote_filename PARAMS((char *, int, char *));
 
-static int get_y_or_n PARAMS((void));
+static void set_completion_defaults PARAMS((int));
+static int get_y_or_n PARAMS((int));
+static int _rl_internal_pager PARAMS((int));
 static char *printable_part PARAMS((char *));
 static int print_filename PARAMS((char *, char *));
-static char find_completion_word PARAMS((int *, int *));
 
 static char **gen_completion_matches PARAMS((char *, int, int, rl_compentry_func_t *, int, int));
 
@@ -116,7 +118,6 @@ static int compute_lcd_of_matches PARAMS((char **, int, const char *));
 static int postprocess_matches PARAMS((char ***, int));
 
 static char *make_quoted_replacement PARAMS((char *, int, char *));
-static void free_match_list PARAMS((char **));
 
 /* **************************************************************** */
 /*                                                                 */
@@ -132,6 +133,12 @@ int _rl_complete_show_all = 0;
 /* If non-zero, completed directory names have a slash appended. */
 int _rl_complete_mark_directories = 1;
 
+/* If non-zero, the symlinked directory completion behavior introduced in
+   readline-4.2a is disabled, and symlinks that point to directories have
+   a slash appended (subject to the value of _rl_complete_mark_directories).
+   This is user-settable via the mark-symlinked-directories variable. */
+int _rl_complete_mark_symlink_dirs = 0;
+
 /* If non-zero, completions are printed horizontally in alphabetical order,
    like `ls -x'. */
 int _rl_print_completions_horizontally;
@@ -194,10 +201,12 @@ int rl_completion_type = 0;
    she is sure she wants to see them all. */
 int rl_completion_query_items = 100;
 
+int _rl_page_completions = 1;
+
 /* The basic list of characters that signal a break between words for the
    completer routine.  The contents of this variable is what breaks words
    in the shell, i.e. " \t\n\"\\'`@$><=" */
-const char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{(";
+const char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{("; /* }) */
 
 /* List of basic quoting characters. */
 const char *rl_basic_quote_characters = "\"'";
@@ -264,10 +273,26 @@ rl_dequote_func_t *rl_filename_dequoting_function = (rl_dequote_func_t *)NULL;
    completer. */
 rl_linebuf_func_t *rl_char_is_quoted_p = (rl_linebuf_func_t *)NULL;
 
+/* If non-zero, the completion functions don't append anything except a
+   possible closing quote.  This is set to 0 by rl_complete_internal and
+   may be changed by an application-specific completion function. */
+int rl_completion_suppress_append = 0;
+
 /* Character appended to completed words when at the end of the line.  The
    default is a space. */
 int rl_completion_append_character = ' ';
 
+/* 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. */
+int rl_completion_mark_symlink_dirs;
+
 /* If non-zero, inhibit completion (temporarily). */
 int rl_inhibit_completion;
 
@@ -290,7 +315,7 @@ rl_complete (ignore, invoking_key)
      int ignore, invoking_key;
 {
   if (rl_inhibit_completion)
-    return (rl_insert (ignore, invoking_key));
+    return (_rl_insert_char (ignore, invoking_key));
   else if (rl_last_func == rl_complete && !completion_changed_buffer)
     return (rl_complete_internal ('?'));
   else if (_rl_complete_show_all)
@@ -314,15 +339,49 @@ rl_insert_completions (ignore, invoking_key)
   return (rl_complete_internal ('*'));
 }
 
+/* Return the correct value to pass to rl_complete_internal performing
+   the same tests as rl_complete.  This allows consecutive calls to an
+   application's completion function to list possible completions and for
+   an application-specific completion function to honor the
+   show-all-if-ambiguous readline variable. */
+int
+rl_completion_mode (cfunc)
+     rl_command_func_t *cfunc;
+{
+  if (rl_last_func == cfunc && !completion_changed_buffer)
+    return '?';
+  else if (_rl_complete_show_all)
+    return '!';
+  else
+    return TAB;
+}
+
 /************************************/
 /*                                 */
 /*    Completion utility functions  */
 /*                                 */
 /************************************/
 
+/* Set default values for readline word completion.  These are the variables
+   that application completion functions can change or inspect. */
+static void
+set_completion_defaults (what_to_do)
+     int what_to_do;
+{
+  /* Only the completion entry function can change these. */
+  rl_filename_completion_desired = 0;
+  rl_filename_quoting_desired = 1;
+  rl_completion_type = what_to_do;
+  rl_completion_suppress_append = 0;
+
+  /* The completion entry function may optionally change this. */
+  rl_completion_mark_symlink_dirs = _rl_complete_mark_symlink_dirs;
+}
+
 /* The user must press "y" or "n". Non-zero return means "y" pressed. */
 static int
-get_y_or_n ()
+get_y_or_n (for_pager)
+     int for_pager;
 {
   int c;
 
@@ -338,10 +397,32 @@ get_y_or_n ()
        return (0);
       if (c == ABORT_CHAR)
        _rl_abort_internal ();
+      if (for_pager && (c == NEWLINE || c == RETURN))
+       return (2);
+      if (for_pager && (c == 'q' || c == 'Q'))
+       return (0);
       rl_ding ();
     }
 }
 
+static int
+_rl_internal_pager (lines)
+     int lines;
+{
+  int i;
+
+  fprintf (rl_outstream, "--More--");
+  fflush (rl_outstream);
+  i = get_y_or_n (1);
+  _rl_erase_entire_line ();
+  if (i == 0)
+    return -1;
+  else if (i == 2)
+    return (lines - 1);
+  else
+    return 0;
+}
+
 #if defined (VISIBLE_STATS)
 /* Return the character which best describes FILENAME.
      `@' for symbolic links
@@ -402,19 +483,41 @@ stat_char (filename)
 /* Return the portion of PATHNAME that should be output when listing
    possible completions.  If we are hacking filename completion, we
    are only interested in the basename, the portion following the
-   final slash.  Otherwise, we return what we were passed. */
+   final slash.  Otherwise, we return what we were passed.  Since
+   printing empty strings is not very informative, if we're doing
+   filename completion, and the basename is the empty string, we look
+   for the previous slash and return the portion following that.  If
+   there's no previous slash, we just return what we were passed. */
 static char *
 printable_part (pathname)
       char *pathname;
 {
-  char *temp;
+  char *temp, *x;
+
+  if (rl_filename_completion_desired == 0)     /* don't need to do anything */
+    return (pathname);
 
-  temp = rl_filename_completion_desired ? strrchr (pathname, '/') : (char *)NULL;
+  temp = strrchr (pathname, '/');
 #if defined (__MSDOS__)
-  if (rl_filename_completion_desired && temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':')
+  if (temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':')
     temp = pathname + 1;
 #endif
-  return (temp ? ++temp : pathname);
+
+  if (temp == 0 || *temp == '\0')
+    return (pathname);
+  /* If the basename is NULL, we might have a pathname like '/usr/src/'.
+     Look for a previous slash and, if one is found, return the portion
+     following that slash.  If there's no previous slash, just return the
+     pathname we were passed. */
+  else if (temp[1] == '\0')
+    {
+      for (x = temp - 1; x > pathname; x--)
+        if (*x == '/')
+          break;
+      return ((*x == '/') ? x + 1 : pathname);
+    }
+  else
+    return ++temp;
 }
 
 /* Output TO_PRINT to rl_outstream.  If VISIBLE_STATS is defined and we
@@ -543,8 +646,8 @@ rl_quote_filename (s, rtype, qcp)
    quote, or backslash) anywhere in the string.  DP, if non-null, is set to
    the value of the delimiter character that caused a word break. */
 
-static char
-find_completion_word (fp, dp)
+char
+_rl_find_completion_word (fp, dp)
      int *fp, *dp;
 {
   int scan, end, found_quote, delimiter, pass_next, isbrk;
@@ -599,6 +702,8 @@ find_completion_word (fp, dp)
                found_quote |= RL_QF_SINGLE_QUOTE;
              else if (quote_char == '"')
                found_quote |= RL_QF_DOUBLE_QUOTE;
+             else
+               found_quote |= RL_QF_OTHER_QUOTE;      
            }
        }
     }
@@ -608,7 +713,11 @@ find_completion_word (fp, dp)
       /* We didn't find an unclosed quoted substring upon which to do
          completion, so use the word break characters to find the
          substring on which to complete. */
+#if defined (HANDLE_MULTIBYTE)
+      while (rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_ANY))
+#else
       while (--rl_point)
+#endif
        {
          scan = rl_line_buffer[rl_point];
 
@@ -780,6 +889,11 @@ compute_lcd_of_matches (match_list, matches, text)
 {
   register int i, c1, c2, si;
   int low;             /* Count of max-matched characters. */
+#if defined (HANDLE_MULTIBYTE)
+  int v;
+  mbstate_t ps1, ps2;
+  wchar_t wc1, wc2;
+#endif
 
   /* If only one match, just use that.  Otherwise, compare each
      member of the list with the next, finding out where they
@@ -793,12 +907,33 @@ compute_lcd_of_matches (match_list, matches, text)
 
   for (i = 1, low = 100000; i < matches; i++)
     {
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         memset (&ps1, 0, sizeof (mbstate_t));
+         memset (&ps2, 0, sizeof (mbstate_t));
+       }
+#endif
       if (_rl_completion_case_fold)
        {
          for (si = 0;
               (c1 = _rl_to_lower(match_list[i][si])) &&
               (c2 = _rl_to_lower(match_list[i + 1][si]));
               si++)
+#if defined (HANDLE_MULTIBYTE)
+           if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+             {
+               v = mbrtowc (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1);
+               mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2);
+               wc1 = towlower (wc1);
+               wc2 = towlower (wc2);
+               if (wc1 != wc2)
+                 break;
+               else if (v > 1)
+                 si += v - 1;
+             }
+           else
+#endif
            if (c1 != c2)
              break;
        }
@@ -808,6 +943,17 @@ compute_lcd_of_matches (match_list, matches, text)
               (c1 = match_list[i][si]) &&
               (c2 = match_list[i + 1][si]);
               si++)
+#if defined (HANDLE_MULTIBYTE)
+           if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+             {
+               mbstate_t ps_back = ps1;
+               if (!_rl_compare_chars (match_list[i], si, &ps1, match_list[i+1], si, &ps2))
+                 break;
+               else if ((v = _rl_get_char_len (&match_list[i][si], &ps_back)) > 1)
+                 si += v - 1;
+             }
+           else
+#endif
            if (c1 != c2)
              break;
        }
@@ -828,6 +974,8 @@ compute_lcd_of_matches (match_list, matches, text)
     {
       match_list[0] = (char *)xmalloc (low + 1);
 
+      /* XXX - this might need changes in the presence of multibyte chars */
+
       /* If we are ignoring case, try to preserve the case of the string
         the user typed in the face of multiple matches differing in case. */
       if (_rl_completion_case_fold)
@@ -871,6 +1019,9 @@ postprocess_matches (matchesp, matching_filenames)
 
   matches = *matchesp;
 
+  if (matches == 0)
+    return 0;
+
   /* It seems to me that in all the cases we handle we would like
      to ignore duplicate possiblilities.  Scan for the text to
      insert being identical to the other completions. */
@@ -923,7 +1074,7 @@ rl_display_match_list (matches, len, max)
      char **matches;
      int len, max;
 {
-  int count, limit, printed_len;
+  int count, limit, printed_len, lines;
   int i, j, k, l;
   char *temp;
 
@@ -951,6 +1102,7 @@ rl_display_match_list (matches, len, max)
 
   rl_crlf ();
 
+  lines = 0;
   if (_rl_print_completions_horizontally == 0)
     {
       /* Print the sorted items, up-and-down alphabetically, like ls. */
@@ -972,6 +1124,13 @@ rl_display_match_list (matches, len, max)
              l += count;
            }
          rl_crlf ();
+         lines++;
+         if (_rl_page_completions && lines >= (_rl_screenheight - 1) && i < count)
+           {
+             lines = _rl_internal_pager (lines);
+             if (lines < 0)
+               return;
+           }
        }
     }
   else
@@ -985,7 +1144,16 @@ rl_display_match_list (matches, len, max)
          if (matches[i+1])
            {
              if (i && (limit > 1) && (i % limit) == 0)
-               rl_crlf ();
+               {
+                 rl_crlf ();
+                 lines++;
+                 if (_rl_page_completions && lines >= _rl_screenheight - 1)
+                   {
+                     lines = _rl_internal_pager (lines);
+                     if (lines < 0)
+                       return;
+                   }
+               }
              else
                for (k = 0; k < max - printed_len; k++)
                  putc (' ', rl_outstream);
@@ -1057,7 +1225,7 @@ display_matches (matches)
       rl_crlf ();
       fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len);
       fflush (rl_outstream);
-      if (get_y_or_n () == 0)
+      if (get_y_or_n (0) == 0)
        {
          rl_crlf ();
 
@@ -1155,7 +1323,11 @@ insert_match (match, start, mtype, qc)
    default trailing character is a space.  Returns the number of characters
    appended.  If NONTRIVIAL_MATCH is set, we test for a symlink (if the OS
    has them) and don't add a suffix for a symlink to a directory.  A
-   nontrivial match is one that actually adds to the word being completed.  */
+   nontrivial match is one that actually adds to the word being completed.
+   The variable rl_completion_mark_symlink_dirs controls this behavior
+   (it's initially set to the what the user has chosen, indicated by the
+   value of _rl_complete_mark_symlink_dirs, but may be modified by an
+   application's completion function). */
 static int
 append_to_match (text, delimiter, quote_char, nontrivial_match)
      char *text;
@@ -1171,7 +1343,7 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
 
   if (delimiter)
     temp_string[temp_string_index++] = delimiter;
-  else if (rl_completion_append_character)
+  else if (rl_completion_suppress_append == 0 && rl_completion_append_character)
     temp_string[temp_string_index++] = rl_completion_append_character;
 
   temp_string[temp_string_index++] = '\0';
@@ -1179,11 +1351,21 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
   if (rl_filename_completion_desired)
     {
       filename = tilde_expand (text);
-      s = nontrivial_match ? LSTAT (filename, &finfo) : stat (filename, &finfo);
+      s = (nontrivial_match && rl_completion_mark_symlink_dirs == 0)
+               ? LSTAT (filename, &finfo)
+               : stat (filename, &finfo);
       if (s == 0 && S_ISDIR (finfo.st_mode))
        {
-         if (_rl_complete_mark_directories && rl_line_buffer[rl_point] != '/')
-           rl_insert_text ("/");
+         if (_rl_complete_mark_directories)
+           {
+             /* This is clumsy.  Avoid putting in a double slash if point
+                is at the end of the line and the previous character is a
+                slash. */
+             if (rl_point && rl_line_buffer[rl_point] == '\0' && rl_line_buffer[rl_point - 1] == '/')
+               ;
+             else if (rl_line_buffer[rl_point] != '/')
+               rl_insert_text ("/");
+           }
        }
 #ifdef S_ISLNK
       /* Don't add anything if the filename is a symlink and resolves to a
@@ -1194,14 +1376,14 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
 #endif
       else
        {
-         if (rl_point == rl_end)
+         if (rl_point == rl_end && temp_string_index)
            rl_insert_text (temp_string);
        }
       free (filename);
     }
   else
     {
-      if (rl_point == rl_end)
+      if (rl_point == rl_end && temp_string_index)
        rl_insert_text (temp_string);
     }
 
@@ -1247,12 +1429,15 @@ insert_all_matches (matches, point, qc)
   rl_end_undo_group ();
 }
 
-static void
-free_match_list (matches)
+void
+_rl_free_match_list (matches)
      char **matches;
 {
   register int i;
 
+  if (matches == 0)
+    return;
+
   for (i = 0; matches[i]; i++)
     free (matches[i]);
   free (matches);
@@ -1276,10 +1461,8 @@ rl_complete_internal (what_to_do)
   char quote_char;
 
   RL_SETSTATE(RL_STATE_COMPLETING);
-  /* Only the completion entry function can change these. */
-  rl_filename_completion_desired = 0;
-  rl_filename_quoting_desired = 1;
-  rl_completion_type = what_to_do;
+
+  set_completion_defaults (what_to_do);
 
   saved_line_buffer = rl_line_buffer ? savestring (rl_line_buffer) : (char *)NULL;
   our_func = rl_completion_entry_function
@@ -1294,7 +1477,7 @@ rl_complete_internal (what_to_do)
   if (rl_point)
     /* This (possibly) changes rl_point.  If it returns a non-zero char,
        we know we have an open quote. */
-    quote_char = find_completion_word (&found_quote, &delimiter);
+    quote_char = _rl_find_completion_word (&found_quote, &delimiter);
 
   start = rl_point;
   rl_point = end;
@@ -1310,6 +1493,7 @@ rl_complete_internal (what_to_do)
     {
       rl_ding ();
       FREE (saved_line_buffer);
+      completion_changed_buffer = 0;
       RL_UNSETSTATE(RL_STATE_COMPLETING);
       return (0);
     }
@@ -1375,7 +1559,7 @@ rl_complete_internal (what_to_do)
       return 1;
     }
 
-  free_match_list (matches);
+  _rl_free_match_list (matches);
 
   /* Check to see if the line has changed through all of this manipulation. */
   if (saved_line_buffer)
@@ -1735,15 +1919,13 @@ rl_menu_complete (count, ignore)
       /* Clean up from previous call, if any. */
       FREE (orig_text);
       if (matches)
-       free_match_list (matches);
+       _rl_free_match_list (matches);
 
       match_list_index = match_list_size = 0;
       matches = (char **)NULL;
 
       /* Only the completion entry function can change these. */
-      rl_filename_completion_desired = 0;
-      rl_filename_quoting_desired = 1;
-      rl_completion_type = '%';
+      set_completion_defaults ('%');
 
       our_func = rl_completion_entry_function
                        ? rl_completion_entry_function
@@ -1757,7 +1939,7 @@ rl_menu_complete (count, ignore)
       if (rl_point)
        /* This (possibly) changes rl_point.  If it returns a non-zero char,
           we know we have an open quote. */
-       quote_char = find_completion_word (&found_quote, &delimiter);
+       quote_char = _rl_find_completion_word (&found_quote, &delimiter);
 
       orig_start = rl_point;
       rl_point = orig_end;
index 4ce7d6bf63849af461fa74e38943360b81de2a47..5150ea6a07bef5ba8efaf3d7bb514f427052aaf4 100644 (file)
@@ -43,6 +43,7 @@
 
 /* System-specific feature definitions and include files. */
 #include "rldefs.h"
+#include "rlmbutil.h"
 
 /* Termcap library stuff. */
 #include "tcap.h"
@@ -65,9 +66,16 @@ extern char *_rl_term_forward_char;
 static void update_line PARAMS((char *, char *, int, int, int, int));
 static void space_to_eol PARAMS((int));
 static void delete_chars PARAMS((int));
-static void insert_some_chars PARAMS((char *, int));
+static void insert_some_chars PARAMS((char *, int, int));
 static void cr PARAMS((void));
 
+#if defined (HANDLE_MULTIBYTE)
+static int _rl_col_width PARAMS((char *, int, int));
+static int *_rl_wrapped_line;
+#else
+#  define _rl_col_width(l, s, e)       (((e) <= (s)) ? 0 : (e) - (s))
+#endif
+
 static int *inv_lbreaks, *vis_lbreaks;
 static int inv_lbsize, vis_lbsize;
 
@@ -359,6 +367,9 @@ init_line_structures (minsize)
       inv_lbsize = vis_lbsize = 256;
       inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
       vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
+#if defined (HANDLE_MULTIBYTE)
+      _rl_wrapped_line = (int *)xmalloc (vis_lbsize * sizeof (int));
+#endif
       inv_lbreaks[0] = vis_lbreaks[0] = 0;
     }
 }
@@ -372,6 +383,13 @@ rl_redisplay ()
   int c_pos, inv_botlin, lb_botlin, lb_linenum;
   int newlines, lpos, temp;
   char *prompt_this_line;
+#if defined (HANDLE_MULTIBYTE)
+  wchar_t wc;
+  size_t wc_bytes;
+  int wc_width;
+  mbstate_t ps;
+  int _rl_wrapped_multicolumn = 0;
+#endif
 
   if (!readline_echoing_p)
     return;
@@ -472,7 +490,8 @@ rl_redisplay ()
            inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
          } \
       } while (0)
-         
+
+#if defined (HANDLE_MULTIBYTE)   
 #define CHECK_LPOS() \
       do { \
        lpos++; \
@@ -482,15 +501,36 @@ rl_redisplay ()
              { \
                inv_lbsize *= 2; \
                inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
+               _rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \
              } \
            inv_lbreaks[++newlines] = out; \
+           _rl_wrapped_line[newlines] = _rl_wrapped_multicolumn; \
            lpos = 0; \
          } \
       } while (0)
+#else
+#define CHECK_LPOS() \
+      do { \
+       lpos++; \
+       if (lpos >= _rl_screenwidth) \
+         { \
+           if (newlines >= (inv_lbsize - 2)) \
+             { \
+               inv_lbsize *= 2; \
+               inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
+             } \
+           inv_lbreaks[++newlines] = out; \
+           lpos = 0; \
+         } \
+      } while (0)
+#endif
 
   /* inv_lbreaks[i] is where line i starts in the buffer. */
   inv_lbreaks[newlines = 0] = 0;
   lpos = out - wrap_offset;
+#if defined (HANDLE_MULTIBYTE)
+  memset (_rl_wrapped_line, 0, vis_lbsize);
+#endif
 
   /* prompt_invis_chars_first_line is the number of invisible characters in
      the first physical line of the prompt.
@@ -508,7 +548,11 @@ rl_redisplay ()
          probably too much work for the benefit gained.  How many people have
          prompts that exceed two physical lines? */
       temp = ((newlines + 1) * _rl_screenwidth) +
+#if 0
              ((newlines == 0) ? prompt_invis_chars_first_line : 0) +
+#else
+             ((newlines == 0 && local_prompt_prefix == 0) ? prompt_invis_chars_first_line : 0) +
+#endif
              ((newlines == 1) ? wrap_offset : 0);
 
       inv_lbreaks[++newlines] = temp;
@@ -523,10 +567,44 @@ rl_redisplay ()
      It maintains an array of line breaks for display (inv_lbreaks).
      This handles expanding tabs for display and displaying meta characters. */
   lb_linenum = 0;
+#if defined (HANDLE_MULTIBYTE)
+  in = 0;
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    {
+      memset (&ps, 0, sizeof (mbstate_t));
+      wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
+    }
+  else
+    wc_bytes = 1;
+  while (in < rl_end)
+#else
   for (in = 0; in < rl_end; in++)
+#endif
     {
       c = (unsigned char)rl_line_buffer[in];
 
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         if (wc_bytes == (size_t)-1 || wc_bytes == (size_t)-2)
+           {
+             /* Byte sequence is invalid or shortened.  Assume that the
+                first byte represents a character. */
+             wc_bytes = 1;
+             /* Assume that a character occupies a single column. */
+             wc_width = 1;
+             memset (&ps, 0, sizeof (mbstate_t));
+           }
+         else if (wc_bytes == (size_t)0)
+           break;                      /* Found '\0' */
+         else
+           {
+             temp = wcwidth (wc);
+             wc_width = (temp < 0) ? 1 : temp;
+           }
+       }
+#endif
+
       if (out + 8 >= line_size)                /* XXX - 8 for \t */
        {
          line_size *= 2;
@@ -541,7 +619,11 @@ rl_redisplay ()
          lb_linenum = newlines;
        }
 
+#if defined (HANDLE_MULTIBYTE)
+      if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */
+#else
       if (META_CHAR (c))
+#endif
        {
          if (_rl_output_meta_chars == 0)
            {
@@ -610,9 +692,52 @@ rl_redisplay ()
        }
       else
        {
+#if defined (HANDLE_MULTIBYTE)
+         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+           {
+             register int i;
+
+             _rl_wrapped_multicolumn = 0;
+
+             if (_rl_screenwidth < lpos + wc_width)
+               for (i = lpos; i < _rl_screenwidth; i++)
+                 {
+                   /* The space will be removed in update_line() */
+                   line[out++] = ' ';
+                   _rl_wrapped_multicolumn++;
+                   CHECK_LPOS();
+                 }
+             if (in == rl_point)
+               {
+                 c_pos = out;
+                 lb_linenum = newlines;
+               }
+             for (i = in; i < in+wc_bytes; i++)
+               line[out++] = rl_line_buffer[i];
+             for (i = 0; i < wc_width; i++)
+               CHECK_LPOS();
+           }
+         else
+           {
+             line[out++] = c;
+             CHECK_LPOS();
+           }
+#else
          line[out++] = c;
          CHECK_LPOS();
+#endif
+       }
+
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         in += wc_bytes;
+         wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
        }
+      else
+        in++;
+#endif
+
     }
   line[out] = '\0';
   if (c_pos < 0)
@@ -650,7 +775,12 @@ rl_redisplay ()
             only display a screenful.  We should display the last screen,
             not the first.  */
          if (out >= _rl_screenchars)
-           out = _rl_screenchars - 1;
+           {
+             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+               out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY);
+             else
+               out = _rl_screenchars - 1;
+           }
 
          /* The first line is at character position 0 in the buffer.  The
             second and subsequent lines start at inv_lbreaks[N], offset by
@@ -736,7 +866,10 @@ rl_redisplay ()
                tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif
              _rl_output_some_chars (local_prompt, nleft);
-             _rl_last_c_pos = nleft;
+             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+               _rl_last_c_pos = _rl_col_width(local_prompt, 0, nleft);
+             else
+               _rl_last_c_pos = nleft;
            }
 
          /* Where on that line?  And where does that line start
@@ -752,10 +885,15 @@ rl_redisplay ()
          if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
            {
              _rl_backspace (_rl_last_c_pos - nleft);
-             _rl_last_c_pos = nleft;
+             if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+               _rl_last_c_pos = _rl_col_width (&visible_line[pos], 0, nleft);
+             else
+               _rl_last_c_pos = nleft;
            }
 
-         if (nleft != _rl_last_c_pos)
+         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+           _rl_move_cursor_relative (nleft, &invisible_line[pos]);
+         else if (nleft != _rl_last_c_pos)
            _rl_move_cursor_relative (nleft, &invisible_line[pos]);
        }
     }
@@ -900,6 +1038,11 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
   register char *ofd, *ols, *oe, *nfd, *nls, *ne;
   int temp, lendiff, wsatend, od, nd;
   int current_invis_chars;
+  int col_lendiff, col_temp;
+#if defined (HANDLE_MULTIBYTE)
+  mbstate_t ps_new, ps_old;
+  int new_offset, old_offset, tmp;
+#endif
 
   /* If we're at the right edge of a terminal that supports xn, we're
      ready to wrap around, so do so.  This fixes problems with knowing
@@ -908,19 +1051,97 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
      position of the cursor. */
   temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
   if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
-      && _rl_last_v_pos == current_line - 1)
+       && _rl_last_v_pos == current_line - 1)
     {
-      if (new[0])
-       putc (new[0], rl_outstream);
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         wchar_t wc;
+         mbstate_t ps;
+         int tempwidth, bytes;
+         size_t ret;
+
+         /* This fixes only double-column characters, but if the wrapped
+            character comsumes more than three columns, spaces will be
+            inserted in the string buffer. */
+         if (_rl_wrapped_line[current_line] > 0)
+           _rl_clear_to_eol (_rl_wrapped_line[current_line]);
+
+         memset (&ps, 0, sizeof (mbstate_t));
+         ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
+         if (ret == (size_t)-1 || ret == (size_t)-2)
+           {
+             tempwidth = 1;
+             ret = 1;
+           }
+         else if (ret == 0)
+           tempwidth = 0;
+         else
+           tempwidth = wcwidth (wc);
+
+         if (tempwidth > 0)
+           {
+             int count;
+             bytes = ret;
+             for (count = 0; count < bytes; count++)
+               putc (new[count], rl_outstream);
+             _rl_last_c_pos = tempwidth;
+             _rl_last_v_pos++;
+             memset (&ps, 0, sizeof (mbstate_t));
+             ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
+             if (ret != 0 && bytes != 0)
+               {
+                 if (ret == (size_t)-1 || ret == (size_t)-2)
+                   memmove (old+bytes, old+1, strlen (old+1));
+                 else
+                   memmove (old+bytes, old+ret, strlen (old+ret));
+                 memcpy (old, new, bytes);
+               }
+           }
+         else
+           {
+             putc (' ', rl_outstream);
+             _rl_last_c_pos = 1;
+             _rl_last_v_pos++;
+             if (old[0] && new[0])
+               old[0] = new[0];
+           }
+       }
       else
-       putc (' ', rl_outstream);
-      _rl_last_c_pos = 1;              /* XXX */
-      _rl_last_v_pos++;
-      if (old[0] && new[0])
-       old[0] = new[0];
+#endif
+       {
+         if (new[0])
+           putc (new[0], rl_outstream);
+         else
+           putc (' ', rl_outstream);
+         _rl_last_c_pos = 1;           /* XXX */
+         _rl_last_v_pos++;
+         if (old[0] && new[0])
+           old[0] = new[0];
+       }
     }
+
       
   /* Find first difference. */
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    {
+      memset (&ps_new, 0, sizeof(mbstate_t));
+      memset (&ps_old, 0, sizeof(mbstate_t));
+
+      new_offset = old_offset = 0;
+      for (ofd = old, nfd = new;
+          (ofd - old < omax) && *ofd &&
+            _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
+       {
+         old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
+         new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
+         ofd = old + old_offset;
+         nfd = new + new_offset;
+       }
+    }
+  else
+#endif
   for (ofd = old, nfd = new;
        (ofd - old < omax) && *ofd && (*ofd == *nfd);
        ofd++, nfd++)
@@ -937,6 +1158,33 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
     return;
 
   wsatend = 1;                 /* flag for trailing whitespace */
+
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    {
+      ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
+      nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
+      while ((ols > ofd) && (nls > nfd))
+       {
+         memset (&ps_old, 0, sizeof (mbstate_t));
+         memset (&ps_new, 0, sizeof (mbstate_t));
+
+         _rl_adjust_point (old, ols - old, &ps_old);
+         _rl_adjust_point (new, nls - new, &ps_new);
+
+         if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
+           break;
+
+         if (*ols == ' ')
+           wsatend = 0;
+
+         ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
+         nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
+       }
+    }
+  else
+    {
+#endif /* HANDLE_MULTIBYTE */
   ols = oe - 1;                        /* find last same */
   nls = ne - 1;
   while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
@@ -946,18 +1194,38 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
       ols--;
       nls--;
     }
+#if defined (HANDLE_MULTIBYTE)
+    }
+#endif
 
   if (wsatend)
     {
       ols = oe;
       nls = ne;
     }
+#if defined (HANDLE_MULTIBYTE)
+  /* This may not work for stateful encoding, but who cares?  To handle
+     stateful encoding properly, we have to scan each string from the
+     beginning and compare. */
+  else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
+#else
   else if (*ols != *nls)
+#endif
     {
       if (*ols)                        /* don't step past the NUL */
-       ols++;
+       {
+         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+           ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
+         else
+           ols++;
+       }
       if (*nls)
-       nls++;
+       {
+         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+           nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
+         else
+           nls++;
+       }
     }
 
   /* count of invisible characters in the current invisible line. */
@@ -993,24 +1261,50 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
       tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif
       _rl_output_some_chars (local_prompt, lendiff);
-      _rl_last_c_pos = lendiff;
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff);
+      else
+       _rl_last_c_pos = lendiff;
     }
 
   _rl_move_cursor_relative (od, old);
 
-  /* if (len (new) > len (old)) */
+  /* if (len (new) > len (old))
+     lendiff == difference in buffer
+     col_lendiff == difference on screen
+     When not using multibyte characters, these are equal */
   lendiff = (nls - nfd) - (ols - ofd);
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old);
+  else
+    col_lendiff = lendiff;
 
   /* If we are changing the number of invisible characters in a line, and
      the spot of first difference is before the end of the invisible chars,
      lendiff needs to be adjusted. */
   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
       current_invis_chars != visible_wrap_offset)
-    lendiff += visible_wrap_offset - current_invis_chars;
+    {
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         lendiff += visible_wrap_offset - current_invis_chars;
+         col_lendiff += visible_wrap_offset - current_invis_chars;
+       }
+      else
+       {
+         lendiff += visible_wrap_offset - current_invis_chars;
+         col_lendiff = lendiff;
+       }
+    }
 
   /* Insert (diff (len (old), len (new)) ch. */
   temp = ne - nfd;
-  if (lendiff > 0)
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    col_temp = _rl_col_width (new, nfd - new, ne - new);
+  else
+    col_temp = temp;
+
+  if (col_lendiff > 0) /* XXX - was lendiff */
     {
       /* Non-zero if we're increasing the number of lines. */
       int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
@@ -1018,7 +1312,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
         use the terminal's capabilities.  If we're growing the number
         of lines, make sure we actually cause the new line to wrap
         around on auto-wrapping terminals. */
-      if (_rl_terminal_can_insert && ((2 * temp) >= lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
+      if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
        {
          /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
             _rl_horizontal_scroll_mode == 1, inserting the characters with
@@ -1027,8 +1321,8 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
          if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
                        lendiff <= prompt_visible_length || !current_invis_chars))
            {
-             insert_some_chars (nfd, lendiff);
-             _rl_last_c_pos += lendiff;
+             insert_some_chars (nfd, lendiff, col_lendiff);
+             _rl_last_c_pos += col_lendiff;
            }
          else if (*ols == 0)
            {
@@ -1037,7 +1331,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
              /* However, this screws up the rest of this block, which
                 assumes you've done the insert because you can. */
              _rl_output_some_chars (nfd, lendiff);
-             _rl_last_c_pos += lendiff;
+             _rl_last_c_pos += col_lendiff;
            }
          else
            {
@@ -1045,7 +1339,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
                 the end.  We have invisible characters in this line.  This
                 is a dumb update. */
              _rl_output_some_chars (nfd, temp);
-             _rl_last_c_pos += temp;
+             _rl_last_c_pos += col_temp;
              return;
            }
          /* Copy (new) chars to screen from first diff to last match. */
@@ -1053,37 +1347,41 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
          if ((temp - lendiff) > 0)
            {
              _rl_output_some_chars (nfd + lendiff, temp - lendiff);
-             _rl_last_c_pos += temp - lendiff;
+#if 0
+             _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff) - col_lendiff;
+#else
+             _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
+#endif
            }
        }
       else
        {
          /* cannot insert chars, write to EOL */
          _rl_output_some_chars (nfd, temp);
-         _rl_last_c_pos += temp;
+         _rl_last_c_pos += col_temp;
        }
     }
   else                         /* Delete characters from line. */
     {
       /* If possible and inexpensive to use terminal deletion, then do so. */
-      if (_rl_term_dc && (2 * temp) >= -lendiff)
+      if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
        {
          /* If all we're doing is erasing the invisible characters in the
             prompt string, don't bother.  It screws up the assumptions
             about what's on the screen. */
          if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
              -lendiff == visible_wrap_offset)
-           lendiff = 0;
+           col_lendiff = 0;
 
-         if (lendiff)
-           delete_chars (-lendiff); /* delete (diff) characters */
+         if (col_lendiff)
+           delete_chars (-col_lendiff); /* delete (diff) characters */
 
          /* Copy (new) chars to screen from first diff to last match */
          temp = nls - nfd;
          if (temp > 0)
            {
              _rl_output_some_chars (nfd, temp);
-             _rl_last_c_pos += temp;
+             _rl_last_c_pos += _rl_col_width (nfd, 0, temp);;
            }
        }
       /* Otherwise, print over the existing material. */
@@ -1092,15 +1390,20 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
          if (temp > 0)
            {
              _rl_output_some_chars (nfd, temp);
-             _rl_last_c_pos += temp;
+             _rl_last_c_pos += col_temp;
            }
          lendiff = (oe - old) - (ne - new);
-         if (lendiff)
+         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+           col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new);
+         else
+           col_lendiff = lendiff;
+
+         if (col_lendiff)
            {     
              if (_rl_term_autowrap && current_line < inv_botlin)
-               space_to_eol (lendiff);
+               space_to_eol (col_lendiff);
              else
-               _rl_clear_to_eol (lendiff);
+               _rl_clear_to_eol (col_lendiff);
            }
        }
     }
@@ -1146,7 +1449,10 @@ rl_on_new_line_with_prompt ()
     prompt_last_line = rl_prompt;
 
   l = strlen (prompt_last_line);
-  _rl_last_c_pos = l;
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l);
+  else
+    _rl_last_c_pos = l;
 
   /* Dissect prompt_last_line into screen lines. Note that here we have
      to use the real screenwidth. Readline's notion of screenwidth might be
@@ -1201,7 +1507,14 @@ _rl_move_cursor_relative (new, data)
   register int i;
 
   /* If we don't have to do anything, then return. */
+#if defined (HANDLE_MULTIBYTE)
+  /* If we have multibyte characters, NEW is indexed by the buffer point in
+     a multibyte string, but _rl_last_c_pos is the display position.  In
+     this case, NEW's display position is not obvious. */
+  if ((MB_CUR_MAX == 1 || rl_byte_oriented ) && _rl_last_c_pos == new) return;
+#else
   if (_rl_last_c_pos == new) return;
+#endif
 
   /* It may be faster to output a CR, and then move forwards instead
      of moving backwards. */
@@ -1231,19 +1544,69 @@ _rl_move_cursor_relative (new, data)
         data is underneath the cursor. */
 #if defined (HACK_TERMCAP_MOTION)
       if (_rl_term_forward_char)
+       {
+         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+           {
+             int width;
+             width = _rl_col_width (data, _rl_last_c_pos, new);
+             for (i = 0; i < width; i++)
+               tputs (_rl_term_forward_char, 1, _rl_output_character_function);
+           }
+         else
+           {
+             for (i = _rl_last_c_pos; i < new; i++)
+               tputs (_rl_term_forward_char, 1, _rl_output_character_function);
+           }
+       }
+      else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         tputs (_rl_term_cr, 1, _rl_output_character_function);
+         for (i = 0; i < new; i++)
+           putc (data[i], rl_outstream);
+       }
+      else
        for (i = _rl_last_c_pos; i < new; i++)
-         tputs (_rl_term_forward_char, 1, _rl_output_character_function);
+         putc (data[i], rl_outstream);
+
+#else /* !HACK_TERMCAP_MOTION */
+
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         tputs (_rl_term_cr, 1, _rl_output_character_function);
+         for (i = 0; i < new; i++)
+           putc (data[i], rl_outstream);
+       }
       else
        for (i = _rl_last_c_pos; i < new; i++)
          putc (data[i], rl_outstream);
-#else
-      for (i = _rl_last_c_pos; i < new; i++)
-       putc (data[i], rl_outstream);
-#endif /* HACK_TERMCAP_MOTION */
+
+#endif /* !HACK_TERMCAP_MOTION */
+
     }
+#if defined (HANDLE_MULTIBYTE)
+  /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
+     The byte length of the string is probably bigger than the column width
+     of the string, which means that if NEW == _rl_last_c_pos, then NEW's
+     display point is less than _rl_last_c_pos. */
+  else if (_rl_last_c_pos >= new)
+#else
   else if (_rl_last_c_pos > new)
-    _rl_backspace (_rl_last_c_pos - new);
-  _rl_last_c_pos = new;
+#endif
+    {
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         tputs (_rl_term_cr, 1, _rl_output_character_function);
+         for (i = 0; i < new; i++)
+           putc (data[i], rl_outstream);
+       }
+      else
+       _rl_backspace (_rl_last_c_pos - new);
+    }
+
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    _rl_last_c_pos =  _rl_col_width (data, 0, new);
+  else
+    _rl_last_c_pos = new;
 }
 
 /* PWP: move the cursor up or down. */
@@ -1514,17 +1877,23 @@ _rl_clear_screen ()
     rl_crlf ();
 }
 
-/* Insert COUNT characters from STRING to the output stream. */
+/* Insert COUNT characters from STRING to the output stream at column COL. */
 static void
-insert_some_chars (string, count)
+insert_some_chars (string, count, col)
      char *string;
-     int count;
+     int count, col;
 {
+  /* DEBUGGING */
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    if (count != col)
+      fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col);
+
   /* If IC is defined, then we do not have to "enter" insert mode. */
   if (_rl_term_IC)
     {
       char *buffer;
-      buffer = tgoto (_rl_term_IC, 0, count);
+
+      buffer = tgoto (_rl_term_IC, 0, col);
       tputs (buffer, 1, _rl_output_character_function);
       _rl_output_some_chars (string, count);
     }
@@ -1540,7 +1909,7 @@ insert_some_chars (string, count)
         use that first to open up the space. */
       if (_rl_term_ic && *_rl_term_ic)
        {
-         for (i = count; i--; )
+         for (i = col; i--; )
            tputs (_rl_term_ic, 1, _rl_output_character_function);
        }
 
@@ -1595,11 +1964,8 @@ _rl_update_final ()
   if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
     {
       char *last_line;
-#if 0
-      last_line = &visible_line[inv_lbreaks[_rl_vis_botlin]];
-#else
+
       last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
-#endif
       _rl_move_cursor_relative (_rl_screenwidth - 1, last_line);
       _rl_clear_to_eol (0);
       putc (last_line[_rl_screenwidth - 1], rl_outstream);
@@ -1744,3 +2110,87 @@ _rl_current_display_line ()
 
   return ret;
 }
+
+#if defined (HANDLE_MULTIBYTE)
+/* Calculate the number of screen columns occupied by STR from START to END.
+   In the case of multibyte characters with stateful encoding, we have to
+   scan from the beginning of the string to take the state into account. */
+static int
+_rl_col_width (str, start, end)
+     char *str;
+     int start, end;
+{
+  wchar_t wc;
+  mbstate_t ps = {0};
+  int tmp, point, width, max;
+
+  if (end <= start)
+    return 0;
+
+  point = 0;
+  max = end;
+
+  while (point < start)
+    {
+      tmp = mbrlen (str + point, max, &ps);
+      if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2)
+       {
+         /* In this case, the bytes are invalid or too short to compose a
+            multibyte character, so we assume that the first byte represents
+            a single character. */
+         point++;
+         max--;
+
+         /* Clear the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         memset (&ps, 0, sizeof (mbstate_t));
+       }
+      else if (tmp == 0)
+        break;         /* Found '\0' */
+      else
+       {
+         point += tmp;
+         max -= tmp;
+       }
+    }
+
+  /* If START is not a byte that starts a character, then POINT will be
+     greater than START.  In this case, assume that (POINT - START) gives
+     a byte count that is the number of columns of difference. */
+  width = point - start;
+
+  while (point < end)
+    {
+      tmp = mbrtowc (&wc, str + point, max, &ps);
+      if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2)
+       {
+         /* In this case, the bytes are invalid or too short to compose a
+            multibyte character, so we assume that the first byte represents
+            a single character. */
+         point++;
+         max--;
+
+         /* and assume that the byte occupies a single column. */
+         width++;
+
+         /* Clear the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         memset (&ps, 0, sizeof (mbstate_t));
+       }
+      else if (tmp == 0)
+        break;                 /* Found '\0' */
+      else
+       {
+         point += tmp;
+         max -= tmp;
+         tmp = wcwidth(wc);
+         width += (tmp >= 0) ? tmp : 1;
+       }
+    }
+
+  width += point - end;
+
+  return width;
+}
+#endif /* HANDLE_MULTIBYTE */
+         
index 42b578e1f1fa82f965df23616c3525e07b9dc54f..32f22280d396b406343518e3107f9b8ade05fc3f 100644 (file)
@@ -1,6 +1,23 @@
 # Derived by hand from the generated readline-src/doc/Makefile
 # This makefile for Readline library documentation is in -*- text -*- mode.
 # Emacs likes it that way.
+
+# Copyright (C) 1996-2002 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.
+
 topdir = .
 srcdir = .
 VPATH = .
index 90ace3cc1b954681a192002c8cd8c7d233e480c2..63ceb16e6079dd565bae6761f27d94ce39a80ca7 100644 (file)
@@ -18,7 +18,7 @@ This document describes the GNU History library, a programming tool that
 provides a consistent user interface for recalling lines of previously
 typed input.
 
-Copyright (C) 1988-2001 Free Software Foundation, Inc.
+Copyright (C) 1988-2002 Free Software Foundation, Inc.
 
 Permission is granted to make and distribute verbatim copies of
 this manual provided the copyright notice and this permission notice
@@ -73,7 +73,7 @@ except that this permission notice may be stated in a translation approved
 by the Free Software Foundation.
 
 @vskip 0pt plus 1filll
-Copyright @copyright{} 1988-2001 Free Software Foundation, Inc.
+Copyright @copyright{} 1988-2002 Free Software Foundation, Inc.
 @end titlepage
 
 @ifinfo
index 003721a7003c2721fe2fc820edc2d95d84a6dbcd..949444668fcf870c9a1831e5e96f49cfa1eb8167 100644 (file)
@@ -1,7 +1,7 @@
 @ignore
 This file documents the user interface to the GNU History library.
 
-Copyright (C) 1988-2001 Free Software Foundation, Inc.
+Copyright (C) 1988-2002 Free Software Foundation, Inc.
 Authored by Brian Fox and Chet Ramey.
 
 Permission is granted to make and distribute verbatim copies of this manual
@@ -188,8 +188,9 @@ Stifle the history list, remembering only the last @var{max} entries.
 @end deftypefun
 
 @deftypefun int unstifle_history (void)
-Stop stifling the history.  This returns the previous amount the
-history was stifled.  The value is positive if the history was
+Stop stifling the history.  This returns the previously-set
+maximum number of history entries (as set by @code{stifle_history()}).
+The value is positive if the history was
 stifled, negative if it wasn't.
 @end deftypefun
 
index 6926b26f5c9e479cf43d7aa612cbf1fdab056023..418bfa8eff65d8f4ba2921bcf403a78e16602246 100644 (file)
@@ -1,7 +1,7 @@
 @ignore
 This file documents the user interface to the GNU History library.
 
-Copyright (C) 1988-1999 Free Software Foundation, Inc.
+Copyright (C) 1988-2002 Free Software Foundation, Inc.
 Authored by Brian Fox and Chet Ramey.
 
 Permission is granted to make and distribute verbatim copies of this manual
index 859afc1e4e7a5ac710d5e7633a3cd31e29612db8..1206cf0f235d05cf1b0a32f555b44fc871cc8b70 100644 (file)
@@ -1,6 +1,10 @@
-@set EDITION 4.2a
-@set VERSION 4.2a
-@set UPDATED 2001 October 9
-@set UPDATE-MONTH October 2001
+@ignore
+Copyright (C) 1988-2002 Free Software Foundation, Inc. 
+@end ignore
 
-@set LASTCHANGE Tue Oct  9 15:03:34 EDT 2001
+@set EDITION 4.3
+@set VERSION 4.3
+@set UPDATED 2002 March 4
+@set UPDATE-MONTH March 2002
+
+@set LASTCHANGE Mon Mar  4 12:00:16 EST 2002
index 894c5163874223f472a9988aa927e5d0bd25b6c4..1ffebad08a73e5f7c646ff584870987613b43db6 100644 (file)
@@ -18,7 +18,7 @@ This document describes the GNU Readline Library, a utility which aids
 in the consistency of user interface across discrete programs that need
 to provide a command line interface.
 
-Copyright (C) 1988-2001 Free Software Foundation, Inc.
+Copyright (C) 1988-2002 Free Software Foundation, Inc.
 
 Permission is granted to make and distribute verbatim copies of
 this manual provided the copyright notice and this permission notice
@@ -73,7 +73,7 @@ except that this permission notice may be stated in a translation approved
 by the Free Software Foundation.
 
 @vskip 0pt plus 1filll
-Copyright @copyright{} 1988-2001 Free Software Foundation, Inc.
+Copyright @copyright{} 1988-2002 Free Software Foundation, Inc.
 @end titlepage
 
 @ifinfo
index be9f662f389fce02d80b5eac60f7b5670ae6622c..037e824e28aef27ace0b0f6edaaa31a55be22a64 100644 (file)
@@ -8,7 +8,7 @@ This document describes the GNU Readline Library, a utility for aiding
 in the consitency of user interface across discrete programs that need
 to provide a command line interface.
 
-Copyright (C) 1988-2001 Free Software Foundation, Inc.
+Copyright (C) 1988-2002 Free Software Foundation, Inc.
 
 Permission is granted to make and distribute verbatim copies of
 this manual provided the copyright notice and this permission notice
@@ -111,12 +111,13 @@ function, and has the advantage of no static buffer to overflow:
 /* 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. */
+/* 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 the buffer has already been allocated,
+     return the memory to the free pool. */
   if (line_read)
     @{
       free (line_read);
@@ -126,7 +127,8 @@ rl_gets ()
   /* Get a line from the user. */
   line_read = readline ("");
 
-  /* If the line has any text in it, save it on the history. */
+  /* If the line has any text in it,
+     save it on the history. */
   if (line_read && *line_read)
     add_history (line_read);
 
@@ -263,7 +265,7 @@ variables that describe the current state of the line read so far.
 The calling sequence for a command @code{foo} looks like
 
 @example
-@code{foo (int count, int key)}
+@code{int foo (int count, int key)}
 @end example
 
 @noindent
@@ -280,6 +282,9 @@ 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.
+
 @node Readline Variables
 @section Readline Variables
 
@@ -385,10 +390,12 @@ The value allows conditional parsing of the inputrc file
 
 @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 {rl_command_func_t *} rl_last_func
@@ -766,9 +773,9 @@ This is done with @code{rl_begin_undo_group()} and
 
 The types of events that can be undone are:
 
-@example
+@smallexample
 enum undo_code @{ UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END @}; 
-@end example
+@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
@@ -901,10 +908,12 @@ to the result.
 
 @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)
@@ -947,7 +956,9 @@ be the keyboard.
 @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()}.
+@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)
@@ -1000,6 +1011,13 @@ environment variable is used.
 @node Utility Functions
 @subsection Utility Functions
 
+@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 int 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.
@@ -1123,16 +1141,26 @@ The function takes the text of the line as an argument.
 @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.  @code{EOF} is  indicated by calling @var{lhandler} with a
+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
@@ -1185,8 +1213,8 @@ invert_case_line (count, key)
       end = temp;
     @}
 
-  /* Tell readline that we are modifying the line, so it will save
-     the undo information. */
+  /* 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++)
@@ -1442,6 +1470,14 @@ 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 value of the @code{show-all-if-ambiguous} variable.
+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}.
@@ -1528,10 +1564,41 @@ character found in @code{rl_completer_word_break_characters} should be
 used to break words for the completer.
 @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, we ask the user if she is sure
-she wants to see them all.  The default value is 100.
+@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 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 displayed as part of the completion, replacing
+the directory portion of the pathname the user typed.
+It returns an integer that should be non-zero if the function modifies
+its directory argument.
+It could be used to expand symbolic links or shell variables in pathnames.
+@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
@@ -1571,6 +1638,12 @@ 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, we ask the user if she is sure
+she wants to see them all.  The default value is 100.
+@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
@@ -1581,6 +1654,24 @@ 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.
+@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 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 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.
@@ -1625,43 +1716,6 @@ 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
 
-@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 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 displayed as part of the completion, replacing
-the directory portion of the pathname the user typed.
-It returns an integer that should be non-zero if the function modifies
-its directory argument.
-It could be used to expand symbolic links or shell variables in pathnames.
-@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
-
 @node A Short Completion Example
 @subsection A Short Completion Example
 
@@ -2089,12 +2143,13 @@ too_dangerous (caller)
      char *caller;
 @{
   fprintf (stderr,
-           "%s: Too dangerous for me to distribute.  Write it yourself.\n",
+           "%s: Too dangerous for me to distribute.\n"
            caller);
+  fprintf (stderr, "Write it yourself.\n");
 @}
 
-/* Return non-zero if ARG is a valid argument for CALLER, else print
-   an error message and return zero. */
+/* 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;
index e4e56ff1d9c65f55547a8ce2435c009409fe494e..94f851e67f29837dde62a8e17f8d33360e75eab2 100644 (file)
@@ -10,7 +10,7 @@ use these features.  There is a document entitled "readline.texinfo"
 which contains both end-user and programmer documentation for the
 GNU Readline Library.
 
-Copyright (C) 1988-2001 Free Software Foundation, Inc.
+Copyright (C) 1988-2002 Free Software Foundation, Inc.
 
 Authored by Brian Fox and Chet Ramey.
 
@@ -512,6 +512,13 @@ This variable, when set to @samp{on}, causes Readline to display an
 asterisk (@samp{*}) at the start of history lines which have been modified.
 This variable is @samp{off} by default.
 
+@item mark-symlinked-directories
+@vindex mark-symlinked-directories
+If set to @samp{on}, completed names which are symbolic links
+to directories have a slash appended (subject to the value of
+@code{mark-directories}).
+The default is @samp{off}.
+
 @item match-hidden-files
 @vindex match-hidden-files
 This variable, when set to @samp{on}, causes Readline to match files whose
@@ -526,6 +533,12 @@ If set to @samp{on}, Readline will display characters with the
 eighth bit set directly rather than as a meta-prefixed escape
 sequence.  The default is @samp{off}.
 
+@item page-completions
+@vindex page-completions
+If set to @samp{on}, Readline uses an internal @code{more}-like pager
+to display a screenful of possible completions at a time.
+This variable is @samp{on} by default.
+
 @item print-completions-horizontally
 If set to @samp{on}, Readline will display completions with matches
 sorted horizontally in alphabetical order, rather than down the screen.
@@ -757,14 +770,14 @@ binding, variable assignment, and conditional syntax.
 @example
 @page
 # This file controls the behaviour of line input editing for
-# programs that use the Gnu Readline library.  Existing programs
-# include FTP, Bash, and Gdb.
+# programs that use the GNU Readline library.  Existing
+# programs include FTP, Bash, and GDB.
 #
 # You can re-read the inputrc file with C-x C-r.
 # Lines beginning with '#' are comments.
 #
-# First, include any systemwide bindings and variable assignments from
-# /etc/Inputrc
+# First, include any systemwide bindings and variable
+# assignments from /etc/Inputrc
 $include /etc/Inputrc
 
 #
@@ -816,10 +829,12 @@ TAB: complete
 $if Bash
 # edit the path
 "\C-xp": "PATH=$@{PATH@}\e\C-e\C-a\ef\C-f"
-# prepare to type a quoted word -- insert open and close double quotes
+# prepare to type a quoted word --
+# insert open and close double quotes
 # and move to just after the open quote
 "\C-x\"": "\"\"\C-b"
-# insert a backslash (testing backslash escapes in sequences and macros)
+# insert a backslash (testing backslash escapes
+# in sequences and macros)
 "\C-x\\": "\\"
 # Quote the current or previous word
 "\C-xq": "\eb\"\ef\""
@@ -835,16 +850,16 @@ set bell-style visible
 # don't strip characters to 7 bits when reading
 set input-meta on
 
-# allow iso-latin1 characters to be inserted rather than converted to
-# prefix-meta sequences
+# allow iso-latin1 characters to be inserted rather
+# than converted to prefix-meta sequences
 set convert-meta off
 
-# display characters with the eighth bit set directly rather than
-# as meta-prefixed characters
+# display characters with the eighth bit set directly
+# rather than as meta-prefixed characters
 set output-meta on
 
-# if there are more than 150 possible completions for a word, ask the
-# user if he wants to see all of them
+# if there are more than 150 possible completions for
+# a word, ask the user if he wants to see all of them
 set completion-query-items 150
 
 # For FTP
@@ -1053,6 +1068,20 @@ lowercase the previous word, but do not move the cursor.
 Capitalize the current (or following) word.  With a negative argument,
 capitalize the previous word, but do not move the cursor.
 
+@item 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
+@code{emacs} mode; @code{vi} mode does overwrite differently.
+Each call to @code{readline()} starts in insert mode.
+
+In overwrite mode, characters bound to @code{self-insert} replace
+the text at point rather than pushing the text to the right.
+Characters bound to @code{backward-delete-char} replace the character
+before point with a space.
+
+By default, this command is unbound.
+
 @end ftable
 
 @node Commands For Killing
@@ -1312,12 +1341,19 @@ of that character.  A negative count searches for subsequent
 occurrences.
 
 @item insert-comment (M-#)
-The value of the @code{comment-begin}
-variable is inserted at the beginning of the current line,
-and the line is accepted as if a newline had been typed.
+Without a numeric argument, the value of the @code{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 @code{comment-begin}, the value is inserted, otherwise
+the characters in @code{comment-begin} are deleted from the beginning of
+the line.
+In either case, the line is accepted as if a newline had been typed.
 @ifset BashFeatures
 The default value of @code{comment-begin} 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.
 @end ifset
 
 @item dump-functions ()
@@ -1339,13 +1375,22 @@ the output is formatted in such a way that it can be made part
 of an @var{inputrc} file.  This command is unbound by default.
 
 @ifset BashFeatures
+@item 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 file names for possible completions.
+
 @item glob-expand-word (C-x *)
 The word before point is treated as a pattern for pathname expansion,
 and the list of matching file names is inserted, replacing the word.
+If a numeric argument is supplied, a @samp{*} is appended before
+pathname expansion.
 
 @item glob-list-expansions (C-x g)
 The list of expansions that would have been generated by
 @code{glob-expand-word} is displayed, and the line is redrawn.
+If a numeric argument is supplied, a @samp{*} is appended before
+pathname expansion.
 
 @item display-shell-version (C-x C-v)
 Display version information about the current instance of Bash.
@@ -1376,13 +1421,26 @@ 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.
 
-@item emacs-editing-mode (C-e)
-When in @code{vi} editing mode, this causes a switch back to
-@code{emacs} editing mode, as if the command @samp{set -o emacs} had
-been executed.
+@item edit-and-execute-command (C-xC-e)
+Invoke an editor on the current command line, and execute the result as shell
+commands.
+Bash attempts to invoke
+@code{$FCEDIT}, @code{$EDITOR}, and @code{emacs}
+as the editor, in that order.
 
 @end ifset
 
+@ifclear BashFeatures
+@item emacs-editing-mode (C-e)
+When in @code{vi} command mode, this causes a switch to @code{emacs}
+editing mode.
+
+@item vi-editing-mode (M-C-j)
+When in @code{emacs} editing mode, this causes a switch to @code{vi}
+editing mode.
+
+@end ifclear
+
 @end ftable
 
 @node Readline vi Mode
@@ -1518,6 +1576,12 @@ If the @option{-o default} option was supplied to @code{complete} when the
 compspec was defined, Readline's default completion will be performed
 if the compspec generates no matches.
 
+When a compspec indicates that directory name completion is desired,
+the programmable completion functions force Readline to append a slash
+to completed names which are symbolic links to directories, subject to
+the value of the @var{mark-directories} Readline variable, regardless
+of the setting of the @var{mark-symlinked-directories} Readline variable.
+
 @node Programmable Completion Builtins
 @section Programmable Completion Builtins
 @cindex completion builtins
@@ -1553,7 +1617,7 @@ matches were generated.
 @item complete
 @btindex complete
 @example
-@code{complete [-abcdefgjkvu] [-o @var{comp-option}] [-A @var{action}] [-G @var{globpat}] [-W @var{wordlist}]
+@code{complete [-abcdefgjksuv] [-o @var{comp-option}] [-A @var{action}] [-G @var{globpat}] [-W @var{wordlist}]
 [-P @var{prefix}] [-S @var{suffix}] [-X @var{filterpat}] [-F @var{function}]
 [-C @var{command}] @var{name} [@var{name} @dots{}]}
 @code{complete -pr [@var{name} @dots{}]}
@@ -1586,7 +1650,8 @@ beyond the simple generation of completions.
 @table @code
 
 @item default
-Use readline's default completion if the compspec generates no matches.
+Use Readline's default filename completion if the compspec generates
+no matches.
 
 @item dirnames
 Perform directory name completion if the compspec generates no matches.
@@ -1596,6 +1661,10 @@ Tell Readline that the compspec generates filenames, so it can perform any
 filename\-specific processing (like adding a slash to directory names or
 suppressing trailing spaces).  This option is intended to be used with
 shell functions specified with @option{-F}.
+
+@item nospace
+Tell Readline not to append a space (the default) to words completed at
+the end of the line.
 @end table
 
 @item -A @var{action}
@@ -1655,6 +1724,9 @@ Shell reserved words.  May also be specified as @option{-k}.
 @item running
 Names of running jobs, if job control is active.
 
+@item service
+Service names.  May also be specified as @option{-s}.
+
 @item setopt
 Valid arguments for the @option{-o} option to the @code{set} builtin
 (@pxref{The Set Builtin}).
index db560b9cb565aaf0f1889cb1db7f154bff61ee87..89abe31aeb5a73713a3c542695fa420c4beb0d21 100644 (file)
@@ -17,7 +17,7 @@ This document describes the end user interface of the GNU Readline Library,
 a utility which aids in the consistency of user interface across discrete
 programs that need to provide a command line interface.
 
-Copyright (C) 1988-2001 Free Software Foundation, Inc.
+Copyright (C) 1988-2002 Free Software Foundation, Inc.
 
 Permission is granted to make and distribute verbatim copies of
 this manual provided the copyright notice and this permission notice
@@ -72,7 +72,7 @@ except that this permission notice may be stated in a translation approved
 by the Free Software Foundation.
 
 @vskip 0pt plus 1filll
-Copyright @copyright{} 1988-2001 Free Software Foundation, Inc.
+Copyright @copyright{} 1988-2002 Free Software Foundation, Inc.
 @end titlepage
 
 @ifinfo
index e2f2b30fd7f2baabb36adabd42004261d73287cc..ca9d1343b655ca2eae3a04d6bc99c87e1be69854 100644 (file)
@@ -35,11 +35,11 @@ KEYMAP_ENTRY_ARRAY emacs_standard_keymap = {
   /* Control keys. */
   { ISFUNC, rl_set_mark },                     /* Control-@ */
   { ISFUNC, rl_beg_of_line },                  /* Control-a */
-  { ISFUNC, rl_backward },                     /* Control-b */
+  { ISFUNC, rl_backward_char },                        /* Control-b */
   { ISFUNC, (rl_command_func_t *)0x0 },                /* Control-c */
   { ISFUNC, rl_delete },                       /* Control-d */
   { ISFUNC, rl_end_of_line },                  /* Control-e */
-  { ISFUNC, rl_forward },                      /* Control-f */
+  { ISFUNC, rl_forward_char },                 /* Control-f */
   { ISFUNC, rl_abort },                                /* Control-g */
   { ISFUNC, rl_rubout },                       /* Control-h */
   { ISFUNC, rl_complete },                     /* Control-i */
index 5b71bd701c4e373b8cd6e0e73b9494f303962331..d7fdb42efaae44612c512201ebe97021d2f627ae 100644 (file)
@@ -4,6 +4,22 @@
 # on which program is running, or what terminal is active.
 #
 
+# Copyright (C) 1989-2002 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.
+
 # In all programs, all terminals, make sure this is bound.
 "\C-x\C-r": re-read-init-file
 
index d8df38c8b52622710f98de5f00c1238125805a3b..636a1dc332305e84bd4254c2bcc9d8dcc280264c 100644 (file)
@@ -35,6 +35,10 @@ fileman: fileman.o
 rltest: rltest.o
        $(CC) $(LDFLAGS) -o $@ rltest.o -lreadline -ltermcap
 
+rlcat: rlcat.o
+       $(CC) $(LDFLAGS) -o $@ rlcat.o -lreadline -ltermcap
+
 fileman.o: fileman.c
 rltest.o: rltest.c
 rl.o: rl.c
+rlcat.o: rlcat.c
index 578491a416c54440fcf6e5bc1de29763d12c417f..340eee739f602c99e4738ebc093930c9bb5d9ba8 100644 (file)
@@ -1,3 +1,23 @@
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library 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.
+
+   The GNU Readline Library 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.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 /* 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. */
index fa0de1bea3ba5f521bb20e99e03712a71710eb61..45651dfb13792b71ec2e61c4b47d0309cece4bd2 100644 (file)
@@ -1,3 +1,23 @@
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library 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.
+
+   The GNU Readline Library 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.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 #include <stdio.h>
 
 #ifdef READLINE_LIBRARY
index 132e2bfea380c9ee5dd1d70e055d5e3dc8bf28af..9c6cf2c76c6133df1b7755f2066fafb5a9f841b4 100644 (file)
@@ -1,5 +1,25 @@
 /* manexamp.c -- The examples which appear in the documentation are here. */
 
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library 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.
+
+   The GNU Readline Library 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.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 #include <stdio.h>
 #include <readline/readline.h>
 
index 863618450696ad575d057c0324fa7d803b9e333c..d2604895e52fc0cb5467517ae9a27b95e08e362b 100644 (file)
@@ -5,6 +5,26 @@
  * usage: rl [-p prompt] [-u unit] [-d default] [-n nchars]
  */
 
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library 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.
+
+   The GNU Readline Library 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.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 #if defined (HAVE_CONFIG_H)
 #  include <config.h>
 #endif
diff --git a/lib/readline/examples/rlcat.c b/lib/readline/examples/rlcat.c
new file mode 100644 (file)
index 0000000..176b9f4
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * rlcat - cat(1) using readline
+ *
+ * usage: rlcat
+ */
+
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library 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.
+
+   The GNU Readline Library 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.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
+#include <sys/types.h>
+#include "posixstat.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+
+#ifndef errno
+extern int errno;
+#endif
+
+#if defined (READLINE_LIBRARY)
+#  include "readline.h"
+#  include "history.h"
+#else
+#  include <readline/readline.h>
+#  include <readline/history.h>
+#endif
+
+extern int optind;
+extern char *optarg;
+
+static int stdcat();
+
+static char *progname;
+static int vflag;
+
+static void
+usage()
+{
+  fprintf (stderr, "%s: usage: %s [-vEVN] [filename]\n", progname, progname);
+}
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  char *temp;
+  int opt, Vflag, Nflag;
+
+  progname = strrchr(argv[0], '/');
+  if (progname == 0)
+    progname = argv[0];
+  else
+    progname++;
+
+  vflag = Vflag = Nflag = 0;
+  while ((opt = getopt(argc, argv, "vEVN")) != EOF)
+    {
+      switch (opt)
+       {
+       case 'v':
+         vflag = 1;
+         break;
+       case 'V':
+         Vflag = 1;
+         break;
+       case 'E':
+         Vflag = 0;
+         break;
+       case 'N':
+         Nflag = 1;
+         break;
+       default:
+         usage ();
+         exit (2);
+       }
+    }
+
+  argc -= optind;
+  argv += optind;
+
+  if (isatty(0) == 0 || argc || Nflag)
+    return stdcat(argc, argv);
+
+  rl_variable_bind ("editing-mode", Vflag ? "vi" : "emacs");
+  while (temp = readline (""))
+    {
+      if (*temp)
+        add_history (temp);
+      printf ("%s\n", temp);
+    }
+
+  return (ferror (stdout));
+}
+
+static int
+fcopy(fp)
+     FILE *fp;
+{
+  int c;
+  char *x;
+
+  while ((c = getc(fp)) != EOF)
+    {
+      if (vflag && isascii ((unsigned char)c) && isprint((unsigned char)c) == 0)
+       {
+         x = rl_untranslate_keyseq (c);
+         if (fputs (x, stdout) != 0)
+           return 1;
+       }
+      else if (putchar (c) == EOF)
+        return 1;
+    }
+  return (ferror (stdout));
+}
+
+int
+stdcat (argc, argv)
+     int argc;
+     char **argv;
+{
+  int  i, fd, r;
+  char *s;
+  FILE *fp;
+
+  if (argc == 0)
+    return (fcopy(stdin));
+
+  for (i = 0, r = 1; i < argc; i++)
+    {
+      if (*argv[i] == '-' && argv[i][1] == 0)
+       fp = stdin;
+      else
+       {
+         fp = fopen (argv[i], "r");
+         if (fp == 0)
+           {
+             fprintf (stderr, "%s: %s: cannot open: %s\n", progname, argv[i], strerror(errno));
+             continue;
+           }
+        }
+      r = fcopy (fp);
+      if (fp != stdin)
+       fclose(fp);
+    }
+  return r;
+}
index 6250f900d42d0237420667ecf7b31cddc3dc380c..99f083b2b9c73d34090b5c58baf88568167c3aad 100644 (file)
@@ -4,6 +4,26 @@
 /*                                                                 */
 /* **************************************************************** */
 
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library 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.
+
+   The GNU Readline Library 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.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 #if defined (HAVE_CONFIG_H)
 #include <config.h>
 #endif
index e4f28012bf11da708ff621c7dc517559ad82059e..fe9a1da43d7ee73fc05fe0b9be89c52164fbd257 100644 (file)
@@ -60,7 +60,8 @@ static FUNMAP default_funmap[] = {
   { "abort", rl_abort },
   { "accept-line", rl_newline },
   { "arrow-key-prefix", rl_arrow_keys },
-  { "backward-char", rl_backward },
+  { "backward-byte", rl_backward_byte },
+  { "backward-char", rl_backward_char },
   { "backward-delete-char", rl_rubout },
   { "backward-kill-line", rl_backward_kill_line },
   { "backward-kill-word", rl_backward_kill_word },
@@ -91,7 +92,8 @@ static FUNMAP default_funmap[] = {
   { "end-of-line", rl_end_of_line },
   { "exchange-point-and-mark", rl_exchange_point_and_mark },
   { "forward-backward-delete-char", rl_rubout_or_delete },
-  { "forward-char", rl_forward },
+  { "forward-byte", rl_forward_byte },
+  { "forward-char", rl_forward_char },
   { "forward-search-history", rl_forward_search_history },
   { "forward-word", rl_forward_word },
   { "history-search-backward", rl_history_search_backward },
@@ -108,6 +110,7 @@ static FUNMAP default_funmap[] = {
   { "non-incremental-reverse-search-history", rl_noninc_reverse_search },
   { "non-incremental-forward-search-history-again", rl_noninc_forward_search_again },
   { "non-incremental-reverse-search-history-again", rl_noninc_reverse_search_again },
+  { "overwrite-mode", rl_overwrite_mode },
 #ifdef __CYGWIN__
   { "paste-from-clipboard", rl_paste_from_clipboard },
 #endif
index 04f6478e41ae2d6ef06206281556d37d3aefb91f..6c81196161d86df3e707b59eb7453a72523aaf95 100644 (file)
 #  include <unistd.h>
 #endif
 
-#if defined (HAVE_STRING_H)
-#  include <string.h>
-#else
-#  include <strings.h>
-#endif /* !HAVE_STRING_H */
+#include "rlmbutil.h"
 
 #include "history.h"
 #include "histlib.h"
@@ -58,6 +54,8 @@
 
 typedef int _hist_search_func_t PARAMS((const char *, int));
 
+extern int rl_byte_oriented;   /* declared in mbutil.c */
+
 static char error_pointer;
 
 static char *subst_lhs;
@@ -204,12 +202,30 @@ get_history_event (string, caller_index, delimiting_quote)
 
   /* Only a closing `?' or a newline delimit a substring search string. */
   for (local_index = i; c = string[i]; i++)
-    if ((!substring_okay && (whitespace (c) || c == ':' ||
-       (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) ||
-       string[i] == delimiting_quote)) ||
-       string[i] == '\n' ||
-       (substring_okay && string[i] == '?'))
-      break;
+#if defined (HANDLE_MULTIBYTE)
+    if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+      {
+       int v;
+       mbstate_t ps;
+
+       memset (&ps, 0, sizeof (mbstate_t));
+       /* These produce warnings because we're passing a const string to a
+          function that takes a non-const string. */
+       _rl_adjust_point (string, i, &ps);
+       if ((v = _rl_get_char_len (string + i, &ps)) > 1)
+         {
+           i += v - 1;
+           continue;
+         }
+      }
+    else
+#endif /* HANDLE_MULTIBYTE */
+      if ((!substring_okay && (whitespace (c) || c == ':' ||
+         (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) ||
+         string[i] == delimiting_quote)) ||
+         string[i] == '\n' ||
+         (substring_okay && string[i] == '?'))
+       break;
 
   which = i - local_index;
   temp = (char *)xmalloc (1 + which);
@@ -405,13 +421,33 @@ get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr)
      int *iptr, delimiter, is_rhs, *lenptr;
 {
   register int si, i, j, k;
-  char *s = (char *) NULL;
+  char *s;
+#if defined (HANDLE_MULTIBYTE)
+  mbstate_t ps;
+#endif
 
+  s = (char *)NULL;
   i = *iptr;
 
+#if defined (HANDLE_MULTIBYTE)
+  memset (&ps, 0, sizeof (mbstate_t));
+  _rl_adjust_point (str, i, &ps);
+#endif
+
   for (si = i; str[si] && str[si] != delimiter; si++)
-    if (str[si] == '\\' && str[si + 1] == delimiter)
-      si++;
+#if defined (HANDLE_MULTIBYTE)
+    if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+      {
+       int v;
+       if ((v = _rl_get_char_len (str + si, &ps)) > 1)
+         si += v - 1;
+       else if (str[si] == '\\' && str[si + 1] == delimiter)
+         si++;
+      }
+    else
+#endif /* HANDLE_MULTIBYTE */
+      if (str[si] == '\\' && str[si + 1] == delimiter)
+       si++;
 
   if (si > i || is_rhs)
     {
@@ -484,6 +520,11 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
   int substitute_globally, want_quotes, print_only;
   char *event, *temp, *result, *tstr, *t, c, *word_spec;
   int result_len;
+#if defined (HANDLE_MULTIBYTE)
+  mbstate_t ps;
+
+  memset (&ps, 0, sizeof (mbstate_t));
+#endif
 
   result = (char *)xmalloc (result_len = 128);
 
@@ -514,8 +555,21 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
         quote, then this expansion takes place inside of the
         quoted string.  If we have to search for some text ("!foo"),
         allow the delimiter to end the search string. */
-      if (i && (string[i - 1] == '\'' || string[i - 1] == '"'))
-       quoted_search_delimiter = string[i - 1];
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         int c, l;
+         l = _rl_find_prev_mbchar (string, i, MB_FIND_ANY);
+         c = string[l];
+         /* XXX - original patch had i - 1 ???  If i == 0 it would fail. */
+         if (i && (c == '\'' || c == '"'))
+           quoted_search_delimiter = c;
+       }
+      else
+#endif /* HANDLE_MULTIBYTE */    
+       if (i && (string[i - 1] == '\'' || string[i - 1] == '"'))
+         quoted_search_delimiter = string[i - 1];
+
       event = get_history_event (string, &i, quoted_search_delimiter);
     }
          
@@ -634,7 +688,20 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
            if (c == 's')
              {
                if (i + 2 < (int)strlen (string))
-                 delimiter = string[i + 2];
+                 {
+#if defined (HANDLE_MULTIBYTE)
+                   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+                     {
+                       _rl_adjust_point (string, i + 2, &ps);
+                       if (_rl_get_char_len (string + i + 2, &ps) > 1)
+                         delimiter = 0;
+                       else
+                         delimiter = string[i + 2];
+                     }
+                   else
+#endif /* HANDLE_MULTIBYTE */
+                     delimiter = string[i + 2];
+                 }
                else
                  break;        /* no search delimiter */
 
@@ -819,6 +886,11 @@ history_expand (hstring, output)
   int result_len;
   char *result;
 
+#if defined (HANDLE_MULTIBYTE)
+  char mb[MB_LEN_MAX];
+  mbstate_t ps;
+#endif
+
   /* Used when adding the string. */
   char *temp;
 
@@ -861,6 +933,10 @@ history_expand (hstring, output)
     }
   else
     {
+#if defined (HANDLE_MULTIBYTE)
+      memset (&ps, 0, sizeof (mbstate_t));
+#endif
+
       string = hstring;
       /* If not quick substitution, still maybe have to do expansion. */
 
@@ -868,8 +944,21 @@ history_expand (hstring, output)
         is NOT an expansion. */
       for (i = 0; string[i]; i++)
        {
+#if defined (HANDLE_MULTIBYTE)
+         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+           {
+             int v;
+             v = _rl_get_char_len (string + i, &ps);
+             if (v > 1)
+               {
+                 i += v - 1;
+                 continue;
+               }
+           }
+#endif /* HANDLE_MULTIBYTE */
+
          cc = string[i + 1];
-         /* The history_comment_char, if set, appearing that the beginning
+         /* The history_comment_char, if set, appearing at the beginning
             of a word signifies that the rest of the line should not have
             history expansion performed on it.
             Skip the rest of the line and break out of the loop. */
@@ -932,6 +1021,30 @@ history_expand (hstring, output)
          continue;
        }
 
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         int k, c;
+
+         c = tchar;
+         memset (mb, 0, sizeof (mb));
+         for (k = 0; k < MB_LEN_MAX; k++)
+           {
+             mb[k] = (char)c;
+             memset (&ps, 0, sizeof (mbstate_t));
+             if (_rl_get_char_len (mb, &ps) == -2)
+               c = string[++i];
+             else
+               break;
+           }
+         if (strlen (mb) > 1)
+           {
+             ADD_STRING (mb);
+             break;
+           }
+       }
+#endif /* HANDLE_MULTIBYTE */
+
       if (tchar == history_expansion_char)
        tchar = -3;
       else if (tchar == history_comment_char)
index ab3c6c1dc79e4ec02d7afd0b51c0dc3c0ba57b43..60a91251b7aec1a754ce02ca0623e7bde4c6b8fb 100644 (file)
 #  include <unistd.h>
 #endif
 
-#if defined (HAVE_STRING_H)
-#  include <string.h>
-#else
-#  include <strings.h>
-#endif /* !HAVE_STRING_H */
+#if defined (__EMX__) || defined (__CYGWIN__)
+#  undef HAVE_MMAP
+#endif
 
+#ifdef HAVE_MMAP
+#  include <sys/mman.h>
+
+#  ifdef MAP_FILE
+#    define MAP_RFLAGS (MAP_FILE|MAP_PRIVATE)
+#    define MAP_WFLAGS (MAP_FILE|MAP_SHARED)
+#  else
+#    define MAP_RFLAGS MAP_PRIVATE
+#    define MAP_WFLAGS MAP_SHARED
+#  endif
+
+#  ifndef MAP_FAILED
+#    define MAP_FAILED ((void *)-1)
+#  endif
+
+#endif /* HAVE_MMAP */
 
 /* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
    on win 95/98/nt), we want to open files with O_BINARY mode so that there
@@ -137,8 +151,8 @@ read_history_range (filename, from, to)
      const char *filename;
      int from, to;
 {
-  register int line_start, line_end;
-  char *input, *buffer;
+  register char *line_start, *line_end;
+  char *input, *buffer, *bufend;
   int file, current_line, chars_read;
   struct stat finfo;
   size_t file_size;
@@ -157,23 +171,39 @@ read_history_range (filename, from, to)
     {
 #if defined (EFBIG)
       errno = EFBIG;
+#elif defined (EOVERFLOW)
+      errno = EOVERFLOW;
 #endif
       goto error_and_exit;
     }
 
-  buffer = (char *)xmalloc (file_size + 1);
+#ifdef HAVE_MMAP
+  /* We map read/write and private so we can change newlines to NULs without
+     affecting the underlying object. */
+  buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0);
+  if ((void *)buffer == MAP_FAILED)
+    goto error_and_exit;
+  chars_read = file_size;
+#else
+  buffer = (char *)malloc (file_size + 1);
+  if (buffer == 0)
+    goto error_and_exit;
 
   chars_read = read (file, buffer, file_size);
+#endif
   if (chars_read < 0)
     {
   error_and_exit:
+      chars_read = errno;
       if (file >= 0)
        close (file);
 
       FREE (input);
+#ifndef HAVE_MMAP
       FREE (buffer);
+#endif
 
-      return (errno);
+      return (chars_read);
     }
 
   close (file);
@@ -183,29 +213,25 @@ read_history_range (filename, from, to)
     to = chars_read;
 
   /* Start at beginning of file, work to end. */
-  line_start = line_end = current_line = 0;
+  bufend = buffer + chars_read;
+  current_line = 0;
 
   /* Skip lines until we are at FROM. */
-  while (line_start < chars_read && current_line < from)
-    {
-      for (line_end = line_start; line_end < chars_read; line_end++)
-       if (buffer[line_end] == '\n')
-         {
-           current_line++;
-           line_start = line_end + 1;
-           if (current_line == from)
-             break;
-         }
-    }
+  for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++)
+    if (*line_end == '\n')
+      {
+       current_line++;
+       line_start = line_end + 1;
+      }
 
   /* If there are lines left to gobble, then gobble them now. */
-  for (line_end = line_start; line_end < chars_read; line_end++)
-    if (buffer[line_end] == '\n')
+  for (line_end = line_start; line_end < bufend; line_end++)
+    if (*line_end == '\n')
       {
-       buffer[line_end] = '\0';
+       *line_end = '\0';
 
-       if (buffer[line_start])
-         add_history (buffer + line_start);
+       if (*line_start)
+         add_history (line_start);
 
        current_line++;
 
@@ -216,7 +242,11 @@ read_history_range (filename, from, to)
       }
 
   FREE (input);
+#ifndef HAVE_MMAP
   FREE (buffer);
+#else
+  munmap (buffer, file_size);
+#endif
 
   return (0);
 }
@@ -229,9 +259,8 @@ history_truncate_file (fname, lines)
      const char *fname;
      int lines;
 {
-  register int i;
+  char *buffer, *filename, *bp;
   int file, chars_read, rv;
-  char *buffer, *filename;
   struct stat finfo;
   size_t file_size;
 
@@ -276,7 +305,13 @@ history_truncate_file (fname, lines)
       goto truncate_exit;
     }
 
-  buffer = (char *)xmalloc (file_size + 1);
+  buffer = (char *)malloc (file_size + 1);
+  if (buffer == 0)
+    {
+      close (file);
+      goto truncate_exit;
+    }
+
   chars_read = read (file, buffer, file_size);
   close (file);
 
@@ -288,9 +323,9 @@ history_truncate_file (fname, lines)
 
   /* Count backwards from the end of buffer until we have passed
      LINES lines. */
-  for (i = chars_read - 1; lines && i; i--)
+  for (bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
     {
-      if (buffer[i] == '\n')
+      if (*bp == '\n')
        lines--;
     }
 
@@ -299,22 +334,22 @@ history_truncate_file (fname, lines)
      anything.  It's the first line if we don't find a newline between
      the current value of i and 0.  Otherwise, write from the start of
      this line until the end of the buffer. */
-  for ( ; i; i--)
-    if (buffer[i] == '\n')
+  for ( ; bp > buffer; bp--)
+    if (*bp == '\n')
       {
-       i++;
+       bp++;
        break;
       }
 
   /* Write only if there are more lines in the file than we want to
      truncate to. */
-  if (i && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
+  if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
     {
-      write (file, buffer + i, chars_read - i);
+      write (file, bp, chars_read - (bp - buffer));
 
 #if defined (__BEOS__)
       /* BeOS ignores O_TRUNC. */
-      ftruncate (file, chars_read - i);
+      ftruncate (file, chars_read - (bp - buffer));
 #endif
 
       close (file);
@@ -339,8 +374,13 @@ history_do_write (filename, nelements, overwrite)
   register int i;
   char *output;
   int file, mode, rv;
+  size_t cursize;
 
+#ifdef HAVE_MMAP
+  mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY;
+#else
   mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
+#endif
   output = history_filename (filename);
   rv = 0;
 
@@ -350,6 +390,10 @@ history_do_write (filename, nelements, overwrite)
       return (errno);
     }
 
+#ifdef HAVE_MMAP
+  cursize = overwrite ? 0 : lseek (file, 0, SEEK_END);
+#endif
+
   if (nelements > history_length)
     nelements = history_length;
 
@@ -367,7 +411,28 @@ history_do_write (filename, nelements, overwrite)
       buffer_size += 1 + strlen (the_history[i]->line);
 
     /* Allocate the buffer, and fill it. */
-    buffer = (char *)xmalloc (buffer_size);
+#ifdef HAVE_MMAP
+    if (ftruncate (file, buffer_size+cursize) == -1)
+      goto mmap_error;
+    buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize);
+    if ((void *)buffer == MAP_FAILED)
+      {
+mmap_error:
+       rv = errno;
+       FREE (output);
+       close (file);
+       return rv;
+      }
+#else    
+    buffer = (char *)malloc (buffer_size);
+    if (buffer == 0)
+      {
+       rv = errno;
+       FREE (output);
+       close (file);
+       return rv;
+      }
+#endif
 
     for (j = 0, i = history_length - nelements; i < history_length; i++)
       {
@@ -376,9 +441,14 @@ history_do_write (filename, nelements, overwrite)
        buffer[j++] = '\n';
       }
 
+#ifdef HAVE_MMAP
+    if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0)
+      rv = errno;
+#else
     if (write (file, buffer, buffer_size) < 0)
       rv = errno;
     free (buffer);
+#endif
   }
 
   close (file);
index bc948b08003546704d319bc7c58f94b5aa209369..c39af71814c81d5c7b73fe43497fc2e77ba7d333 100644 (file)
 #if !defined (_HISTLIB_H_)
 #define _HISTLIB_H_
 
+#if defined (HAVE_STRING_H)
+#  include <string.h>
+#else
+#  include <strings.h>
+#endif /* !HAVE_STRING_H */
+
 #if !defined (STREQ)
 #define STREQ(a, b)    (((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0))
 #define STREQN(a, b, n) (((n) == 0) ? (1) \
@@ -29,9 +35,6 @@
 #endif
 
 #ifndef savestring
-#  ifndef strcpy
-extern char *strcpy ();
-#  endif
 #define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
 #endif
 
index e2d65ea504de46a9b04d7f99b21d325ce696f5ed..4242f33efe19e05dd120ec0aa9c2bc8946f49943 100644 (file)
 #  include <unistd.h>
 #endif
 
-#if defined (HAVE_STRING_H)
-#  include <string.h>
-#else
-#  include <strings.h>
-#endif /* !HAVE_STRING_H */
-
 #include "history.h"
 #include "histlib.h"
 
@@ -349,19 +343,19 @@ stifle_history (max)
   max_input_history = history_max_entries = max;
 }
 
-/* Stop stifling the history.  This returns the previous amount the 
-   history was stifled by.  The value is positive if the history was
-   stifled,  negative if it wasn't. */
+/* Stop stifling the history.  This returns the previous maximum
+   number of history entries.  The value is positive if the history
+   was stifled,  negative if it wasn't. */
 int
 unstifle_history ()
 {
   if (history_stifled)
     {
       history_stifled = 0;
-      return (-history_max_entries);
+      return (history_max_entries);
     }
-
-  return (history_max_entries);
+  else
+    return (-history_max_entries);
 }
 
 int
index 76303f4c3993aafcd90284181a0e0918de3eee5b..d94fd6cd9c656b1acdf8af91ae59e3529b201f97 100644 (file)
 #else
 #  include "ansi_stdlib.h"
 #endif /* HAVE_STDLIB_H */
+
 #if defined (HAVE_UNISTD_H)
 #  ifdef _MINIX
 #    include <sys/types.h>
 #  endif
 #  include <unistd.h>
 #endif
-#if defined (HAVE_STRING_H)
-#  include <string.h>
-#else
-#  include <strings.h>
-#endif /* !HAVE_STRING_H */
 
 #include "history.h"
 #include "histlib.h"
index e34558bf8586aaa21f8dfedf78f8b3d53eaf1d49..841f05d1af9ccf55a7cae4cc59beee899c6f0e3a 100644 (file)
@@ -63,6 +63,7 @@ extern int errno;
 
 /* System-specific feature definitions and include files. */
 #include "rldefs.h"
+#include "rlmbutil.h"
 
 /* Some standard library routines. */
 #include "readline.h"
@@ -86,8 +87,7 @@ 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_unget_char PARAMS((int));
-static void rl_gather_tyi PARAMS((void));
+static int rl_gather_tyi PARAMS((void));
 
 /* **************************************************************** */
 /*                                                                 */
@@ -139,8 +139,8 @@ rl_get_char (key)
 /* Stuff KEY into the *front* of the input buffer.
    Returns non-zero if successful, zero if there is
    no space left in the buffer. */
-static int
-rl_unget_char (key)
+int
+_rl_unget_char (key)
      int key;
 {
   if (ibuffer_space ())
@@ -154,9 +154,10 @@ rl_unget_char (key)
   return (0);
 }
 
-/* If a character is available to be read, then read it
-   and stuff it into IBUFFER.  Otherwise, just return. */
-static void
+/* 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;
@@ -177,13 +178,17 @@ rl_gather_tyi ()
   FD_SET (tty, &exceptfds);
   timeout.tv_sec = 0;
   timeout.tv_usec = _keyboard_input_timeout;
-  if (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) <= 0)
-    return;    /* Nothing to read. */
+  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)
@@ -196,14 +201,14 @@ rl_gather_tyi ()
 
       fcntl (tty, F_SETFL, tem);
       if (chars_avail == -1 && errno == EAGAIN)
-       return;
+       return 0;
     }
 #endif /* O_NDELAY */
 
   /* If there's nothing available, don't waste time trying to read
      something. */
   if (chars_avail <= 0)
-    return;
+    return 0;
 
   tem = ibuffer_space ();
 
@@ -227,6 +232,8 @@ rl_gather_tyi ()
       if (chars_avail)
        rl_stuff_char (input);
     }
+
+  return 1;
 }
 
 int
@@ -242,7 +249,11 @@ rl_set_keyboard_input_timeout (u)
 }
 
 /* Is there input available to be read on the readline input file
-   descriptor?  Only works if the system has select(2) or FIONREAD. */
+   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 ()
 {
@@ -277,6 +288,18 @@ _rl_input_available ()
   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;     
@@ -294,7 +317,7 @@ _rl_insert_typein (c)
     string[i++] = key;
 
   if (t)
-    rl_unget_char (key);
+    _rl_unget_char (key);
 
   string[i] = '\0';
   rl_insert_text (string);
@@ -375,7 +398,11 @@ rl_read_key ()
              (*rl_event_hook) ();
              if (rl_done)              /* XXX - experimental */
                return ('\n');
-             rl_gather_tyi ();
+             if (rl_gather_tyi () < 0) /* XXX - EIO */
+               {
+                 rl_done = 1;
+                 return ('\n');
+               }
            }
        }
       else
@@ -441,3 +468,73 @@ rl_getc (stream)
        return (EOF);
     }
 }
+
+#if defined (HANDLE_MULTIBYTE)
+/* read multibyte char */
+int
+_rl_read_mbchar (mbchar, size)
+     char *mbchar;
+     int size;
+{
+  int mb_len = 0;
+  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));
+  
+  while (mb_len < size)
+    {
+      RL_SETSTATE(RL_STATE_MOREINPUT);
+      mbchar[mb_len++] = rl_read_key ();
+      RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+      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 > (size_t)(0))
+       break;
+    }
+
+  return mb_len;
+}
+
+/* Read a multibyte-character string whose first character is FIRST into
+   the buffer MB of length MBLEN.  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, mblen)
+     int first;
+     char *mb;
+     int mblen;
+{
+  int i, c;
+  mbstate_t ps;
+
+  c = first;
+  memset (mb, 0, mblen);
+  for (i = 0; i < mblen; 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 */
index 2e3e16b8a9993edd99cf82a75e450b7a2b01cda7..c1ea5b30852eddbaae4e35a254bec0e9339e78b7 100644 (file)
@@ -4,7 +4,7 @@
 /*                                                                 */
 /* **************************************************************** */
 
-/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file contains the Readline Library (the Library), a set of
    routines for providing Emacs style line input to programs that ask
@@ -45,6 +45,8 @@
 #endif
 
 #include "rldefs.h"
+#include "rlmbutil.h"
+
 #include "readline.h"
 #include "history.h"
 
@@ -165,8 +167,12 @@ rl_search_history (direction, invoking_key)
   HIST_ENTRY **hlist;
 
   register int i;
-  int orig_point, orig_line, last_found_line;
+  int orig_point, orig_mark, orig_line, last_found_line;
   int c, found, failed, sline_len;
+  int n, wstart, wlen;
+#if defined (HANDLE_MULTIBYTE)
+  char mb[MB_LEN_MAX];
+#endif
 
   /* The line currently being searched. */
   char *sline;
@@ -184,6 +190,7 @@ rl_search_history (direction, invoking_key)
 
   RL_SETSTATE(RL_STATE_ISEARCH);
   orig_point = rl_point;
+  orig_mark = rl_mark;
   last_found_line = orig_line = where_history ();
   reverse = direction < 0;
   hlist = history_list ();
@@ -246,6 +253,12 @@ rl_search_history (direction, invoking_key)
       c = rl_read_key ();
       RL_UNSETSTATE(RL_STATE_MOREINPUT);
 
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       c = _rl_read_mbstring (c, mb, MB_LEN_MAX);
+#endif
+
+      /* Translate the keys we do something with to opcodes. */
       if (c >= 0 && _rl_keymap[c].type == ISFUNC)
        {
          f = _rl_keymap[c].function;
@@ -254,33 +267,53 @@ rl_search_history (direction, invoking_key)
            c = reverse ? -1 : -2;
          else if (f == rl_forward_search_history)
            c =  !reverse ? -1 : -2;
+         else if (f == rl_rubout)
+           c = -3;
+         else if (c == CTRL ('G'))
+           c = -4;
+         else if (c == CTRL ('W'))     /* XXX */
+           c = -5;
+         else if (c == CTRL ('Y'))     /* XXX */
+           c = -6;
        }
 
-#if 0
-      /* Let NEWLINE (^J) terminate the search for people who don't like
-        using ESC.  ^M can still be used to terminate the search and
-        immediately execute the command. */
-      if (c == ESC || c == NEWLINE)
-#else
       /* The characters in isearch_terminators (set from the user-settable
         variable isearch-terminators) are used to terminate the search but
         not subsequently execute the character as a command.  The default
         value is "\033\012" (ESC and C-J). */
       if (strchr (isearch_terminators, c))
-#endif
        {
          /* ESC still terminates the search, but if there is pending
             input or if input arrives within 0.1 seconds (on systems
             with select(2)) it is used as a prefix character
             with rl_execute_next.  WATCH OUT FOR THIS!  This is intended
             to allow the arrow keys to be used like ^F and ^B are used
-            to terminate the search and execute the movement command. */
-         if (c == ESC && _rl_input_available ())       /* XXX */
+            to terminate the search and execute the movement command.
+            XXX - since _rl_input_available depends on the application-
+            settable keyboard timeout value, this could alternatively
+            use _rl_input_queued(100000) */
+         if (c == ESC && _rl_input_available ())
            rl_execute_next (ESC);
          break;
        }
 
-      if (c >= 0 && (CTRL_CHAR (c) || META_CHAR (c) || c == RUBOUT) && c != CTRL ('G'))
+#define ENDSRCH_CHAR(c) \
+  ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
+
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         if (c >= 0 && strlen (mb) == 1 && ENDSRCH_CHAR (c))
+           {
+             /* This sets rl_pending_input to c; it will be picked up the next
+                time rl_read_key is called. */
+             rl_execute_next (c);
+             break;
+           }
+       }
+      else
+#endif
+      if (c >= 0 && ENDSRCH_CHAR (c))
        {
          /* This sets rl_pending_input to c; it will be picked up the next
             time rl_read_key is called. */
@@ -318,10 +351,23 @@ rl_search_history (direction, invoking_key)
          reverse = direction < 0;
          break;
 
-       case CTRL ('G'):
-         strcpy (rl_line_buffer, lines[orig_line]);
+       /* delete character from search string. */
+       case -3:        /* C-H, DEL */
+         /* This is tricky.  To do this right, we need to keep a
+            stack of search positions for the current search, with
+            sentinels marking the beginning and end.  But this will
+            do until we have a real isearch-undo. */
+         if (search_string_index == 0)
+           rl_ding ();
+         else
+           search_string[--search_string_index] = '\0';
+
+         break;
+
+       case -4:        /* C-G */
+         rl_replace_line (lines[orig_line], 0);
          rl_point = orig_point;
-         rl_end = strlen (rl_line_buffer);
+         rl_mark = orig_mark;
          rl_restore_prompt();
          rl_clear_message ();
          if (allocated_line)
@@ -330,20 +376,53 @@ rl_search_history (direction, invoking_key)
          RL_UNSETSTATE(RL_STATE_ISEARCH);
          return 0;
 
-#if 0
-       /* delete character from search string. */
-       case -3:
-         if (search_string_index == 0)
-           rl_ding ();
-         else
+       case -5:        /* C-W */
+         /* skip over portion of line we already matched */
+         wstart = rl_point + search_string_index;
+         if (wstart >= rl_end)
+           {
+             rl_ding ();
+             break;
+           }
+
+         /* if not in a word, move to one. */
+         if (rl_alphabetic(rl_line_buffer[wstart]) == 0)
            {
-             search_string[--search_string_index] = '\0';
-             /* This is tricky.  To do this right, we need to keep a
-                stack of search positions for the current search, with
-                sentinels marking the beginning and end. */
+             rl_ding ();
+             break;
            }
+         n = wstart;
+         while (n < rl_end && rl_alphabetic(rl_line_buffer[n]))
+           n++;
+         wlen = n - wstart + 1;
+         if (search_string_index + wlen + 1 >= search_string_size)
+           {
+             search_string_size += wlen + 1;
+             search_string = (char *)xrealloc (search_string, search_string_size);
+           }
+         for (; wstart < n; wstart++)
+           search_string[search_string_index++] = rl_line_buffer[wstart];
+         search_string[search_string_index] = '\0';
+         break;
+
+       case -6:        /* C-Y */
+         /* skip over portion of line we already matched */
+         wstart = rl_point + search_string_index;
+         if (wstart >= rl_end)
+           {
+             rl_ding ();
+             break;
+           }
+         n = rl_end - wstart + 1;
+         if (search_string_index + n + 1 >= search_string_size)
+           {
+             search_string_size += n + 1;
+             search_string = (char *)xrealloc (search_string, search_string_size);
+           }
+         for (n = wstart; n < rl_end; n++)
+           search_string[search_string_index++] = rl_line_buffer[n];
+         search_string[search_string_index] = '\0';
          break;
-#endif
 
        default:
          /* Add character to search string and continue search. */
@@ -352,7 +431,16 @@ rl_search_history (direction, invoking_key)
              search_string_size += 128;
              search_string = (char *)xrealloc (search_string, search_string_size);
            }
-         search_string[search_string_index++] = c;
+#if defined (HANDLE_MULTIBYTE)
+         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+           {
+             int j, l;
+             for (j = 0, l = strlen (mb); j < l; )
+               search_string[search_string_index++] = mb[j++];
+           }
+         else
+#endif
+           search_string[search_string_index++] = c;
          search_string[search_string_index] = '\0';
          break;
        }
@@ -417,17 +505,9 @@ rl_search_history (direction, invoking_key)
         the location. */
       if (found)
        {
-         int line_len;
-
          prev_line_found = lines[i];
-         line_len = strlen (lines[i]);
-
-         if (line_len >= rl_line_buffer_len)
-           rl_extend_line_buffer (line_len);
-
-         strcpy (rl_line_buffer, lines[i]);
+         rl_replace_line (lines[i], 0);
          rl_point = line_index;
-         rl_end = line_len;
          last_found_line = i;
          rl_display_search (search_string, reverse, (i == orig_line) ? -1 : i);
        }
@@ -443,25 +523,32 @@ rl_search_history (direction, invoking_key)
 
   rl_restore_prompt ();
 
-#if 1
   /* Save the search string for possible later use. */
   FREE (last_isearch_string);
   last_isearch_string = search_string;
   last_isearch_string_len = search_string_index;
-#else
-  /* Free the search string. */
-  free (search_string);
-#endif
 
   if (last_found_line < orig_line)
     rl_get_previous_history (orig_line - last_found_line, 0);
   else
     rl_get_next_history (last_found_line - orig_line, 0);
 
-  /* If the string was not found, put point at the end of the line. */
+  /* If the string was not found, put point at the end of the last matching
+     line.  If last_found_line == orig_line, we didn't find any matching
+     history lines at all, so put point back in its original position. */
   if (line_index < 0)
-    line_index = strlen (rl_line_buffer);
+    {
+      if (last_found_line == orig_line)
+       line_index = orig_point;
+      else
+       line_index = strlen (rl_line_buffer);
+      rl_mark = orig_mark;
+    }
+
   rl_point = line_index;
+  /* Don't worry about where to put the mark here; rl_get_previous_history
+     and rl_get_next_history take care of it. */
+
   rl_clear_message ();
 
   FREE (allocated_line);
index 93cc8208f8b6174c31276b3731119f2944326c35..66fa2a5ec14a07650b6a195dc4402be63066ecf2 100644 (file)
@@ -49,8 +49,9 @@ typedef struct _keymap_entry {
 
 /* This must be large enough to hold bindings for all of the characters
    in a desired character set (e.g, 128 for ASCII, 256 for ISO Latin-x,
-   and so on). */
-#define KEYMAP_SIZE 256
+   and so on) plus one for subsequence matching. */
+#define KEYMAP_SIZE 257
+#define ANYOTHERKEY KEYMAP_SIZE-1
 
 /* I wanted to make the above structure contain a union of:
    union { rl_command_func_t *function; struct _keymap_entry *keymap; } value;
index 90ce6e45db35806693708094fcd793b17d63c3f5..a616b920d903b592411bb3e4e61bfbef5919df7b 100644 (file)
@@ -201,18 +201,21 @@ int
 rl_kill_word (count, key)
      int count, key;
 {
-  int orig_point = rl_point;
+  int orig_point;
 
   if (count < 0)
     return (rl_backward_kill_word (-count, key));
   else
     {
+      orig_point = rl_point;
       rl_forward_word (count, key);
 
       if (rl_point != orig_point)
        rl_kill_text (orig_point, rl_point);
 
       rl_point = orig_point;
+      if (rl_editing_mode == emacs_mode)
+       rl_mark = rl_point;
     }
   return 0;
 }
@@ -222,16 +225,20 @@ int
 rl_backward_kill_word (count, ignore)
      int count, ignore;
 {
-  int orig_point = rl_point;
+  int orig_point;
 
   if (count < 0)
     return (rl_kill_word (-count, ignore));
   else
     {
+      orig_point = rl_point;
       rl_backward_word (count, ignore);
 
       if (rl_point != orig_point)
        rl_kill_text (orig_point, rl_point);
+
+      if (rl_editing_mode == emacs_mode)
+       rl_mark = rl_point;
     }
   return 0;
 }
@@ -242,16 +249,19 @@ int
 rl_kill_line (direction, ignore)
      int direction, ignore;
 {
-  int orig_point = rl_point;
+  int orig_point;
 
   if (direction < 0)
     return (rl_backward_kill_line (1, ignore));
   else
     {
+      orig_point = rl_point;
       rl_end_of_line (1, ignore);
       if (orig_point != rl_point)
        rl_kill_text (orig_point, rl_point);
       rl_point = orig_point;
+      if (rl_editing_mode == emacs_mode)
+       rl_mark = rl_point;
     }
   return 0;
 }
@@ -262,7 +272,7 @@ int
 rl_backward_kill_line (direction, ignore)
      int direction, ignore;
 {
-  int orig_point = rl_point;
+  int orig_point;
 
   if (direction < 0)
     return (rl_kill_line (1, ignore));
@@ -272,8 +282,12 @@ rl_backward_kill_line (direction, ignore)
        rl_ding ();
       else
        {
+         orig_point = rl_point;
          rl_beg_of_line (1, ignore);
-         rl_kill_text (orig_point, rl_point);
+         if (rl_point != orig_point)
+           rl_kill_text (orig_point, rl_point);
+         if (rl_editing_mode == emacs_mode)
+           rl_mark = rl_point;
        }
     }
   return 0;
@@ -287,6 +301,7 @@ rl_kill_full_line (count, ignore)
   rl_begin_undo_group ();
   rl_point = 0;
   rl_kill_text (rl_point, rl_end);
+  rl_mark = 0;
   rl_end_undo_group ();
   return 0;
 }
@@ -321,6 +336,8 @@ rl_unix_word_rubout (count, key)
        }
 
       rl_kill_text (orig_point, rl_point);
+      if (rl_editing_mode == emacs_mode)
+       rl_mark = rl_point;
     }
   return 0;
 }
@@ -341,6 +358,8 @@ rl_unix_line_discard (count, key)
     {
       rl_kill_text (rl_point, 0);
       rl_point = 0;
+      if (rl_editing_mode == emacs_mode)
+       rl_mark = rl_point;
     }
   return 0;
 }
@@ -353,17 +372,14 @@ region_kill_internal (delete)
 {
   char *text;
 
-  if (rl_mark == rl_point)
+  if (rl_mark != rl_point)
     {
-      _rl_last_command_was_kill++;
-      return 0;
+      text = rl_copy_text (rl_point, rl_mark);
+      if (delete)
+       rl_delete_text (rl_point, rl_mark);
+      _rl_copy_to_kill_ring (text, rl_point < rl_mark);
     }
 
-  text = rl_copy_text (rl_point, rl_mark);
-  if (delete)
-    rl_delete_text (rl_point, rl_mark);
-  _rl_copy_to_kill_ring (text, rl_point < rl_mark);
-
   _rl_last_command_was_kill++;
   return 0;
 }
@@ -530,6 +546,8 @@ rl_yank_nth_arg_internal (count, ignore, history_skip)
 
   rl_begin_undo_group ();
 
+  _rl_set_mark_at_pos (rl_point);
+
 #if defined (VI_MODE)
   /* Vi mode always inserts a space before yanking the argument, and it
      inserts it right *after* rl_point. */
@@ -623,6 +641,7 @@ rl_paste_from_clipboard (count, key)
        }
       else
         ptr = data;
+      _rl_set_mark_at_pos (rl_point);
       rl_insert_text (ptr);
       if (ptr != data)
        free (ptr);
index 347f89bf9906606ec05853a03728327b9796d8c2..b73c3af9aa47304b02200df7edfbf717f6388dc5 100644 (file)
@@ -49,8 +49,6 @@
 #include "rlprivate.h"
 #include "xmalloc.h"
 
-#define SWAP(s, e)  do { int t; t = s; s = e; e = t; } while (0)
-
 /* **************************************************************** */
 /*                                                                 */
 /*                     Hacking Keyboard Macros                     */
@@ -61,9 +59,6 @@
    then it is a malloc ()'ed string where input is coming from. */
 char *rl_executing_macro = (char *)NULL;
 
-/* Non-zero means to save keys that we dispatch on in a kbd macro. */
-int _rl_defining_kbd_macro = 0;
-
 /* The offset in the above string to the next character to be read. */
 static int executing_macro_index;
 
@@ -186,7 +181,6 @@ _rl_kill_kbd_macro ()
   rl_executing_macro = (char *) NULL;
   executing_macro_index = 0;
 
-  _rl_defining_kbd_macro = 0;
   RL_UNSETSTATE(RL_STATE_MACRODEF);
 }
 
@@ -200,7 +194,7 @@ int
 rl_start_kbd_macro (ignore1, ignore2)
      int ignore1, ignore2;
 {
-  if (_rl_defining_kbd_macro)
+  if (RL_ISSTATE (RL_STATE_MACRODEF))
     {
       _rl_abort_internal ();
       return -1;
@@ -214,7 +208,6 @@ rl_start_kbd_macro (ignore1, ignore2)
   else
     current_macro_index = 0;
 
-  _rl_defining_kbd_macro = 1;
   RL_SETSTATE(RL_STATE_MACRODEF);
   return 0;
 }
@@ -226,7 +219,7 @@ int
 rl_end_kbd_macro (count, ignore)
      int count, ignore;
 {
-  if (_rl_defining_kbd_macro == 0)
+  if (RL_ISSTATE (RL_STATE_MACRODEF) == 0)
     {
       _rl_abort_internal ();
       return -1;
@@ -235,7 +228,6 @@ rl_end_kbd_macro (count, ignore)
   current_macro_index -= rl_key_sequence_length - 1;
   current_macro[current_macro_index] = '\0';
 
-  _rl_defining_kbd_macro = 0;
   RL_UNSETSTATE(RL_STATE_MACRODEF);
 
   return (rl_call_last_kbd_macro (--count, 0));
@@ -250,7 +242,7 @@ rl_call_last_kbd_macro (count, ignore)
   if (current_macro == 0)
     _rl_abort_internal ();
 
-  if (_rl_defining_kbd_macro)
+  if (RL_ISSTATE (RL_STATE_MACRODEF))
     {
       rl_ding ();              /* no recursive macros */
       current_macro[--current_macro_index] = '\0';     /* erase this char */
diff --git a/lib/readline/mbutil.c b/lib/readline/mbutil.c
new file mode 100644 (file)
index 0000000..50302f0
--- /dev/null
@@ -0,0 +1,337 @@
+/* mbutil.c -- readline multibyte character utility functions */
+
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library 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.
+
+   The GNU Readline Library 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.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include "posixjmp.h"
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>     /* for _POSIX_VERSION */
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <stdio.h>
+#include <ctype.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#if defined (TIOCSTAT_IN_SYS_IOCTL)
+#  include <sys/ioctl.h>
+#endif /* TIOCSTAT_IN_SYS_IOCTL */
+
+/* Some standard library routines. */
+#include "readline.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+/* Declared here so it can be shared between the readline and history
+   libraries. */
+#if defined (HANDLE_MULTIBYTE)
+int rl_byte_oriented = 0;
+#else
+int rl_byte_oriented = 1;
+#endif
+
+/* **************************************************************** */
+/*                                                                 */
+/*             Multibyte Character Utility Functions               */
+/*                                                                 */
+/* **************************************************************** */
+
+#if defined(HANDLE_MULTIBYTE)
+
+static int
+_rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
+     char *string;
+     int seed, count, find_non_zero;
+{
+  size_t tmp = 0;
+  mbstate_t ps;
+  int point = 0;
+  wchar_t wc;
+
+  memset(&ps, 0, sizeof (mbstate_t));
+  if (seed < 0)
+    seed = 0;
+  if (count <= 0)
+    return seed;
+
+  point = seed + _rl_adjust_point(string, seed, &ps);
+  /* if this is true, means that seed was not pointed character
+     started byte.  So correct the point and consume count */
+  if (seed < point)
+    count --;
+
+  while (count > 0)  
+    {
+      tmp = mbrtowc (&wc, string+point, strlen(string + point), &ps);
+      if ((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2)
+       {
+         /* invalid bytes. asume a byte represents a character */
+         point++;
+         count--;
+         /* reset states. */
+         memset(&ps, 0, sizeof(mbstate_t));
+       }
+      else if (tmp == (size_t)0)
+       /* found '\0' char */
+       break;
+      else
+       {
+         /* valid bytes */
+         point += tmp;
+         if (find_non_zero)
+           {
+             if (wcwidth (wc) == 0)
+               continue;
+             else
+               count--;
+           }
+         else
+           count--;
+       }
+    }
+
+  if (find_non_zero)
+    {
+      tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
+      while (wcwidth (wc) == 0)
+       {
+         point += tmp;
+         tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
+         if (tmp == (size_t)(0) || tmp == (size_t)(-1) || tmp == (size_t)(-2))
+           break;
+       }
+    }
+    return point;
+}
+
+static int
+_rl_find_prev_mbchar_internal (string, seed, find_non_zero)
+     char *string;
+     int seed, find_non_zero;
+{
+  mbstate_t ps;
+  int prev, non_zero_prev, point, length;
+  size_t tmp;
+  wchar_t wc;
+
+  memset(&ps, 0, sizeof(mbstate_t));
+  length = strlen(string);
+  
+  if (seed < 0)
+    return 0;
+  else if (length < seed)
+    return length;
+
+  prev = non_zero_prev = point = 0;
+  while (point < seed)
+    {
+      tmp = mbrtowc (&wc, string + point, length - point, &ps);
+      if ((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2)
+       {
+         /* in this case, bytes are invalid or shorted to compose
+            multibyte char, so assume that the first byte represents
+            a single character anyway. */
+         tmp = 1;
+         /* clear the state of the byte sequence, because
+            in this case effect of mbstate is undefined  */
+         memset(&ps, 0, sizeof (mbstate_t));
+       }
+      else if (tmp == 0)
+       break;                  /* Found '\0' char.  Can this happen? */
+      else
+       {
+         if (find_non_zero)
+           {
+             if (wcwidth (wc) != 0)
+               prev = point;
+           }
+         else
+           prev = point;  
+       }
+
+      point += tmp;
+    }
+
+  return prev;
+}
+
+/* return the number of bytes parsed from the multibyte sequence starting
+   at src, if a non-L'\0' wide character was recognized. It returns 0, 
+   if a L'\0' wide character was recognized. It  returns (size_t)(-1), 
+   if an invalid multibyte sequence was encountered. It returns (size_t)(-2) 
+   if it couldn't parse a complete  multibyte character.  */
+int
+_rl_get_char_len (src, ps)
+     char *src;
+     mbstate_t *ps;
+{
+  size_t tmp;
+
+  tmp = mbrlen((const char *)src, (size_t)strlen (src), ps);
+  if (tmp == (size_t)(-2))
+    {
+      /* shorted to compose multibyte char */
+      memset (ps, 0, sizeof(mbstate_t));
+      return -2;
+    }
+  else if (tmp == (size_t)(-1))
+    {
+      /* invalid to compose multibyte char */
+      /* initialize the conversion state */
+      memset (ps, 0, sizeof(mbstate_t));
+      return -1;
+    }
+  else if (tmp == (size_t)0)
+    return 0;
+  else
+    return (int)tmp;
+}
+
+/* compare the specified two characters. If the characters matched,
+   return 1. Otherwise return 0. */
+int
+_rl_compare_chars (buf1, pos1, ps1, buf2, pos2, ps2)
+     char *buf1, *buf2;
+     mbstate_t *ps1, *ps2;
+     int pos1, pos2;
+{
+  int i, w1, w2;
+
+  if ((w1 = _rl_get_char_len (&buf1[pos1], ps1)) <= 0 || 
+       (w2 = _rl_get_char_len (&buf2[pos2], ps2)) <= 0 ||
+       (w1 != w2) ||
+       (buf1[pos1] != buf2[pos2]))
+    return 0;
+
+  for (i = 1; i < w1; i++)
+    if (buf1[pos1+i] != buf2[pos2+i])
+      return 0;
+
+  return 1;
+}
+
+/* adjust pointed byte and find mbstate of the point of string.
+   adjusted point will be point <= adjusted_point, and returns
+   differences of the byte(adjusted_point - point).
+   if point is invalied (point < 0 || more than string length),
+   it returns -1 */
+int
+_rl_adjust_point(string, point, ps)
+     char *string;
+     int point;
+     mbstate_t *ps;
+{
+  size_t tmp = 0;
+  int length;
+  int pos = 0;
+
+  length = strlen(string);
+  if (point < 0)
+    return -1;
+  if (length < point)
+    return -1;
+  
+  while (pos < point)
+    {
+      tmp = mbrlen (string + pos, length - pos, ps);
+      if((size_t)(tmp) == (size_t)-1 || (size_t)(tmp) == (size_t)-2)
+       {
+         /* in this case, bytes are invalid or shorted to compose
+            multibyte char, so assume that the first byte represents
+            a single character anyway. */
+         pos++;
+         /* clear the state of the byte sequence, because
+            in this case effect of mbstate is undefined  */
+         memset (ps, 0, sizeof (mbstate_t));
+       }
+      else
+       pos += tmp;
+    }
+
+  return (pos - point);
+}
+
+int
+_rl_is_mbchar_matched (string, seed, end, mbchar, length)
+     char *string;
+     int seed, end;
+     char *mbchar;
+     int length;
+{
+  int i;
+
+  if ((end - seed) < length)
+    return 0;
+
+  for (i = 0; i < length; i++)
+    if (string[seed + i] != mbchar[i])
+      return 0;
+  return 1;
+}
+#endif /* HANDLE_MULTIBYTE */
+
+/* Find next `count' characters started byte point of the specified seed.
+   If flags is MB_FIND_NONZERO, we look for non-zero-width multibyte
+   characters. */
+#undef _rl_find_next_mbchar
+int
+_rl_find_next_mbchar (string, seed, count, flags)
+     char *string;
+     int seed, count, flags;
+{
+#if defined (HANDLE_MULTIBYTE)
+  return _rl_find_next_mbchar_internal (string, seed, count, flags);
+#else
+  return (seed + count);
+#endif
+}
+
+/* Find previous character started byte point of the specified seed.
+   Returned point will be point <= seed.  If flags is MB_FIND_NONZERO,
+   we look for non-zero-width multibyte characters. */
+#undef _rl_find_prev_mbchar
+int
+_rl_find_prev_mbchar (string, seed, flags)
+     char *string;
+     int seed, flags;
+{
+#if defined (HANDLE_MULTIBYTE)
+  return _rl_find_prev_mbchar_internal (string, seed, flags);
+#else
+  return ((seed == 0) ? seed : seed - 1);
+#endif
+}
diff --git a/lib/readline/misc.c b/lib/readline/misc.c
new file mode 100644 (file)
index 0000000..f3775d3
--- /dev/null
@@ -0,0 +1,496 @@
+/* misc.c -- miscellaneous bindable readline functions. */
+
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library 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.
+
+   The GNU Readline Library 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.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_LOCALE_H)
+#  include <locale.h>
+#endif
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+static int rl_digit_loop PARAMS((void));
+static void _rl_history_set_point PARAMS((void));
+
+/* Forward declarations used in this file */
+void _rl_free_history_entry PARAMS((HIST_ENTRY *));
+
+/* If non-zero, rl_get_previous_history and rl_get_next_history attempt
+   to preserve the value of rl_point from line to line. */
+int _rl_history_preserve_point = 0;
+
+/* Saved target point for when _rl_history_preserve_point is set.  Special
+   value of -1 means that point is at the end of the line. */
+int _rl_history_saved_point = -1;
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Numeric Arguments                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Handle C-u style numeric args, as well as M--, and M-digits. */
+static int
+rl_digit_loop ()
+{
+  int key, c, sawminus, sawdigits;
+
+  rl_save_prompt ();
+
+  RL_SETSTATE(RL_STATE_NUMERICARG);
+  sawminus = sawdigits = 0;
+  while (1)
+    {
+      if (rl_numeric_arg > 1000000)
+       {
+         sawdigits = rl_explicit_arg = rl_numeric_arg = 0;
+         rl_ding ();
+         rl_restore_prompt ();
+         rl_clear_message ();
+         RL_UNSETSTATE(RL_STATE_NUMERICARG);
+         return 1;
+       }
+      rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
+      RL_SETSTATE(RL_STATE_MOREINPUT);
+      key = c = rl_read_key ();
+      RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+      if (c < 0)
+       {
+         _rl_abort_internal ();
+         return -1;
+       }
+
+      /* If we see a key bound to `universal-argument' after seeing digits,
+        it ends the argument but is otherwise ignored. */
+      if (_rl_keymap[c].type == ISFUNC &&
+         _rl_keymap[c].function == rl_universal_argument)
+       {
+         if (sawdigits == 0)
+           {
+             rl_numeric_arg *= 4;
+             continue;
+           }
+         else
+           {
+             RL_SETSTATE(RL_STATE_MOREINPUT);
+             key = rl_read_key ();
+             RL_UNSETSTATE(RL_STATE_MOREINPUT);
+             rl_restore_prompt ();
+             rl_clear_message ();
+             RL_UNSETSTATE(RL_STATE_NUMERICARG);
+             return (_rl_dispatch (key, _rl_keymap));
+           }
+       }
+
+      c = UNMETA (c);
+
+      if (_rl_digit_p (c))
+       {
+         rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + c - '0' : c - '0';
+         sawdigits = rl_explicit_arg = 1;
+       }
+      else if (c == '-' && rl_explicit_arg == 0)
+       {
+         rl_numeric_arg = sawminus = 1;
+         rl_arg_sign = -1;
+       }
+      else
+       {
+         /* Make M-- command equivalent to M--1 command. */
+         if (sawminus && rl_numeric_arg == 1 && rl_explicit_arg == 0)
+           rl_explicit_arg = 1;
+         rl_restore_prompt ();
+         rl_clear_message ();
+         RL_UNSETSTATE(RL_STATE_NUMERICARG);
+         return (_rl_dispatch (key, _rl_keymap));
+       }
+    }
+
+  /*NOTREACHED*/
+}
+
+/* Add the current digit to the argument in progress. */
+int
+rl_digit_argument (ignore, key)
+     int ignore, key;
+{
+  rl_execute_next (key);
+  return (rl_digit_loop ());
+}
+
+/* What to do when you abort reading an argument. */
+int
+rl_discard_argument ()
+{
+  rl_ding ();
+  rl_clear_message ();
+  _rl_init_argument ();
+  return 0;
+}
+
+/* Create a default argument. */
+int
+_rl_init_argument ()
+{
+  rl_numeric_arg = rl_arg_sign = 1;
+  rl_explicit_arg = 0;
+  return 0;
+}
+
+/* C-u, universal argument.  Multiply the current argument by 4.
+   Read a key.  If the key has nothing to do with arguments, then
+   dispatch on it.  If the key is the abort character then abort. */
+int
+rl_universal_argument (count, key)
+     int count, key;
+{
+  rl_numeric_arg *= 4;
+  return (rl_digit_loop ());
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     History Utilities                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* We already have a history library, and that is what we use to control
+   the history features of readline.  This is our local interface to
+   the history mechanism. */
+
+/* While we are editing the history, this is the saved
+   version of the original line. */
+HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
+
+/* Set the history pointer back to the last entry in the history. */
+void
+_rl_start_using_history ()
+{
+  using_history ();
+  if (_rl_saved_line_for_history)
+    _rl_free_history_entry (_rl_saved_line_for_history);
+
+  _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
+}
+
+/* Free the contents (and containing structure) of a HIST_ENTRY. */
+void
+_rl_free_history_entry (entry)
+     HIST_ENTRY *entry;
+{
+  if (entry == 0)
+    return;
+  if (entry->line)
+    free (entry->line);
+  free (entry);
+}
+
+/* Perhaps put back the current line if it has changed. */
+int
+rl_maybe_replace_line ()
+{
+  HIST_ENTRY *temp;
+
+  temp = current_history ();
+  /* If the current line has changed, save the changes. */
+  if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
+    {
+      temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
+      free (temp->line);
+      free (temp);
+    }
+  return 0;
+}
+
+/* Restore the _rl_saved_line_for_history if there is one. */
+int
+rl_maybe_unsave_line ()
+{
+  if (_rl_saved_line_for_history)
+    {
+      rl_replace_line (_rl_saved_line_for_history->line, 0);
+      rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
+      _rl_free_history_entry (_rl_saved_line_for_history);
+      _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
+      rl_point = rl_end;       /* rl_replace_line sets rl_end */
+    }
+  else
+    rl_ding ();
+  return 0;
+}
+
+/* Save the current line in _rl_saved_line_for_history. */
+int
+rl_maybe_save_line ()
+{
+  if (_rl_saved_line_for_history == 0)
+    {
+      _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+      _rl_saved_line_for_history->line = savestring (rl_line_buffer);
+      _rl_saved_line_for_history->data = (char *)rl_undo_list;
+    }
+  return 0;
+}
+
+int
+_rl_free_saved_history_line ()
+{
+  if (_rl_saved_line_for_history)
+    {
+      _rl_free_history_entry (_rl_saved_line_for_history);
+      _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
+    }
+  return 0;
+}
+
+static void
+_rl_history_set_point ()
+{
+  rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1)
+               ? _rl_history_saved_point
+               : rl_end;
+  if (rl_point > rl_end)
+    rl_point = rl_end;
+
+#if defined (VI_MODE)
+  if (rl_editing_mode == vi_mode)
+    rl_point = 0;
+#endif /* VI_MODE */
+
+  if (rl_editing_mode == emacs_mode)
+    rl_mark = (rl_point == rl_end ? 0 : rl_end);
+}
+
+void
+rl_replace_from_history (entry, flags)
+     HIST_ENTRY *entry;
+     int flags;                        /* currently unused */
+{
+  rl_replace_line (entry->line, 0);
+  rl_undo_list = (UNDO_LIST *)entry->data;
+  rl_point = rl_end;
+  rl_mark = 0;
+
+#if defined (VI_MODE)
+  if (rl_editing_mode == vi_mode)
+    {
+      rl_point = 0;
+      rl_mark = rl_end;
+    }
+#endif
+}  
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     History Commands                            */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Meta-< goes to the start of the history. */
+int
+rl_beginning_of_history (count, key)
+     int count, key;
+{
+  return (rl_get_previous_history (1 + where_history (), key));
+}
+
+/* Meta-> goes to the end of the history.  (The current line). */
+int
+rl_end_of_history (count, key)
+     int count, key;
+{
+  rl_maybe_replace_line ();
+  using_history ();
+  rl_maybe_unsave_line ();
+  return 0;
+}
+
+/* Move down to the next history line. */
+int
+rl_get_next_history (count, key)
+     int count, key;
+{
+  HIST_ENTRY *temp;
+
+  if (count < 0)
+    return (rl_get_previous_history (-count, key));
+
+  if (count == 0)
+    return 0;
+
+  rl_maybe_replace_line ();
+
+  /* either not saved by rl_newline or at end of line, so set appropriately. */
+  if (_rl_history_saved_point == -1 && (rl_point || rl_end))
+    _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
+
+  temp = (HIST_ENTRY *)NULL;
+  while (count)
+    {
+      temp = next_history ();
+      if (!temp)
+       break;
+      --count;
+    }
+
+  if (temp == 0)
+    rl_maybe_unsave_line ();
+  else
+    {
+      rl_replace_from_history (temp, 0);
+      _rl_history_set_point ();
+    }
+  return 0;
+}
+
+/* Get the previous item out of our interactive history, making it the current
+   line.  If there is no previous history, just ding. */
+int
+rl_get_previous_history (count, key)
+     int count, key;
+{
+  HIST_ENTRY *old_temp, *temp;
+
+  if (count < 0)
+    return (rl_get_next_history (-count, key));
+
+  if (count == 0)
+    return 0;
+
+  /* either not saved by rl_newline or at end of line, so set appropriately. */
+  if (_rl_history_saved_point == -1 && (rl_point || rl_end))
+    _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
+
+  /* If we don't have a line saved, then save this one. */
+  rl_maybe_save_line ();
+
+  /* If the current line has changed, save the changes. */
+  rl_maybe_replace_line ();
+
+  temp = old_temp = (HIST_ENTRY *)NULL;
+  while (count)
+    {
+      temp = previous_history ();
+      if (temp == 0)
+       break;
+
+      old_temp = temp;
+      --count;
+    }
+
+  /* If there was a large argument, and we moved back to the start of the
+     history, that is not an error.  So use the last value found. */
+  if (!temp && old_temp)
+    temp = old_temp;
+
+  if (temp == 0)
+    rl_ding ();
+  else
+    {
+      rl_replace_from_history (temp, 0);
+      _rl_history_set_point ();
+    }
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                         Editing Modes                           */
+/*                                                                 */
+/* **************************************************************** */
+/* How to toggle back and forth between editing modes. */
+int
+rl_vi_editing_mode (count, key)
+     int count, key;
+{
+#if defined (VI_MODE)
+  _rl_set_insert_mode (RL_IM_INSERT, 1);       /* vi mode ignores insert mode */
+  rl_editing_mode = vi_mode;
+  rl_vi_insertion_mode (1, key);
+#endif /* VI_MODE */
+
+  return 0;
+}
+
+int
+rl_emacs_editing_mode (count, key)
+     int count, key;
+{
+  rl_editing_mode = emacs_mode;
+  _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
+  _rl_keymap = emacs_standard_keymap;
+  return 0;
+}
+
+/* Function for the rest of the library to use to set insert/overwrite mode. */
+void
+_rl_set_insert_mode (im, force)
+     int im, force;
+{
+#ifdef CURSOR_MODE
+  _rl_set_cursor (im, force);
+#endif
+
+  rl_insert_mode = im;
+}
+
+/* Toggle overwrite mode.  A positive explicit argument selects overwrite
+   mode.  A negative or zero explicit argument selects insert mode. */
+int
+rl_overwrite_mode (count, key)
+     int count, key;
+{
+  if (rl_explicit_arg == 0)
+    _rl_set_insert_mode (rl_insert_mode ^ 1, 0);
+  else if (count > 0)
+    _rl_set_insert_mode (RL_IM_OVERWRITE, 0);
+  else
+    _rl_set_insert_mode (RL_IM_INSERT, 0);
+
+  return 0;
+}
index ca6c368842d44047d5b55d7c406c50babcb9a0a6..54ef1f3695faf8ff4545139fe46357949134f42d 100644 (file)
 #include <stdio.h>
 #include <sys/types.h>
 
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
 #if defined (FD_SET) && !defined (HAVE_SELECT)
 #  define HAVE_SELECT
 #endif
@@ -103,7 +107,7 @@ rl_insert_close (count, invoking_key)
      int count, invoking_key;
 {
   if (rl_explicit_arg || !rl_blink_matching_paren)
-    rl_insert (count, invoking_key);
+    _rl_insert_char (count, invoking_key);
   else
     {
 #if defined (HAVE_SELECT)
@@ -111,7 +115,7 @@ rl_insert_close (count, invoking_key)
       struct timeval timer;
       fd_set readfds;
 
-      rl_insert (1, invoking_key);
+      _rl_insert_char (1, invoking_key);
       (*rl_redisplay_function) ();
       match_point =
        find_matching_open (rl_line_buffer, rl_point - 2, invoking_key);
@@ -131,7 +135,7 @@ rl_insert_close (count, invoking_key)
       ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer);
       rl_point = orig_point;
 #else /* !HAVE_SELECT */
-      rl_insert (count, invoking_key);
+      _rl_insert_char (count, invoking_key);
 #endif /* !HAVE_SELECT */
     }
   return 0;
index 98ced75b346b2654b9b3356b77823d26e66757ea..505e27954f1683671ed12b7e1a140fb9ae9e7ba4 100644 (file)
 #  define d_fileno d_ino
 #endif
 
+#if defined (_POSIX_SOURCE) && (!defined (STRUCT_DIRENT_HAS_D_INO) || defined (BROKEN_DIRENT_D_INO))
+/* Posix does not require that the d_ino field be present, and some
+   systems do not provide it. */
+#  define REAL_DIR_ENTRY(dp) 1
+#else
+#  define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+#endif /* _POSIX_SOURCE */
+
 #endif /* !_POSIXDIR_H_ */
index 3efd8102e66c0590c351b06e43cca6888f522e56..28801f19dfc1ea1036258440ee690a1b1438ffd7 100644 (file)
@@ -1,7 +1,7 @@
 /* readline.c -- a general facility for reading lines of input
    with emacs style editing and completion. */
 
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file is part of the GNU Readline Library, a library for
    reading lines of text with interactive input and history editing.
@@ -52,6 +52,7 @@
 
 /* System-specific feature definitions and include files. */
 #include "rldefs.h"
+#include "rlmbutil.h"
 
 #if defined (__EMX__)
 #  define INCL_DOSPROCESS
 #include "xmalloc.h"
 
 #ifndef RL_LIBRARY_VERSION
-#  define RL_LIBRARY_VERSION "4.2a"
+#  define RL_LIBRARY_VERSION "4.3"
 #endif
 
 #ifndef RL_READLINE_VERSION
-#  define RL_READLINE_VERSION  0x0402
+#  define RL_READLINE_VERSION  0x0403
 #endif
 
-/* Evaluates its arguments multiple times. */
-#define SWAP(s, e)  do { int t; t = s; s = e; e = t; } while (0)
+extern void _rl_free_history_entry PARAMS((HIST_ENTRY *));
 
 /* Forward declarations used in this file. */
-void _rl_free_history_entry PARAMS((HIST_ENTRY *));
-
 static char *readline_internal PARAMS((void));
 static void readline_initialize_everything PARAMS((void));
-static void start_using_history PARAMS((void));
+
+static void bind_arrow_keys_internal PARAMS((Keymap));
 static void bind_arrow_keys PARAMS((void));
-static int rl_change_case PARAMS((int, int));
 
 static void readline_default_bindings PARAMS((void));
 
@@ -108,6 +106,9 @@ 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. */
@@ -249,14 +250,6 @@ int _rl_convert_meta_chars_to_ascii = 1;
    rather than as a meta-prefixed escape sequence. */
 int _rl_output_meta_chars = 0;
 
-/* If non-zero, rl_get_previous_history and rl_get_next_history attempt
-   to preserve the value of rl_point from line to line. */
-int _rl_history_preserve_point = 0;
-
-/* Saved target point for when _rl_history_preserve_point is set.  Special
-   value of -1 means that point is at the end of the line. */
-static int _rl_history_saved_point = -1;
-
 /* **************************************************************** */
 /*                                                                 */
 /*                     Top Level Functions                         */
@@ -330,7 +323,10 @@ readline_internal_setup ()
   if (rl_startup_hook)
     (*rl_startup_hook) ();
 
-  if (readline_echoing_p == 0)
+  /* 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 (readline_echoing_p == 0 && rl_redisplay_function == rl_redisplay)
     {
       if (rl_prompt && rl_already_prompted == 0)
        {
@@ -347,11 +343,12 @@ readline_internal_setup ()
       else
        rl_on_new_line ();
       (*rl_redisplay_function) ();
+    }
+
 #if defined (VI_MODE)
-      if (rl_editing_mode == vi_mode)
-       rl_vi_insertion_mode (1, 0);
+  if (rl_editing_mode == vi_mode)
+    rl_vi_insertion_mode (1, 0);
 #endif /* VI_MODE */
-    }
 
   if (rl_pre_input_hook)
     (*rl_pre_input_hook) ();
@@ -384,6 +381,9 @@ readline_internal_teardown (eof)
   if (rl_undo_list)
     rl_free_undo_list ();
 
+  /* Restore normal cursor, if available. */
+  _rl_set_insert_mode (RL_IM_INSERT, 0);
+
   return (eof ? (char *)NULL : savestring (the_line));
 }
 
@@ -507,7 +507,7 @@ readline_internal ()
 void
 _rl_init_line_state ()
 {
-  rl_point = rl_end = 0;
+  rl_point = rl_end = rl_mark = 0;
   the_line = rl_line_buffer;
   the_line[0] = 0;
 }
@@ -525,6 +525,15 @@ int
 _rl_dispatch (key, map)
      register int key;
      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;
@@ -534,7 +543,7 @@ _rl_dispatch (key, map)
     {
       if (map[ESC].type == ISKMAP)
        {
-         if (_rl_defining_kbd_macro)
+         if (RL_ISSTATE (RL_STATE_MACRODEF))
            _rl_add_macro_char (ESC);
          map = FUNCTION_TO_KEYMAP (map, ESC);
          key = UNMETA (key);
@@ -546,7 +555,7 @@ _rl_dispatch (key, map)
       return 0;
     }
 
-  if (_rl_defining_kbd_macro)
+  if (RL_ISSTATE (RL_STATE_MACRODEF))
     _rl_add_macro_char (key);
 
   r = 0;
@@ -578,6 +587,23 @@ _rl_dispatch (key, map)
          if (rl_pending_input == 0 && map[key].function != rl_digit_argument)
            rl_last_func = map[key].function;
        }
+      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. */
+         _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. */
+         _rl_unget_char (key);
+         return -1;
+       }
       else
        {
          _rl_abort_internal ();
@@ -588,6 +614,18 @@ _rl_dispatch (key, map)
     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. */
+         if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap
+             && _rl_input_queued (0) == 0)
+           return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)));
+#endif
+
          rl_key_sequence_length++;
 
          if (key == ESC)
@@ -604,7 +642,29 @@ _rl_dispatch (key, map)
              return -1;
            }
 
-         r = _rl_dispatch (newkey, FUNCTION_TO_KEYMAP (map, key));
+         r = _rl_dispatch_subseq (newkey, FUNCTION_TO_KEYMAP (map, key), got_subseq || map[ANYOTHERKEY].function);
+
+         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. */
+           r = _rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key));
+         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. */
+             _rl_unget_char (key);
+             return -2;
+           }
+         else if (r && got_subseq)
+           {
+             /* OK, back up the chain. */
+             _rl_unget_char (key);
+             return -1;
+           }
        }
       else
        {
@@ -659,7 +719,7 @@ rl_initialize ()
   RL_UNSETSTATE(RL_STATE_DONE);
 
   /* Tell the history routines what is going on. */
-  start_using_history ();
+  _rl_start_using_history ();
 
   /* Make the display buffer match the state of the line. */
   rl_reset_line_state ();
@@ -675,6 +735,9 @@ rl_initialize ()
     _rl_vi_initialize_line ();
 #endif
 
+  /* Each line starts in insert mode (the default). */
+  _rl_set_insert_mode (RL_IM_DEFAULT, 1);
+
   return 0;
 }
 
@@ -787,1426 +850,124 @@ readline_default_bindings ()
   rl_tty_set_default_bindings (_rl_keymap);
 }
 
+/* Bind some common arrow key sequences in MAP. */
 static void
-bind_arrow_keys_internal ()
+bind_arrow_keys_internal (map)
+     Keymap map;
 {
-  rl_command_func_t *f;
+  Keymap xkeymap;
+
+  xkeymap = _rl_keymap;
+  _rl_keymap = map;
 
 #if defined (__MSDOS__)
-  f = rl_function_of_keyseq ("\033[0A", _rl_keymap, (int *)NULL);
-  if (!f || f == rl_do_lowercase_version)
-    {
-       _rl_bind_if_unbound ("\033[0A", rl_get_previous_history);
-       _rl_bind_if_unbound ("\033[0B", rl_backward);
-       _rl_bind_if_unbound ("\033[0C", rl_forward);
-       _rl_bind_if_unbound ("\033[0D", rl_get_next_history);
-    }
+   _rl_bind_if_unbound ("\033[0A", rl_get_previous_history);
+   _rl_bind_if_unbound ("\033[0B", rl_backward_char);
+   _rl_bind_if_unbound ("\033[0C", rl_forward_char);
+   _rl_bind_if_unbound ("\033[0D", rl_get_next_history);
 #endif
-       
-  f = rl_function_of_keyseq ("\033[A", _rl_keymap, (int *)NULL);
-  if (!f || f == rl_do_lowercase_version)
-    {
-      _rl_bind_if_unbound ("\033[A", rl_get_previous_history);
-      _rl_bind_if_unbound ("\033[B", rl_get_next_history);
-      _rl_bind_if_unbound ("\033[C", rl_forward);
-      _rl_bind_if_unbound ("\033[D", rl_backward);
-    }
 
-  f = rl_function_of_keyseq ("\033OA", _rl_keymap, (int *)NULL);
-  if (!f || f == rl_do_lowercase_version)
-    {
-      _rl_bind_if_unbound ("\033OA", rl_get_previous_history);
-      _rl_bind_if_unbound ("\033OB", rl_get_next_history);
-      _rl_bind_if_unbound ("\033OC", rl_forward);
-      _rl_bind_if_unbound ("\033OD", rl_backward);
-    }
+  _rl_bind_if_unbound ("\033[A", rl_get_previous_history);
+  _rl_bind_if_unbound ("\033[B", rl_get_next_history);
+  _rl_bind_if_unbound ("\033[C", rl_forward_char);
+  _rl_bind_if_unbound ("\033[D", rl_backward_char);
+  _rl_bind_if_unbound ("\033[H", rl_beg_of_line);
+  _rl_bind_if_unbound ("\033[F", rl_end_of_line);
+
+  _rl_bind_if_unbound ("\033OA", rl_get_previous_history);
+  _rl_bind_if_unbound ("\033OB", rl_get_next_history);
+  _rl_bind_if_unbound ("\033OC", rl_forward_char);
+  _rl_bind_if_unbound ("\033OD", rl_backward_char);
+  _rl_bind_if_unbound ("\033OH", rl_beg_of_line);
+  _rl_bind_if_unbound ("\033OF", rl_end_of_line);
+
+  _rl_keymap = xkeymap;
 }
 
-/* Try and bind the common arrow key prefix after giving termcap and
+/* 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 ()
 {
-  Keymap xkeymap;
-
-  xkeymap = _rl_keymap;
-
-  _rl_keymap = emacs_standard_keymap;
-  bind_arrow_keys_internal ();
+  bind_arrow_keys_internal (emacs_standard_keymap);
 
 #if defined (VI_MODE)
-  _rl_keymap = vi_movement_keymap;
-  bind_arrow_keys_internal ();
+  bind_arrow_keys_internal (vi_movement_keymap);
+  bind_arrow_keys_internal (vi_insertion_keymap);
 #endif
-
-  _rl_keymap = xkeymap;
-}
-
-\f
-/* **************************************************************** */
-/*                                                                 */
-/*                     Numeric Arguments                           */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Handle C-u style numeric args, as well as M--, and M-digits. */
-static int
-rl_digit_loop ()
-{
-  int key, c, sawminus, sawdigits;
-
-  rl_save_prompt ();
-
-  RL_SETSTATE(RL_STATE_NUMERICARG);
-  sawminus = sawdigits = 0;
-  while (1)
-    {
-      if (rl_numeric_arg > 1000000)
-       {
-         sawdigits = rl_explicit_arg = rl_numeric_arg = 0;
-         rl_ding ();
-         rl_restore_prompt ();
-         rl_clear_message ();
-         RL_UNSETSTATE(RL_STATE_NUMERICARG);
-         return 1;
-       }
-      rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
-      RL_SETSTATE(RL_STATE_MOREINPUT);
-      key = c = rl_read_key ();
-      RL_UNSETSTATE(RL_STATE_MOREINPUT);
-
-      if (c < 0)
-       {
-         _rl_abort_internal ();
-         return -1;
-       }
-
-      /* If we see a key bound to `universal-argument' after seeing digits,
-        it ends the argument but is otherwise ignored. */
-      if (_rl_keymap[c].type == ISFUNC &&
-         _rl_keymap[c].function == rl_universal_argument)
-       {
-         if (sawdigits == 0)
-           {
-             rl_numeric_arg *= 4;
-             continue;
-           }
-         else
-           {
-             RL_SETSTATE(RL_STATE_MOREINPUT);
-             key = rl_read_key ();
-             RL_UNSETSTATE(RL_STATE_MOREINPUT);
-             rl_restore_prompt ();
-             rl_clear_message ();
-             RL_UNSETSTATE(RL_STATE_NUMERICARG);
-             return (_rl_dispatch (key, _rl_keymap));
-           }
-       }
-
-      c = UNMETA (c);
-
-      if (_rl_digit_p (c))
-       {
-         rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + c - '0' : c - '0';
-         sawdigits = rl_explicit_arg = 1;
-       }
-      else if (c == '-' && rl_explicit_arg == 0)
-       {
-         rl_numeric_arg = sawminus = 1;
-         rl_arg_sign = -1;
-       }
-      else
-       {
-         /* Make M-- command equivalent to M--1 command. */
-         if (sawminus && rl_numeric_arg == 1 && rl_explicit_arg == 0)
-           rl_explicit_arg = 1;
-         rl_restore_prompt ();
-         rl_clear_message ();
-         RL_UNSETSTATE(RL_STATE_NUMERICARG);
-         return (_rl_dispatch (key, _rl_keymap));
-       }
-    }
-
-  /*NOTREACHED*/
-}
-
-/* Add the current digit to the argument in progress. */
-int
-rl_digit_argument (ignore, key)
-     int ignore, key;
-{
-  rl_execute_next (key);
-  return (rl_digit_loop ());
-}
-
-/* What to do when you abort reading an argument. */
-int
-rl_discard_argument ()
-{
-  rl_ding ();
-  rl_clear_message ();
-  _rl_init_argument ();
-  return 0;
-}
-
-/* Create a default argument. */
-int
-_rl_init_argument ()
-{
-  rl_numeric_arg = rl_arg_sign = 1;
-  rl_explicit_arg = 0;
-  return 0;
-}
-
-/* C-u, universal argument.  Multiply the current argument by 4.
-   Read a key.  If the key has nothing to do with arguments, then
-   dispatch on it.  If the key is the abort character then abort. */
-int
-rl_universal_argument (count, key)
-     int count, key;
-{
-  rl_numeric_arg *= 4;
-  return (rl_digit_loop ());
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Insert and Delete                           */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Insert a string of text into the line at point.  This is the only
-   way that you should do insertion.  rl_insert () calls this
-   function. */
-int
-rl_insert_text (string)
-     const char *string;
-{
-  register int i, l = strlen (string);
-
-  if (rl_end + l >= rl_line_buffer_len)
-    rl_extend_line_buffer (rl_end + l);
-
-  for (i = rl_end; i >= rl_point; i--)
-    the_line[i + l] = the_line[i];
-  strncpy (the_line + rl_point, string, l);
-
-  /* Remember how to undo this if we aren't undoing something. */
-  if (!_rl_doing_an_undo)
-    {
-      /* If possible and desirable, concatenate the undos. */
-      if ((l == 1) &&
-         rl_undo_list &&
-         (rl_undo_list->what == UNDO_INSERT) &&
-         (rl_undo_list->end == rl_point) &&
-         (rl_undo_list->end - rl_undo_list->start < 20))
-       rl_undo_list->end++;
-      else
-       rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
-    }
-  rl_point += l;
-  rl_end += l;
-  the_line[rl_end] = '\0';
-  return l;
-}
-
-/* Delete the string between FROM and TO.  FROM is
-   inclusive, TO is not. */
-int
-rl_delete_text (from, to)
-     int from, to;
-{
-  register char *text;
-  register int diff, i;
-
-  /* Fix it if the caller is confused. */
-  if (from > to)
-    SWAP (from, to);
-
-  /* fix boundaries */
-  if (to > rl_end)
-    {
-      to = rl_end;
-      if (from > to)
-        from = to;
-    }
-
-  text = rl_copy_text (from, to);
-
-  /* Some versions of strncpy() can't handle overlapping arguments. */
-  diff = to - from;
-  for (i = from; i < rl_end - diff; i++)
-    the_line[i] = the_line[i + diff];
-
-  /* Remember how to undo this delete. */
-  if (_rl_doing_an_undo == 0)
-    rl_add_undo (UNDO_DELETE, from, to, text);
-  else
-    free (text);
-
-  rl_end -= diff;
-  the_line[rl_end] = '\0';
-  return (diff);
-}
-
-/* Fix up point so that it is within the line boundaries after killing
-   text.  If FIX_MARK_TOO is non-zero, the mark is forced within line
-   boundaries also. */
-
-#define _RL_FIX_POINT(x) \
-       do { \
-       if (x > rl_end) \
-         x = rl_end; \
-       else if (x < 0) \
-         x = 0; \
-       } while (0)
-
-void
-_rl_fix_point (fix_mark_too)
-     int fix_mark_too;
-{
-  _RL_FIX_POINT (rl_point);
-  if (fix_mark_too)
-    _RL_FIX_POINT (rl_mark);
-}
-#undef _RL_FIX_POINT
-
-void
-_rl_replace_text (text, start, end)
-     const char *text;
-     int start, end;
-{
-  rl_begin_undo_group ();
-  rl_delete_text (start, end + 1);
-  rl_point = start;
-  rl_insert_text (text);
-  rl_end_undo_group ();
 }
 
 /* **************************************************************** */
 /*                                                                 */
-/*                     Readline character functions                */
-/*                                                                 */
-/* **************************************************************** */
-
-/* This is not a gap editor, just a stupid line input routine.  No hair
-   is involved in writing any of the functions, and none should be. */
-
-/* Note that:
-
-   rl_end is the place in the string that we would place '\0';
-   i.e., it is always safe to place '\0' there.
-
-   rl_point is the place in the string where the cursor is.  Sometimes
-   this is the same as rl_end.
-
-   Any command that is called interactively receives two arguments.
-   The first is a count: the numeric arg pased to this command.
-   The second is the key which invoked this command.
-*/
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Movement Commands                           */
+/*             Saving and Restoring Readline's state               */
 /*                                                                 */
 /* **************************************************************** */
 
-/* Note that if you `optimize' the display for these functions, you cannot
-   use said functions in other functions which do not do optimizing display.
-   I.e., you will have to update the data base for rl_redisplay, and you
-   might as well let rl_redisplay do that job. */
-
-/* Move forward COUNT characters. */
-int
-rl_forward (count, key)
-     int count, key;
-{
-  if (count < 0)
-    rl_backward (-count, key);
-  else if (count > 0)
-    {
-      int end = rl_point + count;
-#if defined (VI_MODE)
-      int lend = rl_end > 0 ? rl_end - (rl_editing_mode == vi_mode) : rl_end;
-#else
-      int lend = rl_end;
-#endif
-
-      if (end > lend)
-       {
-         rl_point = lend;
-         rl_ding ();
-       }
-      else
-       rl_point = end;
-    }
-
-  if (rl_end < 0)
-    rl_end = 0;
-
-  return 0;
-}
-
-/* Move backward COUNT characters. */
-int
-rl_backward (count, key)
-     int count, key;
-{
-  if (count < 0)
-    rl_forward (-count, key);
-  else if (count > 0)
-    {
-      if (rl_point < count)
-       {
-         rl_point = 0;
-         rl_ding ();
-       }
-      else
-        rl_point -= count;
-    }
-
-  if (rl_point < 0)
-    rl_point = 0;
-
-  return 0;
-}
-
-/* Move to the beginning of the line. */
-int
-rl_beg_of_line (count, key)
-     int count, key;
-{
-  rl_point = 0;
-  return 0;
-}
-
-/* Move to the end of the line. */
-int
-rl_end_of_line (count, key)
-     int count, key;
-{
-  rl_point = rl_end;
-  return 0;
-}
-
-/* Move forward a word.  We do what Emacs does. */
 int
-rl_forward_word (count, key)
-     int count, key;
+rl_save_state (sp)
+     struct readline_state *sp;
 {
-  int c;
-
-  if (count < 0)
-    {
-      rl_backward_word (-count, key);
-      return 0;
-    }
-
-  while (count)
-    {
-      if (rl_point == rl_end)
-       return 0;
-
-      /* If we are not in a word, move forward until we are in one.
-        Then, move forward until we hit a non-alphabetic character. */
-      c = the_line[rl_point];
-      if (rl_alphabetic (c) == 0)
-       {
-         while (++rl_point < rl_end)
-           {
-             c = the_line[rl_point];
-             if (rl_alphabetic (c))
-               break;
-           }
-       }
-      if (rl_point == rl_end)
-       return 0;
-      while (++rl_point < rl_end)
-       {
-         c = the_line[rl_point];
-         if (rl_alphabetic (c) == 0)
-           break;
-       }
-      --count;
-    }
-  return 0;
-}
-
-/* Move backward a word.  We do what Emacs does. */
-int
-rl_backward_word (count, key)
-     int count, key;
-{
-  int c;
-
-  if (count < 0)
-    {
-      rl_forward_word (-count, key);
-      return 0;
-    }
-
-  while (count)
-    {
-      if (!rl_point)
-       return 0;
-
-      /* Like rl_forward_word (), except that we look at the characters
-        just before point. */
-
-      c = the_line[rl_point - 1];
-      if (rl_alphabetic (c) == 0)
-       {
-         while (--rl_point)
-           {
-             c = the_line[rl_point - 1];
-             if (rl_alphabetic (c))
-               break;
-           }
-       }
-
-      while (rl_point)
-       {
-         c = the_line[rl_point - 1];
-         if (rl_alphabetic (c) == 0)
-           break;
-         else
-           --rl_point;
-       }
-      --count;
-    }
-  return 0;
-}
-
-/* Clear the current line.  Numeric argument to C-l does this. */
-int
-rl_refresh_line (ignore1, ignore2)
-     int ignore1, ignore2;
-{
-  int curr_line;
-
-  curr_line = _rl_current_display_line ();
-
-  _rl_move_vert (curr_line);
-  _rl_move_cursor_relative (0, the_line);   /* XXX is this right */
-
-  _rl_clear_to_eol (0);                /* arg of 0 means to not use spaces */
-
-  rl_forced_update_display ();
-  rl_display_fixed = 1;
-
-  return 0;
-}
-
-/* C-l typed to a line without quoting clears the screen, and then reprints
-   the prompt and the current input line.  Given a numeric arg, redraw only
-   the current line. */
-int
-rl_clear_screen (count, key)
-     int count, key;
-{
-  if (rl_explicit_arg)
-    {
-      rl_refresh_line (count, key);
-      return 0;
-    }
+  if (sp == 0)
+    return -1;
 
-  _rl_clear_screen ();         /* calls termcap function to clear screen */
-  rl_forced_update_display ();
-  rl_display_fixed = 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;
+  return (0);
 }
 
 int
-rl_arrow_keys (count, c)
-     int count, c;
+rl_restore_state (sp)
+     struct readline_state *sp;
 {
-  int ch;
-
-  RL_SETSTATE(RL_STATE_MOREINPUT);
-  ch = rl_read_key ();
-  RL_UNSETSTATE(RL_STATE_MOREINPUT);
-
-  switch (_rl_to_upper (ch))
-    {
-    case 'A':
-      rl_get_previous_history (count, ch);
-      break;
+  if (sp == 0)
+    return -1;
 
-    case 'B':
-      rl_get_next_history (count, ch);
-      break;
+  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;
 
-    case 'C':
-      rl_forward (count, ch);
-      break;
-
-    case 'D':
-      rl_backward (count, ch);
-      break;
-
-    default:
-      rl_ding ();
-    }
-  return 0;
-}
-
-\f
-/* **************************************************************** */
-/*                                                                 */
-/*                     Text commands                               */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Insert the character C at the current location, moving point forward. */
-int
-rl_insert (count, c)
-     int count, c;
-{
-  register int i;
-  char *string;
-
-  if (count <= 0)
-    return 0;
-
-  /* If we can optimize, then do it.  But don't let people crash
-     readline because of extra large arguments. */
-  if (count > 1 && count <= 1024)
-    {
-      string = (char *)xmalloc (1 + count);
-
-      for (i = 0; i < count; i++)
-       string[i] = c;
-
-      string[i] = '\0';
-      rl_insert_text (string);
-      free (string);
-
-      return 0;
-    }
-
-  if (count > 1024)
-    {
-      int decreaser;
-      char str[1024+1];
-
-      for (i = 0; i < 1024; i++)
-       str[i] = c;
-
-      while (count)
-       {
-         decreaser = (count > 1024 ? 1024 : count);
-         str[decreaser] = '\0';
-         rl_insert_text (str);
-         count -= decreaser;
-       }
-
-      return 0;
-    }
-
-  /* We are inserting a single character.
-     If there is pending input, then make a string of all of the
-     pending characters that are bound to rl_insert, and insert
-     them all. */
-  if (_rl_any_typein ())
-    _rl_insert_typein (c);
-  else
-    {
-      /* Inserting a single character. */
-      char str[2];
-
-      str[1] = '\0';
-      str[0] = c;
-      rl_insert_text (str);
-    }
-  return 0;
-}
-
-/* Insert the next typed character verbatim. */
-int
-rl_quoted_insert (count, key)
-     int count, key;
-{
-  int c;
-
-#if defined (HANDLE_SIGNALS)
-  _rl_disable_tty_signals ();
-#endif
-
-  RL_SETSTATE(RL_STATE_MOREINPUT);
-  c = rl_read_key ();
-  RL_UNSETSTATE(RL_STATE_MOREINPUT);
-
-#if defined (HANDLE_SIGNALS)
-  _rl_restore_tty_signals ();
-#endif
-
-  return (rl_insert (count, c));  
-}
-
-/* Insert a tab character. */
-int
-rl_tab_insert (count, key)
-     int count, key;
-{
-  return (rl_insert (count, '\t'));
-}
-
-/* What to do when a NEWLINE is pressed.  We accept the whole line.
-   KEY is the key that invoked this command.  I guess it could have
-   meaning in the future. */
-int
-rl_newline (count, key)
-     int count, key;
-{
-  rl_done = 1;
-
-  if (_rl_history_preserve_point)
-    _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
-
-  RL_SETSTATE(RL_STATE_DONE);
-
-#if defined (VI_MODE)
-  if (rl_editing_mode == vi_mode)
-    {
-      _rl_vi_done_inserting ();
-      _rl_vi_reset_last ();
-    }
-#endif /* VI_MODE */
-
-  /* If we've been asked to erase empty lines, suppress the final update,
-     since _rl_update_final calls rl_crlf(). */
-  if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
-    return 0;
-
-  if (readline_echoing_p)
-    _rl_update_final ();
-  return 0;
-}
-
-/* What to do for some uppercase characters, like meta characters,
-   and some characters appearing in emacs_ctlx_keymap.  This function
-   is just a stub, you bind keys to it and the code in _rl_dispatch ()
-   is special cased. */
-int
-rl_do_lowercase_version (ignore1, ignore2)
-     int ignore1, ignore2;
-{
-  return 0;
-}
-
-/* Rubout the character behind point. */
-int
-rl_rubout (count, key)
-     int count, key;
-{
-  if (count < 0)
-    {
-      rl_delete (-count, key);
-      return 0;
-    }
-
-  if (!rl_point)
-    {
-      rl_ding ();
-      return -1;
-    }
-
-  if (count > 1 || rl_explicit_arg)
-    {
-      int orig_point = rl_point;
-      rl_backward (count, key);
-      rl_kill_text (orig_point, rl_point);
-    }
-  else
-    {
-      unsigned char c = the_line[--rl_point];
-      rl_delete_text (rl_point, rl_point + 1);
-
-      if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos)
-       {
-         int l;
-         l = rl_character_len (c, rl_point);
-         _rl_erase_at_end_of_line (l);
-       }
-    }
-  return 0;
-}
-
-/* Delete the character under the cursor.  Given a numeric argument,
-   kill that many characters instead. */
-int
-rl_delete (count, key)
-     int count, key;
-{
-  if (count < 0)
-    return (rl_rubout (-count, key));
-
-  if (rl_point == rl_end)
-    {
-      rl_ding ();
-      return -1;
-    }
-
-  if (count > 1 || rl_explicit_arg)
-    {
-      int orig_point = rl_point;
-      rl_forward (count, key);
-      rl_kill_text (orig_point, rl_point);
-      rl_point = orig_point;
-      return 0;
-    }
-  else
-    return (rl_delete_text (rl_point, rl_point + 1));
-}
-
-/* Delete the character under the cursor, unless the insertion
-   point is at the end of the line, in which case the character
-   behind the cursor is deleted.  COUNT is obeyed and may be used
-   to delete forward or backward that many characters. */      
-int
-rl_rubout_or_delete (count, key)
-     int count, key;
-{
-  if (rl_end != 0 && rl_point == rl_end)
-    return (rl_rubout (count, key));
-  else
-    return (rl_delete (count, key));
-}  
-
-/* Delete all spaces and tabs around point. */
-int
-rl_delete_horizontal_space (count, ignore)
-     int count, ignore;
-{
-  int start = rl_point;
-
-  while (rl_point && whitespace (the_line[rl_point - 1]))
-    rl_point--;
-
-  start = rl_point;
-
-  while (rl_point < rl_end && whitespace (the_line[rl_point]))
-    rl_point++;
-
-  if (start != rl_point)
-    {
-      rl_delete_text (start, rl_point);
-      rl_point = start;
-    }
-  return 0;
-}
-
-/* Like the tcsh editing function delete-char-or-list.  The eof character
-   is caught before this is invoked, so this really does the same thing as
-   delete-char-or-list-or-eof, as long as it's bound to the eof character. */
-int
-rl_delete_or_show_completions (count, key)
-     int count, key;
-{
-  if (rl_end != 0 && rl_point == rl_end)
-    return (rl_possible_completions (count, key));
-  else
-    return (rl_delete (count, key));
-}
-
-#ifndef RL_COMMENT_BEGIN_DEFAULT
-#define RL_COMMENT_BEGIN_DEFAULT "#"
-#endif
-
-/* Turn the current line into a comment in shell history.
-   A K*rn shell style function. */
-int
-rl_insert_comment (count, key)
-     int count, key;
-{
-  rl_beg_of_line (1, key);
-  rl_insert_text (_rl_comment_begin ? _rl_comment_begin
-                                   : RL_COMMENT_BEGIN_DEFAULT);
-  (*rl_redisplay_function) ();
-  rl_newline (1, '\n');
   return (0);
 }
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Changing Case                               */
-/*                                                                 */
-/* **************************************************************** */
-
-/* The three kinds of things that we know how to do. */
-#define UpCase 1
-#define DownCase 2
-#define CapCase 3
-
-/* Uppercase the word at point. */
-int
-rl_upcase_word (count, key)
-     int count, key;
-{
-  return (rl_change_case (count, UpCase));
-}
-
-/* Lowercase the word at point. */
-int
-rl_downcase_word (count, key)
-     int count, key;
-{
-  return (rl_change_case (count, DownCase));
-}
-
-/* Upcase the first letter, downcase the rest. */
-int
-rl_capitalize_word (count, key)
-     int count, key;
-{
- return (rl_change_case (count, CapCase));
-}
-
-/* The meaty function.
-   Change the case of COUNT words, performing OP on them.
-   OP is one of UpCase, DownCase, or CapCase.
-   If a negative argument is given, leave point where it started,
-   otherwise, leave it where it moves to. */
-static int
-rl_change_case (count, op)
-     int count, op;
-{
-  register int start, end;
-  int inword, c;
-
-  start = rl_point;
-  rl_forward_word (count, 0);
-  end = rl_point;
-
-  if (count < 0)
-    SWAP (start, end);
-
-  /* We are going to modify some text, so let's prepare to undo it. */
-  rl_modifying (start, end);
-
-  for (inword = 0; start < end; start++)
-    {
-      c = the_line[start];
-      switch (op)
-       {
-       case UpCase:
-         the_line[start] = _rl_to_upper (c);
-         break;
-
-       case DownCase:
-         the_line[start] = _rl_to_lower (c);
-         break;
-
-       case CapCase:
-         the_line[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c);
-         inword = rl_alphabetic (the_line[start]);
-         break;
-
-       default:
-         rl_ding ();
-         return -1;
-       }
-    }
-  rl_point = end;
-  return 0;
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Transposition                               */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Transpose the words at point.  If point is at the end of the line,
-   transpose the two words before point. */
-int
-rl_transpose_words (count, key)
-     int count, key;
-{
-  char *word1, *word2;
-  int w1_beg, w1_end, w2_beg, w2_end;
-  int orig_point = rl_point;
-
-  if (!count)
-    return 0;
-
-  /* Find the two words. */
-  rl_forward_word (count, key);
-  w2_end = rl_point;
-  rl_backward_word (1, key);
-  w2_beg = rl_point;
-  rl_backward_word (count, key);
-  w1_beg = rl_point;
-  rl_forward_word (1, key);
-  w1_end = rl_point;
-
-  /* Do some check to make sure that there really are two words. */
-  if ((w1_beg == w2_beg) || (w2_beg < w1_end))
-    {
-      rl_ding ();
-      rl_point = orig_point;
-      return -1;
-    }
-
-  /* Get the text of the words. */
-  word1 = rl_copy_text (w1_beg, w1_end);
-  word2 = rl_copy_text (w2_beg, w2_end);
-
-  /* We are about to do many insertions and deletions.  Remember them
-     as one operation. */
-  rl_begin_undo_group ();
-
-  /* Do the stuff at word2 first, so that we don't have to worry
-     about word1 moving. */
-  rl_point = w2_beg;
-  rl_delete_text (w2_beg, w2_end);
-  rl_insert_text (word1);
-
-  rl_point = w1_beg;
-  rl_delete_text (w1_beg, w1_end);
-  rl_insert_text (word2);
-
-  /* This is exactly correct since the text before this point has not
-     changed in length. */
-  rl_point = w2_end;
-
-  /* I think that does it. */
-  rl_end_undo_group ();
-  free (word1);
-  free (word2);
-
-  return 0;
-}
-
-/* Transpose the characters at point.  If point is at the end of the line,
-   then transpose the characters before point. */
-int
-rl_transpose_chars (count, key)
-     int count, key;
-{
-  char dummy[2];
-
-  if (!count)
-    return 0;
-
-  if (!rl_point || rl_end < 2)
-    {
-      rl_ding ();
-      return -1;
-    }
-
-  rl_begin_undo_group ();
-
-  if (rl_point == rl_end)
-    {
-      --rl_point;
-      count = 1;
-    }
-  rl_point--;
-
-  dummy[0] = the_line[rl_point];
-  dummy[1] = '\0';
-
-  rl_delete_text (rl_point, rl_point + 1);
-
-  rl_point += count;
-  _rl_fix_point (0);
-  rl_insert_text (dummy);
-
-  rl_end_undo_group ();
-  return 0;
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     Character Searching                         */
-/*                                                                 */
-/* **************************************************************** */
-
-int
-_rl_char_search_internal (count, dir, schar)
-     int count, dir, schar;
-{
-  int pos, inc;
-
-  pos = rl_point;
-  inc = (dir < 0) ? -1 : 1;
-  while (count)
-    {
-      if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
-       {
-         rl_ding ();
-         return -1;
-       }
-
-      pos += inc;
-      do
-       {
-         if (rl_line_buffer[pos] == schar)
-           {
-             count--;
-             if (dir < 0)
-               rl_point = (dir == BTO) ? pos + 1 : pos;
-             else
-               rl_point = (dir == FTO) ? pos - 1 : pos;
-             break;
-           }
-       }
-      while ((dir < 0) ? pos-- : ++pos < rl_end);
-    }
-  return (0);
-}
-
-/* Search COUNT times for a character read from the current input stream.
-   FDIR is the direction to search if COUNT is non-negative; otherwise
-   the search goes in BDIR. */
-static int
-_rl_char_search (count, fdir, bdir)
-     int count, fdir, bdir;
-{
-  int c;
-
-  RL_SETSTATE(RL_STATE_MOREINPUT);
-  c = rl_read_key ();
-  RL_UNSETSTATE(RL_STATE_MOREINPUT);
-
-  if (count < 0)
-    return (_rl_char_search_internal (-count, bdir, c));
-  else
-    return (_rl_char_search_internal (count, fdir, c));
-}
-
-int
-rl_char_search (count, key)
-     int count, key;
-{
-  return (_rl_char_search (count, FFIND, BFIND));
-}
-
-int
-rl_backward_char_search (count, key)
-     int count, key;
-{
-  return (_rl_char_search (count, BFIND, FFIND));
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     History Utilities                           */
-/*                                                                 */
-/* **************************************************************** */
-
-/* We already have a history library, and that is what we use to control
-   the history features of readline.  This is our local interface to
-   the history mechanism. */
-
-/* While we are editing the history, this is the saved
-   version of the original line. */
-HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
-
-/* Set the history pointer back to the last entry in the history. */
-static void
-start_using_history ()
-{
-  using_history ();
-  if (_rl_saved_line_for_history)
-    _rl_free_history_entry (_rl_saved_line_for_history);
-
-  _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
-}
-
-/* Free the contents (and containing structure) of a HIST_ENTRY. */
-void
-_rl_free_history_entry (entry)
-     HIST_ENTRY *entry;
-{
-  if (entry == 0)
-    return;
-  if (entry->line)
-    free (entry->line);
-  free (entry);
-}
-
-/* Perhaps put back the current line if it has changed. */
-int
-rl_maybe_replace_line ()
-{
-  HIST_ENTRY *temp;
-
-  temp = current_history ();
-  /* If the current line has changed, save the changes. */
-  if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
-    {
-      temp = replace_history_entry (where_history (), the_line, (histdata_t)rl_undo_list);
-      free (temp->line);
-      free (temp);
-    }
-  return 0;
-}
-
-/* Restore the _rl_saved_line_for_history if there is one. */
-int
-rl_maybe_unsave_line ()
-{
-  int line_len;
-
-  if (_rl_saved_line_for_history)
-    {
-      line_len = strlen (_rl_saved_line_for_history->line);
-
-      if (line_len >= rl_line_buffer_len)
-       rl_extend_line_buffer (line_len);
-
-      strcpy (the_line, _rl_saved_line_for_history->line);
-      rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
-      _rl_free_history_entry (_rl_saved_line_for_history);
-      _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
-      rl_end = rl_point = strlen (the_line);
-    }
-  else
-    rl_ding ();
-  return 0;
-}
-
-/* Save the current line in _rl_saved_line_for_history. */
-int
-rl_maybe_save_line ()
-{
-  if (_rl_saved_line_for_history == 0)
-    {
-      _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
-      _rl_saved_line_for_history->line = savestring (the_line);
-      _rl_saved_line_for_history->data = (char *)rl_undo_list;
-    }
-  return 0;
-}
-
-int
-_rl_free_saved_history_line ()
-{
-  if (_rl_saved_line_for_history)
-    {
-      _rl_free_history_entry (_rl_saved_line_for_history);
-      _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
-    }
-  return 0;
-}      
-
-/* **************************************************************** */
-/*                                                                 */
-/*                     History Commands                            */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Meta-< goes to the start of the history. */
-int
-rl_beginning_of_history (count, key)
-     int count, key;
-{
-  return (rl_get_previous_history (1 + where_history (), key));
-}
-
-/* Meta-> goes to the end of the history.  (The current line). */
-int
-rl_end_of_history (count, key)
-     int count, key;
-{
-  rl_maybe_replace_line ();
-  using_history ();
-  rl_maybe_unsave_line ();
-  return 0;
-}
-
-/* Move down to the next history line. */
-int
-rl_get_next_history (count, key)
-     int count, key;
-{
-  HIST_ENTRY *temp;
-  int line_len;
-
-  if (count < 0)
-    return (rl_get_previous_history (-count, key));
-
-  if (count == 0)
-    return 0;
-
-  rl_maybe_replace_line ();
-
-  /* either not saved by rl_newline or at end of line, so set appropriately. */
-  if (_rl_history_saved_point == -1 && (rl_point || rl_end))
-    _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
-
-  temp = (HIST_ENTRY *)NULL;
-  while (count)
-    {
-      temp = next_history ();
-      if (!temp)
-       break;
-      --count;
-    }
-
-  if (temp == 0)
-    rl_maybe_unsave_line ();
-  else
-    {
-      line_len = strlen (temp->line);
-
-      if (line_len >= rl_line_buffer_len)
-       rl_extend_line_buffer (line_len);
-
-      strcpy (the_line, temp->line);
-      rl_undo_list = (UNDO_LIST *)temp->data;
-      rl_end = strlen (the_line);
-      rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1)
-                       ? _rl_history_saved_point
-                       : rl_end;
-      if (rl_point > rl_end)
-       rl_point = rl_end;
-#if defined (VI_MODE)
-      if (rl_editing_mode == vi_mode)
-       rl_point = 0;
-#endif /* VI_MODE */
-    }
-  return 0;
-}
-
-/* Get the previous item out of our interactive history, making it the current
-   line.  If there is no previous history, just ding. */
-int
-rl_get_previous_history (count, key)
-     int count, key;
-{
-  HIST_ENTRY *old_temp, *temp;
-  int line_len;
-
-  if (count < 0)
-    return (rl_get_next_history (-count, key));
-
-  if (count == 0)
-    return 0;
-
-  /* either not saved by rl_newline or at end of line, so set appropriately. */
-  if (_rl_history_saved_point == -1 && (rl_point || rl_end))
-    _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
-
-  /* If we don't have a line saved, then save this one. */
-  rl_maybe_save_line ();
-
-  /* If the current line has changed, save the changes. */
-  rl_maybe_replace_line ();
-
-  temp = old_temp = (HIST_ENTRY *)NULL;
-  while (count)
-    {
-      temp = previous_history ();
-      if (temp == 0)
-       break;
-
-      old_temp = temp;
-      --count;
-    }
-
-  /* If there was a large argument, and we moved back to the start of the
-     history, that is not an error.  So use the last value found. */
-  if (!temp && old_temp)
-    temp = old_temp;
-
-  if (temp == 0)
-    rl_ding ();
-  else
-    {
-      line_len = strlen (temp->line);
-
-      if (line_len >= rl_line_buffer_len)
-       rl_extend_line_buffer (line_len);
-
-      strcpy (the_line, temp->line);
-      rl_undo_list = (UNDO_LIST *)temp->data;
-      rl_end = line_len;
-      rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1)
-                       ? _rl_history_saved_point
-                       : rl_end;
-      if (rl_point > rl_end)
-       rl_point = rl_end;
-
-#if defined (VI_MODE)
-      if (rl_editing_mode == vi_mode)
-       rl_point = 0;
-#endif /* VI_MODE */
-    }
-  return 0;
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                The Mark and the Region.                         */
-/*                                                                 */
-/* **************************************************************** */
-
-/* Set the mark at POSITION. */
-int
-_rl_set_mark_at_pos (position)
-     int position;
-{
-  if (position > rl_end)
-    return -1;
-
-  rl_mark = position;
-  return 0;
-}
-
-/* A bindable command to set the mark. */
-int
-rl_set_mark (count, key)
-     int count, key;
-{
-  return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
-}
-
-/* Exchange the position of mark and point. */
-int
-rl_exchange_point_and_mark (count, key)
-     int count, key;
-{
-  if (rl_mark > rl_end)
-    rl_mark = -1;
-
-  if (rl_mark == -1)
-    {
-      rl_ding ();
-      return -1;
-    }
-  else
-    SWAP (rl_point, rl_mark);
-
-  return 0;
-}
-
-/* **************************************************************** */
-/*                                                                 */
-/*                         Editing Modes                           */
-/*                                                                 */
-/* **************************************************************** */
-/* How to toggle back and forth between editing modes. */
-int
-rl_vi_editing_mode (count, key)
-     int count, key;
-{
-#if defined (VI_MODE)
-  rl_editing_mode = vi_mode;
-  rl_vi_insertion_mode (1, key);
-#endif /* VI_MODE */
-  return 0;
-}
-
-int
-rl_emacs_editing_mode (count, key)
-     int count, key;
-{
-  rl_editing_mode = emacs_mode;
-  _rl_keymap = emacs_standard_keymap;
-  return 0;
-}
index d608c7ab8b3ae41c27c8a10441b1c168552520e6..f11b3d0357c89cb440274cd2f4a040a0b91824cb 100644 (file)
@@ -29,18 +29,20 @@ extern "C" {
 
 #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    0x0402          /* Readline 4.2 */
+#define RL_READLINE_VERSION    0x0403          /* Readline 4.3 */
 #define RL_VERSION_MAJOR       4
-#define RL_VERSION_MINOR       2
+#define RL_VERSION_MINOR       3
 
 /* Readline data structures. */
 
@@ -82,7 +84,11 @@ 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));
@@ -132,6 +138,9 @@ extern int rl_exchange_point_and_mark PARAMS((int, int));
 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));
@@ -365,6 +374,7 @@ 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));
@@ -417,6 +427,8 @@ 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));
@@ -453,6 +465,10 @@ extern int rl_readline_state;
    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;
@@ -675,18 +691,33 @@ extern int rl_completion_type;
    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;
+
 /* 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;
 
+/* 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;
-   
+
 /* Definitions available for use by readline clients. */
 #define RL_PROMPT_START_IGNORE '\001'
 #define RL_PROMPT_END_IGNORE   '\002'
@@ -725,6 +756,42 @@ extern int rl_inhibit_completion;
 #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;
+
+  /* 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
index d2ab70401250b691d3870bd77caf82fc6e127dd6..c651fd8b41f66ad39807ee1e18e714fcb8dae961 100644 (file)
@@ -54,4 +54,7 @@
    X `callback' style. */
 #define READLINE_CALLBACKS
 
+/* Define this if you want the cursor to indicate insert or overwrite mode. */
+/* #define CURSOR_MODE */
+
 #endif /* _RLCONF_H_ */
index bd055e3bc8021219faa90010b13d073735220969..4a28bd1e49c2d14571a8b599ed17c70be7e649bb 100644 (file)
@@ -74,7 +74,7 @@ extern char *strchr (), *strrchr ();
 #define _rl_strnicmp strncasecmp
 #else
 extern int _rl_stricmp PARAMS((char *, char *));
-extern int _rl_strnicmp PARAMS((char *, char *));
+extern int _rl_strnicmp PARAMS((char *, char *, int));
 #endif
 
 #if defined (HAVE_STRPBRK)
@@ -89,6 +89,13 @@ extern char *_rl_strpbrk PARAMS((const char *, const char *));
 #  define emacs_mode 1
 #endif
 
+#if !defined (RL_IM_INSERT)
+#  define RL_IM_INSERT         1
+#  define RL_IM_OVERWRITE      0
+#
+#  define RL_IM_DEFAULT                RL_IM_INSERT
+#endif
+
 /* If you cast map[key].function to type (Keymap) on a Cray,
    the compiler takes the value of map[key].function and
    divides it by 4 to convert between pointer types (pointers
@@ -121,9 +128,10 @@ extern char *_rl_strpbrk PARAMS((const char *, const char *));
 /* Possible values for the found_quote flags word used by the completion
    functions.  It says what kind of (shell-like) quoting we found anywhere
    in the line. */
-#define RL_QF_SINGLE_QUOTE     0x1
-#define RL_QF_DOUBLE_QUOTE     0x2
-#define RL_QF_BACKSLASH                0x4
+#define RL_QF_SINGLE_QUOTE     0x01
+#define RL_QF_DOUBLE_QUOTE     0x02
+#define RL_QF_BACKSLASH                0x04
+#define RL_QF_OTHER_QUOTE      0x08
 
 /* Default readline line buffer length. */
 #define DEFAULT_BUFFER_SIZE 256
@@ -138,6 +146,10 @@ extern char *_rl_strpbrk PARAMS((const char *, const char *));
 #  define FREE(x)      if (x) free (x)
 #endif
 
+#if !defined (SWAP)
+#  define SWAP(s, e)  do { int t; t = s; s = e; e = t; } while (0)
+#endif
+
 /* CONFIGURATION SECTION */
 #include "rlconf.h"
 
diff --git a/lib/readline/rlmbutil.h b/lib/readline/rlmbutil.h
new file mode 100644 (file)
index 0000000..27ca32b
--- /dev/null
@@ -0,0 +1,108 @@
+/* rlmbutil.h -- utility functions for multibyte characters. */
+
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library 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.
+
+   The GNU Readline Library 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.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_RL_MBUTIL_H_)
+#define _RL_MBUTIL_H_
+
+#include "rlstdc.h"
+
+/************************************************/
+/* check multibyte capability for I18N code     */
+/************************************************/
+
+/* For platforms which support the ISO C amendement 1 functionality we
+   support user defined character classes.  */
+   /* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
+#if defined (HAVE_WCTYPE_H) && defined (HAVE_WCHAR_H)
+#  include <wchar.h>
+#  include <wctype.h>
+#  if defined (HAVE_MBSRTOWCS) /* system is supposed to support XPG5 */
+#    define HANDLE_MULTIBYTE      1
+#  endif
+#endif
+
+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t.  */
+#if HANDLE_MULTIBYTE && !defined (HAVE_MBSTATE_T)
+#  define wcsrtombs(dest, src, len, ps) (wcsrtombs) (dest, src, len, 0)
+#  define mbsrtowcs(dest, src, len, ps) (mbsrtowcs) (dest, src, len, 0)
+#  define wcrtomb(s, wc, ps) (wcrtomb) (s, wc, 0)
+#  define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
+#  define mbrlen(s, n, ps) (mbrlen) (s, n, 0)
+#  define mbstate_t int
+#endif
+
+/* Make sure MB_LEN_MAX is at least 16 on systems that claim to be able to
+   handle multibyte chars (some systems define MB_LEN_MAX as 1) */
+#ifdef HANDLE_MULTIBYTE
+#  include <limits.h>
+#  if defined(MB_LEN_MAX) && (MB_LEN_MAX < 16)
+#    undef MB_LEN_MAX
+#  endif
+#  if !defined (MB_LEN_MAX)
+#    define MB_LEN_MAX 16
+#  endif
+#endif
+
+/************************************************/
+/* end of multibyte capability checks for I18N  */
+/************************************************/
+
+/*
+ * Flags for _rl_find_prev_mbchar and _rl_find_next_mbchar:
+ *
+ * MB_FIND_ANY         find any multibyte character
+ * MB_FIND_NONZERO     find a non-zero-width multibyte character
+ */
+
+#define MB_FIND_ANY    0x00
+#define MB_FIND_NONZERO        0x01
+
+extern int _rl_find_prev_mbchar PARAMS((char *, int, int));
+extern int _rl_find_next_mbchar PARAMS((char *, int, int, int));
+
+#ifdef HANDLE_MULTIBYTE
+
+extern int _rl_compare_chars PARAMS((char *, int, mbstate_t *, char *, int, mbstate_t *));
+extern int _rl_get_char_len PARAMS((char *, mbstate_t *));
+extern int _rl_adjust_point PARAMS((char *, int, mbstate_t *));
+
+extern int _rl_read_mbchar PARAMS((char *, int));
+extern int _rl_read_mbstring PARAMS((int, char *, int));
+
+extern int _rl_is_mbchar_matched PARAMS((char *, int, int, char *, int));
+
+#else /* !HANDLE_MULTIBYTE */
+
+#undef MB_LEN_MAX
+#undef MB_CUR_MAX
+
+#define MB_LEN_MAX     1
+#define MB_CUR_MAX     1
+
+#define _rl_find_prev_mbchar(b, i, f)          (((i) == 0) ? (i) : ((i) - 1))
+#define _rl_find_next_mbchar(b, i1, i2, f)     ((i1) + (i2))
+
+#endif /* !HANDLE_MULTIBYTE */
+
+extern int rl_byte_oriented;
+
+#endif /* _RL_MBUTIL_H_ */
index 9347b361599934c95f4bb17a7d2549424076725a..ccb914469e7507e5ea4305ba505b2f76bade3ed5 100644 (file)
@@ -52,6 +52,7 @@ extern int rl_arg_sign;
 extern int rl_visible_prompt_length;
 extern int readline_echoing_p;
 extern int rl_key_sequence_length;
+extern int rl_byte_oriented;
 
 /* display.c */
 extern int rl_display_fixed;
@@ -65,18 +66,9 @@ extern int rl_blink_matching_paren;
  *                                                                      *
  *************************************************************************/
 
-/* bind.c */
-extern char *rl_untranslate_keyseq PARAMS((int));
-
 /* kill.c */
 extern int rl_set_retained_kills PARAMS((int));
 
-/* readline.c */
-extern int rl_discard_argument PARAMS((void));
-
-/* rltty.c */
-extern int rl_stop_output PARAMS((int, int));
-
 /* terminal.c */
 extern void _rl_set_screen_size PARAMS((int, int));
 
@@ -113,6 +105,10 @@ extern int readline_internal_char PARAMS((void));
 /* bind.c */
 extern void _rl_bind_if_unbound PARAMS((const char *, rl_command_func_t *));
 
+/* complete.c */
+extern char _rl_find_completion_word PARAMS((int *, int *));
+extern void _rl_free_match_list PARAMS((char **));
+
 /* display.c */
 extern char *_rl_strip_prompt PARAMS((char *));
 extern void _rl_move_cursor_relative PARAMS((int, const char *));
@@ -132,7 +128,9 @@ extern int _rl_current_display_line PARAMS((void));
 /* input.c */
 extern int _rl_any_typein PARAMS((void));
 extern int _rl_input_available PARAMS((void));
+extern int _rl_input_queued PARAMS((int));
 extern void _rl_insert_typein PARAMS((int));
+extern int _rl_unget_char PARAMS((int));
 
 /* macro.c */
 extern void _rl_with_macro_input PARAMS((char *));
@@ -142,6 +140,12 @@ extern void _rl_pop_executing_macro PARAMS((void));
 extern void _rl_add_macro_char PARAMS((int));
 extern void _rl_kill_kbd_macro PARAMS((void));
 
+/* misc.c */
+extern int _rl_init_argument PARAMS((void));
+extern void _rl_start_using_history PARAMS((void));
+extern int _rl_free_saved_history_line PARAMS((void));
+extern void _rl_set_insert_mode PARAMS((int, int));
+
 /* nls.c */
 extern int _rl_init_eightbit PARAMS((void));
 
@@ -152,12 +156,7 @@ extern void _rl_enable_paren_matching PARAMS((int));
 extern void _rl_init_line_state PARAMS((void));
 extern void _rl_set_the_line PARAMS((void));
 extern int _rl_dispatch PARAMS((int, Keymap));
-extern int _rl_init_argument PARAMS((void));
-extern void _rl_fix_point PARAMS((int));
-extern void _rl_replace_text PARAMS((const char *, int, int));
-extern int _rl_char_search_internal PARAMS((int, int, int));
-extern int _rl_set_mark_at_pos PARAMS((int));
-extern int _rl_free_saved_history_line PARAMS((void));
+extern int _rl_dispatch_subseq PARAMS((int, Keymap, int));
 
 /* rltty.c */
 extern int _rl_disable_tty_signals PARAMS((void));
@@ -175,9 +174,23 @@ extern void _rl_output_some_chars PARAMS((const char *, int));
 extern int _rl_backspace PARAMS((int));
 extern void _rl_enable_meta_key PARAMS((void));
 extern void _rl_control_keypad PARAMS((int));
+extern void _rl_set_cursor PARAMS((int, int));
+
+/* text.c */
+extern void _rl_fix_point PARAMS((int));
+extern int _rl_replace_text PARAMS((const char *, int, int));
+extern int _rl_insert_char PARAMS((int, int));
+extern int _rl_overwrite_char PARAMS((int, int));
+extern int _rl_overwrite_rubout PARAMS((int, int));
+extern int _rl_rubout_char PARAMS((int, int));
+#if defined (HANDLE_MULTIBYTE)
+extern int _rl_char_search_internal PARAMS((int, int, char *, int));
+#else
+extern int _rl_char_search_internal PARAMS((int, int, int));
+#endif
+extern int _rl_set_mark_at_pos PARAMS((int));
 
 /* util.c */
-extern int rl_alphabetic PARAMS((int));
 extern int _rl_abort_internal PARAMS((void));
 extern char *_rl_strindex PARAMS((const char *, const char *));
 extern int _rl_qsort_string_compare PARAMS((char **, char **));
@@ -207,9 +220,11 @@ extern const char *_rl_possible_meta_prefixes[];
 /* complete.c */
 extern int _rl_complete_show_all;
 extern int _rl_complete_mark_directories;
+extern int _rl_complete_mark_symlink_dirs;
 extern int _rl_print_completions_horizontally;
 extern int _rl_completion_case_fold;
 extern int _rl_match_hidden_files;
+extern int _rl_page_completions;
 
 /* display.c */
 extern int _rl_vis_botlin;
@@ -221,9 +236,12 @@ extern char *rl_display_prompt;
 extern char *_rl_isearch_terminators;
 
 /* macro.c */
-extern int _rl_defining_kbd_macro;
 extern char *_rl_executing_macro;
 
+/* misc.c */
+extern int _rl_history_preserve_point;
+extern int _rl_history_saved_point;
+
 /* readline.c */
 extern int _rl_horizontal_scroll_mode;
 extern int _rl_mark_modified_lines;
@@ -231,7 +249,6 @@ extern int _rl_bell_preference;
 extern int _rl_meta_flag;
 extern int _rl_convert_meta_chars_to_ascii;
 extern int _rl_output_meta_chars;
-extern int _rl_history_preserve_point;
 extern char *_rl_comment_begin;
 extern unsigned char _rl_parsing_conditionalized_out;
 extern Keymap _rl_keymap;
index cc0dc0301181b0edefa06b5a614787d910110dd9..755efebaadf038d206b8c68ee616e9bfa909e25e 100644 (file)
@@ -647,7 +647,6 @@ rl_prep_terminal (meta_flag)
   if (get_tty_settings (tty, &tio) < 0)
     {
       release_sigint ();
-fprintf(stderr, "readline: warning: rl_prep_terminal: cannot get terminal settings");
       return;
     }
 
index 9c2feb1728f2017a9d4e8dfc185b00af08003889..7e0d60b5eb46903aac8aa0e4c688796f4a4cdf3d 100644 (file)
@@ -40,6 +40,8 @@
 #endif
 
 #include "rldefs.h"
+#include "rlmbutil.h"
+
 #include "readline.h"
 #include "history.h"
 
@@ -80,15 +82,8 @@ static void
 make_history_line_current (entry)
      HIST_ENTRY *entry;
 {
-  int line_len;
-
-  line_len = strlen (entry->line);
-  if (line_len >= rl_line_buffer_len)
-    rl_extend_line_buffer (line_len);
-  strcpy (rl_line_buffer, entry->line);
-
+  rl_replace_line (entry->line, 0);
   rl_undo_list = (UNDO_LIST *)entry->data;
-  rl_end = line_len;
 
   if (_rl_saved_line_for_history)
     _rl_free_history_entry (_rl_saved_line_for_history);
@@ -169,6 +164,8 @@ noninc_dosearch (string, dir)
   make_history_line_current (entry);
 
   rl_point = 0;
+  rl_mark = rl_end;
+
   rl_clear_message ();
 }
 
@@ -182,11 +179,15 @@ noninc_search (dir, pchar)
      int dir;
      int pchar;
 {
-  int saved_point, c;
+  int saved_point, saved_mark, c;
   char *p;
+#if defined (HANDLE_MULTIBYTE)
+  char mb[MB_LEN_MAX];
+#endif
 
   rl_maybe_save_line ();
   saved_point = rl_point;
+  saved_mark = rl_mark;
 
   /* Use the line buffer to read the search string. */
   rl_line_buffer[0] = 0;
@@ -206,6 +207,11 @@ noninc_search (dir, pchar)
       c = rl_read_key ();
       RL_UNSETSTATE(RL_STATE_MOREINPUT);
 
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       c = _rl_read_mbstring (c, mb, MB_LEN_MAX);
+#endif
+
       if (c == 0)
        break;
 
@@ -218,9 +224,10 @@ noninc_search (dir, pchar)
              rl_maybe_unsave_line ();
              rl_clear_message ();
              rl_point = saved_point;
+             rl_mark = saved_mark;
              SEARCH_RETURN;
            }
-         rl_rubout (1, c);
+         _rl_rubout_char (1, c);
          break;
 
        case CTRL('W'):
@@ -242,17 +249,25 @@ noninc_search (dir, pchar)
          rl_maybe_unsave_line ();
          rl_clear_message ();
          rl_point = saved_point;
+         rl_mark = saved_mark;
          rl_ding ();
          SEARCH_RETURN;
 
        default:
-         rl_insert (1, c);
+#if defined (HANDLE_MULTIBYTE)
+         if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+           rl_insert_text (mb);
+         else
+#endif
+           _rl_insert_char (1, c);
          break;
        }
       (*rl_redisplay_function) ();
     }
 
  dosearch:
+  rl_mark = saved_mark;
+
   /* If rl_point == 0, we want to re-use the previous search string and
      start from the saved history position.  If there's no previous search
      string, punt. */
@@ -373,9 +388,11 @@ rl_history_search_internal (count, dir)
         {
           rl_point = rl_end = rl_history_search_len;
           rl_line_buffer[rl_end] = '\0';
+          rl_mark = 0;
         }
 #else
       rl_point = rl_history_search_len;        /* rl_maybe_unsave_line changes it */
+      rl_mark = rl_end;
 #endif
       return 1;
     }
@@ -384,6 +401,8 @@ rl_history_search_internal (count, dir)
   make_history_line_current (temp);
 
   rl_point = rl_history_search_len;
+  rl_mark = rl_end;
+
   return 0;
 }
 
index a1912691b66ac0817afe074fb16a63a24f557e53..0a1468b6b2a5db9f446cdff80fc82fd620cc25b0 100644 (file)
@@ -74,6 +74,7 @@ typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt
 #endif /* !HAVE_POSIX_SIGNALS */
 
 static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
+static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
 
 /* Exported variables for use by applications. */
 
@@ -232,7 +233,7 @@ rl_set_sighandler (sig, handler, ohandler)
   struct sigaction act;
 
   act.sa_handler = handler;
-  act.sa_flags = 0;
+  act.sa_flags = 0;    /* XXX - should we set SA_RESTART for SIGWINCH? */
   sigemptyset (&act.sa_mask);
   sigemptyset (&ohandler->sa_mask);
   sigaction (sig, &act, &old_handler);
index 4d2268c0612ebaf079fad3d24c6507a4909b66b3..f3f5b6c47fb2011b9f7d7e982c74b8da13439844 100644 (file)
@@ -66,6 +66,9 @@
 #include "rlshell.h"
 #include "xmalloc.h"
 
+#define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
+#define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
+
 /* **************************************************************** */
 /*                                                                 */
 /*                     Terminal and Termcap                        */
@@ -140,6 +143,16 @@ static char *_rl_term_ke;
 /* The key sequences sent by the Home and End keys, if any. */
 static char *_rl_term_kh;
 static char *_rl_term_kH;
+static char *_rl_term_at7;     /* @7 */
+
+/* Insert key */
+static char *_rl_term_kI;
+
+/* Cursor control */
+static char *_rl_term_vs;      /* very visible */
+static char *_rl_term_ve;      /* normal */
+
+static void bind_termcap_arrow_keys PARAMS((Keymap));
 
 /* Variables that hold the screen dimensions, used by the display code. */
 int _rl_screenwidth, _rl_screenheight, _rl_screenchars;
@@ -274,7 +287,10 @@ rl_resize_terminal ()
   if (readline_echoing_p)
     {
       _rl_get_screen_size (fileno (rl_instream), 1);
-      _rl_redisplay_after_sigwinch ();
+      if (CUSTOM_REDISPLAY_FUNC ())
+       rl_forced_update_display ();
+      else
+       _rl_redisplay_after_sigwinch ();
     }
 }
 
@@ -287,6 +303,7 @@ struct _tc_string {
    search algorithm to something smarter. */
 static struct _tc_string tc_strings[] =
 {
+  { "@7", &_rl_term_at7 },
   { "DC", &_rl_term_DC },
   { "IC", &_rl_term_IC },
   { "ce", &_rl_term_clreol },
@@ -296,14 +313,15 @@ static struct _tc_string tc_strings[] =
   { "ei", &_rl_term_ei },
   { "ic", &_rl_term_ic },
   { "im", &_rl_term_im },
+  { "kH", &_rl_term_kH },      /* home down ?? */
+  { "kI", &_rl_term_kI },      /* insert */
   { "kd", &_rl_term_kd },
+  { "ke", &_rl_term_ke },      /* end keypad mode */
   { "kh", &_rl_term_kh },      /* home */
-  { "kH", &_rl_term_kH },      /* end */
   { "kl", &_rl_term_kl },
   { "kr", &_rl_term_kr },
+  { "ks", &_rl_term_ks },      /* start keypad mode */
   { "ku", &_rl_term_ku },
-  { "ks", &_rl_term_ks },
-  { "ke", &_rl_term_ke },
   { "le", &_rl_term_backspace },
   { "mm", &_rl_term_mm },
   { "mo", &_rl_term_mo },
@@ -313,6 +331,8 @@ static struct _tc_string tc_strings[] =
   { "pc", &_rl_term_pc },
   { "up", &_rl_term_up },
   { "vb", &_rl_visible_bell },
+  { "vs", &_rl_term_vs },
+  { "ve", &_rl_term_ve },
 };
 
 #define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
@@ -336,9 +356,6 @@ get_term_capabilities (bp)
   tcap_initialized = 1;
 }
 
-#define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
-#define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
-
 int
 _rl_init_terminal_io (terminal_name)
      const char *terminal_name;
@@ -346,7 +363,6 @@ _rl_init_terminal_io (terminal_name)
   const char *term;
   char *buffer;
   int tty, tgetent_ret;
-  Keymap xkeymap;
 
   term = terminal_name ? terminal_name : sh_get_env_value ("TERM");
   _rl_term_clrpag = _rl_term_cr = _rl_term_clreol = (char *)NULL;
@@ -404,7 +420,10 @@ _rl_init_terminal_io (terminal_name)
       _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
       _rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
       _rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
+      _rl_term_kh = _rl_term_kH = _rl_term_kI = (char *)NULL;
+      _rl_term_ks = _rl_term_ke = _rl_term_at7 = (char *)NULL;
       _rl_term_mm = _rl_term_mo = (char *)NULL;
+      _rl_term_ve = _rl_term_vs = (char *)NULL;
 #if defined (HACK_TERMCAP_MOTION)
       term_forward_char = (char *)NULL;
 #endif
@@ -449,31 +468,36 @@ _rl_init_terminal_io (terminal_name)
 
   /* Attempt to find and bind the arrow keys.  Do not override already
      bound keys in an overzealous attempt, however. */
-  xkeymap = _rl_keymap;
 
-  _rl_keymap = emacs_standard_keymap;
-  _rl_bind_if_unbound (_rl_term_ku, rl_get_previous_history);
-  _rl_bind_if_unbound (_rl_term_kd, rl_get_next_history);
-  _rl_bind_if_unbound (_rl_term_kr, rl_forward);
-  _rl_bind_if_unbound (_rl_term_kl, rl_backward);
-
-  _rl_bind_if_unbound (_rl_term_kh, rl_beg_of_line);   /* Home */
-  _rl_bind_if_unbound (_rl_term_kH, rl_end_of_line);   /* End */
+  bind_termcap_arrow_keys (emacs_standard_keymap);
 
 #if defined (VI_MODE)
-  _rl_keymap = vi_movement_keymap;
+  bind_termcap_arrow_keys (vi_movement_keymap);
+  bind_termcap_arrow_keys (vi_insertion_keymap);
+#endif /* VI_MODE */
+
+  return 0;
+}
+
+/* Bind the arrow key sequences from the termcap description in MAP. */
+static void
+bind_termcap_arrow_keys (map)
+     Keymap map;
+{
+  Keymap xkeymap;
+
+  xkeymap = _rl_keymap;
+  _rl_keymap = map;
+
   _rl_bind_if_unbound (_rl_term_ku, rl_get_previous_history);
   _rl_bind_if_unbound (_rl_term_kd, rl_get_next_history);
   _rl_bind_if_unbound (_rl_term_kr, rl_forward);
   _rl_bind_if_unbound (_rl_term_kl, rl_backward);
 
   _rl_bind_if_unbound (_rl_term_kh, rl_beg_of_line);   /* Home */
-  _rl_bind_if_unbound (_rl_term_kH, rl_end_of_line);   /* End */
-#endif /* VI_MODE */
+  _rl_bind_if_unbound (_rl_term_at7, rl_end_of_line);  /* End */
 
   _rl_keymap = xkeymap;
-
-  return 0;
 }
 
 char *
@@ -610,3 +634,29 @@ _rl_control_keypad (on)
     tputs (_rl_term_ke, 1, _rl_output_character_function);
 #endif
 }
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Controlling the Cursor                      */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Set the cursor appropriately depending on IM, which is one of the
+   insert modes (insert or overwrite).  Insert mode gets the normal
+   cursor.  Overwrite mode gets a very visible cursor.  Only does
+   anything if we have both capabilities. */
+void
+_rl_set_cursor (im, force)
+     int im, force;
+{
+  if (_rl_term_ve && _rl_term_vs)
+    {
+      if (force || im != rl_insert_mode)
+       {
+         if (im == RL_IM_OVERWRITE)
+           tputs (_rl_term_vs, 1, _rl_output_character_function);
+         else
+           tputs (_rl_term_ve, 1, _rl_output_character_function);
+       }
+    }
+}
diff --git a/lib/readline/text.c b/lib/readline/text.c
new file mode 100644 (file)
index 0000000..2a7b724
--- /dev/null
@@ -0,0 +1,1540 @@
+/* text.c -- text handling commands for readline. */
+
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library 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.
+
+   The GNU Readline Library 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.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_LOCALE_H)
+#  include <locale.h>
+#endif
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#if defined (__EMX__)
+#  define INCL_DOSPROCESS
+#  include <os2.h>
+#endif /* __EMX__ */
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+/* Forward declarations. */
+static int rl_change_case PARAMS((int, int));
+static int _rl_char_search PARAMS((int, int, int));
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Insert and Delete                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Insert a string of text into the line at point.  This is the only
+   way that you should do insertion.  _rl_insert_char () calls this
+   function.  Returns the number of characters inserted. */
+int
+rl_insert_text (string)
+     const char *string;
+{
+  register int i, l;
+
+  l = (string && *string) ? strlen (string) : 0;
+  if (l == 0)
+    return 0;
+
+  if (rl_end + l >= rl_line_buffer_len)
+    rl_extend_line_buffer (rl_end + l);
+
+  for (i = rl_end; i >= rl_point; i--)
+    rl_line_buffer[i + l] = rl_line_buffer[i];
+  strncpy (rl_line_buffer + rl_point, string, l);
+
+  /* Remember how to undo this if we aren't undoing something. */
+  if (_rl_doing_an_undo == 0)
+    {
+      /* If possible and desirable, concatenate the undos. */
+      if ((l == 1) &&
+         rl_undo_list &&
+         (rl_undo_list->what == UNDO_INSERT) &&
+         (rl_undo_list->end == rl_point) &&
+         (rl_undo_list->end - rl_undo_list->start < 20))
+       rl_undo_list->end++;
+      else
+       rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
+    }
+  rl_point += l;
+  rl_end += l;
+  rl_line_buffer[rl_end] = '\0';
+  return l;
+}
+
+/* Delete the string between FROM and TO.  FROM is inclusive, TO is not.
+   Returns the number of characters deleted. */
+int
+rl_delete_text (from, to)
+     int from, to;
+{
+  register char *text;
+  register int diff, i;
+
+  /* Fix it if the caller is confused. */
+  if (from > to)
+    SWAP (from, to);
+
+  /* fix boundaries */
+  if (to > rl_end)
+    {
+      to = rl_end;
+      if (from > to)
+       from = to;
+    }
+  if (from < 0)
+    from = 0;
+
+  text = rl_copy_text (from, to);
+
+  /* Some versions of strncpy() can't handle overlapping arguments. */
+  diff = to - from;
+  for (i = from; i < rl_end - diff; i++)
+    rl_line_buffer[i] = rl_line_buffer[i + diff];
+
+  /* Remember how to undo this delete. */
+  if (_rl_doing_an_undo == 0)
+    rl_add_undo (UNDO_DELETE, from, to, text);
+  else
+    free (text);
+
+  rl_end -= diff;
+  rl_line_buffer[rl_end] = '\0';
+  return (diff);
+}
+
+/* Fix up point so that it is within the line boundaries after killing
+   text.  If FIX_MARK_TOO is non-zero, the mark is forced within line
+   boundaries also. */
+
+#define _RL_FIX_POINT(x) \
+       do { \
+       if (x > rl_end) \
+         x = rl_end; \
+       else if (x < 0) \
+         x = 0; \
+       } while (0)
+
+void
+_rl_fix_point (fix_mark_too)
+     int fix_mark_too;
+{
+  _RL_FIX_POINT (rl_point);
+  if (fix_mark_too)
+    _RL_FIX_POINT (rl_mark);
+}
+#undef _RL_FIX_POINT
+
+int
+_rl_replace_text (text, start, end)
+     const char *text;
+     int start, end;
+{
+  int n;
+
+  rl_begin_undo_group ();
+  rl_delete_text (start, end + 1);
+  rl_point = start;
+  n = rl_insert_text (text);
+  rl_end_undo_group ();
+
+  return n;
+}
+
+/* Replace the current line buffer contents with TEXT.  If CLEAR_UNDO is
+   non-zero, we free the current undo list. */
+void
+rl_replace_line (text, clear_undo)
+     const char *text;
+     int clear_undo;
+{
+  int len;
+
+  len = strlen (text);
+  if (len >= rl_line_buffer_len)
+    rl_extend_line_buffer (len);
+  strcpy (rl_line_buffer, text);
+  rl_end = len;
+
+  if (clear_undo)
+    rl_free_undo_list ();
+
+  _rl_fix_point (1);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Readline character functions                */
+/*                                                                 */
+/* **************************************************************** */
+
+/* This is not a gap editor, just a stupid line input routine.  No hair
+   is involved in writing any of the functions, and none should be. */
+
+/* Note that:
+
+   rl_end is the place in the string that we would place '\0';
+   i.e., it is always safe to place '\0' there.
+
+   rl_point is the place in the string where the cursor is.  Sometimes
+   this is the same as rl_end.
+
+   Any command that is called interactively receives two arguments.
+   The first is a count: the numeric arg pased to this command.
+   The second is the key which invoked this command.
+*/
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Movement Commands                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Note that if you `optimize' the display for these functions, you cannot
+   use said functions in other functions which do not do optimizing display.
+   I.e., you will have to update the data base for rl_redisplay, and you
+   might as well let rl_redisplay do that job. */
+
+/* Move forward COUNT bytes. */
+int
+rl_forward_byte (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_backward_byte (-count, key));
+
+  if (count > 0)
+    {
+      int end = rl_point + count;
+#if defined (VI_MODE)
+      int lend = rl_end > 0 ? rl_end - (rl_editing_mode == vi_mode) : rl_end;
+#else
+      int lend = rl_end;
+#endif
+
+      if (end > lend)
+       {
+         rl_point = lend;
+         rl_ding ();
+       }
+      else
+       rl_point = end;
+    }
+
+  if (rl_end < 0)
+    rl_end = 0;
+
+  return 0;
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Move forward COUNT characters. */
+int
+rl_forward_char (count, key)
+     int count, key;
+{
+  int point;
+
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    return (rl_forward_byte (count, key));
+
+  if (count < 0)
+    return (rl_backward_char (-count, key));
+
+  if (count > 0)
+    {
+      point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+
+#if defined (VI_MODE)
+      if (rl_end <= point && rl_editing_mode == vi_mode)
+       point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO);
+#endif
+
+      if (rl_point == point)
+       rl_ding ();
+
+      rl_point = point;
+
+      if (rl_end < 0)
+       rl_end = 0;
+    }
+
+  return 0;
+}
+#else /* !HANDLE_MULTIBYTE */
+int
+rl_forward_char (count, key)
+     int count, key;
+{
+  return (rl_forward_byte (count, key));
+}
+#endif /* !HANDLE_MULTIBYTE */
+  
+/* Backwards compatibility. */
+int
+rl_forward (count, key)
+     int count, key;
+{
+  return (rl_forward_char (count, key));
+}
+
+/* Move backward COUNT bytes. */
+int
+rl_backward_byte (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_forward_byte (-count, key));
+
+  if (count > 0)
+    {
+      if (rl_point < count)
+       {
+         rl_point = 0;
+         rl_ding ();
+       }
+      else
+       rl_point -= count;
+    }
+
+  if (rl_point < 0)
+    rl_point = 0;
+
+  return 0;
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Move backward COUNT characters. */
+int
+rl_backward_char (count, key)
+     int count, key;
+{
+  int point;
+
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    return (rl_backward_byte (count, key));
+
+  if (count < 0)
+    return (rl_forward_char (-count, key));
+
+  if (count > 0)
+    {
+      point = rl_point;
+
+      while (count > 0 && point > 0)
+       {
+         point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO);
+         count--;
+       }
+      if (count > 0)
+       {
+         rl_point = 0;
+         rl_ding ();
+       }
+      else
+        rl_point = point;
+    }
+
+  return 0;
+}
+#else
+int
+rl_backward_char (count, key)
+     int count, key;
+{
+  return (rl_backward_byte (count, key));
+}
+#endif
+
+/* Backwards compatibility. */
+int
+rl_backward (count, key)
+     int count, key;
+{
+  return (rl_backward_char (count, key));
+}
+
+/* Move to the beginning of the line. */
+int
+rl_beg_of_line (count, key)
+     int count, key;
+{
+  rl_point = 0;
+  return 0;
+}
+
+/* Move to the end of the line. */
+int
+rl_end_of_line (count, key)
+     int count, key;
+{
+  rl_point = rl_end;
+  return 0;
+}
+
+/* XXX - these might need changes for multibyte characters */
+/* Move forward a word.  We do what Emacs does. */
+int
+rl_forward_word (count, key)
+     int count, key;
+{
+  int c;
+
+  if (count < 0)
+    return (rl_backward_word (-count, key));
+
+  while (count)
+    {
+      if (rl_point == rl_end)
+       return 0;
+
+      /* If we are not in a word, move forward until we are in one.
+        Then, move forward until we hit a non-alphabetic character. */
+      c = rl_line_buffer[rl_point];
+      if (rl_alphabetic (c) == 0)
+       {
+         while (++rl_point < rl_end)
+           {
+             c = rl_line_buffer[rl_point];
+             if (rl_alphabetic (c))
+               break;
+           }
+       }
+
+      if (rl_point == rl_end)
+       return 0;
+
+      while (++rl_point < rl_end)
+       {
+         c = rl_line_buffer[rl_point];
+         if (rl_alphabetic (c) == 0)
+           break;
+       }
+      --count;
+    }
+
+  return 0;
+}
+
+/* Move backward a word.  We do what Emacs does. */
+int
+rl_backward_word (count, key)
+     int count, key;
+{
+  int c;
+
+  if (count < 0)
+    return (rl_forward_word (-count, key));
+
+  while (count)
+    {
+      if (!rl_point)
+       return 0;
+
+      /* Like rl_forward_word (), except that we look at the characters
+        just before point. */
+
+      c = rl_line_buffer[rl_point - 1];
+      if (rl_alphabetic (c) == 0)
+       {
+         while (--rl_point)
+           {
+             c = rl_line_buffer[rl_point - 1];
+             if (rl_alphabetic (c))
+               break;
+           }
+       }
+
+      while (rl_point)
+       {
+         c = rl_line_buffer[rl_point - 1];
+         if (rl_alphabetic (c) == 0)
+           break;
+         else
+           --rl_point;
+       }
+
+      --count;
+    }
+
+  return 0;
+}
+
+/* Clear the current line.  Numeric argument to C-l does this. */
+int
+rl_refresh_line (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  int curr_line;
+
+  curr_line = _rl_current_display_line ();
+
+  _rl_move_vert (curr_line);
+  _rl_move_cursor_relative (0, rl_line_buffer);   /* XXX is this right */
+
+  _rl_clear_to_eol (0);                /* arg of 0 means to not use spaces */
+
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+
+  return 0;
+}
+
+/* C-l typed to a line without quoting clears the screen, and then reprints
+   the prompt and the current input line.  Given a numeric arg, redraw only
+   the current line. */
+int
+rl_clear_screen (count, key)
+     int count, key;
+{
+  if (rl_explicit_arg)
+    {
+      rl_refresh_line (count, key);
+      return 0;
+    }
+
+  _rl_clear_screen ();         /* calls termcap function to clear screen */
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+
+  return 0;
+}
+
+int
+rl_arrow_keys (count, c)
+     int count, c;
+{
+  int ch;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  ch = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  switch (_rl_to_upper (ch))
+    {
+    case 'A':
+      rl_get_previous_history (count, ch);
+      break;
+
+    case 'B':
+      rl_get_next_history (count, ch);
+      break;
+
+    case 'C':
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_forward_char (count, ch);
+      else
+       rl_forward_byte (count, ch);
+      break;
+
+    case 'D':
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_backward_char (count, ch);
+      else
+       rl_backward_byte (count, ch);
+      break;
+
+    default:
+      rl_ding ();
+    }
+
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Text commands                               */
+/*                                                                 */
+/* **************************************************************** */
+
+#ifdef HANDLE_MULTIBYTE
+static char pending_bytes[MB_LEN_MAX];
+static int pending_bytes_length = 0;
+static mbstate_t ps = {0};
+#endif
+
+/* Insert the character C at the current location, moving point forward.
+   If C introduces a multibyte sequence, we read the whole sequence and
+   then insert the multibyte char into the line buffer. */
+int
+_rl_insert_char (count, c)
+     int count, c;
+{
+  register int i;
+  char *string;
+#ifdef HANDLE_MULTIBYTE
+  int string_size;
+  char incoming[MB_LEN_MAX + 1];
+  int incoming_length = 0;
+  mbstate_t ps_back;
+  static int stored_count = 0;
+#endif
+
+  if (count <= 0)
+    return 0;
+
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    {
+      incoming[0] = c;
+      incoming[1] = '\0';
+      incoming_length = 1;
+    }
+  else
+    {
+      wchar_t wc;
+      size_t ret;
+
+      if (stored_count <= 0)
+       stored_count = count;
+      else
+       count = stored_count;
+
+      ps_back = ps;
+      pending_bytes[pending_bytes_length++] = c;
+      ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps);
+
+      if (ret == (size_t)-2)
+       {
+         /* Bytes too short to compose character, try to wait for next byte.
+            Restore the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         ps = ps_back;
+         return 1;
+       }
+      else if (ret == (size_t)-1)
+       {
+         /* Invalid byte sequence for the current locale.  Treat first byte
+            as a single character. */
+         incoming[0] = pending_bytes[0];
+         incoming[1] = '\0';
+         incoming_length = 1;
+         pending_bytes_length--;
+         memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
+         /* Clear the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         memset (&ps, 0, sizeof (mbstate_t));
+       }
+      else if (ret == (size_t)0)
+       {
+         incoming[0] = '\0';
+         incoming_length = 0;
+         pending_bytes_length--;
+         /* Clear the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         memset (&ps, 0, sizeof (mbstate_t));
+       }
+      else
+       {
+         /* We successfully read a single multibyte character. */
+         memcpy (incoming, pending_bytes, pending_bytes_length);
+         incoming[pending_bytes_length] = '\0';
+         incoming_length = pending_bytes_length;
+         pending_bytes_length = 0;
+       }
+    }
+#endif /* HANDLE_MULTIBYTE */
+         
+  /* If we can optimize, then do it.  But don't let people crash
+     readline because of extra large arguments. */
+  if (count > 1 && count <= 1024)
+    {
+#if defined (HANDLE_MULTIBYTE)
+      string_size = count * incoming_length;
+      string = (char *)xmalloc (1 + string_size);
+
+      i = 0;
+      while (i < string_size)
+       {
+         strncpy (string + i, incoming, incoming_length);
+         i += incoming_length;
+       }
+      incoming_length = 0;
+      stored_count = 0;
+#else /* !HANDLE_MULTIBYTE */
+      string = (char *)xmalloc (1 + count);
+
+      for (i = 0; i < count; i++)
+       string[i] = c;
+#endif /* !HANDLE_MULTIBYTE */
+
+      string[i] = '\0';
+      rl_insert_text (string);
+      free (string);
+
+      return 0;
+    }
+
+  if (count > 1024)
+    {
+      int decreaser;
+#if defined (HANDLE_MULTIBYTE)
+      string_size = incoming_length * 1024;
+      string = (char *)xmalloc (1 + string_size);
+
+      i = 0;
+      while (i < string_size)
+       {
+         strncpy (string + i, incoming, incoming_length);
+         i += incoming_length;
+       }
+
+      while (count)
+       {
+         decreaser = (count > 1024) ? 1024 : count;
+         string[decreaser*incoming_length] = '\0';
+         rl_insert_text (string);
+         count -= decreaser;
+       }
+
+      free (string);
+      incoming_length = 0;
+      stored_count = 0;
+#else /* !HANDLE_MULTIBYTE */
+      char str[1024+1];
+
+      for (i = 0; i < 1024; i++)
+       str[i] = c;
+
+      while (count)
+       {
+         decreaser = (count > 1024 ? 1024 : count);
+         str[decreaser] = '\0';
+         rl_insert_text (str);
+         count -= decreaser;
+       }
+#endif /* !HANDLE_MULTIBYTE */
+
+      return 0;
+    }
+
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    {
+#endif
+      /* We are inserting a single character.
+        If there is pending input, then make a string of all of the
+        pending characters that are bound to rl_insert, and insert
+        them all. */
+      if (_rl_any_typein ())
+       _rl_insert_typein (c);
+      else
+       {
+         /* Inserting a single character. */
+         char str[2];
+
+         str[1] = '\0';
+         str[0] = c;
+         rl_insert_text (str);
+       }
+#if defined (HANDLE_MULTIBYTE)
+    }
+  else
+    {
+      rl_insert_text (incoming);
+      stored_count = 0;
+    }
+#endif
+
+  return 0;
+}
+
+/* Overwrite the character at point (or next COUNT characters) with C.
+   If C introduces a multibyte character sequence, read the entire sequence
+   before starting the overwrite loop. */
+int
+_rl_overwrite_char (count, c)
+     int count, c;
+{
+  int i;
+#if defined (HANDLE_MULTIBYTE)
+  char mbkey[MB_LEN_MAX];
+  int k;
+
+  /* Read an entire multibyte character sequence to insert COUNT times. */
+  if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX);
+#endif
+
+  for (i = 0; i < count; i++)
+    {
+      rl_begin_undo_group ();
+
+      if (rl_point < rl_end)
+       rl_delete (1, c);
+
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_insert_text (mbkey);
+      else
+#endif
+       _rl_insert_char (1, c);
+
+      rl_end_undo_group ();
+    }
+
+  return 0;
+}
+
+int
+rl_insert (count, c)
+     int count, c;
+{
+  return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c)
+                                        : _rl_overwrite_char (count, c));
+}
+
+/* Insert the next typed character verbatim. */
+int
+rl_quoted_insert (count, key)
+     int count, key;
+{
+  int c;
+
+#if defined (HANDLE_SIGNALS)
+  _rl_disable_tty_signals ();
+#endif
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  c = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+#if defined (HANDLE_SIGNALS)
+  _rl_restore_tty_signals ();
+#endif
+
+  return (_rl_insert_char (count, c));  
+}
+
+/* Insert a tab character. */
+int
+rl_tab_insert (count, key)
+     int count, key;
+{
+  return (_rl_insert_char (count, '\t'));
+}
+
+/* What to do when a NEWLINE is pressed.  We accept the whole line.
+   KEY is the key that invoked this command.  I guess it could have
+   meaning in the future. */
+int
+rl_newline (count, key)
+     int count, key;
+{
+  rl_done = 1;
+
+  if (_rl_history_preserve_point)
+    _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
+
+  RL_SETSTATE(RL_STATE_DONE);
+
+#if defined (VI_MODE)
+  if (rl_editing_mode == vi_mode)
+    {
+      _rl_vi_done_inserting ();
+      _rl_vi_reset_last ();
+    }
+#endif /* VI_MODE */
+
+  /* If we've been asked to erase empty lines, suppress the final update,
+     since _rl_update_final calls rl_crlf(). */
+  if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
+    return 0;
+
+  if (readline_echoing_p)
+    _rl_update_final ();
+  return 0;
+}
+
+/* What to do for some uppercase characters, like meta characters,
+   and some characters appearing in emacs_ctlx_keymap.  This function
+   is just a stub, you bind keys to it and the code in _rl_dispatch ()
+   is special cased. */
+int
+rl_do_lowercase_version (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  return 0;
+}
+
+/* This is different from what vi does, so the code's not shared.  Emacs
+   rubout in overwrite mode has one oddity:  it replaces a control
+   character that's displayed as two characters (^X) with two spaces. */
+int
+_rl_overwrite_rubout (count, key)
+     int count, key;
+{
+  int opoint;
+  int i, l;
+
+  if (rl_point == 0)
+    {
+      rl_ding ();
+      return 1;
+    }
+
+  opoint = rl_point;
+
+  /* L == number of spaces to insert */
+  for (i = l = 0; i < count; i++)
+    {
+      rl_backward_char (1, key);
+      l += rl_character_len (rl_line_buffer[rl_point], rl_point);      /* not exactly right */
+    }
+
+  rl_begin_undo_group ();
+
+  if (count > 1 || rl_explicit_arg)
+    rl_kill_text (opoint, rl_point);
+  else
+    rl_delete_text (opoint, rl_point);
+
+  /* Emacs puts point at the beginning of the sequence of spaces. */
+  opoint = rl_point;
+  _rl_insert_char (l, ' ');
+  rl_point = opoint;
+
+  rl_end_undo_group ();
+
+  return 0;
+}
+  
+/* Rubout the character behind point. */
+int
+rl_rubout (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_delete (-count, key));
+
+  if (!rl_point)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  if (rl_insert_mode == RL_IM_OVERWRITE)
+    return (_rl_overwrite_rubout (count, key));
+
+  return (_rl_rubout_char (count, key));
+}
+
+int
+_rl_rubout_char (count, key)
+     int count, key;
+{
+  int orig_point;
+  unsigned char c;
+
+  /* Duplicated code because this is called from other parts of the library. */
+  if (count < 0)
+    return (rl_delete (-count, key));
+
+  if (rl_point == 0)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  if (count > 1 || rl_explicit_arg)
+    {
+      orig_point = rl_point;
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_backward_char (count, key);
+      else
+#endif
+        rl_backward_byte (count, key);
+      rl_kill_text (orig_point, rl_point);
+    }
+  else
+    {
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX == 1 || rl_byte_oriented)
+       {
+#endif
+         c = rl_line_buffer[--rl_point];
+         rl_delete_text (rl_point, rl_point + 1);
+#if defined (HANDLE_MULTIBYTE)
+       }
+      else
+       {
+         int orig_point;
+
+         orig_point = rl_point;
+         rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+         c = rl_line_buffer[rl_point];
+         rl_delete_text (rl_point, orig_point);
+       }
+#endif /* HANDLE_MULTIBYTE */
+
+      /* I don't think that the hack for end of line is needed for
+        multibyte chars. */
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX == 1 || rl_byte_oriented)
+#endif
+      if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos)
+       {
+         int l;
+         l = rl_character_len (c, rl_point);
+         _rl_erase_at_end_of_line (l);
+       }
+    }
+
+  return 0;
+}
+
+/* Delete the character under the cursor.  Given a numeric argument,
+   kill that many characters instead. */
+int
+rl_delete (count, key)
+     int count, key;
+{
+  int r;
+
+  if (count < 0)
+    return (_rl_rubout_char (-count, key));
+
+  if (rl_point == rl_end)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  if (count > 1 || rl_explicit_arg)
+    {
+      int orig_point = rl_point;
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_forward_char (count, key);
+      else
+#endif
+       rl_forward_byte (count, key);
+
+      r = rl_kill_text (orig_point, rl_point);
+      rl_point = orig_point;
+      return r;
+    }
+  else
+    {
+      int new_point;
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       new_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+      else
+       new_point = rl_point + 1;
+       
+      return (rl_delete_text (rl_point, new_point));
+    }
+}
+
+/* Delete the character under the cursor, unless the insertion
+   point is at the end of the line, in which case the character
+   behind the cursor is deleted.  COUNT is obeyed and may be used
+   to delete forward or backward that many characters. */      
+int
+rl_rubout_or_delete (count, key)
+     int count, key;
+{
+  if (rl_end != 0 && rl_point == rl_end)
+    return (_rl_rubout_char (count, key));
+  else
+    return (rl_delete (count, key));
+}  
+
+/* Delete all spaces and tabs around point. */
+int
+rl_delete_horizontal_space (count, ignore)
+     int count, ignore;
+{
+  int start = rl_point;
+
+  while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
+    rl_point--;
+
+  start = rl_point;
+
+  while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+    rl_point++;
+
+  if (start != rl_point)
+    {
+      rl_delete_text (start, rl_point);
+      rl_point = start;
+    }
+  return 0;
+}
+
+/* Like the tcsh editing function delete-char-or-list.  The eof character
+   is caught before this is invoked, so this really does the same thing as
+   delete-char-or-list-or-eof, as long as it's bound to the eof character. */
+int
+rl_delete_or_show_completions (count, key)
+     int count, key;
+{
+  if (rl_end != 0 && rl_point == rl_end)
+    return (rl_possible_completions (count, key));
+  else
+    return (rl_delete (count, key));
+}
+
+#ifndef RL_COMMENT_BEGIN_DEFAULT
+#define RL_COMMENT_BEGIN_DEFAULT "#"
+#endif
+
+/* Turn the current line into a comment in shell history.
+   A K*rn shell style function. */
+int
+rl_insert_comment (count, key)
+     int count, key;
+{
+  char *rl_comment_text;
+  int rl_comment_len;
+
+  rl_beg_of_line (1, key);
+  rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT;
+
+  if (rl_explicit_arg == 0)
+    rl_insert_text (rl_comment_text);
+  else
+    {
+      rl_comment_len = strlen (rl_comment_text);
+      if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len))
+       rl_delete_text (rl_point, rl_point + rl_comment_len);
+      else
+       rl_insert_text (rl_comment_text);
+    }
+
+  (*rl_redisplay_function) ();
+  rl_newline (1, '\n');
+
+  return (0);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Changing Case                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The three kinds of things that we know how to do. */
+#define UpCase 1
+#define DownCase 2
+#define CapCase 3
+
+/* Uppercase the word at point. */
+int
+rl_upcase_word (count, key)
+     int count, key;
+{
+  return (rl_change_case (count, UpCase));
+}
+
+/* Lowercase the word at point. */
+int
+rl_downcase_word (count, key)
+     int count, key;
+{
+  return (rl_change_case (count, DownCase));
+}
+
+/* Upcase the first letter, downcase the rest. */
+int
+rl_capitalize_word (count, key)
+     int count, key;
+{
+ return (rl_change_case (count, CapCase));
+}
+
+/* The meaty function.
+   Change the case of COUNT words, performing OP on them.
+   OP is one of UpCase, DownCase, or CapCase.
+   If a negative argument is given, leave point where it started,
+   otherwise, leave it where it moves to. */
+static int
+rl_change_case (count, op)
+     int count, op;
+{
+  register int start, end;
+  int inword, c;
+
+  start = rl_point;
+  rl_forward_word (count, 0);
+  end = rl_point;
+
+  if (count < 0)
+    SWAP (start, end);
+
+  /* We are going to modify some text, so let's prepare to undo it. */
+  rl_modifying (start, end);
+
+  for (inword = 0; start < end; start++)
+    {
+      c = rl_line_buffer[start];
+      switch (op)
+       {
+       case UpCase:
+         rl_line_buffer[start] = _rl_to_upper (c);
+         break;
+
+       case DownCase:
+         rl_line_buffer[start] = _rl_to_lower (c);
+         break;
+
+       case CapCase:
+         rl_line_buffer[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c);
+         inword = rl_alphabetic (rl_line_buffer[start]);
+         break;
+
+       default:
+         rl_ding ();
+         return -1;
+       }
+    }
+  rl_point = end;
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Transposition                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Transpose the words at point.  If point is at the end of the line,
+   transpose the two words before point. */
+int
+rl_transpose_words (count, key)
+     int count, key;
+{
+  char *word1, *word2;
+  int w1_beg, w1_end, w2_beg, w2_end;
+  int orig_point = rl_point;
+
+  if (!count)
+    return 0;
+
+  /* Find the two words. */
+  rl_forward_word (count, key);
+  w2_end = rl_point;
+  rl_backward_word (1, key);
+  w2_beg = rl_point;
+  rl_backward_word (count, key);
+  w1_beg = rl_point;
+  rl_forward_word (1, key);
+  w1_end = rl_point;
+
+  /* Do some check to make sure that there really are two words. */
+  if ((w1_beg == w2_beg) || (w2_beg < w1_end))
+    {
+      rl_ding ();
+      rl_point = orig_point;
+      return -1;
+    }
+
+  /* Get the text of the words. */
+  word1 = rl_copy_text (w1_beg, w1_end);
+  word2 = rl_copy_text (w2_beg, w2_end);
+
+  /* We are about to do many insertions and deletions.  Remember them
+     as one operation. */
+  rl_begin_undo_group ();
+
+  /* Do the stuff at word2 first, so that we don't have to worry
+     about word1 moving. */
+  rl_point = w2_beg;
+  rl_delete_text (w2_beg, w2_end);
+  rl_insert_text (word1);
+
+  rl_point = w1_beg;
+  rl_delete_text (w1_beg, w1_end);
+  rl_insert_text (word2);
+
+  /* This is exactly correct since the text before this point has not
+     changed in length. */
+  rl_point = w2_end;
+
+  /* I think that does it. */
+  rl_end_undo_group ();
+  free (word1);
+  free (word2);
+
+  return 0;
+}
+
+/* Transpose the characters at point.  If point is at the end of the line,
+   then transpose the characters before point. */
+int
+rl_transpose_chars (count, key)
+     int count, key;
+{
+#if defined (HANDLE_MULTIBYTE)
+  char *dummy;
+  int i, prev_point;
+#else
+  char dummy[2];
+#endif
+  int char_length;
+
+  if (count == 0)
+    return 0;
+
+  if (!rl_point || rl_end < 2)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  rl_begin_undo_group ();
+
+  if (rl_point == rl_end)
+    {
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+      else
+       --rl_point;
+      count = 1;
+    }
+
+#if defined (HANDLE_MULTIBYTE)
+  prev_point = rl_point;
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+  else
+#endif
+    rl_point--;
+
+#if defined (HANDLE_MULTIBYTE)
+  char_length = prev_point - rl_point;
+  dummy = (char *)xmalloc (char_length + 1);
+  for (i = 0; i < char_length; i++)
+    dummy[i] = rl_line_buffer[rl_point + i];
+  dummy[i] = '\0';
+#else
+  dummy[0] = rl_line_buffer[rl_point];
+  dummy[char_length = 1] = '\0';
+#endif
+
+  rl_delete_text (rl_point, rl_point + char_length);
+
+  rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+
+  _rl_fix_point (0);
+  rl_insert_text (dummy);
+  rl_end_undo_group ();
+
+#if defined (HANDLE_MULTIBYTE)
+  free (dummy);
+#endif
+
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Character Searching                         */
+/*                                                                 */
+/* **************************************************************** */
+
+int
+#if defined (HANDLE_MULTIBYTE)
+_rl_char_search_internal (count, dir, smbchar, len)
+     int count, dir;
+     char *smbchar;
+     int len;
+#else
+_rl_char_search_internal (count, dir, schar)
+     int count, dir, schar;
+#endif
+{
+  int pos, inc;
+#if defined (HANDLE_MULTIBYTE)
+  int prepos;
+#endif
+
+  pos = rl_point;
+  inc = (dir < 0) ? -1 : 1;
+  while (count)
+    {
+      if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
+       {
+         rl_ding ();
+         return -1;
+       }
+
+#if defined (HANDLE_MULTIBYTE)
+      pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
+                     : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
+#else
+      pos += inc;
+#endif
+      do
+       {
+#if defined (HANDLE_MULTIBYTE)
+         if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len))
+#else
+         if (rl_line_buffer[pos] == schar)
+#endif
+           {
+             count--;
+             if (dir < 0)
+               rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
+                                       : pos;
+             else
+               rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)
+                                       : pos;
+             break;
+           }
+#if defined (HANDLE_MULTIBYTE)
+         prepos = pos;
+#endif
+       }
+#if defined (HANDLE_MULTIBYTE)
+      while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos
+                      : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos);
+#else
+      while ((dir < 0) ? pos-- : ++pos < rl_end);
+#endif
+    }
+  return (0);
+}
+
+/* Search COUNT times for a character read from the current input stream.
+   FDIR is the direction to search if COUNT is non-negative; otherwise
+   the search goes in BDIR.  So much is dependent on HANDLE_MULTIBYTE
+   that there are two separate versions of this function. */
+#if defined (HANDLE_MULTIBYTE)
+static int
+_rl_char_search (count, fdir, bdir)
+     int count, fdir, bdir;
+{
+  char mbchar[MB_LEN_MAX];
+  int mb_len;
+
+  mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
+
+  if (count < 0)
+    return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
+  else
+    return (_rl_char_search_internal (count, fdir, mbchar, mb_len));
+}
+#else /* !HANDLE_MULTIBYTE */
+static int
+_rl_char_search (count, fdir, bdir)
+     int count, fdir, bdir;
+{
+  int c;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  c = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  if (count < 0)
+    return (_rl_char_search_internal (-count, bdir, c));
+  else
+    return (_rl_char_search_internal (count, fdir, c));
+}
+#endif /* !HANDLE_MULTIBYTE */
+
+int
+rl_char_search (count, key)
+     int count, key;
+{
+  return (_rl_char_search (count, FFIND, BFIND));
+}
+
+int
+rl_backward_char_search (count, key)
+     int count, key;
+{
+  return (_rl_char_search (count, BFIND, FFIND));
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                The Mark and the Region.                         */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Set the mark at POSITION. */
+int
+_rl_set_mark_at_pos (position)
+     int position;
+{
+  if (position > rl_end)
+    return -1;
+
+  rl_mark = position;
+  return 0;
+}
+
+/* A bindable command to set the mark. */
+int
+rl_set_mark (count, key)
+     int count, key;
+{
+  return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
+}
+
+/* Exchange the position of mark and point. */
+int
+rl_exchange_point_and_mark (count, key)
+     int count, key;
+{
+  if (rl_mark > rl_end)
+    rl_mark = -1;
+
+  if (rl_mark == -1)
+    {
+      rl_ding ();
+      return -1;
+    }
+  else
+    SWAP (rl_point, rl_mark);
+
+  return 0;
+}
index 6e4f116f7573dfd83f6bb440c2f41f2b6c87419b..154f7f8108d075569576990c9ee5c23be93b2950 100644 (file)
@@ -59,9 +59,6 @@ extern struct passwd *getpwnam PARAMS((const char *));
 #endif /* !HAVE_GETPW_DECLS */
 
 #if !defined (savestring)
-#  ifndef strcpy
-extern char *strcpy ();
-#  endif
 #define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x))
 #endif /* !savestring */
 
index 0df608b3458441c2899a49df570557f06de103b7..f8182c999d9b43c2b88cceb0f4142eb607b95154 100644 (file)
 #if !defined (_TILDE_H_)
 #  define _TILDE_H_
 
-#if defined (HAVE_CONFIG_H)
-#  include <config.h>
-#endif
-
 #ifdef __cplusplus
 extern "C" {
 #endif
index 9be231ded236157d14a445d504b2f064e401c649..25c287b5a2df3df04c7d9fd98f1978949c6d7016 100644 (file)
@@ -50,8 +50,6 @@
 #include "rlprivate.h"
 #include "xmalloc.h"
 
-#define SWAP(s, e)  do { int t; t = s; s = e; e = t; } while (0)
-
 /* Non-zero tells rl_delete_text and rl_insert_text to not add to
    the undo list. */
 int _rl_doing_an_undo = 0;
index bd08b38a52bb495fed55b85b2e29376a51886ae9..c7bd360e43cd3940922d163265ed8c0795d2a166 100644 (file)
@@ -55,8 +55,6 @@
 #include "rlprivate.h"
 #include "xmalloc.h"
 
-#define SWAP(s, e)  do { int t; t = s; s = e; e = t; } while (0)
-
 /* **************************************************************** */
 /*                                                                 */
 /*                     Utility Functions                           */
@@ -89,7 +87,7 @@ _rl_abort_internal ()
   _rl_init_argument ();
   rl_clear_pending_input ();
 
-  _rl_defining_kbd_macro = 0;
+  RL_UNSETSTATE (RL_STATE_MACRODEF);
   while (rl_executing_macro)
     _rl_pop_executing_macro ();
 
@@ -233,6 +231,12 @@ _rl_strpbrk (string1, string2)
      const char *string1, *string2;
 {
   register const char *scan;
+#if defined (HANDLE_MULTIBYTE)
+  mbstate_t ps;
+  register int i, v;
+
+  memset (&ps, 0, sizeof (mbstate_t));
+#endif
 
   for (; *string1; string1++)
     {
@@ -241,6 +245,14 @@ _rl_strpbrk (string1, string2)
          if (*string1 == *scan)
            return ((char *)string1);
        }
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         v = _rl_get_char_len (string1, &ps);
+         if (v > 1)
+           string += v - 1;    /* -1 to account for auto-increment in loop */
+       }
+#endif
     }
   return ((char *)NULL);
 }
index cb84c06d3f1e228073888d67f450c588a4f613f2..53a67c674ce0c1fa90e3cc28d593d0b036a833cb 100644 (file)
@@ -41,7 +41,7 @@ KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
   { ISFUNC, rl_emacs_editing_mode },           /* Control-e */
   { ISFUNC, (rl_command_func_t *)0x0 },                /* Control-f */
   { ISFUNC, rl_abort },                                /* Control-g */
-  { ISFUNC, rl_backward },                     /* Control-h */
+  { ISFUNC, rl_backward_char },                        /* Control-h */
   { ISFUNC, (rl_command_func_t *)0x0 },                /* Control-i */
   { ISFUNC, rl_newline },                      /* Control-j */
   { ISFUNC, rl_kill_line },                    /* Control-k */
@@ -68,7 +68,7 @@ KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
   { ISFUNC, rl_vi_undo },                      /* Control-_ */
 
   /* The start of printing characters. */
-  { ISFUNC, rl_forward },                      /* SPACE */
+  { ISFUNC, rl_forward_char },                 /* SPACE */
   { ISFUNC, (rl_command_func_t *)0x0 },                /* ! */
   { ISFUNC, (rl_command_func_t *)0x0 },                /* " */
   { ISFUNC, rl_insert_comment },               /* # */
@@ -150,11 +150,11 @@ KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
   { ISFUNC, rl_vi_end_word },                  /* e */
   { ISFUNC, rl_vi_char_search },               /* f */
   { ISFUNC, (rl_command_func_t *)0x0 },                /* g */
-  { ISFUNC, rl_backward },                     /* h */
+  { ISFUNC, rl_backward_char },                        /* h */
   { ISFUNC, rl_vi_insertion_mode },            /* i */
   { ISFUNC, rl_get_next_history },             /* j */
   { ISFUNC, rl_get_previous_history },         /* k */
-  { ISFUNC, rl_forward },                      /* l */
+  { ISFUNC, rl_forward_char },                 /* l */
   { ISFUNC, rl_vi_set_mark },                  /* m */
   { ISFUNC, rl_vi_search_again },              /* n */
   { ISFUNC, (rl_command_func_t *)0x0 },                /* o */
index 09ccecf61cacce286f340e0f6a9f1879c60a433e..5d146b3f705604d4668f85c722a2387d31a0b7ac 100644 (file)
@@ -51,6 +51,8 @@
 
 /* Some standard library routines. */
 #include "rldefs.h"
+#include "rlmbutil.h"
+
 #include "readline.h"
 #include "history.h"
 
 #define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
 #endif
 
-#ifndef exchange
-#define exchange(x, y) do {int temp = x; x = y; y = temp;} while (0)
-#endif
-
 /* Non-zero means enter insertion mode. */
 static int _rl_vi_doing_insert;
 
@@ -89,7 +87,11 @@ static int _rl_vi_last_command = 'i';        /* default `.' puts you in insert mode */
 static int _rl_vi_last_repeat = 1;
 static int _rl_vi_last_arg_sign = 1;
 static int _rl_vi_last_motion;
+#if defined (HANDLE_MULTIBYTE)
+static char _rl_vi_last_search_mbchar[MB_LEN_MAX];
+#else
 static int _rl_vi_last_search_char;
+#endif
 static int _rl_vi_last_replacement;
 
 static int _rl_vi_last_key_before_insert;
@@ -158,12 +160,15 @@ int
 rl_vi_redo (count, c)
      int count, c;
 {
+  int r;
+
   if (!rl_explicit_arg)
     {
       rl_numeric_arg = _rl_vi_last_repeat;
       rl_arg_sign = _rl_vi_last_arg_sign;
     }
 
+  r = 0;
   vi_redoing = 1;
   /* If we're redoing an insert with `i', stuff in the inserted text
      and do not go into insertion mode. */
@@ -175,10 +180,10 @@ rl_vi_redo (count, c)
        rl_point--;
     }
   else
-    _rl_dispatch (_rl_vi_last_command, _rl_keymap);
+    r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
   vi_redoing = 0;
 
-  return (0);
+  return (r);
 }
 
 /* A placeholder for further expansion. */
@@ -547,7 +552,17 @@ rl_vi_append_mode (count, key)
      int count, key;
 {
   if (rl_point < rl_end)
-    rl_point++;
+    {
+      if (MB_CUR_MAX == 1 || rl_byte_oriented)
+       rl_point++;
+      else
+        {
+          int point = rl_point;
+          rl_forward_char (1, key);
+          if (point == rl_point)
+            rl_point = rl_end;
+        }
+    }
   rl_vi_insertion_mode (1, key);
   return (0);
 }
@@ -612,6 +627,7 @@ _rl_vi_done_inserting ()
 {
   if (_rl_vi_doing_insert)
     {
+      /* The `C', `s', and `S' commands set this. */
       rl_end_undo_group ();
       /* Now, the text between rl_undo_list->next->start and
         rl_undo_list->next->end is what was inserted while in insert
@@ -640,7 +656,7 @@ rl_vi_movement_mode (count, key)
      int count, key;
 {
   if (rl_point > 0)
-    rl_backward (1, key);
+    rl_backward_char (1, key);
 
   _rl_keymap = vi_movement_keymap;
   _rl_vi_done_inserting ();
@@ -657,6 +673,51 @@ rl_vi_arg_digit (count, c)
     return (rl_digit_argument (count, c));
 }
 
+/* Change the case of the next COUNT characters. */
+#if defined (HANDLE_MULTIBYTE)
+static int
+_rl_vi_change_mbchar_case (count)
+     int count;
+{
+  wchar_t wc;
+  char mb[MB_LEN_MAX];
+  mbstate_t ps;
+
+  memset (&ps, 0, sizeof (mbstate_t));
+  if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0)
+    count--;
+  while (count-- && rl_point < rl_end)
+    {
+      mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
+      if (iswupper (wc))
+       wc = towlower (wc);
+      else if (iswlower (wc))
+       wc = towupper (wc);
+      else
+       {
+         /* Just skip over chars neither upper nor lower case */
+         rl_forward_char (1, 0);
+         continue;
+       }
+
+      /* Vi is kind of strange here. */
+      if (wc)
+       {
+         wctomb (mb, wc);
+         rl_begin_undo_group ();
+         rl_delete (1, 0);
+         rl_insert_text (mb);
+         rl_end_undo_group ();
+         rl_vi_check ();
+       }
+      else
+        rl_forward_char (1, 0);
+    }
+
+  return 0;
+}
+#endif
+
 int
 rl_vi_change_case (count, ignore)
      int count, ignore;
@@ -667,6 +728,11 @@ rl_vi_change_case (count, ignore)
   if (rl_point >= rl_end)
     return (0);
 
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    return (_rl_vi_change_mbchar_case (count));
+#endif
+
   while (count-- && rl_point < rl_end)
     {
       if (_rl_uppercase_p (rl_line_buffer[rl_point]))
@@ -676,7 +742,7 @@ rl_vi_change_case (count, ignore)
       else
        {
          /* Just skip over characters neither upper nor lower case. */
-         rl_forward (1, c);
+         rl_forward_char (1, c);
          continue;
        }
 
@@ -685,12 +751,12 @@ rl_vi_change_case (count, ignore)
        {
          rl_begin_undo_group ();
          rl_delete (1, c);
-         rl_insert (1, c);
+         _rl_insert_char (1, c);
          rl_end_undo_group ();
          rl_vi_check ();
         }
       else
-       rl_forward (1, c);
+       rl_forward_char (1, c);
     }
   return (0);
 }
@@ -700,10 +766,10 @@ rl_vi_put (count, key)
      int count, key;
 {
   if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
-    rl_point++;
+    rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
 
   rl_yank (1, key);
-  rl_backward (1, key);
+  rl_backward_char (1, key);
   return (0);
 }
 
@@ -711,7 +777,12 @@ int
 rl_vi_check ()
 {
   if (rl_point && rl_point == rl_end)
-    rl_point--;
+    {
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+      else
+        rl_point--;
+    }
   return (0);
 }
 
@@ -813,7 +884,7 @@ rl_vi_domove (key, nextkey)
     }
 
   if (rl_mark < rl_point)
-    exchange (rl_point, rl_mark);
+    SWAP (rl_point, rl_mark);
 
   return (0);
 }
@@ -991,7 +1062,10 @@ rl_vi_delete (count, key)
       return -1;
     }
 
-  end = rl_point + count;
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+  else
+    end = rl_point + count;
 
   if (end >= rl_end)
     end = rl_end;
@@ -999,7 +1073,7 @@ rl_vi_delete (count, key)
   rl_kill_text (rl_point, end);
   
   if (rl_point > 0 && rl_point == rl_end)
-    rl_backward (1, key);
+    rl_backward_char (1, key);
   return (0);
 }
 
@@ -1024,7 +1098,12 @@ int
 rl_vi_char_search (count, key)
      int count, key;
 {
+#if defined (HANDLE_MULTIBYTE)
+  static char *target;
+  static int mb_len;
+#else
   static char target;
+#endif
   static int orig_dir, dir;
 
   if (key == ';' || key == ',')
@@ -1032,12 +1111,21 @@ rl_vi_char_search (count, key)
   else
     {
       if (vi_redoing)
+#if defined (HANDLE_MULTIBYTE)
+       target = _rl_vi_last_search_mbchar;
+#else
        target = _rl_vi_last_search_char;
+#endif
       else
        {
+#if defined (HANDLE_MULTIBYTE)
+         mb_len = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
+         target = _rl_vi_last_search_mbchar;
+#else
          RL_SETSTATE(RL_STATE_MOREINPUT);
          _rl_vi_last_search_char = target = rl_read_key ();
          RL_UNSETSTATE(RL_STATE_MOREINPUT);
+#endif
        }
 
       switch (key)
@@ -1060,7 +1148,11 @@ rl_vi_char_search (count, key)
         }
     }
 
+#if defined (HANDLE_MULTIBYTE)
+   return (_rl_char_search_internal (count, dir, target, mb_len));
+#else
   return (_rl_char_search_internal (count, dir, target));
+#endif
 }
 
 /* Match brackets */
@@ -1068,14 +1160,25 @@ int
 rl_vi_match (ignore, key)
      int ignore, key;
 {
-  int count = 1, brack, pos;
+  int count = 1, brack, pos, tmp, pre;
 
   pos = rl_point;
   if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
     {
-      while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
-            rl_point < rl_end - 1)
-       rl_forward (1, key);
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
+           {
+             pre = rl_point;
+             rl_forward_char (1, key);
+             if (pre == rl_point)
+               break;
+           }
+       }
+      else
+       while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
+               rl_point < rl_end - 1)
+         rl_forward_char (1, key);
 
       if (brack <= 0)
        {
@@ -1091,7 +1194,16 @@ rl_vi_match (ignore, key)
     {
       while (count)
        {
-         if (--pos >= 0)
+         tmp = pos;
+         if (MB_CUR_MAX == 1 || rl_byte_oriented)
+           pos--;
+         else
+           {
+             pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
+             if (tmp == pos)
+               pos--;
+           }
+         if (pos >= 0)
            {
              int b = rl_vi_bracktype (rl_line_buffer[pos]);
              if (b == -brack)
@@ -1110,7 +1222,12 @@ rl_vi_match (ignore, key)
     {                  /* brack > 0 */
       while (count)
        {
-         if (++pos < rl_end)
+         if (MB_CUR_MAX == 1 || rl_byte_oriented)
+           pos++;
+         else
+           pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY);
+
+         if (pos < rl_end)
            {
              int b = rl_vi_bracktype (rl_line_buffer[pos]);
              if (b == -brack)
@@ -1145,6 +1262,11 @@ rl_vi_bracktype (c)
     }
 }
 
+/* XXX - think about reading an entire mbchar with _rl_read_mbchar and
+   inserting it in one bunch instead of the loop below (like in
+   rl_vi_char_search or _rl_vi_change_mbchar_case.  Set c to mbchar[0]
+   for test against 033 or ^C.  Make sure that _rl_read_mbchar does
+   this right. */
 int
 rl_vi_change_char (count, key)
      int count, key;
@@ -1168,9 +1290,19 @@ rl_vi_change_char (count, key)
       rl_begin_undo_group ();
 
       rl_delete (1, c);
-      rl_insert (1, c);
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       while (_rl_insert_char (1, c))
+         {
+           RL_SETSTATE (RL_STATE_MOREINPUT);
+           c = rl_read_key ();
+           RL_UNSETSTATE (RL_STATE_MOREINPUT);
+         }
+      else
+#endif
+       _rl_insert_char (1, c);
       if (count == 0)
-       rl_backward (1, c);
+       rl_backward_char (1, c);
 
       rl_end_undo_group ();
     }
@@ -1181,66 +1313,29 @@ int
 rl_vi_subst (count, key)
      int count, key;
 {
-  rl_begin_undo_group ();
-
-  if (_rl_uppercase_p (key))
-    {
-      rl_beg_of_line (1, key);
-      rl_kill_line (1, key);
-    }
-  else
-    rl_delete_text (rl_point, rl_point+count);
-
-  rl_end_undo_group ();
-
-  _rl_vi_set_last (key, count, rl_arg_sign);
+  /* If we are redoing, rl_vi_change_to will stuff the last motion char */
+  if (vi_redoing == 0)
+    rl_stuff_char ((key == 'S') ? 'c' : ' ');  /* `S' == `cc', `s' == `c ' */
 
-  if (vi_redoing)
-    {
-      int o = _rl_doing_an_undo;
-
-      _rl_doing_an_undo = 1;
-      if (vi_insert_buffer && *vi_insert_buffer)
-       rl_insert_text (vi_insert_buffer);
-      _rl_doing_an_undo = o;
-    }
-  else
-    {
-      rl_begin_undo_group ();
-      _rl_vi_doing_insert = 1;
-      rl_vi_insertion_mode (1, key);
-    }
-
-  return (0);
+  return (rl_vi_change_to (count, 'c'));
 }
 
 int
 rl_vi_overstrike (count, key)
      int count, key;
 {
-  int i;
-
   if (_rl_vi_doing_insert == 0)
     {
       _rl_vi_doing_insert = 1;
       rl_begin_undo_group ();
     }
 
-  for (i = 0; i < count; i++)
+  if (count > 0)
     {
-      vi_replace_count++;
-      rl_begin_undo_group ();
-
-      if (rl_point < rl_end)
-       {
-         rl_delete (1, key);
-         rl_insert (1, key);
-       }
-      else
-       rl_insert (1, key);
-
-      rl_end_undo_group ();
+      _rl_overwrite_char (count, key);
+      vi_replace_count += count;
     }
+
   return (0);
 }
 
@@ -1263,7 +1358,7 @@ rl_vi_overstrike_delete (count, key)
        vi_replace_count--;
 
       if (rl_point == s)
-       rl_backward (1, key);
+       rl_backward_char (1, key);
     }
 
   if (vi_replace_count == 0 && _rl_vi_doing_insert)
index 126f5f82288e7be77f1196ef146da84f9acd11b8..468899d2cc2a5630479e10415154eb64d2d899eb 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the Bash library
 #
 #
-# Copyright (C) 1998 Free Software Foundation, Inc.     
+# Copyright (C) 1998-2002 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
@@ -68,10 +68,12 @@ LIBRARY_NAME = libsh.a
 CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \
           strcasecmp.c strerror.c strtod.c strtol.c strtoul.c \
           vprint.c itos.c rename.c zread.c zwrite.c shtty.c \
-          inet_aton.c netopen.c strpbrk.c timeval.c makepath.c pathcanon.c \
-          pathphys.c tmpfile.c stringlist.c stringvec.c spell.c \
-          shquote.c strtrans.c strindex.c snprintf.c mailstat.c fmtulong.c \
-          fmtullong.c strtoll.c strtoull.c strtoimax.c strtoumax.c
+          inet_aton.c netconn.c netopen.c strpbrk.c timeval.c makepath.c \
+          pathcanon.c pathphys.c tmpfile.c stringlist.c stringvec.c spell.c \
+          shquote.c strtrans.c strindex.c snprintf.c mailstat.c \
+          fmtulong.c fmtullong.c fmtumax.c \
+          strtoll.c strtoull.c strtoimax.c strtoumax.c memset.c \
+          mktime.c strftime.c xstrchr.c zcatfd.c 
 
 # The header files for this library.
 HSOURCES = 
@@ -80,10 +82,10 @@ HSOURCES =
 LIBOBJS = @LIBOBJS@
 OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o \
          itos.o zread.o zwrite.o shtty.o \
-         netopen.o timeval.o makepath.o pathcanon.o \
+         netconn.o netopen.o timeval.o makepath.o pathcanon.o \
          pathphys.o tmpfile.o stringlist.o stringvec.o spell.o shquote.o \
          strtrans.o strindex.o snprintf.o mailstat.o fmtulong.o \
-         fmtullong.o ${LIBOBJS}
+         fmtullong.o fmtumax.o xstrchr.o zcatfd.o ${LIBOBJS}
 
 SUPPORT = Makefile
 
@@ -116,12 +118,16 @@ clktck.o: clktck.c
 clock.o: clock.c
 fmtullong.o: fmtullong.c
 fmtulong.o: fmtulong.c
+fmtumax.o: fmtumax.c
 getcwd.o: getcwd.c
 getenv.o: getenv.c
 inet_aton.o: inet_aton.c
 itos.o: itos.c
 mailstat.o: mailstat.c
 makepath.o: makepath.c
+memset.o: memset.c
+mktime.o: mktime.c
+netconn.o: netconn.c
 netopen.o: netopen.c
 oslib.o: oslib.c
 pathcanon.o: pathcanon.c
@@ -134,6 +140,7 @@ snprintf.o: snprintf.c
 spell.o: spell.c
 strcasecmp.o: strcasecmp.c
 strerror.o: strerror.c
+strftime.o: strftime.c
 strindex.o: strindex.c
 stringlist.o: stringlist.c
 stringvec.o: stringvec.c
@@ -150,11 +157,14 @@ times.o: times.c
 timeval.o: timeval.c
 tmpfile.o: tmpfile.c
 vprint.o: vprint.c
+xstrchr.o: xstrchr.c
+zcatfd.o: zcatfd.c
 zread.o: zread.c
 zwrite.o: zwrite.c
 
 # dependencies for c files that include other c files
 fmtullong.o: fmtulong.c
+fmtumax.o: fmtulong.c
 strtoll.o: strtol.c
 strtoul.o: strtol.c
 strtoull.o: strtol.c
@@ -164,12 +174,16 @@ clktck.o: ${BUILD_DIR}/config.h
 clock.o: ${BUILD_DIR}/config.h
 fmtullong.o: ${BUILD_DIR}/config.h
 fmtulong.o: ${BUILD_DIR}/config.h
+fmtumax.o: ${BUILD_DIR}/config.h
 getcwd.o: ${BUILD_DIR}/config.h
 getenv.o: ${BUILD_DIR}/config.h
 inet_aton.o: ${BUILD_DIR}/config.h
 itos.o: ${BUILD_DIR}/config.h
 mailstat.o: ${BUILD_DIR}/config.h
 makepath.o: ${BUILD_DIR}/config.h
+memset.o: ${BUILD_DIR}/config.h
+mktime.o: ${BUILD_DIR}/config.h
+netconn.o: ${BUILD_DIR}/config.h
 netopen.o: ${BUILD_DIR}/config.h
 oslib.o: ${BUILD_DIR}/config.h
 pathcanon.o: ${BUILD_DIR}/config.h
@@ -182,6 +196,7 @@ snprintf.o: ${BUILD_DIR}/config.h
 spell.o: ${BUILD_DIR}/config.h
 strcasecmp.o: ${BUILD_DIR}/config.h
 strerror.o: ${BUILD_DIR}/config.h
+strftime.o: ${BUILD_DIR}/config.h
 strindex.o: ${BUILD_DIR}/config.h
 stringlist.o: ${BUILD_DIR}/config.h
 stringvec.o: ${BUILD_DIR}/config.h
@@ -198,6 +213,8 @@ times.o: ${BUILD_DIR}/config.h
 timeval.o: ${BUILD_DIR}/config.h
 tmpfile.o: ${BUILD_DIR}/config.h
 vprint.o: ${BUILD_DIR}/config.h
+xstrchr.o: ${BUILD_DIR}/config.h
+zcatfd.o: ${BUILD_DIR}/config.h
 zread.o: ${BUILD_DIR}/config.h
 zwrite.o: ${BUILD_DIR}/config.h
 
@@ -237,6 +254,9 @@ makepath.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
 makepath.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
 makepath.o: ${topdir}/pathnames.h ${topdir}/externs.h
 
+netconn.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
+netconn.o: ${topdir}/bashtypes.h
+
 netopen.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${topdir}/xmalloc.h
 netopen.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
 netopen.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
@@ -280,6 +300,7 @@ pathphys.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
 pathphys.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
 
 rename.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h
+rename.o: ${BASHINCDIR}/posixstat.h
 
 setlinebuf.o: ${topdir}/xmalloc.h ${topdir}/bashansi.h
 setlinebuf.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/stdc.h
@@ -395,3 +416,13 @@ fmtullong.o: ${BASHINCDIR}/ansi_stdlib.h
 fmtullong.o: ${BASHINCDIR}/chartypes.h
 fmtullong.o: ${BASHINCDIR}/stdc.h
 fmtullong.o: ${BASHINCDIR}/typemax.h
+
+fmtumax.o: ${topdir}/bashansi.h
+fmtumax.o: ${BASHINCDIR}/ansi_stdlib.h
+fmtumax.o: ${BASHINCDIR}/chartypes.h
+fmtumax.o: ${BASHINCDIR}/stdc.h
+fmtumax.o: ${BASHINCDIR}/typemax.h
+
+xstrchr.o: ${topdir}/bashansi.h
+xstrchr.o: ${BASHINCDIR}/ansi_stdlib.h
+xstrchr.o: ${BASHINCDIR}/shmbutil.h
index b0b674e292880b9ff9ae3cfbc8e2c2b1498385e1..546b49c50abb450593b11a1967bfbed2077a74b6 100644 (file)
 #  include <unistd.h>
 #endif
 
+#if defined (HAVE_LIMITS_H)
+#  include <limits.h>
+#endif
+
 #if !defined (HAVE_SYSCONF) || !defined (_SC_CLK_TCK)
 #  if !defined (CLK_TCK)
 #    if defined (HZ)
index 8139a7ec5ebff3ae0b0f54ee70d532543593515f..df27944a16cd2517209ec6d311012c8e2d0b4550 100644 (file)
@@ -1,4 +1,6 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* fmtullong.c - convert `long long int' to string */
+
+/* Copyright (C) 2001-2002 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
@@ -18,7 +20,10 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #ifdef HAVE_LONG_LONG
 
-#define QUAD 1
+#define LONG           long long
+#define UNSIGNED_LONG  unsigned long long
+#define fmtulong       fmtullong
+
 #include "fmtulong.c"
 
 #endif
index 15e73efac3ce3b15b3c917b866a89c8013d6ce04..dc313be9941a455a140d2cf862b90c43c73e7ec1 100644 (file)
@@ -1,6 +1,6 @@
 /* fmtulong.c -- Convert unsigned long int to string. */
 
-/* Copyright (C) 1998, Free Software Foundation, Inc.
+/* Copyright (C) 1998-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -67,20 +67,9 @@ extern int errno;
 #  define FL_UNSIGNED  0x08    /* don't add any sign */
 #endif
 
-#ifdef QUAD
-   /* fmtullong */
-#  define LONG long long
-#  define FMTUL_LONG_MAX       LLONG_MAX
-#  define FMTUL_ULONG_MAX      ULLONG_MAX
-#else
+#ifndef LONG
 #  define LONG long
-#  define FMTUL_LONG_MAX       LONG_MAX
-#  define FMTUL_ULONG_MAX      ULONG_MAX
-#endif
-
-/* Set the name */
-#ifdef QUAD
-#  define fmtulong     fmtullong
+#  define UNSIGNED_LONG unsigned long
 #endif
 
 /* `unsigned long' (or unsigned long long) to string conversion for a given
@@ -88,7 +77,7 @@ extern int errno;
    check for buffer underflow, but currently does not. */
 char *
 fmtulong (ui, base, buf, len, flags)
-     unsigned LONG ui;
+     UNSIGNED_LONG ui;
      int base;
      char *buf;
      size_t len;
@@ -134,7 +123,7 @@ fmtulong (ui, base, buf, len, flags)
        }
       /* Favor signed arithmetic over unsigned arithmetic; it is faster on
         many machines. */
-      if (ui > FMTUL_LONG_MAX)
+      if ((LONG)ui < 0)
        {
          *p-- = TOCHAR (ui % 10);
          si = ui / 10;
diff --git a/lib/sh/fmtumax.c b/lib/sh/fmtumax.c
new file mode 100644 (file)
index 0000000..9bb4718
--- /dev/null
@@ -0,0 +1,25 @@
+/* fmtumax.c -- Convert uintmax_t to string.  */
+
+/* Copyright (C) 2002 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-1307, USA.  */
+
+#include <config.h>
+
+#define LONG   intmax_t
+#define UNSIGNED_LONG  uintmax_t
+#define fmtulong       fmtumax
+
+#include "fmtulong.c"
index 3d81ee4c1ea5a8bd933389f23f5e07633037f4f3..028afb1521dee690b8e5f6283bcd0dbb5b6ca185 100644 (file)
@@ -1,7 +1,7 @@
 /* getenv.c - get environment variable value from the shell's variable
              list. */
 
-/* Copyright (C) 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1997-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 #endif
 
 #include <bashansi.h>
+#include <errno.h>
 #include <shell.h>
 
+#ifndef errno
+extern int errno;
+#endif
+
 extern char **environ;
 
 /* We supply our own version of getenv () because we want library
@@ -43,21 +48,19 @@ static char *last_tempenv_value = (char *)NULL;
 
 char *
 getenv (name)
-#if defined (__linux__) || defined (__bsdi__) || defined (convex)
      const char *name;
-#else
-     char const *name;
-#endif /* !__linux__ && !__bsdi__ && !convex */
 {
   SHELL_VAR *var;
 
+  if (name == 0 || *name == '\0')
+    return ((char *)NULL);
+
   var = find_tempenv_variable ((char *)name);
   if (var)
     {
       FREE (last_tempenv_value);
 
       last_tempenv_value = value_cell (var) ? savestring (value_cell (var)) : (char *)NULL;
-      dispose_variable (var);
       return (last_tempenv_value);
     }
   else if (shell_variables)
@@ -88,12 +91,143 @@ getenv (name)
 /* Some versions of Unix use _getenv instead. */
 char *
 _getenv (name)
-#if defined (__linux__) || defined (__bsdi__) || defined (convex)
      const char *name;
-#else
-     char const *name;
-#endif /* !__linux__ && !__bsdi__ && !convex */
 {
   return (getenv (name));
 }
+
+/* SUSv3 says argument is a `char *'; BSD implementations disagree */
+int
+putenv (str)
+#ifndef HAVE_STD_PUTENV
+     const char *str;
+#else
+     char *str;
+#endif
+{
+  SHELL_VAR *var;
+  char *name, *value;
+  int offset;
+
+  if (str == 0 || *str == '\0')
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  offset = assignment (str);
+  if (str[offset] != '=')
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  name = savestring (str);
+  name[offset] = 0;
+
+  value = name + offset + 1;
+
+  /* XXX - should we worry about readonly here? */
+  var = bind_variable (name, value);
+  if (var == 0)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  VUNSETATTR (var, att_invisible);
+  VSETATTR (var, att_exported);
+
+  return 0;
+}
+
+#if 0
+int
+_putenv (name)
+#ifndef HAVE_STD_PUTENV
+     const char *name;
+#else
+     char *name;
+#endif
+{
+  return putenv (name);
+}
+#endif
+
+int
+setenv (name, value, rewrite)
+     const char *name;
+     const char *value;
+     int rewrite;
+{
+  SHELL_VAR *var;
+  char *v;
+
+  if (name == 0 || *name == '\0' || strchr (name, '=') != 0)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  var = 0;
+  v = value;
+  /* XXX - should we worry about readonly here? */
+  if (rewrite == 0)
+    var = find_variable (name);
+
+  if (var == 0)
+    var = bind_variable (name, v);
+
+  if (var == 0)
+    return -1;
+
+  VUNSETATTR (var, att_invisible);
+  VSETATTR (var, att_exported);
+
+  return 0;
+}
+
+#if 0
+int
+_setenv (name, value, rewrite)
+     const char *name;
+     const char *value;
+     int rewrite;
+{
+  return setenv (name, value, rewrite);
+}
+#endif
+
+/* SUSv3 says unsetenv returns int; existing implementations (BSD) disagree. */
+
+#ifdef HAVE_STD_UNSETENV
+#define UNSETENV_RETURN(N)     return(N)
+#define UNSETENV_RETTYPE       int
+#else
+#define UNSETENV_RETURN(N)     return
+#define UNSETENV_RETTYPE       void
+#endif
+
+UNSETENV_RETTYPE
+unsetenv (name)
+     const char *name;
+{
+  if (name == 0 || *name == '\0' || strchr (name, '=') != 0)
+    {
+      errno = EINVAL;
+      UNSETENV_RETURN(-1);
+    }
+
+  /* XXX - should we just remove the export attribute here? */
+#if 1
+  unbind_variable (name);
+#else
+  SHELL_VAR *v;
+
+  v = find_variable (name);
+  if (v)
+    VUNSETATTR (v, att_exported);
+#endif
+
+  UNSETENV_RETURN(0);
+}
 #endif /* CAN_REDEFINE_GETENV */
index e8365364d27b5696b437213135d4cb8ff5c96999..e9a794275509504ddc545551785dfbb605427374 100644 (file)
@@ -1,6 +1,6 @@
 /* itos.c -- Convert integer to string. */
 
-/* Copyright (C) 1998, Free Software Foundation, Inc.
+/* Copyright (C) 1998-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 #endif
 
 #include <bashansi.h>
-#include <chartypes.h>
 #include "shell.h"
 
 char *
 inttostr (i, buf, len)
-     long i;
+     intmax_t i;
      char *buf;
      size_t len;
 {
-  return (fmtulong (i, 10, buf, len, 0));
+  return (fmtumax (i, 10, buf, len, 0));
 }
 
 /* Integer to string conversion.  This conses the string; the
    caller should free it. */
 char *
 itos (i)
-     long i;
+     intmax_t i;
 {
-  char *p, lbuf[INT_STRLEN_BOUND(long) + 1];
+  char *p, lbuf[INT_STRLEN_BOUND(intmax_t) + 1];
 
-  p = fmtulong (i, 10, lbuf, sizeof(lbuf), 0);
+  p = fmtumax (i, 10, lbuf, sizeof(lbuf), 0);
   return (savestring (p));
 }
 
 char *
 uinttostr (i, buf, len)
-     unsigned long i;
+     uintmax_t i;
      char *buf;
      size_t len;
 {
-  return (fmtulong (i, 10, buf, len, FL_UNSIGNED));
+  return (fmtumax (i, 10, buf, len, FL_UNSIGNED));
 }
 
 /* Integer to string conversion.  This conses the string; the
    caller should free it. */
 char *
 uitos (i)
-     unsigned long i;
+     uintmax_t i;
 {
-  char *p, lbuf[INT_STRLEN_BOUND(long) + 1];
+  char *p, lbuf[INT_STRLEN_BOUND(uintmax_t) + 1];
 
-  p = fmtulong (i, 10, lbuf, sizeof(lbuf), FL_UNSIGNED);
+  p = fmtumax (i, 10, lbuf, sizeof(lbuf), FL_UNSIGNED);
   return (savestring (p));
 }
index 13aad3f0e8134aadefa91f2970646eb82b910c7c..c496154b764f955f5d0c5da8ea83ba471c765943 100644 (file)
@@ -91,7 +91,7 @@ sh_makepath (path, dir, flags)
     }
   else
     {
-      xpath = ((flags & MP_DOTILDE) && *path == '~') ? bash_tilde_expand (path) : (char *)path;
+      xpath = ((flags & MP_DOTILDE) && *path == '~') ? bash_tilde_expand (path, 0) : (char *)path;
       pathlen = strlen (xpath);
     }
 
diff --git a/lib/sh/memset.c b/lib/sh/memset.c
new file mode 100644 (file)
index 0000000..ddc36b6
--- /dev/null
@@ -0,0 +1,26 @@
+/* memset.c -- set an area of memory to a given value
+   Copyright (C) 1991-2002 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-1307, USA.  */
+
+char *
+memset (char *str, int c, unsigned int len)
+{
+  register char *st = str;
+
+  while (len-- > 0)
+    *st++ = c;
+  return str;
+}
diff --git a/lib/sh/mktime.c b/lib/sh/mktime.c
new file mode 100644 (file)
index 0000000..81aeb22
--- /dev/null
@@ -0,0 +1,425 @@
+/* Copyright (C) 1993-2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Paul Eggert (eggert@twinsun.com).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* Define this to have a standalone program to test this implementation of
+   mktime.  */
+/* #define DEBUG 1 */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef _LIBC
+# define HAVE_LIMITS_H 1
+# define HAVE_LOCALTIME_R 1
+# define STDC_HEADERS 1
+#endif
+
+/* Assume that leap seconds are possible, unless told otherwise.
+   If the host has a `zic' command with a `-L leapsecondfilename' option,
+   then it supports leap seconds; otherwise it probably doesn't.  */
+#ifndef LEAP_SECONDS_POSSIBLE
+#define LEAP_SECONDS_POSSIBLE 1
+#endif
+
+#ifndef VMS
+#include <sys/types.h>         /* Some systems define `time_t' here.  */
+#else
+#include <stddef.h>
+#endif
+#include <time.h>
+
+#if HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#if DEBUG
+#include <stdio.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+/* Make it work even if the system's libc has its own mktime routine.  */
+#define mktime my_mktime
+#endif /* DEBUG */
+
+#ifndef __P
+#if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
+#define __P(args) args
+#else
+#define __P(args) ()
+#endif  /* GCC.  */
+#endif  /* Not __P.  */
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
+#ifndef INT_MIN
+#define INT_MIN (~0 << (sizeof (int) * CHAR_BIT - 1))
+#endif
+#ifndef INT_MAX
+#define INT_MAX (~0 - INT_MIN)
+#endif
+
+#ifndef TIME_T_MIN
+#define TIME_T_MIN (0 < (time_t) -1 ? (time_t) 0 \
+                   : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
+#endif
+#ifndef TIME_T_MAX
+#define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
+#endif
+
+#define TM_YEAR_BASE 1900
+#define EPOCH_YEAR 1970
+
+#ifndef __isleap
+/* Nonzero if YEAR is a leap year (every 4 years,
+   except every 100th isn't, and every 400th is).  */
+#define        __isleap(year)  \
+  ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+#endif
+
+/* How many days come before each month (0-12).  */
+const unsigned short int __mon_yday[2][13] =
+  {
+    /* Normal years.  */
+    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+    /* Leap years.  */
+    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+  };
+
+static time_t ydhms_tm_diff __P ((int, int, int, int, int, const struct tm *));
+time_t __mktime_internal __P ((struct tm *,
+                              struct tm *(*) (const time_t *, struct tm *),
+                              time_t *));
+
+
+static struct tm *my_localtime_r __P ((const time_t *, struct tm *));
+static struct tm *
+my_localtime_r (t, tp)
+     const time_t *t;
+     struct tm *tp;
+{
+  struct tm *l = localtime (t);
+  if (! l)
+    return 0;
+  *tp = *l;
+  return tp;
+}
+
+
+/* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
+   measured in seconds, ignoring leap seconds.
+   YEAR uses the same numbering as TM->tm_year.
+   All values are in range, except possibly YEAR.
+   If overflow occurs, yield the low order bits of the correct answer.  */
+static time_t
+ydhms_tm_diff (year, yday, hour, min, sec, tp)
+     int year, yday, hour, min, sec;
+     const struct tm *tp;
+{
+  /* Compute intervening leap days correctly even if year is negative.
+     Take care to avoid int overflow.  time_t overflow is OK, since
+     only the low order bits of the correct time_t answer are needed.
+     Don't convert to time_t until after all divisions are done, since
+     time_t might be unsigned.  */
+  int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
+  int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
+  int a100 = a4 / 25 - (a4 % 25 < 0);
+  int b100 = b4 / 25 - (b4 % 25 < 0);
+  int a400 = a100 >> 2;
+  int b400 = b100 >> 2;
+  int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
+  time_t years = year - (time_t) tp->tm_year;
+  time_t days = (365 * years + intervening_leap_days
+                + (yday - tp->tm_yday));
+  return (60 * (60 * (24 * days + (hour - tp->tm_hour))
+               + (min - tp->tm_min))
+         + (sec - tp->tm_sec));
+}
+
+
+static time_t localtime_offset;
+
+/* Convert *TP to a time_t value.  */
+time_t
+mktime (tp)
+     struct tm *tp;
+{
+#ifdef _LIBC
+  /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
+     time zone names contained in the external variable `tzname' shall
+     be set as if the tzset() function had been called.  */
+  __tzset ();
+#endif
+
+  return __mktime_internal (tp, my_localtime_r, &localtime_offset);
+}
+
+/* Convert *TP to a time_t value, inverting
+   the monotonic and mostly-unit-linear conversion function CONVERT.
+   Use *OFFSET to keep track of a guess at the offset of the result,
+   compared to what the result would be for UTC without leap seconds.
+   If *OFFSET's guess is correct, only one CONVERT call is needed.  */
+time_t
+__mktime_internal (tp, convert, offset)
+     struct tm *tp;
+     struct tm *(*convert) __P ((const time_t *, struct tm *));
+     time_t *offset;
+{
+  time_t t, dt, t0;
+  struct tm tm;
+
+  /* The maximum number of probes (calls to CONVERT) should be enough
+     to handle any combinations of time zone rule changes, solar time,
+     and leap seconds.  Posix.1 prohibits leap seconds, but some hosts
+     have them anyway.  */
+  int remaining_probes = 4;
+
+  /* Time requested.  Copy it in case CONVERT modifies *TP; this can
+     occur if TP is localtime's returned value and CONVERT is localtime.  */
+  int sec = tp->tm_sec;
+  int min = tp->tm_min;
+  int hour = tp->tm_hour;
+  int mday = tp->tm_mday;
+  int mon = tp->tm_mon;
+  int year_requested = tp->tm_year;
+  int isdst = tp->tm_isdst;
+
+  /* Ensure that mon is in range, and set year accordingly.  */
+  int mon_remainder = mon % 12;
+  int negative_mon_remainder = mon_remainder < 0;
+  int mon_years = mon / 12 - negative_mon_remainder;
+  int year = year_requested + mon_years;
+
+  /* The other values need not be in range:
+     the remaining code handles minor overflows correctly,
+     assuming int and time_t arithmetic wraps around.
+     Major overflows are caught at the end.  */
+
+  /* Calculate day of year from year, month, and day of month.
+     The result need not be in range.  */
+  int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
+              [mon_remainder + 12 * negative_mon_remainder])
+             + mday - 1);
+
+#if LEAP_SECONDS_POSSIBLE
+  /* Handle out-of-range seconds specially,
+     since ydhms_tm_diff assumes every minute has 60 seconds.  */
+  int sec_requested = sec;
+  if (sec < 0)
+    sec = 0;
+  if (59 < sec)
+    sec = 59;
+#endif
+
+  /* Invert CONVERT by probing.  First assume the same offset as last time.
+     Then repeatedly use the error to improve the guess.  */
+
+  tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
+  tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
+  t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
+
+  for (t = t0 + *offset;
+       (dt = ydhms_tm_diff (year, yday, hour, min, sec, (*convert) (&t, &tm)));
+       t += dt)
+    if (--remaining_probes == 0)
+      return -1;
+
+  /* Check whether tm.tm_isdst has the requested value, if any.  */
+  if (0 <= isdst && 0 <= tm.tm_isdst)
+    {
+      int dst_diff = (isdst != 0) - (tm.tm_isdst != 0);
+      if (dst_diff)
+       {
+         /* Move two hours in the direction indicated by the disagreement,
+            probe some more, and switch to a new time if found.
+            The largest known fallback due to daylight savings is two hours:
+            once, in Newfoundland, 1988-10-30 02:00 -> 00:00.  */
+         time_t ot = t - 2 * 60 * 60 * dst_diff;
+         while (--remaining_probes != 0)
+           {
+             struct tm otm;
+             if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
+                                        (*convert) (&ot, &otm))))
+               {
+                 t = ot;
+                 tm = otm;
+                 break;
+               }
+             if ((ot += dt) == t)
+               break;  /* Avoid a redundant probe.  */
+           }
+       }
+    }
+
+  *offset = t - t0;
+
+#if LEAP_SECONDS_POSSIBLE
+  if (sec_requested != tm.tm_sec)
+    {
+      /* Adjust time to reflect the tm_sec requested, not the normalized value.
+        Also, repair any damage from a false match due to a leap second.  */
+      t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
+      (*convert) (&t, &tm);
+    }
+#endif
+
+  if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
+    {
+      /* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
+        so check for major overflows.  A gross check suffices,
+        since if t has overflowed, it is off by a multiple of
+        TIME_T_MAX - TIME_T_MIN + 1.  So ignore any component of
+        the difference that is bounded by a small value.  */
+
+      double dyear = (double) year_requested + mon_years - tm.tm_year;
+      double dday = 366 * dyear + mday;
+      double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
+
+      if (TIME_T_MAX / 3 - TIME_T_MIN / 3 < (dsec < 0 ? - dsec : dsec))
+       return -1;
+    }
+
+  *tp = tm;
+  return t;
+}
+
+#ifdef weak_alias
+weak_alias (mktime, timelocal)
+#endif
+\f
+#if DEBUG
+
+static int
+not_equal_tm (a, b)
+     struct tm *a;
+     struct tm *b;
+{
+  return ((a->tm_sec ^ b->tm_sec)
+         | (a->tm_min ^ b->tm_min)
+         | (a->tm_hour ^ b->tm_hour)
+         | (a->tm_mday ^ b->tm_mday)
+         | (a->tm_mon ^ b->tm_mon)
+         | (a->tm_year ^ b->tm_year)
+         | (a->tm_mday ^ b->tm_mday)
+         | (a->tm_yday ^ b->tm_yday)
+         | (a->tm_isdst ^ b->tm_isdst));
+}
+
+static void
+print_tm (tp)
+     struct tm *tp;
+{
+  printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
+         tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
+         tp->tm_hour, tp->tm_min, tp->tm_sec,
+         tp->tm_yday, tp->tm_wday, tp->tm_isdst);
+}
+
+static int
+check_result (tk, tmk, tl, tml)
+     time_t tk;
+     struct tm tmk;
+     time_t tl;
+     struct tm tml;
+{
+  if (tk != tl || not_equal_tm (&tmk, &tml))
+    {
+      printf ("mktime (");
+      print_tm (&tmk);
+      printf (")\nyields (");
+      print_tm (&tml);
+      printf (") == %ld, should be %ld\n", (long) tl, (long) tk);
+      return 1;
+    }
+
+  return 0;
+}
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int status = 0;
+  struct tm tm, tmk, tml;
+  time_t tk, tl;
+  char trailer;
+
+  if ((argc == 3 || argc == 4)
+      && (sscanf (argv[1], "%d-%d-%d%c",
+                 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
+         == 3)
+      && (sscanf (argv[2], "%d:%d:%d%c",
+                 &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
+         == 3))
+    {
+      tm.tm_year -= TM_YEAR_BASE;
+      tm.tm_mon--;
+      tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
+      tmk = tm;
+      tl = mktime (&tmk);
+      tml = *localtime (&tl);
+      printf ("mktime returns %ld == ", (long) tl);
+      print_tm (&tmk);
+      printf ("\n");
+      status = check_result (tl, tmk, tl, tml);
+    }
+  else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
+    {
+      time_t from = atol (argv[1]);
+      time_t by = atol (argv[2]);
+      time_t to = atol (argv[3]);
+
+      if (argc == 4)
+       for (tl = from; tl <= to; tl += by)
+         {
+           tml = *localtime (&tl);
+           tmk = tml;
+           tk = mktime (&tmk);
+           status |= check_result (tk, tmk, tl, tml);
+         }
+      else
+       for (tl = from; tl <= to; tl += by)
+         {
+           /* Null benchmark.  */
+           tml = *localtime (&tl);
+           tmk = tml;
+           tk = tl;
+           status |= check_result (tk, tmk, tl, tml);
+         }
+    }
+  else
+    printf ("Usage:\
+\t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
+\t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
+\t%s FROM BY TO - # Do not test those values (for benchmark).\n",
+           argv[0], argv[0], argv[0]);
+
+  return status;
+}
+
+#endif /* DEBUG */
+\f
+/*
+Local Variables:
+compile-command: "gcc -DDEBUG=1 -Wall -O -g mktime.c -o mktime"
+End:
+*/
diff --git a/lib/sh/netconn.c b/lib/sh/netconn.c
new file mode 100644 (file)
index 0000000..f412cb0
--- /dev/null
@@ -0,0 +1,83 @@
+/* netconn.c -- is a particular file descriptor a network connection?. */
+
+/* Copyright (C) 2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
+*/
+
+#include <config.h>
+
+#include <bashtypes.h>
+#ifndef _MINIX
+#  include <sys/file.h>
+#endif
+#include <posixstat.h>
+#include <filecntl.h>
+
+#include <errno.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+/* The second and subsequent conditions must match those used to decide
+   whether or not to call getpeername() in isnetconn(). */
+#if defined (HAVE_SYS_SOCKET_H) && defined (HAVE_GETPEERNAME) && !defined (SVR4_2)
+#  include <sys/socket.h>
+#endif
+
+/* Is FD a socket or network connection? */
+int
+isnetconn (fd)
+     int fd;
+{
+#if defined (HAVE_GETPEERNAME) && !defined (SVR4_2) && !defined (__BEOS__)
+  int rv;
+  socklen_t l;
+  struct sockaddr sa;
+
+  l = sizeof(sa);
+  rv = getpeername(fd, &sa, &l);
+  /* Solaris 2.5 getpeername() returns EINVAL if the fd is not a socket. */
+  return ((rv < 0 && (errno == ENOTSOCK || errno == EINVAL)) ? 0 : 1);
+#else /* !HAVE_GETPEERNAME || SVR4_2 || __BEOS__ */
+#  if defined (SVR4) || defined (SVR4_2)
+  /* Sockets on SVR4 and SVR4.2 are character special (streams) devices. */
+  struct stat sb;
+
+  if (isatty (fd))
+    return (0);
+  if (fstat (fd, &sb) < 0)
+    return (0);
+#    if defined (S_ISFIFO)
+  if (S_ISFIFO (sb.st_mode))
+    return (0);
+#    endif /* S_ISFIFO */
+  return (S_ISCHR (sb.st_mode));
+#  else /* !SVR4 && !SVR4_2 */
+#    if defined (S_ISSOCK) && !defined (__BEOS__)
+  struct stat sb;
+
+  if (fstat (fd, &sb) < 0)
+    return (0);
+  return (S_ISSOCK (sb.st_mode));
+#    else /* !S_ISSOCK || __BEOS__ */
+  return (0);
+#    endif /* !S_ISSOCK || __BEOS__ */
+#  endif /* !SVR4 && !SVR4_2 */
+#endif /* !HAVE_GETPEERNAME || SVR4_2 || __BEOS__ */
+}
index 76a389b45dd867fe9619a79efad7a26104a79034..4197db1b9e842957a53ffa78cb207ba4de18c965 100644 (file)
@@ -5,7 +5,7 @@
  * chet@ins.CWRU.Edu
  */
 
-/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -107,7 +107,7 @@ _getserv (serv, proto, pp)
      int proto;
      unsigned short *pp;
 {
-  long l;
+  intmax_t l;
   unsigned short s;
 
   if (legal_number (serv, &l))
@@ -165,7 +165,7 @@ _netopen4(host, serv, typ)
       return -1;
     }
        
-  bzero ((char *)&sin, sizeof(sin));
+  memset ((char *)&sin, 0, sizeof(sin));
   sin.sin_family = AF_INET;
   sin.sin_port = p;
   sin.sin_addr = ina;
@@ -205,7 +205,7 @@ _netopen6 (host, serv, typ)
   struct addrinfo hints, *res, *res0;
   int gerr;
 
-  bzero ((char *)&hints, sizeof (hints));
+  memset ((char *)&hints, 0, sizeof (hints));
   /* XXX -- if problems with IPv6, set to PF_INET for IPv4 only */
 #ifdef DEBUG   /* PF_INET is the one that works for me */
   hints.ai_family = PF_INET;
index 69a35133d0687daaa6689be985c1ea49d2b9f4ee..90d7be9a7fb39b3cd67ce64f88d463b99b700fec 100644 (file)
 #  include <unistd.h>
 #endif
 
+#if defined (HAVE_LIMITS_H)
+#  include <limits.h>
+#endif
+
 #include <posixstat.h>
 #include <filecntl.h>
 #include <bashansi.h>
@@ -237,3 +241,56 @@ mkfifo (path, mode)
 #endif /* !S_IFIFO */
 }
 #endif /* !HAVE_MKFIFO && PROCESS_SUBSTITUTION */
+
+#define DEFAULT_MAXGROUPS 64
+
+int
+getmaxgroups ()
+{
+  static int maxgroups = -1;
+
+  if (maxgroups > 0)
+    return maxgroups;
+
+#if defined (HAVE_SYSCONF) && defined (_SC_NGROUPS_MAX)
+  maxgroups = sysconf (_SC_NGROUPS_MAX);
+#else
+#  if defined (NGROUPS_MAX)
+  maxgroups = NGROUPS_MAX;
+#  else /* !NGROUPS_MAX */
+#    if defined (NGROUPS)
+  maxgroups = NGROUPS;
+#    else /* !NGROUPS */
+  maxgroups = DEFAULT_MAXGROUPS;
+#    endif /* !NGROUPS */
+#  endif /* !NGROUPS_MAX */  
+#endif /* !HAVE_SYSCONF || !SC_NGROUPS_MAX */
+
+  if (maxgroups <= 0)
+    maxgroups = DEFAULT_MAXGROUPS;
+
+  return maxgroups;
+}
+
+long
+getmaxchild ()
+{
+  static long maxchild = -1L;
+
+  if (maxchild > 0)
+    return maxchild;
+
+#if defined (HAVE_SYSCONF) && defined (_SC_CHILD_MAX)
+  maxchild = sysconf (_SC_CHILD_MAX);
+#else
+#  if defined (CHILD_MAX)
+  maxchild = CHILD_MAX;
+#  else
+#    if defined (MAXUPRC)
+  maxchild = MAXUPRC;
+#    endif /* MAXUPRC */
+#  endif /* CHILD_MAX */
+#endif /* !HAVE_SYSCONF || !_SC_CHILD_MAX */
+
+  return (maxchild);
+}
index dcde8b07c6108fbdaefc34142e5e6929e49fddcf..d74f99c0f308d37e41749ad84c776465af1601ef 100644 (file)
 
 #include "shell.h"
 
+#if defined (__CYGWIN__)
+#include <sys/cygwin.h>
+
+static int
+_is_cygdrive (path)
+     char *path;
+{
+  static char user[MAXPATHLEN];
+  static char system[MAXPATHLEN];
+  static int first_time = 1;
+
+  /* If the path is the first part of a network path, treat it as
+     existing. */
+  if (path[0] == '/' && path[1] == '/' && !strchr (path + 2, '/'))
+    return 1; 
+  /* Otherwise check for /cygdrive prefix. */
+  if (first_time)
+    {
+      char user_flags[MAXPATHLEN];
+      char system_flags[MAXPATHLEN];
+      /* Get the cygdrive info */
+      cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, user_flags, system_flags);
+      first_time = 0;
+    }
+  return !strcasecmp (path, user) || !strcasecmp (path, system);
+}
+#endif /* __CYGWIN__ */        
+
 /* Return 1 if PATH corresponds to a directory.  A function for debugging. */
 static int
 _path_isdir (path)
@@ -46,6 +74,10 @@ _path_isdir (path)
   struct stat sb;
 
   l = stat (path, &sb) == 0 && S_ISDIR (sb.st_mode);
+#if defined (__CYGWIN__)
+  if (l == 0)
+    l = _is_cygdrive (path);
+#endif
   return l;
 }
 
index cc12856649e0436d9c7e5ed48a67d8623bd837db..d5c2778570a46a876d4640e9ac385f978dfd626b 100644 (file)
 #if !defined (HAVE_RENAME)
 
 #include <bashtypes.h>
+#include <posixstat.h>
 
 #if defined (HAVE_UNISTD_H)
 #  include <unistd.h>
 #endif
+#include <errno.h>
 
 #include <stdc.h>
 
+#ifndef errno
+extern int errno;
+#endif
+
 int
 rename (from, to)
      const char *from, *to;
 {
-  unlink (to);
+  struct stat fb, tb;
+
+  if (stat (from, &fb) < 0)
+    return -1;  
+
+  if (stat (to, &tb) < 0)
+    {
+      if (errno != ENOENT)
+       return -1;
+    }
+  else
+    {
+      if (fb.st_dev == tb.st_dev && fb.st_ino == tb.st_ino)
+        return 0;              /* same file */
+      if (unlink (to) < 0 && errno != ENOENT)
+        return -1;
+    }
+
   if (link (from, to) < 0)
     return (-1);
-  unlink (from);
+
+  if (unlink (from) < 0 && errno != ENOENT)
+    {
+      int e = errno;
+      unlink (to);
+      errno = e;
+      return (-1);
+    }
+
   return (0);
 }
 #endif /* !HAVE_RENAME */
index 4160e70ef6ed30059389290e82ebb42bd7607a32..713f48199a8deacef81189482e0d37eec6f429be 100644 (file)
@@ -147,6 +147,7 @@ sh_backslash_quote (string)
        case '*': case '[': case '?': case ']': /* globbing chars */
        case '^':
        case '$': case '`':                     /* expansion chars */
+       case ',':                               /* brace expansion */
          *r++ = '\\';
          *r++ = c;
          break;
index f84d60c1f79f7e86d961436614972254b7f74994..7669576c891da2986b4862d78bc016f362ddeb39 100644 (file)
@@ -47,9 +47,7 @@
  * Currently doesn't handle (and bash/readline doesn't use):
  *     *M$ width, precision specifications
  *     %N$ numbered argument conversions
- *     inf, nan floating values (could use isinf(), isnan())
- *     `,', `'' flags 
- *     `C', `S' conversions
+ *     inf, nan floating values imperfect (if isinf(), isnan() not in libc)
  *     support for `F' is imperfect, since underlying printf may not handle it
  */
 
 #ifdef __linux__
 #define HAVE_PRINTF_A_FORMAT
 #endif
+#define HAVE_ISINF_IN_LIBC
 #define PREFER_STDARG
 #define HAVE_STRINGIZE
 #define HAVE_LIMITS_H
 #define HAVE_STDDEF_H
+#define HAVE_LOCALE_H
 #define intmax_t long
 #endif
 
 #endif
 
 #ifdef FLOATING_POINT
+#  include <float.h>   /* for manifest constants */
 #  include <stdio.h>   /* for sprintf */
 #endif
 
 #include <typemax.h>
 
+#ifdef HAVE_LOCALE_H
+#  include <locale.h>
+#endif
+
 #include "stdc.h"
+#include <shmbutil.h>
 
 #ifndef DRIVER
 #  include "shell.h"
@@ -114,6 +120,10 @@ extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
 extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
 #endif
 
+#ifndef FREE
+#  define FREE(x)      if (x) free (x)
+#endif
+
 /* Bound on length of the string representing an integer value of type T.
    Subtract one for the sign bit if T is signed;
    302 / 1000 is log10 (2) rounded up;
@@ -130,7 +140,7 @@ extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
 #define PF_ZEROPAD     0x00008         /* 0 */
 #define PF_PLUS                0x00010         /* + */
 #define PF_SPACE       0x00020         /* ' ' */
-#define PF_COMMA       0x00040         /* , */
+#define PF_THOUSANDS   0x00040         /* ' */
 
 #define PF_DOT         0x00080         /* `.precision' */
 #define PF_STAR_P      0x00100         /* `*' after precision */
@@ -158,6 +168,10 @@ extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
 
 static char intbuf[INT_STRLEN_BOUND(unsigned long) + 1];
 
+static int decpoint;
+static int thoussep;
+static char *grouping;
+
 /* 
  * For the FLOATING POINT FORMAT :
  *  the challenge was finding a way to
@@ -196,25 +210,27 @@ static char intbuf[INT_STRLEN_BOUND(unsigned long) + 1];
 
 #define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;}
 
+#define GETARG(type)   (va_arg(args, type))
+
 /* Macros that do proper sign extension and handle length modifiers.  Used
    for the integer conversion specifiers. */
 #define GETSIGNED(p) \
   (((p)->flags & PF_LONGINT) \
-       ? va_arg(args, long) \
-       : (((p)->flags & PF_SHORTINT) ? (long)(short)va_arg(args, int) \
-                                     : (long)va_arg(args, int)))
+       ? GETARG (long) \
+       : (((p)->flags & PF_SHORTINT) ? (long)(short)GETARG (int) \
+                                     : (long)GETARG (int)))
 
 #define GETUNSIGNED(p) \
   (((p)->flags & PF_LONGINT) \
-       ? va_arg(args, unsigned long) \
-       : (((p)->flags & PF_SHORTINT) ? (unsigned long)(unsigned short)va_arg(args, int) \
-                                     : (unsigned long)va_arg(args, unsigned int)))
+       ? GETARG (unsigned long) \
+       : (((p)->flags & PF_SHORTINT) ? (unsigned long)(unsigned short)GETARG (int) \
+                                     : (unsigned long)GETARG (unsigned int)))
 
 
 #ifdef HAVE_LONG_DOUBLE
-#define GETLDOUBLE(p) va_arg(args, long double)
+#define GETLDOUBLE(p) GETARG (long double)
 #endif
-#define GETDOUBLE(p) va_arg(args, double)
+#define GETDOUBLE(p) GETARG (double)
 
 #define SET_SIZE_FLAGS(p, type) \
   if (sizeof (type) > sizeof (int)) \
@@ -271,6 +287,8 @@ static void ldfallback __P((struct DATA *, const char *, const char *, long doub
 static void dfallback __P((struct DATA *, const char *, const char *, double));
 #endif
 
+static char *groupnum __P((char *));
+
 #ifdef DRIVER
 static void memory_error_and_abort ();
 static void *xmalloc __P((size_t));
@@ -317,6 +335,20 @@ static void xfree __P((void *));
          } \
        while (0)
 
+/* Output a string.  P->WIDTH has already been adjusted for padding. */
+#define PUT_STRING(string, len, p) \
+       do \
+         { \
+           PAD_RIGHT (p); \
+           while ((len)-- > 0) \
+             { \
+               PUT_CHAR (*(string), (p)); \
+               (string)++; \
+             } \
+           PAD_LEFT (p); \
+         } \
+       while (0)
+
 #define PUT_PLUS(d, p, zero) \
            if ((d) > zero && (p)->justify == RIGHT) \
              PUT_CHAR('+', p)
@@ -340,9 +372,34 @@ static void xfree __P((void *));
 /* if width and prec. in the args */
 #define STAR_ARGS(p) \
            if ((p)->flags & PF_STAR_W) \
-             (p)->width = va_arg(args, int); \
+             (p)->width = GETARG (int); \
            if ((p)->flags & PF_STAR_P) \
-             (p)->precision = va_arg(args, int)
+             (p)->precision = GETARG (int)
+
+#if defined (HAVE_LOCALE_H)
+#  define GETLOCALEDATA(d, t, g) \
+      do \
+       { \
+         struct lconv *lv; \
+         if ((d) == 0) { \
+         (d) = '.'; (t) = -1; (g) = 0; /* defaults */ \
+         lv = localeconv(); \
+         if (lv) \
+           { \
+             if (lv->decimal_point && lv->decimal_point[0]) \
+               (d) = lv->decimal_point[0]; \
+             if (lv->thousands_sep && lv->thousands_sep[0]) \
+               (t) = lv->thousands_sep[0]; \
+             (g) = lv->grouping ? lv->grouping : ""; \
+             if (*(g) == '\0' || *(g) == CHAR_MAX || (t) == -1) (g) = 0; \
+           } \
+         } \
+       } \
+      while (0);
+#else
+#  define GETLOCALEDATA(d, t, g) \
+      ( (d) = '.', (t) = ',', g = "\003" )
+#endif
 
 #ifdef FLOATING_POINT
 /*
@@ -496,6 +553,8 @@ numtoa(number, base, precision, fract)
       integral_part[1] = '\0';
       fraction_part[0] = '0';
       fraction_part[1] = '\0';
+      if (fract)
+       *fract = fraction_part;
       return integral_part;
     }
 
@@ -570,7 +629,7 @@ number(p, d, base)
      unsigned long d;
      int base;
 {
-  char *tmp;
+  char *tmp, *t;
   long sd;
   int flags;
 
@@ -580,6 +639,14 @@ number(p, d, base)
     flags |= FL_HEXUPPER;
 
   tmp = fmtulong (d, base, intbuf, sizeof(intbuf), flags);
+  t = 0;
+  if ((p->flags & PF_THOUSANDS))
+    {
+      GETLOCALEDATA(decpoint, thoussep, grouping);
+      if (grouping && (t = groupnum (tmp)))
+        tmp = t;
+    }
+
   p->width -= strlen(tmp);
   PAD_RIGHT(p);
 
@@ -609,6 +676,7 @@ number(p, d, base)
     }
 
   PAD_LEFT(p);
+  FREE (t);
 }
 
 #ifdef HAVE_LONG_LONG
@@ -621,7 +689,7 @@ lnumber(p, d, base)
      unsigned long long d;
      int base;
 {
-  char *tmp;
+  char *tmp, *t;
   long long sd;
   int flags;
 
@@ -631,6 +699,14 @@ lnumber(p, d, base)
     flags |= FL_HEXUPPER;
 
   tmp = fmtullong (d, base, intbuf, sizeof(intbuf), flags);
+  t = 0;
+  if ((p->flags & PF_THOUSANDS))
+    {
+      GETLOCALEDATA(decpoint, thoussep, grouping);
+      if (grouping && (t = groupnum (tmp)))
+        tmp = t;
+    }
+
   p->width -= strlen(tmp);
   PAD_RIGHT(p);
 
@@ -660,6 +736,7 @@ lnumber(p, d, base)
     }
 
   PAD_LEFT(p);
+  FREE (t);
 }
 #endif
 
@@ -692,34 +769,162 @@ strings(p, tmp)
      struct DATA *p;
      char *tmp;
 {
-  int i;
+  size_t len;
 
-  i = strlen(tmp);
+  len = strlen(tmp);
   if (p->precision != NOT_FOUND) /* the smallest number */
-    i = (i < p->precision ? i : p->precision);
-  p->width -= i;
-  PAD_RIGHT(p);
-  while (i-- > 0)
-    { /* put the sting */
-      PUT_CHAR(*tmp, p);
-      tmp++;
+    len = (len < p->precision ? len : p->precision);
+  p->width -= len;
+
+  PUT_STRING (tmp, len, p);
+}
+
+#if HANDLE_MULTIBYTE
+/* %ls wide-character strings */
+static void
+wstrings(p, tmp)
+     struct DATA *p;
+     wchar_t *tmp;
+{
+  size_t len;
+  mbstate_t mbs;
+  char *os;
+  const wchar_t *ws;
+
+  memset (&mbs, '\0', sizeof (mbstate_t));
+  ws = (const wchar_t *)tmp;
+
+  os = (char *)NULL;
+  if (p->precision != NOT_FOUND)
+    {
+      os = (char *)xmalloc (p->precision + 1);
+      len = wcsrtombs (os, &ws, p->precision, &mbs);
     }
-  PAD_LEFT(p);
+  else
+    {
+      len = wcsrtombs (NULL, &ws, 0, &mbs);
+      if (len != (size_t)-1)
+        {
+         memset (&mbs, '\0', sizeof (mbstate_t));
+         os = (char *)xmalloc (len + 1);
+         (void)wcsrtombs (os, &ws, len + 1, &mbs);
+        }
+    }
+  if (len == (size_t)-1)
+    {
+      /* invalid multibyte sequence; bail now. */
+      FREE (os);      
+      return;
+    }
+
+  p->width -= len;
+  PUT_STRING (os, len, p);
+  free (os);
 }
 
+static void
+wchars (p, wc)
+     struct DATA *p;
+     wint_t wc;
+{
+  char *lbuf, *l;
+  mbstate_t mbs;
+  size_t len;
+
+  lbuf = (char *)malloc (MB_CUR_MAX+1);
+  if (lbuf == 0)
+    return;
+  memset (&mbs, '\0', sizeof (mbstate_t));
+  len = wcrtomb (lbuf, wc, &mbs);
+  if (len == (size_t)-1)
+    /* conversion failed; bail now. */
+    return;
+  p->width -= len;
+  l = lbuf;
+  PUT_STRING (l, len, p);
+  free (lbuf);
+}
+#endif /* HANDLE_MULTIBYTE */
+
 #ifdef FLOATING_POINT
+
+#ifndef HAVE_ISINF_IN_LIBC
+/* Half-assed versions, since we don't want to link with libm. */
+static int
+isinf(d)
+     double d;
+{
+#ifdef DBL_MAX
+  if (d < DBL_MIN)
+    return -1;
+  else if (d > DBL_MAX)
+    return 1;
+  else
+#endif
+    return 0;
+}
+
+static int
+isnan(d)
+     double d;
+{
+  return 0;
+}
+#endif
+
+/* Check for [+-]infinity and NaN.  If MODE == 1, we check for Infinity, else
+   (mode == 2) we check for NaN.  This does the necessary printing.  Returns
+   1 if Inf or Nan, 0 if not. */
+static int
+chkinfnan(p, d, mode)
+     struct DATA *p;
+     double d;
+     int mode;         /* == 1 for inf, == 2 for nan */
+{
+  int i;
+  char *tmp;
+  char *big, *small;
+
+  i = (mode == 1) ? isinf(d) : isnan(d);
+  if (i == 0)
+    return 0;
+  big = (mode == 1) ? "INF" : "NAN";
+  small = (mode == 1) ? "inf" : "nan";
+
+  tmp = (*p->pf == 'F' || *p->pf == 'G' || *p->pf == 'E') ? big : small;
+
+  if (i < 0)
+    PUT_CHAR('-', p);
+
+  while (*tmp)
+    {
+      PUT_CHAR (*tmp, p);
+      tmp++;
+    }
+
+  return 1;
+}
+
 /* %f %F %g %G floating point representation */
 static void
 floating(p, d)
      struct DATA *p;
      double d;
 {
-  char *tmp, *tmp2;
+  char *tmp, *tmp2, *t;
   int i;
 
+  if (chkinfnan(p, d, 1) || chkinfnan(p, d, 2))
+    return;    /* already printed nan or inf */
+
+  GETLOCALEDATA(decpoint, thoussep, grouping);
   DEF_PREC(p);
   d = ROUND(d, p);
   tmp = dtoa(d, p->precision, &tmp2);
+  t = 0;
+  if ((p->flags & PF_THOUSANDS) && grouping && (t = groupnum (tmp)))
+    tmp = t;
+
   /* calculate the padding. 1 for the dot */
   p->width = p->width -
            ((d > 0. && p->justify == RIGHT) ? 1:0) -
@@ -728,17 +933,22 @@ floating(p, d)
   PAD_RIGHT(p);  
   PUT_PLUS(d, p, 0.);
   PUT_SPACE(d, p, 0.);
+
   while (*tmp)
     { /* the integral */
       PUT_CHAR(*tmp, p);
       tmp++;
     }
+  FREE (t);
+
   if (p->precision != 0 || (p->flags & PF_ALTFORM))
-    PUT_CHAR('.', p);  /* put the '.' */
+    PUT_CHAR(decpoint, p);  /* put the '.' */
+
   if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
     /* smash the trailing zeros unless altform */
     for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
-       tmp2[i] = '\0'; 
+      tmp2[i] = '\0'; 
+
   for (; *tmp2; tmp2++)
     PUT_CHAR(*tmp2, p); /* the fraction */
   
@@ -752,69 +962,55 @@ exponent(p, d)
      double d;
 {
   char *tmp, *tmp2;
-  int j, i, nsig, ndig;
+  int j, i;
 
+  if (chkinfnan(p, d, 1) || chkinfnan(p, d, 2))
+    return;    /* already printed nan or inf */
+
+  GETLOCALEDATA(decpoint, thoussep, grouping);
   DEF_PREC(p);
   j = log_10(d);
   d = d / pow_10(j);  /* get the Mantissa */
   d = ROUND(d, p);               
   tmp = dtoa(d, p->precision, &tmp2);
+
   /* 1 for unit, 1 for the '.', 1 for 'e|E',
    * 1 for '+|-', 2 for 'exp' */
   /* calculate how much padding need */
   p->width = p->width - 
             ((d > 0. && p->justify == RIGHT) ? 1:0) -
             ((p->flags & PF_SPACE) ? 1:0) - p->precision - 6;
+
   PAD_RIGHT(p);
   PUT_PLUS(d, p, 0.);
   PUT_SPACE(d, p, 0.);
-  /*
-   * When supplied %g or %G, an optional precision is the number of
-   * significant digits to print.
-   *
-   * nsig = number of significant digits we've printed (leading zeros are
-   *       never significant)
-   * ndig = if non-zero, max number of significant digits to print (only
-   *       applicable to %g/%G)
-   */
-  nsig = ndig = 0;
-  if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_DOT))
-    ndig = (p->precision == 0) ? 1 : p->precision;
 
   while (*tmp)
     {
       PUT_CHAR(*tmp, p);
       tmp++;
-      if (ndig && (++nsig >= ndig))
-       break;
     }
 
-  if ((p->precision != 0 || (p->flags & PF_ALTFORM)) && (ndig == 0 || nsig < ndig))
-      PUT_CHAR('.', p);  /* the '.' */
+  if (p->precision != 0 || (p->flags & PF_ALTFORM))
+      PUT_CHAR(decpoint, p);  /* the '.' */
+
   if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
     /* smash the trailing zeros unless altform */
     for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
-       tmp2[i] = '\0'; 
+      tmp2[i] = '\0'; 
+
   for (; *tmp2; tmp2++)
-    {
-      if (ndig && (nsig++ >= ndig))
-       break;
-      PUT_CHAR(*tmp2, p); /* the fraction */
-    }
+    PUT_CHAR(*tmp2, p); /* the fraction */
 
   /* the exponent put the 'e|E' */
   if (*p->pf == 'g' || *p->pf == 'e')
-    {
-      PUT_CHAR('e', p);
-    }
+    PUT_CHAR('e', p);
   else
-     PUT_CHAR('E', p);
+    PUT_CHAR('E', p);
 
   /* the sign of the exp */
   if (j > 0)
-    {
-      PUT_CHAR('+', p);
-    }
+    PUT_CHAR('+', p);
   else
     {
       PUT_CHAR('-', p);
@@ -825,9 +1021,7 @@ exponent(p, d)
    /* pad out to at least two spaces.  pad with `0' if the exponent is a
       single digit. */
    if (j <= 9)
-     {
-       PUT_CHAR('0', p);
-     }
+     PUT_CHAR('0', p);
 
    /* the exponent */
    while (*tmp)
@@ -839,6 +1033,69 @@ exponent(p, d)
 }
 #endif
 
+/* Return a new string with the digits in S grouped according to the locale's
+   grouping info and thousands separator.  If no grouping should be performed,
+   this returns NULL; the caller needs to check for it. */
+static char *
+groupnum (s)
+     char *s;
+{
+  char *se, *ret, *re, *g;
+  int len, slen;
+
+  if (grouping == 0 || *grouping <= 0 || *grouping == CHAR_MAX)
+    return ((char *)NULL);
+
+  /* find min grouping to size returned string */
+  for (len = *grouping, g = grouping; *g; g++)
+      if (*g > 0 && *g < len)
+       len = *g;
+
+  slen = strlen (s);
+  len = slen / len + 1;
+  ret = (char *)xmalloc (slen + len + 1);
+  re = ret + slen + len;
+  *re = '\0';
+
+  g = grouping;
+  se = s + slen;
+  len = *g;
+
+  while (se > s)
+    {
+      *--re = *--se;
+
+      /* handle `-' inserted by numtoa() and the fmtu* family here. */
+      if (se > s && se[-1] == '-')
+       continue;
+
+      /* begin new group. */
+      if (--len == 0 && se > s)
+       {
+         *--re = thoussep;
+         len = *++g;           /* was g++, but that uses first char twice (glibc bug, too) */
+         if (*g == '\0')
+           len = *--g;         /* use previous grouping */
+         else if (*g == CHAR_MAX)
+           {
+             do
+               *--re = *--se;
+             while (se > s);
+             break;
+           }
+       }
+    }
+
+  if (re > ret)
+#ifdef HAVE_MEMMOVE
+    memmove (ret, re, strlen (re) + 1);
+#else
+    strcpy (ret, re);
+#endif
+   
+  return ret;
+}
+
 /* initialize the conversion specifiers */
 static void
 init_conv_flag (p)
@@ -887,18 +1144,26 @@ vsnprintf_internal(data, string, length, format, args)
 #endif
   int state, i, c, n;
   char *s;
+#if HANDLE_MULTIBYTE
+  wchar_t *ws;
+  wint_t wc;
+#endif
   const char *convstart;
 
-  /* Sanity check, the string must be > 1.  C99 actually says that LENGTH
-     can be zero here, in the case of snprintf/vsnprintf (it's never 0 in
-     the case of asprintf/vasprintf), and the return value is the number
+  /* Sanity check, the string length must be >= 0.  C99 actually says that
+     LENGTH can be zero here, in the case of snprintf/vsnprintf (it's never
+     0 in the case of asprintf/vasprintf), and the return value is the number
      of characters that would have been written. */
-  if (length < 1)
+  if (length < 0)
     return -1;
 
   if (format == 0)
     return 0;
 
+  /* Reset these for each call because the locale might have changed. */
+  decpoint = thoussep = 0;
+  grouping = 0;
+
   for (; c = *(data->pf); data->pf++)
     {
       if (c != '%')
@@ -966,8 +1231,8 @@ vsnprintf_internal(data, string, length, format, args)
                data->flags |= PF_PLUS;
                data->justify = RIGHT;
                continue;
-             case ',':
-               data->flags |= PF_COMMA;                /* not implemented yet */
+             case '\'':
+               data->flags |= PF_THOUSANDS;
                continue;
 
              case '1': case '2': case '3':
@@ -1043,9 +1308,18 @@ conv_break:
                 * else use %e|%E
                 */
                if (-4 < i && i < data->precision)
-                 floating(data, d);
+                 {
+                   /* reset precision */
+                   data->precision -= i + 1;
+                   floating(data, d);
+                 }
                else
-                 exponent(data, d);
+                 {
+                   /* reduce precision by 1 because of leading digit before
+                      decimal point in e format. */
+                   data->precision--;
+                   exponent(data, d);
+                 }
                state = 0;
                break;
              case 'e':
@@ -1073,7 +1347,7 @@ conv_break:
 #ifdef HAVE_LONG_LONG
                if (data->flags & PF_LONGLONG)
                  {
-                   ull = va_arg(args, unsigned long long);
+                   ull = GETARG (unsigned long long);
                    lnumber(data, ull, 10);
                  }
                else
@@ -1093,7 +1367,7 @@ conv_break:
 #ifdef HAVE_LONG_LONG
                if (data->flags & PF_LONGLONG)
                  {
-                   ull = va_arg(args, long long);
+                   ull = GETARG (long long);
                    lnumber(data, ull, 10);
                  }
                else
@@ -1109,7 +1383,7 @@ conv_break:
 #ifdef HAVE_LONG_LONG
                if (data->flags & PF_LONGLONG)
                  {
-                   ull = va_arg(args, unsigned long long);
+                   ull = GETARG (unsigned long long);
                    lnumber(data, ull, 8);
                  }
                else
@@ -1126,7 +1400,7 @@ conv_break:
 #ifdef HAVE_LONG_LONG
                if (data->flags & PF_LONGLONG)
                  {
-                   ull = va_arg(args, unsigned long long);
+                   ull = GETARG (unsigned long long);
                    lnumber(data, ull, 16);
                  }
                else
@@ -1139,33 +1413,64 @@ conv_break:
                break;
              case 'p':
                STAR_ARGS(data);
-               ul = (unsigned long)va_arg(args, void *);
+               ul = (unsigned long)GETARG (void *);
                pointer(data, ul);
                state = 0;
                break;
+#if HANDLE_MULTIBYTE
+             case 'C':
+               data->flags |= PF_LONGINT;
+               /* FALLTHROUGH */
+#endif
              case 'c': /* character */
-               ul = va_arg(args, int);
-               PUT_CHAR(ul, data);
+               STAR_ARGS(data);
+#if HANDLE_MULTIBYTE
+               if (data->flags & PF_LONGINT)
+                 {
+                   wc = GETARG (wint_t);
+                   wchars (data, wc);
+                 }
+               else
+#endif
+                 {             
+                   ul = GETARG (int);
+                   PUT_CHAR(ul, data);
+                 }
                state = 0;
                break;
+#if HANDLE_MULTIBYTE
+             case 'S':
+               data->flags |= PF_LONGINT;
+               /* FALLTHROUGH */
+#endif
              case 's':  /* string */
                STAR_ARGS(data);
-               s = va_arg(args, char *);
-               strings(data, s);
+#if HANDLE_MULTIBYTE
+               if (data->flags & PF_LONGINT)
+                 {
+                   ws = GETARG (wchar_t *);
+                   wstrings (data, ws);
+                 }
+               else
+#endif
+                 {
+                   s = GETARG (char *);
+                   strings(data, s);
+                 }
                state = 0;
                break;
              case 'n':
 #ifdef HAVE_LONG_LONG
                if (data->flags & PF_LONGLONG)
-                 *(va_arg(args, long long *)) = data->counter;
+                 *(GETARG (long long *)) = data->counter;
                else
 #endif
                if (data->flags & PF_LONGINT)
-                 *(va_arg(args, long *)) = data->counter;
+                 *(GETARG (long *)) = data->counter;
                else if (data->flags & PF_SHORTINT)
-                 *(va_arg(args, short *)) = data->counter;
+                 *(GETARG (short *)) = data->counter;
                else
-                 *(va_arg(args, int *)) = data->counter;
+                 *(GETARG (int *)) = data->counter;
                state = 0;
                break;
              case '%':  /* nothing just % */
@@ -1201,7 +1506,7 @@ ldfallback (data, fs, fe, ld)
   char fmtbuf[FALLBACK_FMTSIZE], *obuf;
   int fl;
 
-  obuf = xmalloc(LFALLBACK_BASE + (data->precision < 6 ? 6 : data->precision) + 2);
+  obuf = (char *)xmalloc(LFALLBACK_BASE + (data->precision < 6 ? 6 : data->precision) + 2);
   fl = fe - fs + 1;
   strncpy (fmtbuf, fs, fl);
   fmtbuf[fl] = '\0';
@@ -1248,6 +1553,8 @@ vsnprintf(string, length, format, args)
 {
   struct DATA data;
 
+  if (string == 0 && length != 0)
+    return 0;
   init_data (&data, string, length, format, PFM_SN);
   return (vsnprintf_internal(&data, string, length, format, args));
 }
@@ -1267,12 +1574,10 @@ snprintf(string, length, format, va_alist)
   int rval;
   va_list args;
 
-#if defined(PREFER_STDARG)
-  va_start(args, format);
-#else
-  va_start(args);
-#endif
+  SH_VA_START(args, format);
 
+  if (string == 0 && length != 0)
+    return 0;
   init_data (&data, string, length, format, PFM_SN);
   rval = vsnprintf_internal (&data, string, length, format, args);
 
@@ -1319,11 +1624,7 @@ asprintf(stringp, format, va_alist)
   int rval;
   va_list args;
 
-#if defined(PREFER_STDARG)
-  va_start(args, format);
-#else
-  va_start(args);
-#endif
+  SH_VA_START(args, format);
 
   rval = vasprintf (stringp, format, args);
 
@@ -1378,10 +1679,6 @@ xfree(x)
     free (x);
 }
 
-#ifdef FLOATING_POINT
-#  include <float.h>
-#endif
-
 /* set of small tests for snprintf() */
 main()
 {
@@ -1389,6 +1686,18 @@ main()
   char *h;
   int i, si, ai;
 
+#ifdef HAVE_LOCALE_H
+  setlocale(LC_ALL, "");
+#endif
+
+#if 1
+  si = snprintf((char *)NULL, 0, "abcde\n");
+  printf("snprintf returns %d with NULL first argument and size of 0\n", si);
+  si = snprintf(holder, 0, "abcde\n");
+  printf("snprintf returns %d with non-NULL first argument and size of 0\n", si);
+  si = snprintf((char *)NULL, 16, "abcde\n");
+  printf("snprintf returns %d with NULL first argument and non-zero size\n", si);
+  
 /*
   printf("Suite of test for snprintf:\n");
   printf("a_format\n");
@@ -1660,6 +1969,92 @@ main()
   printf ("<%d> <%s>\n", si, holder);
   printf ("<%d> <%s>\n\n", ai, h);
 
+  /* huh? */
+  printf("/%%g/, 421.2345\n");
+  snprintf(holder, sizeof holder, "/%g/\n", 421.2345);
+  asprintf(&h, "/%g/\n", 421.2345);
+  printf("/%g/\n", 421.2345);
+  printf("%s", holder);
+  printf("%s\n", h);
+
+  printf("/%%g/, 4214.2345\n");
+  snprintf(holder, sizeof holder, "/%g/\n", 4214.2345);
+  asprintf(&h, "/%g/\n", 4214.2345);
+  printf("/%g/\n", 4214.2345);
+  printf("%s", holder);
+  printf("%s\n", h);
+
+  printf("/%%.5g/, 4214.2345\n");
+  snprintf(holder, sizeof holder, "/%.5g/\n", 4214.2345);
+  asprintf(&h, "/%.5g/\n", 4214.2345);
+  printf("/%.5g/\n", 4214.2345);
+  printf("%s", holder);
+  printf("%s\n", h);
+
+  printf("/%%.4g/, 4214.2345\n");
+  snprintf(holder, sizeof holder, "/%.4g/\n", 4214.2345);
+  asprintf(&h, "/%.4g/\n", 4214.2345);
+  printf("/%.4g/\n", 4214.2345);
+  printf("%s", holder);
+  printf("%s\n", h);
+
+  printf("/%%'ld %%'ld/, 12345, 1234567\n");
+  snprintf(holder, sizeof holder, "/%'ld %'ld/\n", 12345, 1234567);
+  asprintf(&h, "/%'ld %'ld/\n", 12345, 1234567);
+  printf("/%'ld %'ld/\n", 12345, 1234567);
+  printf("%s", holder);
+  printf("%s\n", h);
+
+  printf("/%%'ld %%'ld/, 336, 3336\n");
+  snprintf(holder, sizeof holder, "/%'ld %'ld/\n", 336, 3336);
+  asprintf(&h, "/%'ld %'ld/\n", 336, 3336);
+  printf("/%'ld %'ld/\n", 336, 3336);
+  printf("%s", holder);
+  printf("%s\n", h);
+
+  printf("/%%'ld %%'ld/, -42786, -142786\n");
+  snprintf(holder, sizeof holder, "/%'ld %'ld/\n", -42786, -142786);
+  asprintf(&h, "/%'ld %'ld/\n", -42786, -142786);
+  printf("/%'ld %'ld/\n", -42786, -142786);
+  printf("%s", holder);
+  printf("%s\n", h);
+
+  printf("/%%'f %%'f/, 421.2345, 421234.56789\n");
+  snprintf(holder, sizeof holder, "/%'f %'f/\n", 421.2345, 421234.56789);
+  asprintf(&h, "/%'f %'f/\n", 421.2345, 421234.56789);
+  printf("/%'f %'f/\n", 421.2345, 421234.56789);
+  printf("%s", holder);
+  printf("%s\n", h);
+
+  printf("/%%'f %%'f/, -421.2345, -421234.56789\n");
+  snprintf(holder, sizeof holder, "/%'f %'f/\n", -421.2345, -421234.56789);
+  asprintf(&h, "/%'f %'f/\n", -421.2345, -421234.56789);
+  printf("/%'f %'f/\n", -421.2345, -421234.56789);
+  printf("%s", holder);
+  printf("%s\n", h);
+
+  printf("/%%'g %%'g/, 421.2345, 421234.56789\n");
+  snprintf(holder, sizeof holder, "/%'g %'g/\n", 421.2345, 421234.56789);
+  asprintf(&h, "/%'g %'g/\n", 421.2345, 421234.56789);
+  printf("/%'g %'g/\n", 421.2345, 421234.56789);
+  printf("%s", holder);
+  printf("%s\n", h);
+
+  printf("/%%'g %%'g/, -421.2345, -421234.56789\n");
+  snprintf(holder, sizeof holder, "/%'g %'g/\n", -421.2345, -421234.56789);
+  asprintf(&h, "/%'g %'g/\n", -421.2345, -421234.56789);
+  printf("/%'g %'g/\n", -421.2345, -421234.56789);
+  printf("%s", holder);
+  printf("%s\n", h);
+#endif
+
+  printf("/%%'g/, 4213455.8392\n");
+  snprintf(holder, sizeof holder, "/%'g/\n", 4213455.8392);
+  asprintf(&h, "/%'g/\n", 4213455.8392);
+  printf("/%'g/\n", 4213455.8392);
+  printf("%s", holder);
+  printf("%s\n", h);
+
   exit (0);
 }
 #endif
index 6da63762ea9e84fe43a6d1cc66cb6cf3f775f30a..cff20b24a248ededd936d7257caa3019e1b059a2 100644 (file)
@@ -38,8 +38,10 @@ Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
 
 #include <bashansi.h>
 #include <maxpath.h>
+#include <stdc.h>
 
-static int mindist (), spdist ();
+static int mindist __P((char *, char *, char *));
+static int spdist __P((char *, char *));
 
 /*
  * `spname' and its helpers are inspired by the code in "The UNIX
diff --git a/lib/sh/strftime.c b/lib/sh/strftime.c
new file mode 100644 (file)
index 0000000..253d1df
--- /dev/null
@@ -0,0 +1,859 @@
+/*
+ * Modified slightly by Chet Ramey for inclusion in Bash
+ */
+
+/*
+ * strftime.c
+ *
+ * Public-domain implementation of ISO C library routine.
+ *
+ * If you can't do prototypes, get GCC.
+ *
+ * The C99 standard now specifies just about all of the formats
+ * that were additional in the earlier versions of this file.
+ *
+ * For extensions from SunOS, add SUNOS_EXT.
+ * For extensions from HP/UX, add HPUX_EXT.
+ * For VMS dates, add VMS_EXT.
+ * For complete POSIX semantics, add POSIX_SEMANTICS.
+ *
+ * The code for %c, %x, and %X follows the C99 specification for
+ * the "C" locale.
+ *
+ * This version ignores LOCALE information.
+ * It also doesn't worry about multi-byte characters.
+ * So there.
+ *
+ * This file is also shipped with GAWK (GNU Awk), gawk specific bits of
+ * code are included if GAWK is defined.
+ *
+ * Arnold Robbins
+ * January, February, March, 1991
+ * Updated March, April 1992
+ * Updated April, 1993
+ * Updated February, 1994
+ * Updated May, 1994
+ * Updated January, 1995
+ * Updated September, 1995
+ * Updated January, 1996
+ * Updated July, 1997
+ * Updated October, 1999
+ * Updated September, 2000
+ *
+ * Fixes from ado@elsie.nci.nih.gov,
+ * February 1991, May 1992
+ * Fixes from Tor Lillqvist tml@tik.vtt.fi,
+ * May 1993
+ * Further fixes from ado@elsie.nci.nih.gov,
+ * February 1994
+ * %z code from chip@chinacat.unicom.com,
+ * Applied September 1995
+ * %V code fixed (again) and %G, %g added,
+ * January 1996
+ * %v code fixed, better configuration,
+ * July 1997
+ * Moved to C99 specification.
+ * September 2000
+ */
+#include <config.h>
+
+#ifndef GAWK
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+#endif
+#if defined(TM_IN_SYS_TIME)
+#include <sys/types.h>
+#include <sys/time.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+/* defaults: season to taste */
+#define SUNOS_EXT      1       /* stuff in SunOS strftime routine */
+#define VMS_EXT                1       /* include %v for VMS date format */
+#define HPUX_EXT       1       /* non-conflicting stuff in HP-UX date */
+#ifndef GAWK
+#define POSIX_SEMANTICS        1       /* call tzset() if TZ changes */
+#endif
+
+#undef strchr  /* avoid AIX weirdness */
+
+extern void tzset(void);
+static int weeknumber(const struct tm *timeptr, int firstweekday);
+static int iso8601wknum(const struct tm *timeptr);
+
+#ifdef __GNUC__
+#define inline __inline__
+#else
+#define inline /**/
+#endif
+
+#define range(low, item, hi)   max(low, min(item, hi))
+
+#if !defined(OS2) && !defined(MSDOS) && defined(HAVE_TZNAME)
+extern char *tzname[2];
+extern int daylight;
+#if defined(SOLARIS) || defined(mips)
+extern long int timezone, altzone;
+#else
+extern int timezone, altzone;
+#endif
+#endif
+
+#undef min     /* just in case */
+
+/* min --- return minimum of two numbers */
+
+static inline int
+min(int a, int b)
+{
+       return (a < b ? a : b);
+}
+
+#undef max     /* also, just in case */
+
+/* max --- return maximum of two numbers */
+
+static inline int
+max(int a, int b)
+{
+       return (a > b ? a : b);
+}
+
+/* strftime --- produce formatted time */
+
+size_t
+strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
+{
+       char *endp = s + maxsize;
+       char *start = s;
+       auto char tbuf[100];
+       long off;
+       int i, w, y;
+       static short first = 1;
+#ifdef POSIX_SEMANTICS
+       static char *savetz = NULL;
+       static int savetzlen = 0;
+       char *tz;
+#endif /* POSIX_SEMANTICS */
+#ifndef HAVE_TM_ZONE
+#ifndef HAVE_TM_NAME
+#ifndef HAVE_TZNAME
+       extern char *timezone();
+       struct timeval tv;
+       struct timezone zone;
+#endif /* HAVE_TZNAME */
+#endif /* HAVE_TM_NAME */
+#endif /* HAVE_TM_ZONE */
+
+       /* various tables, useful in North America */
+       static const char *days_a[] = {
+               "Sun", "Mon", "Tue", "Wed",
+               "Thu", "Fri", "Sat",
+       };
+       static const char *days_l[] = {
+               "Sunday", "Monday", "Tuesday", "Wednesday",
+               "Thursday", "Friday", "Saturday",
+       };
+       static const char *months_a[] = {
+               "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+       };
+       static const char *months_l[] = {
+               "January", "February", "March", "April",
+               "May", "June", "July", "August", "September",
+               "October", "November", "December",
+       };
+       static const char *ampm[] = { "AM", "PM", };
+
+       if (s == NULL || format == NULL || timeptr == NULL || maxsize == 0)
+               return 0;
+
+       /* quick check if we even need to bother */
+       if (strchr(format, '%') == NULL && strlen(format) + 1 >= maxsize)
+               return 0;
+
+#ifndef POSIX_SEMANTICS
+       if (first) {
+               tzset();
+               first = 0;
+       }
+#else  /* POSIX_SEMANTICS */
+#if defined (SHELL)
+       tz = get_string_value ("TZ");
+#else
+       tz = getenv("TZ");
+#endif
+       if (first) {
+               if (tz != NULL) {
+                       int tzlen = strlen(tz);
+
+                       savetz = (char *) malloc(tzlen + 1);
+                       if (savetz != NULL) {
+                               savetzlen = tzlen + 1;
+                               strcpy(savetz, tz);
+                       }
+               }
+               tzset();
+               first = 0;
+       }
+       /* if we have a saved TZ, and it is different, recapture and reset */
+       if (tz && savetz && (tz[0] != savetz[0] || strcmp(tz, savetz) != 0)) {
+               i = strlen(tz) + 1;
+               if (i > savetzlen) {
+                       savetz = (char *) realloc(savetz, i);
+                       if (savetz) {
+                               savetzlen = i;
+                               strcpy(savetz, tz);
+                       }
+               } else
+                       strcpy(savetz, tz);
+               tzset();
+       }
+#endif /* POSIX_SEMANTICS */
+
+       for (; *format && s < endp - 1; format++) {
+               tbuf[0] = '\0';
+               if (*format != '%') {
+                       *s++ = *format;
+                       continue;
+               }
+       again:
+               switch (*++format) {
+               case '\0':
+                       *s++ = '%';
+                       goto out;
+
+               case '%':
+                       *s++ = '%';
+                       continue;
+
+               case 'a':       /* abbreviated weekday name */
+                       if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6)
+                               strcpy(tbuf, "?");
+                       else
+                               strcpy(tbuf, days_a[timeptr->tm_wday]);
+                       break;
+
+               case 'A':       /* full weekday name */
+                       if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6)
+                               strcpy(tbuf, "?");
+                       else
+                               strcpy(tbuf, days_l[timeptr->tm_wday]);
+                       break;
+
+               case 'b':       /* abbreviated month name */
+               short_month:
+                       if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)
+                               strcpy(tbuf, "?");
+                       else
+                               strcpy(tbuf, months_a[timeptr->tm_mon]);
+                       break;
+
+               case 'B':       /* full month name */
+                       if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)
+                               strcpy(tbuf, "?");
+                       else
+                               strcpy(tbuf, months_l[timeptr->tm_mon]);
+                       break;
+
+               case 'c':       /* appropriate date and time representation */
+                       /*
+                        * This used to be:
+                        *
+                        * strftime(tbuf, sizeof tbuf, "%a %b %e %H:%M:%S %Y", timeptr);
+                        *
+                        * Now, per the ISO 1999 C standard, it this:
+                        */
+                       strftime(tbuf, sizeof tbuf, "%A %B %d %T %Y", timeptr);
+                       break;
+
+               case 'C':
+               century:
+                       sprintf(tbuf, "%02d", (timeptr->tm_year + 1900) / 100);
+                       break;
+
+               case 'd':       /* day of the month, 01 - 31 */
+                       i = range(1, timeptr->tm_mday, 31);
+                       sprintf(tbuf, "%02d", i);
+                       break;
+
+               case 'D':       /* date as %m/%d/%y */
+                       strftime(tbuf, sizeof tbuf, "%m/%d/%y", timeptr);
+                       break;
+
+               case 'e':       /* day of month, blank padded */
+                       sprintf(tbuf, "%2d", range(1, timeptr->tm_mday, 31));
+                       break;
+
+               case 'E':
+                       /* POSIX (now C99) locale extensions, ignored for now */
+                       goto again;
+
+               case 'F':       /* ISO 8601 date representation */
+                       strftime(tbuf, sizeof tbuf, "%Y-%m-%d", timeptr);
+                       break;
+
+               case 'g':
+               case 'G':
+                       /*
+                        * Year of ISO week.
+                        *
+                        * If it's December but the ISO week number is one,
+                        * that week is in next year.
+                        * If it's January but the ISO week number is 52 or
+                        * 53, that week is in last year.
+                        * Otherwise, it's this year.
+                        */
+                       w = iso8601wknum(timeptr);
+                       if (timeptr->tm_mon == 11 && w == 1)
+                               y = 1900 + timeptr->tm_year + 1;
+                       else if (timeptr->tm_mon == 0 && w >= 52)
+                               y = 1900 + timeptr->tm_year - 1;
+                       else
+                               y = 1900 + timeptr->tm_year;
+
+                       if (*format == 'G')
+                               sprintf(tbuf, "%d", y);
+                       else
+                               sprintf(tbuf, "%02d", y % 100);
+                       break;
+
+               case 'h':       /* abbreviated month name */
+                       goto short_month;
+
+               case 'H':       /* hour, 24-hour clock, 00 - 23 */
+                       i = range(0, timeptr->tm_hour, 23);
+                       sprintf(tbuf, "%02d", i);
+                       break;
+
+               case 'I':       /* hour, 12-hour clock, 01 - 12 */
+                       i = range(0, timeptr->tm_hour, 23);
+                       if (i == 0)
+                               i = 12;
+                       else if (i > 12)
+                               i -= 12;
+                       sprintf(tbuf, "%02d", i);
+                       break;
+
+               case 'j':       /* day of the year, 001 - 366 */
+                       sprintf(tbuf, "%03d", timeptr->tm_yday + 1);
+                       break;
+
+               case 'm':       /* month, 01 - 12 */
+                       i = range(0, timeptr->tm_mon, 11);
+                       sprintf(tbuf, "%02d", i + 1);
+                       break;
+
+               case 'M':       /* minute, 00 - 59 */
+                       i = range(0, timeptr->tm_min, 59);
+                       sprintf(tbuf, "%02d", i);
+                       break;
+
+               case 'n':       /* same as \n */
+                       tbuf[0] = '\n';
+                       tbuf[1] = '\0';
+                       break;
+
+               case 'O':
+                       /* POSIX (now C99) locale extensions, ignored for now */
+                       goto again;
+
+               case 'p':       /* am or pm based on 12-hour clock */
+                       i = range(0, timeptr->tm_hour, 23);
+                       if (i < 12)
+                               strcpy(tbuf, ampm[0]);
+                       else
+                               strcpy(tbuf, ampm[1]);
+                       break;
+
+               case 'r':       /* time as %I:%M:%S %p */
+                       strftime(tbuf, sizeof tbuf, "%I:%M:%S %p", timeptr);
+                       break;
+
+               case 'R':       /* time as %H:%M */
+                       strftime(tbuf, sizeof tbuf, "%H:%M", timeptr);
+                       break;
+
+#if defined(HAVE_MKTIME) || defined(GAWK)
+               case 's':       /* time as seconds since the Epoch */
+               {
+                       struct tm non_const_timeptr;
+
+                       non_const_timeptr = *timeptr;
+                       sprintf(tbuf, "%ld", mktime(& non_const_timeptr));
+                       break;
+               }
+#endif /* defined(HAVE_MKTIME) || defined(GAWK) */
+
+               case 'S':       /* second, 00 - 60 */
+                       i = range(0, timeptr->tm_sec, 60);
+                       sprintf(tbuf, "%02d", i);
+                       break;
+
+               case 't':       /* same as \t */
+                       tbuf[0] = '\t';
+                       tbuf[1] = '\0';
+                       break;
+
+               case 'T':       /* time as %H:%M:%S */
+               the_time:
+                       strftime(tbuf, sizeof tbuf, "%H:%M:%S", timeptr);
+                       break;
+
+               case 'u':
+               /* ISO 8601: Weekday as a decimal number [1 (Monday) - 7] */
+                       sprintf(tbuf, "%d", timeptr->tm_wday == 0 ? 7 :
+                                       timeptr->tm_wday);
+                       break;
+
+               case 'U':       /* week of year, Sunday is first day of week */
+                       sprintf(tbuf, "%02d", weeknumber(timeptr, 0));
+                       break;
+
+               case 'V':       /* week of year according ISO 8601 */
+                       sprintf(tbuf, "%02d", iso8601wknum(timeptr));
+                       break;
+
+               case 'w':       /* weekday, Sunday == 0, 0 - 6 */
+                       i = range(0, timeptr->tm_wday, 6);
+                       sprintf(tbuf, "%d", i);
+                       break;
+
+               case 'W':       /* week of year, Monday is first day of week */
+                       sprintf(tbuf, "%02d", weeknumber(timeptr, 1));
+                       break;
+
+               case 'x':       /* appropriate date representation */
+                       strftime(tbuf, sizeof tbuf, "%A %B %d %Y", timeptr);
+                       break;
+
+               case 'X':       /* appropriate time representation */
+                       goto the_time;
+                       break;
+
+               case 'y':       /* year without a century, 00 - 99 */
+               year:
+                       i = timeptr->tm_year % 100;
+                       sprintf(tbuf, "%02d", i);
+                       break;
+
+               case 'Y':       /* year with century */
+               fullyear:
+                       sprintf(tbuf, "%d", 1900 + timeptr->tm_year);
+                       break;
+
+               /*
+                * From: Chip Rosenthal <chip@chinacat.unicom.com>
+                * Date: Sun, 19 Mar 1995 00:33:29 -0600 (CST)
+                * 
+                * Warning: the %z [code] is implemented by inspecting the
+                * timezone name conditional compile settings, and
+                * inferring a method to get timezone offsets. I've tried
+                * this code on a couple of machines, but I don't doubt
+                * there is some system out there that won't like it.
+                * Maybe the easiest thing to do would be to bracket this
+                * with an #ifdef that can turn it off. The %z feature
+                * would be an admittedly obscure one that most folks can
+                * live without, but it would be a great help to those of
+                * us that muck around with various message processors.
+                */
+               case 'z':       /* time zone offset east of GMT e.g. -0600 */
+#ifdef HAVE_TM_NAME
+                       /*
+                        * Systems with tm_name probably have tm_tzadj as
+                        * secs west of GMT.  Convert to mins east of GMT.
+                        */
+                       off = -timeptr->tm_tzadj / 60;
+#else /* !HAVE_TM_NAME */
+#ifdef HAVE_TM_ZONE
+                       /*
+                        * Systems with tm_zone probably have tm_gmtoff as
+                        * secs east of GMT.  Convert to mins east of GMT.
+                        */
+                       off = timeptr->tm_gmtoff / 60;
+#else /* !HAVE_TM_ZONE */
+#if HAVE_TZNAME
+                       /*
+                        * Systems with tzname[] probably have timezone as
+                        * secs west of GMT.  Convert to mins east of GMT.
+                        */
+                       off = -(daylight ? timezone : altzone) / 60;
+#else /* !HAVE_TZNAME */
+                       off = -zone.tz_minuteswest;
+#endif /* !HAVE_TZNAME */
+#endif /* !HAVE_TM_ZONE */
+#endif /* !HAVE_TM_NAME */
+                       if (off < 0) {
+                               tbuf[0] = '-';
+                               off = -off;
+                       } else {
+                               tbuf[0] = '+';
+                       }
+                       sprintf(tbuf+1, "%02d%02d", off/60, off%60);
+                       break;
+
+               case 'Z':       /* time zone name or abbrevation */
+#ifdef HAVE_TZNAME
+                       i = (daylight && timeptr->tm_isdst > 0); /* 0 or 1 */
+                       strcpy(tbuf, tzname[i]);
+#else
+#ifdef HAVE_TM_ZONE
+                       strcpy(tbuf, timeptr->tm_zone);
+#else
+#ifdef HAVE_TM_NAME
+                       strcpy(tbuf, timeptr->tm_name);
+#else
+                       gettimeofday(& tv, & zone);
+                       strcpy(tbuf, timezone(zone.tz_minuteswest,
+                                               timeptr->tm_isdst > 0));
+#endif /* HAVE_TM_NAME */
+#endif /* HAVE_TM_ZONE */
+#endif /* HAVE_TZNAME */
+                       break;
+
+#ifdef SUNOS_EXT
+               case 'k':       /* hour, 24-hour clock, blank pad */
+                       sprintf(tbuf, "%2d", range(0, timeptr->tm_hour, 23));
+                       break;
+
+               case 'l':       /* hour, 12-hour clock, 1 - 12, blank pad */
+                       i = range(0, timeptr->tm_hour, 23);
+                       if (i == 0)
+                               i = 12;
+                       else if (i > 12)
+                               i -= 12;
+                       sprintf(tbuf, "%2d", i);
+                       break;
+#endif
+
+#ifdef HPUX_EXT
+               case 'N':       /* Emperor/Era name */
+                       /* this is essentially the same as the century */
+                       goto century;   /* %C */
+
+               case 'o':       /* Emperor/Era year */
+                       goto year;      /* %y */
+#endif /* HPUX_EXT */
+
+
+#ifdef VMS_EXT
+               case 'v':       /* date as dd-bbb-YYYY */
+                       sprintf(tbuf, "%2d-%3.3s-%4d",
+                               range(1, timeptr->tm_mday, 31),
+                               months_a[range(0, timeptr->tm_mon, 11)],
+                               timeptr->tm_year + 1900);
+                       for (i = 3; i < 6; i++)
+                               if (islower(tbuf[i]))
+                                       tbuf[i] = toupper(tbuf[i]);
+                       break;
+#endif
+
+               default:
+                       tbuf[0] = '%';
+                       tbuf[1] = *format;
+                       tbuf[2] = '\0';
+                       break;
+               }
+               i = strlen(tbuf);
+               if (i) {
+                       if (s + i < endp - 1) {
+                               strcpy(s, tbuf);
+                               s += i;
+                       } else
+                               return 0;
+               }
+       }
+out:
+       if (s < endp && *format == '\0') {
+               *s = '\0';
+               return (s - start);
+       } else
+               return 0;
+}
+
+/* isleap --- is a year a leap year? */
+
+static int
+isleap(int year)
+{
+       return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
+}
+
+
+/* iso8601wknum --- compute week number according to ISO 8601 */
+
+static int
+iso8601wknum(const struct tm *timeptr)
+{
+       /*
+        * From 1003.2:
+        *      If the week (Monday to Sunday) containing January 1
+        *      has four or more days in the new year, then it is week 1;
+        *      otherwise it is the highest numbered week of the previous
+        *      year (52 or 53), and the next week is week 1.
+        *
+        * ADR: This means if Jan 1 was Monday through Thursday,
+        *      it was week 1, otherwise week 52 or 53.
+        *
+        * XPG4 erroneously included POSIX.2 rationale text in the
+        * main body of the standard. Thus it requires week 53.
+        */
+
+       int weeknum, jan1day, diff;
+
+       /* get week number, Monday as first day of the week */
+       weeknum = weeknumber(timeptr, 1);
+
+       /*
+        * With thanks and tip of the hatlo to tml@tik.vtt.fi
+        *
+        * What day of the week does January 1 fall on?
+        * We know that
+        *      (timeptr->tm_yday - jan1.tm_yday) MOD 7 ==
+        *              (timeptr->tm_wday - jan1.tm_wday) MOD 7
+        * and that
+        *      jan1.tm_yday == 0
+        * and that
+        *      timeptr->tm_wday MOD 7 == timeptr->tm_wday
+        * from which it follows that. . .
+        */
+       jan1day = timeptr->tm_wday - (timeptr->tm_yday % 7);
+       if (jan1day < 0)
+               jan1day += 7;
+
+       /*
+        * If Jan 1 was a Monday through Thursday, it was in
+        * week 1.  Otherwise it was last year's highest week, which is
+        * this year's week 0.
+        *
+        * What does that mean?
+        * If Jan 1 was Monday, the week number is exactly right, it can
+        *      never be 0.
+        * If it was Tuesday through Thursday, the weeknumber is one
+        *      less than it should be, so we add one.
+        * Otherwise, Friday, Saturday or Sunday, the week number is
+        * OK, but if it is 0, it needs to be 52 or 53.
+        */
+       switch (jan1day) {
+       case 1:         /* Monday */
+               break;
+       case 2:         /* Tuesday */
+       case 3:         /* Wednesday */
+       case 4:         /* Thursday */
+               weeknum++;
+               break;
+       case 5:         /* Friday */
+       case 6:         /* Saturday */
+       case 0:         /* Sunday */
+               if (weeknum == 0) {
+#ifdef USE_BROKEN_XPG4
+                       /* XPG4 (as of March 1994) says 53 unconditionally */
+                       weeknum = 53;
+#else
+                       /* get week number of last week of last year */
+                       struct tm dec31ly;      /* 12/31 last year */
+                       dec31ly = *timeptr;
+                       dec31ly.tm_year--;
+                       dec31ly.tm_mon = 11;
+                       dec31ly.tm_mday = 31;
+                       dec31ly.tm_wday = (jan1day == 0) ? 6 : jan1day - 1;
+                       dec31ly.tm_yday = 364 + isleap(dec31ly.tm_year + 1900);
+                       weeknum = iso8601wknum(& dec31ly);
+#endif
+               }
+               break;
+       }
+
+       if (timeptr->tm_mon == 11) {
+               /*
+                * The last week of the year
+                * can be in week 1 of next year.
+                * Sigh.
+                *
+                * This can only happen if
+                *      M   T  W
+                *      29  30 31
+                *      30  31
+                *      31
+                */
+               int wday, mday;
+
+               wday = timeptr->tm_wday;
+               mday = timeptr->tm_mday;
+               if (   (wday == 1 && (mday >= 29 && mday <= 31))
+                   || (wday == 2 && (mday == 30 || mday == 31))
+                   || (wday == 3 &&  mday == 31))
+                       weeknum = 1;
+       }
+
+       return weeknum;
+}
+
+/* weeknumber --- figure how many weeks into the year */
+
+/* With thanks and tip of the hatlo to ado@elsie.nci.nih.gov */
+
+static int
+weeknumber(const struct tm *timeptr, int firstweekday)
+{
+       int wday = timeptr->tm_wday;
+       int ret;
+
+       if (firstweekday == 1) {
+               if (wday == 0)  /* sunday */
+                       wday = 6;
+               else
+                       wday--;
+       }
+       ret = ((timeptr->tm_yday + 7 - wday) / 7);
+       if (ret < 0)
+               ret = 0;
+       return ret;
+}
+
+#if 0
+/* ADR --- I'm loathe to mess with ado's code ... */
+
+Date:         Wed, 24 Apr 91 20:54:08 MDT
+From: Michal Jaegermann <audfax!emory!vm.ucs.UAlberta.CA!NTOMCZAK>
+To: arnold@audiofax.com
+
+Hi Arnold,
+in a process of fixing of strftime() in libraries on Atari ST I grabbed
+some pieces of code from your own strftime.  When doing that it came
+to mind that your weeknumber() function compiles a little bit nicer
+in the following form:
+/*
+ * firstweekday is 0 if starting in Sunday, non-zero if in Monday
+ */
+{
+    return (timeptr->tm_yday - timeptr->tm_wday +
+           (firstweekday ? (timeptr->tm_wday ? 8 : 1) : 7)) / 7;
+}
+How nicer it depends on a compiler, of course, but always a tiny bit.
+
+   Cheers,
+   Michal
+   ntomczak@vm.ucs.ualberta.ca
+#endif
+
+#ifdef TEST_STRFTIME
+
+/*
+ * NAME:
+ *     tst
+ *
+ * SYNOPSIS:
+ *     tst
+ *
+ * DESCRIPTION:
+ *     "tst" is a test driver for the function "strftime".
+ *
+ * OPTIONS:
+ *     None.
+ *
+ * AUTHOR:
+ *     Karl Vogel
+ *     Control Data Systems, Inc.
+ *     vogelke@c-17igp.wpafb.af.mil
+ *
+ * BUGS:
+ *     None noticed yet.
+ *
+ * COMPILE:
+ *     cc -o tst -DTEST_STRFTIME strftime.c
+ */
+
+/* ADR: I reformatted this to my liking, and deleted some unneeded code. */
+
+#ifndef NULL
+#include       <stdio.h>
+#endif
+#include       <sys/time.h>
+#include       <string.h>
+
+#define                MAXTIME         132
+
+/*
+ * Array of time formats.
+ */
+
+static char *array[] =
+{
+       "(%%A)      full weekday name, var length (Sunday..Saturday)  %A",
+       "(%%B)       full month name, var length (January..December)  %B",
+       "(%%C)                                               Century  %C",
+       "(%%D)                                       date (%%m/%%d/%%y)  %D",
+       "(%%E)                           Locale extensions (ignored)  %E",
+       "(%%F)       full month name, var length (January..December)  %F",
+       "(%%H)                          hour (24-hour clock, 00..23)  %H",
+       "(%%I)                          hour (12-hour clock, 01..12)  %I",
+       "(%%M)                                       minute (00..59)  %M",
+       "(%%N)                                      Emporer/Era Name  %N",
+       "(%%O)                           Locale extensions (ignored)  %O",
+       "(%%R)                                 time, 24-hour (%%H:%%M)  %R",
+       "(%%S)                                       second (00..60)  %S",
+       "(%%T)                              time, 24-hour (%%H:%%M:%%S)  %T",
+       "(%%U)    week of year, Sunday as first day of week (00..53)  %U",
+       "(%%V)                    week of year according to ISO 8601  %V",
+       "(%%W)    week of year, Monday as first day of week (00..53)  %W",
+       "(%%X)     appropriate locale time representation (%H:%M:%S)  %X",
+       "(%%Y)                           year with century (1970...)  %Y",
+       "(%%Z) timezone (EDT), or blank if timezone not determinable  %Z",
+       "(%%a)          locale's abbreviated weekday name (Sun..Sat)  %a",
+       "(%%b)            locale's abbreviated month name (Jan..Dec)  %b",
+       "(%%c)           full date (Sat Nov  4 12:02:33 1989)%n%t%t%t  %c",
+       "(%%d)                             day of the month (01..31)  %d",
+       "(%%e)               day of the month, blank-padded ( 1..31)  %e",
+       "(%%h)                                should be same as (%%b)  %h",
+       "(%%j)                            day of the year (001..366)  %j",
+       "(%%k)               hour, 24-hour clock, blank pad ( 0..23)  %k",
+       "(%%l)               hour, 12-hour clock, blank pad ( 0..12)  %l",
+       "(%%m)                                        month (01..12)  %m",
+       "(%%o)                                      Emporer/Era Year  %o",
+       "(%%p)              locale's AM or PM based on 12-hour clock  %p",
+       "(%%r)                   time, 12-hour (same as %%I:%%M:%%S %%p)  %r",
+       "(%%u) ISO 8601: Weekday as decimal number [1 (Monday) - 7]   %u",
+       "(%%v)                                VMS date (dd-bbb-YYYY)  %v",
+       "(%%w)                       day of week (0..6, Sunday == 0)  %w",
+       "(%%x)                appropriate locale date representation  %x",
+       "(%%y)                      last two digits of year (00..99)  %y",
+       "(%%z)      timezone offset east of GMT as HHMM (e.g. -0500)  %z",
+       (char *) NULL
+};
+
+/* main routine. */
+
+int
+main(argc, argv)
+int argc;
+char **argv;
+{
+       long time();
+
+       char *next;
+       char string[MAXTIME];
+
+       int k;
+       int length;
+
+       struct tm *tm;
+
+       long clock;
+
+       /* Call the function. */
+
+       clock = time((long *) 0);
+       tm = localtime(&clock);
+
+       for (k = 0; next = array[k]; k++) {
+               length = strftime(string, MAXTIME, next, tm);
+               printf("%s\n", string);
+       }
+
+       exit(0);
+}
+#endif /* TEST_STRFTIME */
index 29937d322db055334d4a7be00b00c1842023e28b..efc6fa57f93a160542d2a025784c565baf013f57 100644 (file)
@@ -1,6 +1,6 @@
 /* stringlist.c - functions to handle a generic `list of strings' structure */
 
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -37,7 +37,7 @@
 /* Allocate a new STRINGLIST, with room for N strings. */
 
 STRINGLIST *
-alloc_stringlist (n)
+strlist_create (n)
      int n;
 {
   STRINGLIST *ret;
@@ -46,7 +46,7 @@ alloc_stringlist (n)
   ret = (STRINGLIST *)xmalloc (sizeof (STRINGLIST));
   if (n)
     {
-      ret->list = alloc_array (n+1);
+      ret->list = strvec_create (n+1);
       ret->list_size = n;
       for (i = 0; i < n; i++)
        ret->list[i] = (char *)NULL;
@@ -61,38 +61,64 @@ alloc_stringlist (n)
 }
 
 STRINGLIST *
-realloc_stringlist (sl, n)
+strlist_resize (sl, n)
      STRINGLIST *sl;
      int n;
 {
   register int i;
 
   if (sl == 0)
-    return (sl = alloc_stringlist(n));
+    return (sl = strlist_create (n));
 
   if (n > sl->list_size)
     {
-      sl->list = (char **)xrealloc (sl->list, (n+1) * sizeof (char *));
+      sl->list = strvec_resize (sl->list, n + 1);
       for (i = sl->list_size; i <= n; i++)
        sl->list[i] = (char *)NULL;
       sl->list_size = n;
     }
   return sl;
 }
+
+void
+strlist_flush (sl)
+     STRINGLIST *sl;
+{
+  if (sl == 0 || sl->list == 0)
+    return;
+  strvec_flush (sl->list);
+  sl->list_len = 0;
+}
   
 void
-free_stringlist (sl)
+strlist_dispose (sl)
      STRINGLIST *sl;
 {
   if (sl == 0)
     return;
   if (sl->list)
-    free_array (sl->list);
+    strvec_dispose (sl->list);
   free (sl);
 }
 
+int
+strlist_remove (sl, s)
+     STRINGLIST *sl;
+     char *s;
+{
+  int r;
+
+  if (sl == 0 || sl->list == 0 || sl->list_len == 0)
+    return 0;
+
+  r = strvec_remove (sl->list, s);
+  if (r)
+    sl->list_len--;
+  return r;
+}
+
 STRINGLIST *
-copy_stringlist (sl)
+strlist_copy (sl)
      STRINGLIST *sl;
 {
   STRINGLIST *new;
@@ -100,8 +126,8 @@ copy_stringlist (sl)
 
   if (sl == 0)
     return ((STRINGLIST *)0);
-  new = alloc_stringlist (sl->list_size);
-  /* I'd like to use copy_array, but that doesn't copy everything. */
+  new = strlist_create (sl->list_size);
+  /* I'd like to use strvec_copy, but that doesn't copy everything. */
   if (sl->list)
     {
       for (i = 0; i < sl->list_size; i++)
@@ -118,7 +144,7 @@ copy_stringlist (sl)
 /* Return a new STRINGLIST with everything from M1 and M2. */
 
 STRINGLIST *
-merge_stringlists (m1, m2)
+strlist_merge (m1, m2)
      STRINGLIST *m1, *m2;
 {
   STRINGLIST *sl;
@@ -127,7 +153,7 @@ merge_stringlists (m1, m2)
   l1 = m1 ? m1->list_len : 0;
   l2 = m2 ? m2->list_len : 0;
 
-  sl = alloc_stringlist (l1 + l2 + 1);
+  sl = strlist_create (l1 + l2 + 1);
   for (i = n = 0; i < l1; i++, n++)
     sl->list[n] = STRDUP (m1->list[i]);
   for (i = 0; i < l2; i++, n++)
@@ -139,20 +165,20 @@ merge_stringlists (m1, m2)
 
 /* Make STRINGLIST M1 contain everything in M1 and M2. */
 STRINGLIST *
-append_stringlist (m1, m2)
+strlist_append (m1, m2)
      STRINGLIST *m1, *m2;
 {
   register int i, n, len1, len2;
 
   if (m1 == 0)
-    return (m2 ? copy_stringlist (m2) : (STRINGLIST *)0);
+    return (m2 ? strlist_copy (m2) : (STRINGLIST *)0);
 
   len1 = m1->list_len;
   len2 = m2 ? m2->list_len : 0;
 
   if (len2)
     {
-      m1 = realloc_stringlist (m1, len1 + len2 + 1);
+      m1 = strlist_resize (m1, len1 + len2 + 1);
       for (i = 0, n = len1; i < len2; i++, n++)
        m1->list[n] = STRDUP (m2->list[i]);
       m1->list[n] = (char *)NULL;
@@ -163,7 +189,7 @@ append_stringlist (m1, m2)
 }
 
 STRINGLIST *
-prefix_suffix_stringlist (sl, prefix, suffix)
+strlist_prefix_suffix (sl, prefix, suffix)
      STRINGLIST *sl;
      char *prefix, *suffix;
 {
@@ -197,7 +223,7 @@ prefix_suffix_stringlist (sl, prefix, suffix)
 }
    
 void
-print_stringlist (sl, prefix)
+strlist_print (sl, prefix)
      STRINGLIST *sl;
      char *prefix;
 {
@@ -210,18 +236,32 @@ print_stringlist (sl, prefix)
 }
 
 void
-sort_stringlist (sl)
+strlist_walk (sl, func)
+     STRINGLIST *sl;
+     sh_strlist_map_func_t *func;
+{
+  register int i;
+
+  if (sl == 0)
+    return;
+  for (i = 0; i < sl->list_len; i++)
+    if ((*func)(sl->list[i]) < 0)
+      break;
+} 
+     
+void
+strlist_sort (sl)
      STRINGLIST *sl;
 {
   if (sl == 0 || sl->list_len == 0 || sl->list == 0)
     return;
-  sort_char_array (sl->list);
+  strvec_sort (sl->list);
 }
 
 STRINGLIST *
-word_list_to_stringlist (list, copy, starting_index, ip)
+strlist_from_word_list (list, alloc, starting_index, ip)
      WORD_LIST *list;
-     int copy, starting_index, *ip;
+     int alloc, starting_index, *ip;
 {
   STRINGLIST *ret;
   int slen, len;
@@ -234,7 +274,7 @@ word_list_to_stringlist (list, copy, starting_index, ip)
     }
   slen = list_length (list);
   ret = (STRINGLIST *)xmalloc (sizeof (STRINGLIST));
-  ret->list = word_list_to_argv (list, copy, starting_index, &len);
+  ret->list = strvec_from_word_list (list, alloc, starting_index, &len);
   ret->list_size = slen + starting_index;
   ret->list_len = len;
   if (ip)
@@ -243,15 +283,15 @@ word_list_to_stringlist (list, copy, starting_index, ip)
 }
 
 WORD_LIST *
-stringlist_to_word_list (sl, copy, starting_index)
+strlist_to_word_list (sl, alloc, starting_index)
      STRINGLIST *sl;
-     int copy, starting_index;
+     int alloc, starting_index;
 {
   WORD_LIST *list;
 
   if (sl == 0 || sl->list == 0)
     return ((WORD_LIST *)NULL);
 
-  list = argv_to_word_list (sl->list, copy, starting_index);
+  list = strvec_to_word_list (sl->list, alloc, starting_index);
   return list;
 }
index fa16ad458bdf5ab0a6927b3071fcaadf92b1cf24..222fcd62e19f3515a4b423d3012cdd414ac488da 100644 (file)
@@ -1,6 +1,6 @@
-/* stringvec.c - function for managing arrays of strings. */
+/* stringvec.c - functions for managing arrays of strings. */
 
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 
 #include "shell.h"
 
-#ifdef INCLUDE_UNUSED
-/* Find NAME in ARRAY.  Return the index of NAME, or -1 if not present.
-   ARRAY should be NULL terminated. */
-int
-find_name_in_array (name, array)
-     char *name, **array;
-{
-  int i;
-
-  for (i = 0; array[i]; i++)
-    if (STREQ (name, array[i]))
-      return (i);
-
-  return (-1);
-}
-#endif
-
 /* Allocate an array of strings with room for N members. */
 char **
-alloc_array (n)
+strvec_create (n)
      int n;
 {
   return ((char **)xmalloc ((n) * sizeof (char *)));
 }
 
+char **
+strvec_resize (array, nsize)
+     char **array;
+     int nsize;
+{
+  return ((char **)xrealloc (array, nsize * sizeof (char *)));
+}
+
 /* Return the length of ARRAY, a NULL terminated array of char *. */
 int
-array_len (array)
+strvec_len (array)
      char **array;
 {
   register int i;
@@ -70,7 +61,7 @@ array_len (array)
 
 /* Free the contents of ARRAY, a NULL terminated array of char *. */
 void
-free_array_members (array)
+strvec_flush (array)
      char **array;
 {
   register int i;
@@ -83,26 +74,65 @@ free_array_members (array)
 }
 
 void
-free_array (array)
+strvec_dispose (array)
      char **array;
 {
   if (array == 0)
     return;
 
-  free_array_members (array);
+  strvec_flush (array);
   free (array);
 }
 
+int
+strvec_remove (array, name)
+     char **array, *name;
+{
+  register int i, j;
+  char *x;
+
+  if (array == 0)
+    return 0;
+
+  for (i = 0; array[i]; i++)
+    if (STREQ (name, array[i]))
+      {
+       x = array[i];
+       for (j = i; array[j]; j++)
+         array[j] = array[j + 1];
+       free (x);
+       return 1;
+      }
+  return 0;
+}
+
+#ifdef INCLUDE_UNUSED
+/* Find NAME in ARRAY.  Return the index of NAME, or -1 if not present.
+   ARRAY should be NULL terminated. */
+int
+strvec_search (array, name)
+     char **array, *name;
+{
+  int i;
+
+  for (i = 0; array[i]; i++)
+    if (STREQ (name, array[i]))
+      return (i);
+
+  return (-1);
+}
+#endif
+
 /* Allocate and return a new copy of ARRAY and its contents. */
 char **
-copy_array (array)
+strvec_copy (array)
      char **array;
 {
   register int i;
   int len;
   char **ret;
 
-  len = array_len (array);
+  len = strvec_len (array);
 
   ret = (char **)xmalloc ((len + 1) * sizeof (char *));
   for (i = 0; array[i]; i++)
@@ -115,7 +145,7 @@ copy_array (array)
 /* Comparison routine for use with qsort() on arrays of strings.  Uses
    strcoll(3) if available, otherwise it uses strcmp(3). */
 int
-qsort_string_compare (s1, s2)
+strvec_strcmp (s1, s2)
      register char **s1, **s2;
 {
 #if defined (HAVE_STRCOLL)
@@ -132,8 +162,71 @@ qsort_string_compare (s1, s2)
 
 /* Sort ARRAY, a null terminated array of pointers to strings. */
 void
-sort_char_array (array)
+strvec_sort (array)
+     char **array;
+{
+  qsort (array, strvec_len (array), sizeof (char *), (QSFUNC *)strvec_strcmp);
+}
+
+/* Cons up a new array of words.  The words are taken from LIST,
+   which is a WORD_LIST *.  If ALLOC is true, everything is malloc'ed,
+   so you should free everything in this array when you are done.
+   The array is NULL terminated.  If IP is non-null, it gets the
+   number of words in the returned array.  STARTING_INDEX says where
+   to start filling in the returned array; it can be used to reserve
+   space at the beginning of the array. */
+
+char **
+strvec_from_word_list (list, alloc, starting_index, ip)
+     WORD_LIST *list;
+     int alloc, starting_index, *ip;
+{
+  int count;
+  char **array;
+
+  count = list_length (list);
+  array = (char **)xmalloc ((1 + count + starting_index) * sizeof (char *));
+
+  for (count = 0; count < starting_index; count++)
+    array[count] = (char *)NULL;
+  for (count = starting_index; list; count++, list = list->next)
+    array[count] = alloc ? savestring (list->word->word) : list->word->word;
+  array[count] = (char *)NULL;
+
+  if (ip)
+    *ip = count;
+  return (array);
+}
+
+/* Convert an array of strings into the form used internally by the shell.
+   ALLOC means to allocate new storage for each WORD_DESC in the returned
+   list rather than copy the values in ARRAY.  STARTING_INDEX says where
+   in ARRAY to begin. */
+
+WORD_LIST *
+strvec_to_word_list (array, alloc, starting_index)
      char **array;
+     int alloc, starting_index;
 {
-  qsort (array, array_len (array), sizeof (char *), (QSFUNC *)qsort_string_compare);
+  WORD_LIST *list;
+  WORD_DESC *w;
+  int i, count;
+
+  if (array == 0 || array[0] == 0)
+    return (WORD_LIST *)NULL;
+
+  for (count = 0; array[count]; count++)
+    ;
+
+  for (i = starting_index, list = (WORD_LIST *)NULL; i < count; i++)
+    {
+      w = make_bare_word (alloc ? array[i] : "");
+      if (alloc == 0)
+       {
+         free (w->word);
+         w->word = array[i];
+       }
+      list = make_word_list (w, list);
+    }
+  return (REVERSE_LIST (list, WORD_LIST *));
 }
index 9192e62d99af029028cd163c0201dbd07d59d128..741927c667ef0a027d4ca35a65301f7589173350 100644 (file)
 /* Convert STRING by expanding the escape sequences specified by the
    ANSI C standard.  If SAWC is non-null, recognize `\c' and use that
    as a string terminator.  If we see \c, set *SAWC to 1 before
-   returning.  LEN is the length of STRING.  FOR_ECHO is a flag that
-   means, if non-zero, that we're translating a string for `echo -e',
-   and therefore should not treat a single quote as a character that
-   may be escaped with a backslash. */
+   returning.  LEN is the length of STRING.  If (FLAGS&1) is non-zero,
+   that we're translating a string for `echo -e', and therefore should not
+   treat a single quote as a character that may be escaped with a backslash.
+   If (FLAGS&2) is non-zero, we're expanding for the parser and want to
+   quote CTLESC and CTLNUL with CTLESC */
 char *
-ansicstr (string, len, for_echo, sawc, rlen)
+ansicstr (string, len, flags, sawc, rlen)
      char *string;
-     int len, for_echo, *sawc, *rlen;
+     int len, flags, *sawc, *rlen;
 {
   int c, temp;
   char *ret, *r, *s;
@@ -55,7 +56,7 @@ ansicstr (string, len, for_echo, sawc, rlen)
   if (string == 0 || *string == '\0')
     return ((char *)NULL);
 
-  ret = (char *)xmalloc (len + 1);
+  ret = (char *)xmalloc (2*len + 1);   /* 2*len for possible CTLESC */
   for (r = ret, s = string; s && *s; )
     {
       c = *s++;
@@ -81,7 +82,12 @@ ansicstr (string, len, for_echo, sawc, rlen)
            case 't': c = '\t'; break;
            case '0': case '1': case '2': case '3':
            case '4': case '5': case '6': case '7':
-             for (temp = 2, c -= '0'; ISOCTAL (*s) && temp--; s++)
+             /* If (FLAGS & 1), we're translating a string for echo -e (or
+                the equivalent xpg_echo option), so we obey the SUSv3/
+                POSIX-2001 requirement and accept 0-3 octal digits after
+                a leading `0'. */
+             temp = 2 + ((flags & 1) && (c == '0'));
+             for (c -= '0'; ISOCTAL (*s) && temp--; s++)
                c = (c * 8) + OCTVALUE (*s);
              c &= 0xFF;
              break;
@@ -99,7 +105,7 @@ ansicstr (string, len, for_echo, sawc, rlen)
            case '\\':
              break;
            case '\'':
-             if (for_echo)
+             if (flags & 1)
                *r++ = '\\';
              break;
            case 'c':
@@ -111,8 +117,17 @@ ansicstr (string, len, for_echo, sawc, rlen)
                    *rlen = r - ret;
                  return ret;
                }
+             else if ((flags & 1) == 0 && (c = *s))
+               {
+                 s++;
+                 c = TOCTRL(c);
+                 break;
+               }
+               /*FALLTHROUGH*/
            default:  *r++ = '\\'; break;
            }
+         if ((flags & 2) && (c == CTLESC || c == CTLNUL))
+           *r++ = CTLESC;
          *r++ = c;
        }
     }
@@ -129,7 +144,7 @@ ansic_quote (str, flags, rlen)
      char *str;
      int flags, *rlen;
 {
-  char *r, *ret, *s, obuf[8];
+  char *r, *ret, *s;
   int l, rsize, t;
   unsigned char c;
 
@@ -137,7 +152,7 @@ ansic_quote (str, flags, rlen)
     return ((char *)0);
 
   l = strlen (str);
-  rsize = 2 * l + 4;
+  rsize = 4 * l + 4;
   r = ret = (char *)xmalloc (rsize);
 
   *r++ = '$';
@@ -169,12 +184,10 @@ ansic_quote (str, flags, rlen)
        default:
          if (ISPRINT (c) == 0)
            {
-             sprintf (obuf, "\\%.3o", c);
-             t = r - ret;
-             RESIZE_MALLOCED_BUFFER (ret, t, 5, rsize, 16);
-             r = ret + t;      /* in case reallocated */
-             for (t = 0; t < 4; t++)
-               *r++ = obuf[t];
+             *r++ = '\\';
+             *r++ = TOCHAR ((c >> 6) & 07);
+             *r++ = TOCHAR ((c >> 3) & 07);
+             *r++ = TOCHAR (c & 07);
              continue;
            }
          l = 0;
@@ -193,6 +206,7 @@ ansic_quote (str, flags, rlen)
 }
 
 /* return 1 if we need to quote with $'...' because of non-printing chars. */
+int
 ansic_shouldquote (string)
      const char *string;
 {
@@ -208,3 +222,32 @@ ansic_shouldquote (string)
 
   return 0;
 }
+
+/* $'...' ANSI-C expand the portion of STRING between START and END and
+   return the result.  The result cannot be longer than the input string. */
+char *
+ansiexpand (string, start, end, lenp)
+     char *string;
+     int start, end, *lenp;
+{
+  char *temp, *t;
+  int len, tlen;
+
+  temp = (char *)xmalloc (end - start + 1);
+  for (tlen = 0, len = start; len < end; )
+    temp[tlen++] = string[len++];
+  temp[tlen] = '\0';
+
+  if (*temp)
+    {
+      t = ansicstr (temp, tlen, 2, (int *)NULL, lenp);
+      free (temp);
+      return (t);
+    }
+  else
+    {
+      if (lenp)
+       *lenp = 0;
+      return (temp);
+    }
+}
index d51ac2cff63c544ec2ab8913b3d70773b78df2b6..e28f94d052d0561676d393878c2faf13a180243d 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <bashtypes.h>
 #include <posixstat.h>
+#include <posixtime.h>
 #include <filecntl.h>
 
 #if defined (HAVE_UNISTD_H)
diff --git a/lib/sh/xstrchr.c b/lib/sh/xstrchr.c
new file mode 100644 (file)
index 0000000..3272837
--- /dev/null
@@ -0,0 +1,78 @@
+/* xstrchr.c - strchr(3) that handles multibyte characters. */
+
+/* Copyright (C) 2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#include <config.h>
+
+#ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+#endif
+
+#include "bashansi.h"
+#include "shmbutil.h"
+
+#undef xstrchr
+
+/* In some locales, the non-first byte of some multibyte characters have
+   the same value as some ascii character.  Faced with these strings, a
+   legacy strchr() might return the wrong value. */
+
+char *
+#if defined (PROTOTYPES)
+xstrchr (const char *s, int c)
+#else
+xstrchr (s, c)
+     const char *s;
+     int c;
+#endif
+{
+#if HANDLE_MULTIBYTE
+  char *pos;
+  mbstate_t state;
+  size_t strlength, mblength;
+
+  /* The locale encodings with said weird property are BIG5, BIG5-HKSCS,
+     GBK, GB18030, SHIFT_JIS, and JOHAB.  They exhibit the problem only
+     when c >= 0x30.  We can therefore use the faster bytewise search if
+     c <= 0x30. */
+  if ((unsigned char)c >= '0' && MB_CUR_MAX > 1)
+    {
+      pos = (char *)s;
+      memset (&state, '\0', sizeof(mbstate_t));
+      strlength = strlen (s);
+
+      while (strlength > 0)
+       {
+         mblength = mbrlen (pos, strlength, &state);
+         if (mblength == (size_t)-2 || mblength == (size_t)-1 || mblength == (size_t)0)
+           mblength = 1;
+
+         if (c == (unsigned char)*pos)
+           return pos;
+
+         strlength -= mblength;
+         pos += mblength;
+       }
+
+      return ((char *)NULL);
+    }
+  else
+#endif
+  return (strchr (s, c));
+}
diff --git a/lib/sh/zcatfd.c b/lib/sh/zcatfd.c
new file mode 100644 (file)
index 0000000..24020eb
--- /dev/null
@@ -0,0 +1,68 @@
+/* Copyright (C) 2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include <errno.h>
+
+#include <stdc.h>
+
+#if !defined (errno)
+extern int errno;
+#endif
+
+extern ssize_t zread __P((int, char *, size_t));
+extern int zwrite __P((int, char *, ssize_t));
+
+/* Dump contents of file descriptor FD to OFD.  FN is the filename for
+   error messages (not used right now). */
+int
+zcatfd (fd, ofd, fn)
+     int fd, ofd;
+     char *fn;
+{
+  ssize_t nr;
+  int rval;
+  char lbuf[128];
+
+  rval = 0;
+  while (1)
+    {
+      nr = zread (fd, lbuf, sizeof (lbuf));
+      if (nr == 0)
+       break;
+      else if (nr < 0)
+       {
+         rval = -1;
+         break;
+       }
+      else if (zwrite (ofd, lbuf, nr) < 0)
+       {
+         rval = -1;
+         break;
+       }
+    }
+
+  return rval;
+}
index 2cdfb4e258f16381b2a29a521c3894317f01679f..b5155488f1545b84a4019929a055223dfe3fe7bb 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -58,7 +58,7 @@ zread (fd, buf, len)
 #define NUM_INTR 3
 
 ssize_t
-zread1 (fd, buf, len)
+zreadintr (fd, buf, len)
      int fd;
      char *buf;
      size_t len;
index 39ffbb1e645c21060d99660290af49d0dbf556c1..cf1f9e62acf9afe0f74507de06c36035ee045e34 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
index be7d9e7560e240d9d58958e9fee012904595d368..ad2ab916fa6b7700d1fc0d91eeee186272bbf635 100644 (file)
@@ -1,2 +1,18 @@
+/* Copyright (C) 1985-2002 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; see the file COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 /* Make the library identifiable with the RCS ident command.  */
 static char *termcap_version_string = "\n$Version: GNU termcap 1.3 $\n";
index f53c5d75cf3402ed53443fc0b4475f4e085b5971..aa7bbf0788053ca023b34103d01185012053b593 100644 (file)
@@ -39,6 +39,8 @@ MV = mv
 
 SHELL = @MAKE_SHELL@
 
+PROFILE_FLAGS = @PROFILE_FLAGS@
+
 CFLAGS = @CFLAGS@
 LOCAL_CFLAGS = @LOCAL_CFLAGS@
 CPPFLAGS = @CPPFLAGS@
@@ -51,7 +53,8 @@ BASHINCDIR = ${topdir}/include
 
 INCLUDES = -I. -I../.. -I$(topdir) -I${BASHINCDIR} -I$(topdir)/lib
 
-CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(CPPFLAGS) ${INCLUDES} $(LOCAL_CFLAGS) $(CFLAGS)
+CCFLAGS = $(PROFILE_FLAGS) $(DEFS) $(LOCAL_DEFS) $(CPPFLAGS) \
+         ${INCLUDES} $(LOCAL_CFLAGS) $(CFLAGS)
 
 .c.o:
        $(CC) -c $(CCFLAGS) $<
index 6e4f116f7573dfd83f6bb440c2f41f2b6c87419b..154f7f8108d075569576990c9ee5c23be93b2950 100644 (file)
@@ -59,9 +59,6 @@ extern struct passwd *getpwnam PARAMS((const char *));
 #endif /* !HAVE_GETPW_DECLS */
 
 #if !defined (savestring)
-#  ifndef strcpy
-extern char *strcpy ();
-#  endif
 #define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x))
 #endif /* !savestring */
 
index 0df608b3458441c2899a49df570557f06de103b7..f8182c999d9b43c2b88cceb0f4142eb607b95154 100644 (file)
 #if !defined (_TILDE_H_)
 #  define _TILDE_H_
 
-#if defined (HAVE_CONFIG_H)
-#  include <config.h>
-#endif
-
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/list.c b/list.c
index e1fc9b449e3a6980cb35dbb544c38884b03caebb..bb7943a80c426fbd073c136a37ee0b6e34d36236 100644 (file)
--- a/list.c
+++ b/list.c
@@ -36,22 +36,24 @@ GENERIC_LIST global_error_list;
 #ifdef INCLUDE_UNUSED
 /* Call FUNCTION on every member of LIST, a generic list. */
 void
-map_over_list (list, function)
+list_walk (list, function)
      GENERIC_LIST *list;
      sh_glist_func_t *function;
 {
   for ( ; list; list = list->next)
-    (*function) (list);
+    if ((*function) (list) < 0)
+      return;
 }
 
 /* Call FUNCTION on every string in WORDS. */
 void
-map_over_words (words, function)
+wlist_walk (words, function)
      WORD_LIST *words;
      sh_icpfunc_t *function;
 {
   for ( ; words; words = words->next)
-    (*function) (words->word->word);
+    if ((*function) (words->word->word) < 0)
+      return;
 }
 #endif /* INCLUDE_UNUSED */
 
@@ -59,7 +61,7 @@ map_over_words (words, function)
    of the chain.  You should always assign the output value of this
    function to something, or you will lose the chain. */
 GENERIC_LIST *
-reverse_list (list)
+list_reverse (list)
      GENERIC_LIST *list;
 {
   register GENERIC_LIST *next, *prev;
@@ -108,11 +110,11 @@ list_append (head, tail)
    then ARG.  Note that LIST contains the address of a variable which points
    to the list.  You might call this function like this:
 
-   SHELL_VAR *elt = delete_element (&variable_list, check_var_has_name, "foo");
+   SHELL_VAR *elt = list_remove (&variable_list, check_var_has_name, "foo");
    dispose_variable (elt);
 */
 GENERIC_LIST *
-delete_element (list, comparer, arg)
+list_remove (list, comparer, arg)
      GENERIC_LIST **list;
      Function *comparer;
      char *arg;
index d340d93f47119f7a121217fed389eb7d907ebc94..1805b2fbdeefed0cbf304b048fa62722c90c4ec3 100644 (file)
--- a/locale.c
+++ b/locale.c
@@ -32,6 +32,9 @@
 #include "chartypes.h"
 
 #include "shell.h"
+#include "input.h"     /* For bash_input */
+
+extern int dump_translatable_strings, dump_po_strings;
 
 /* The current locale when the program begins */
 static char *default_locale;
@@ -180,22 +183,14 @@ set_locale_var (var, value)
   return (0);
 }
 
-#if 0
-/* Called when LANG is assigned a value.  Sets LC_ALL if that has not
-   already been set. */
-#else
-/* This no longer does anything; we rely on the C library for correct
-   behavior. */
-#endif
+/* Called when LANG is assigned a value.  Sets LC_ALL category with
+   setlocale(3) if that has not already been set.  Doesn't change any
+   shell variables. */
 int
 set_lang (var, value)
      char *var, *value;
 {
-#if 0
-  return ((lc_all == 0) ? set_locale_var ("LC_ALL", value) : 0);
-#else
-  return 0;
-#endif
+  return ((lc_all == 0 || *lc_all == 0) ? setlocale (LC_ALL, value?value:"") != NULL : 0);
 }
 
 /* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE) */
@@ -276,3 +271,110 @@ localetrans (string, len, lenp)
   return (t);
 #endif /* HAVE_GETTEXT */
 }
+
+/* Change a bash string into a string suitable for inclusion in a `po' file.
+   This backslash-escapes `"' and `\' and changes newlines into \\\n"\n". */
+char *
+mk_msgstr (string, foundnlp)
+     char *string;
+     int *foundnlp;
+{
+  register int c, len;
+  char *result, *r, *s;
+
+  for (len = 0, s = string; s && *s; s++)
+    {
+      len++;
+      if (*s == '"' || *s == '\\')
+       len++;
+      else if (*s == '\n')
+       len += 5;
+    }
+  
+  r = result = (char *)xmalloc (len + 3);
+  *r++ = '"';
+
+  for (s = string; s && (c = *s); s++)
+    {
+      if (c == '\n')   /* <NL> -> \n"<NL>" */
+       {
+         *r++ = '\\';
+         *r++ = 'n';
+         *r++ = '"';
+         *r++ = '\n';
+         *r++ = '"';
+         if (foundnlp)
+           *foundnlp = 1;
+         continue;
+       }
+      if (c == '"' || c == '\\')
+       *r++ = '\\';
+      *r++ = c;
+    }
+
+  *r++ = '"';
+  *r++ = '\0';
+
+  return result;
+}
+
+/* $"..." -- Translate the portion of STRING between START and END
+   according to current locale using gettext (if available) and return
+   the result.  The caller will take care of leaving the quotes intact.
+   The string will be left without the leading `$' by the caller.
+   If translation is performed, the translated string will be double-quoted
+   by the caller.  The length of the translated string is returned in LENP,
+   if non-null. */
+char *
+localeexpand (string, start, end, lineno, lenp)
+     char *string;
+     int start, end, lineno, *lenp;
+{
+  int len, tlen, foundnl;
+  char *temp, *t, *t2;
+
+  temp = (char *)xmalloc (end - start + 1);
+  for (tlen = 0, len = start; len < end; )
+    temp[tlen++] = string[len++];
+  temp[tlen] = '\0';
+
+  /* If we're just dumping translatable strings, don't do anything with the
+     string itself, but if we're dumping in `po' file format, convert it into a form more palatable to gettext(3)
+     and friends by quoting `"' and `\' with backslashes and converting <NL>
+     into `\n"<NL>"'.  If we find a newline in TEMP, we first output a
+     `msgid ""' line and then the translated string; otherwise we output the
+     `msgid' and translated string all on one line. */
+  if (dump_translatable_strings)
+    {
+      if (dump_po_strings)
+       {
+         foundnl = 0;
+         t = mk_msgstr (temp, &foundnl);
+         t2 = foundnl ? "\"\"\n" : "";
+
+         printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
+                       yy_input_name (), lineno, t2, t);
+         free (t);
+       }
+      else
+       printf ("\"%s\"\n", temp);
+
+      if (lenp)
+       *lenp = tlen;
+      return (temp);
+    }
+  else if (*temp)
+    {
+      t = localetrans (temp, tlen, &len);
+      free (temp);
+      if (lenp)
+       *lenp = len;
+      return (t);
+    }
+  else
+    {
+      if (lenp)
+       *lenp = 0;
+      return (temp);
+    }
+}
index 3f8a1b822c0892337270508033e5a5ac3662784b..5cc2fc22652e632add3635c92ebd205eac143e8a 100644 (file)
@@ -1,6 +1,6 @@
 /* mailcheck.c -- The check is in the mail... */
 
-/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -75,7 +75,7 @@ time_to_check_mail ()
 {
   char *temp;
   time_t now;
-  long seconds;
+  intmax_t seconds;
 
   temp = get_string_value ("MAILCHECK");
 
@@ -390,7 +390,7 @@ check_mail ()
             the access time to be equal to the modification time when
             the mail in the file is manipulated, check the size also.  If
             the file has not grown, continue. */
-         if ((atime >= mtime) && !file_is_bigger)
+         if ((atime >= mtime) || !file_is_bigger)
            continue;
 
          /* If the mod time is later than the access time and the file
index c913c0b1d04280bf653acdd631be796c62afe769..1362e798d370bd3b38e33ada1511c1c6e73448f6 100644 (file)
@@ -1,7 +1,7 @@
 /* make_cmd.c -- Functions for making instances of the various
    parser constructs. */
 
-/* Copyright (C) 1989 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -38,31 +38,53 @@ Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
 #include "error.h"
 #include "flags.h"
 #include "make_cmd.h"
+#include "dispose_cmd.h"
 #include "variables.h"
 #include "subst.h"
 #include "input.h"
+#include "ocache.h"
 #include "externs.h"
 
 #if defined (JOB_CONTROL)
 #include "jobs.h"
 #endif
 
+#include "shmbutil.h"
+
 extern int line_number, current_command_line_count;
 extern int last_command_exit_value;
 
+/* Object caching */
+sh_obj_cache_t wdcache = {0, 0, 0};
+sh_obj_cache_t wlcache = {0, 0, 0};
+
+#define WDCACHESIZE    60
+#define WLCACHESIZE    60
+
 static COMMAND *make_for_or_select __P((enum command_type, WORD_DESC *, WORD_LIST *, COMMAND *));
 #if defined (ARITH_FOR_COMMAND)
 static WORD_LIST *make_arith_for_expr __P((char *));
 #endif
 static COMMAND *make_until_or_while __P((enum command_type, COMMAND *, COMMAND *));
 
+void
+cmd_init ()
+{
+  ocache_create (wdcache, WORD_DESC, WDCACHESIZE);
+  ocache_create (wlcache, WORD_LIST, WLCACHESIZE);
+}
+
 WORD_DESC *
 make_bare_word (string)
      const char *string;
 {
   WORD_DESC *temp;
-
+#if 0
   temp = (WORD_DESC *)xmalloc (sizeof (WORD_DESC));
+#else
+  ocache_alloc (wdcache, WORD_DESC, temp);
+#endif
+
   if (*string)
     temp->word = savestring (string);
   else
@@ -80,11 +102,16 @@ make_word_flags (w, string)
      WORD_DESC *w;
      const char *string;
 {
-  register const char *s;
+  register int i;
+  size_t slen;
+  DECLARE_MBSTATE;
 
-  for (s = string; *s; s++)
-    switch (*s)
-      {
+  i = 0;
+  slen = strlen (string);
+  while (i < slen)
+    {
+      switch (string[i])
+       {
        case '$':
          w->flags |= W_HASDOLLAR;
          break;
@@ -95,7 +122,11 @@ make_word_flags (w, string)
        case '"':
          w->flags |= W_QUOTED;
          break;
-      }
+       }
+
+      ADVANCE_CHAR (string, slen, i);
+    }
+
   return (w);
 }
 
@@ -128,25 +159,16 @@ make_word_list (word, wlink)
 {
   WORD_LIST *temp;
 
+#if 0
   temp = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
+#else
+  ocache_alloc (wlcache, WORD_LIST, temp);
+#endif
   temp->word = word;
   temp->next = wlink;
   return (temp);
 }
 
-WORD_LIST *
-add_string_to_list (string, list)
-     char *string;
-     WORD_LIST *list;
-{
-  WORD_LIST *temp;
-
-  temp = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
-  temp->word = make_word (string);
-  temp->next = list;
-  return (temp);
-}
-
 COMMAND *
 make_command (type, pointer)
      enum command_type type;
@@ -222,12 +244,10 @@ make_arith_for_expr (s)
      char *s;
 {
   WORD_LIST *result;
-  WORD_DESC *w;
 
   if (s == 0 || *s == '\0')
     return ((WORD_LIST *)NULL);
-  w = make_word (s);
-  result = make_word_list (w, (WORD_LIST *)NULL);
+  result = make_word_list (make_word (s), (WORD_LIST *)NULL);
   return result;
 }
 #endif
@@ -490,12 +510,7 @@ make_simple_command (element, command)
     command = make_bare_simple_command ();
 
   if (element.word)
-    {
-      WORD_LIST *tw = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
-      tw->word = element.word;
-      tw->next = command->value.Simple->words;
-      command->value.Simple->words = tw;
-    }
+    command->value.Simple->words = make_word_list (element.word, command->value.Simple->words);
   else
     {
       REDIRECT *r = element.redirect;
@@ -624,7 +639,12 @@ make_redirection (source, instruction, dest_and_filename)
      enum r_instruction instruction;
      REDIRECTEE dest_and_filename;
 {
-  REDIRECT *temp = (REDIRECT *)xmalloc (sizeof (REDIRECT));
+  REDIRECT *temp;
+  WORD_DESC *w;
+  int wlen;
+  intmax_t lfd;
+
+  temp = (REDIRECT *)xmalloc (sizeof (REDIRECT));
 
   /* First do the common cases. */
   temp->redirector = source;
@@ -657,11 +677,37 @@ make_redirection (source, instruction, dest_and_filename)
 
     case r_deblank_reading_until:      /* <<-foo */
     case r_reading_until:              /* << foo */
+    case r_reading_string:             /* <<< foo */
     case r_close_this:                 /* <&- */
     case r_duplicating_input:          /* 1<&2 */
     case r_duplicating_output:         /* 1>&2 */
+      break;
+
+    /* the parser doesn't pass these. */
+    case r_move_input:                 /* 1<&2- */
+    case r_move_output:                        /* 1>&2- */
+    case r_move_input_word:            /* 1<&$foo- */
+    case r_move_output_word:           /* 1>&$foo- */
+      break;
+
+    /* The way the lexer works we have to do this here. */
     case r_duplicating_input_word:     /* 1<&$foo */
     case r_duplicating_output_word:    /* 1>&$foo */
+      w = dest_and_filename.filename;
+      wlen = strlen (w->word) - 1;
+      if (w->word[wlen] == '-')                /* Yuck */
+        {
+          w->word[wlen] = '\0';
+         if (all_digits (w->word) && legal_number (w->word, &lfd) && lfd == (int)lfd)
+           {
+             dispose_word (w);
+             temp->instruction = (instruction == r_duplicating_input_word) ? r_move_input : r_move_output;
+             temp->redirectee.dest = lfd;
+           }
+         else
+           temp->instruction = (instruction == r_duplicating_input_word) ? r_move_input_word : r_move_output_word;
+        }
+          
       break;
 
     default:
index 1ea9c2445025c5d8c9b0b6e321320cadf1c23663..7fb5697d39fb3ec31a16b93425ffe048c9c51185 100644 (file)
 
 #include "stdc.h"
 
-extern WORD_LIST *make_word_list __P((WORD_DESC *, WORD_LIST *));
-extern WORD_LIST *add_string_to_list __P((char *, WORD_LIST *));
+extern void cmd_init __P((void));
 
 extern WORD_DESC *make_bare_word __P((const char *));
 extern WORD_DESC *make_word_flags __P((WORD_DESC *, const char *));
 extern WORD_DESC *make_word __P((const char *));
 extern WORD_DESC *make_word_from_token __P((int));
 
+extern WORD_LIST *make_word_list __P((WORD_DESC *, WORD_LIST *));
+
+#define add_string_to_list(s, l) make_word_list (make_word(s), (l))
+
 extern COMMAND *make_command __P((enum command_type, SIMPLE_COM *));
 extern COMMAND *command_connect __P((COMMAND *, COMMAND *, int));
 extern COMMAND *make_for_command __P((WORD_DESC *, WORD_LIST *, COMMAND *));
index f5bc71fd56bd6a6b64462f8604d9e52e64bedc25..2aed86c3d2d1660f9f78e165514584f995ba0dab 100644 (file)
@@ -60,7 +60,8 @@ struct wordflag {
        { CGLOB,        "CGLOB" },
        { CXGLOB,       "CXGLOB" },
        { CXQUOTE,      "CXQUOTE" },
-       { CSPECVAR,     "CSPECVAR" }
+       { CSPECVAR,     "CSPECVAR" },
+       { CSUBSTOP,     "CSUBSTOP" },
 };
        
 #define N_WFLAGS       (sizeof (wordflags) / sizeof (wordflags[0]))
@@ -221,6 +222,8 @@ load_lsyntax ()
   addcchar ('\\', CXQUOTE);
 
   addcstr ("@*#?-$!", CSPECVAR);       /* omits $0...$9 and $_ */
+
+  addcstr ("-=?+", CSUBSTOP);          /* OP in ${paramOPword} */
 }
 
 static void
index a4b553904cd85d413e547095315e0c365463bbbf..77632835ab9ecebbbb43922f97b0e6815c0ac78e 100644 (file)
--- a/nojobs.c
+++ b/nojobs.c
@@ -57,9 +57,7 @@
 
 #include "builtins/builtext.h" /* for wait_builtin */
 
-#if !defined (CHILD_MAX)
-#  define CHILD_MAX 32
-#endif
+#define DEFAULT_CHILD_MAX 32
 
 #if defined (_POSIX_VERSION) || !defined (HAVE_KILLPG)
 #  define killpg(pg, sig)              kill(-(pg),(sig))
@@ -95,6 +93,7 @@ extern sh_builtin_func_t *this_shell_builtin;
 extern sigset_t top_level_mask;
 #endif
 extern procenv_t wait_intr_buf;
+extern int wait_signal_received;
 
 pid_t last_made_pid = NO_PID;
 pid_t last_asynchronous_pid = NO_PID;
@@ -130,6 +129,8 @@ static struct proc_status *pid_list = (struct proc_status *)NULL;
 static int pid_list_size;
 static int wait_sigint_received;
 
+static long child_max = -1L;
+
 static void alloc_pid_list __P((void));
 static int find_proc_slot __P((void));
 static int find_index_by_pid __P((pid_t));
@@ -143,7 +144,7 @@ static void mark_dead_jobs_as_notified __P((int));
 
 static void get_new_window_size __P((int));
 static sighandler sigwinch_sighandler __P((int));
-static sighandler wait_signal_handler __P((int));
+static sighandler wait_sigint_handler __P((int));
 
 #if defined (HAVE_WAITPID)
 static void reap_zombie_children __P((void));
@@ -306,7 +307,12 @@ mark_dead_jobs_as_notified (force)
        ndead++;
     }
 
-  if (force == 0 && ndead <= CHILD_MAX)
+  if (child_max < 0)
+    child_max = getmaxchild ();
+  if (child_max < 0)
+    child_max = DEFAULT_CHILD_MAX;
+
+  if (force == 0 && ndead <= child_max)
     return;
 
   /* If FORCE == 0, we just mark as many non-running async jobs as notified
@@ -319,7 +325,7 @@ mark_dead_jobs_as_notified (force)
           pid_list[i].pid != last_asynchronous_pid)
        {
          pid_list[i].flags |= PROC_NOTIFIED;
-         if (force == 0 && (pid_list[i].flags & PROC_ASYNC) && --ndead <= CHILD_MAX)
+         if (force == 0 && (pid_list[i].flags & PROC_ASYNC) && --ndead <= child_max)
            break;
        }
     }
@@ -588,13 +594,16 @@ wait_for_single_pid (pid)
        set_pid_status (got_pid, status);
     }
 
-  set_pid_status (got_pid, status);
-  set_pid_flags (got_pid, PROC_NOTIFIED);
+  if (got_pid > 0)
+    {
+      set_pid_status (got_pid, status);
+      set_pid_flags (got_pid, PROC_NOTIFIED);
+    }
 
   siginterrupt (SIGINT, 0);
   QUIT;
 
-  return (process_exit_status (status));
+  return (got_pid > 0 ? process_exit_status (status) : -1);
 }
 
 /* Wait for all of the shell's children to exit.  Called by the `wait'
@@ -662,6 +671,7 @@ wait_sigint_handler (sig)
       restore_sigint_handler ();
       interrupt_immediately = 0;
       trap_handler (SIGINT);   /* set pending_traps[SIGINT] */
+      wait_signal_received = SIGINT;
       longjmp (wait_intr_buf, 1);
     }
 
@@ -719,7 +729,8 @@ wait_for (pid)
        set_pid_status (got_pid, status);
     }
 
-  set_pid_status (got_pid, status);
+  if (got_pid > 0)
+    set_pid_status (got_pid, status);
 
 #if defined (HAVE_WAITPID)
   if (got_pid >= 0)
diff --git a/parse.y b/parse.y
index 65f76429e63c78f6ef7dd5df1e7737962810964b..0f6d930a251c50e8fddc9f1d0d8f88f7c4234610 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -1,6 +1,6 @@
 /* Yacc grammar for bash. */
 
-/* Copyright (C) 1989 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -40,6 +40,8 @@
 
 #include "memalloc.h"
 
+#define NEED_STRFTIME_DECL     /* used in externs.h */
+
 #include "shell.h"
 #include "trap.h"
 #include "flags.h"
@@ -49,6 +51,8 @@
 #include "builtins/common.h"
 #include "builtins/builtext.h"
 
+#include "shmbutil.h"
+
 #if defined (READLINE)
 #  include "bashline.h"
 #  include <readline/readline.h>
 #    include <sys/param.h>
 #  endif
 #  include <time.h>
+#  if defined (TM_IN_SYS_TIME)
+#    include <sys/types.h>
+#    include <sys/time.h>
+#  endif /* TM_IN_SYS_TIME */
 #  include "maxpath.h"
 #endif /* PROMPT_STRING_DECODE */
 
 #define RE_READ_TOKEN  -99
 #define NO_EXPANSION   -100
 
-#define YYDEBUG 0
+#ifdef DEBUG
+#  define YYDEBUG 1
+#else
+#  define YYDEBUG 0
+#endif
+
+#if defined (HANDLE_MULTIBYTE)
+#  define last_shell_getc_is_singlebyte \
+       ((shell_input_line_index > 1) \
+               ? shell_input_line_property[shell_input_line_index - 1] \
+               : 1)
+#  define MBTEST(x)    ((x) && last_shell_getc_is_singlebyte)
+#else
+#  define last_shell_getc_is_singlebyte        1
+#  define MBTEST(x)    ((x))
+#endif
 
 #if defined (EXTENDED_GLOB)
 extern int extended_glob;
@@ -136,9 +159,6 @@ static void free_string_list __P((void));
 
 static char *read_a_line __P((int));
 
-static char *ansiexpand __P((char *, int, int, int *));
-static char *mk_msgstr __P((char *, int *));
-static char *localeexpand __P((char *, int, int, int, int *));
 static int reserved_word_acceptable __P((int));
 static int yylex __P((void));
 static int alias_expand_token __P((char *));
@@ -146,10 +166,15 @@ static int time_command_acceptable __P((void));
 static int special_case_tokens __P((char *));
 static int read_token __P((int));
 static char *parse_matched_pair __P((int, int, int, int *, int));
+#if defined (ARRAY_VARS)
+static char *parse_compound_assignment __P((int *));
+#endif
 #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
+static int parse_dparen __P((int));
 static int parse_arith_cmd __P((char **));
 #endif
 #if defined (COND_COMMAND)
+static void cond_error __P((void));
 static COND_COM *cond_expr __P((void));
 static COND_COM *cond_or __P((void));
 static COND_COM *cond_and __P((void));
@@ -157,10 +182,18 @@ static COND_COM *cond_term __P((void));
 static int cond_skip_newlines __P((void));
 static COMMAND *parse_cond_command __P((void));
 #endif
+#if defined (ARRAY_VARS)
+static int token_is_assignment __P((char *, int));
+static int token_is_ident __P((char *, int));
+#endif
 static int read_token_word __P((int));
 static void discard_parser_constructs __P((int));
 
+static char *error_token_from_token __P((int));
+static char *error_token_from_text __P((void));
+static void print_offending_line __P((void));
 static void report_syntax_error __P((char *));
+
 static void handle_eof_input_unit __P((void));
 static void prompt_again __P((void));
 #if 0
@@ -172,8 +205,19 @@ static void print_prompt __P((void));
 char *history_delimiting_chars __P((void));
 #endif
 
+#if defined (HANDLE_MULTIBYTE)
+static void set_line_mbstate __P((void));
+static char *shell_input_line_property = NULL;
+#else
+#  define set_line_mbstate()
+#endif
+
 extern int yyerror __P((const char *));
 
+#ifdef DEBUG
+extern int yydebug;
+#endif
+
 /* Default prompt strings */
 char *primary_prompt = PPROMPT;
 char *secondary_prompt = SPROMPT;
@@ -252,7 +296,7 @@ static REDIRECTEE redir;
 %token <number> NUMBER
 %token <word_list> ARITH_CMD ARITH_FOR_EXPRS
 %token <command> COND_CMD
-%token AND_AND OR_OR GREATER_GREATER LESS_LESS LESS_AND
+%token AND_AND OR_OR GREATER_GREATER LESS_LESS LESS_AND LESS_LESS_LESS
 %token GREATER_AND SEMI_SEMI LESS_LESS_MINUS AND_GREATER LESS_GREATER
 %token GREATER_BAR
 
@@ -279,13 +323,13 @@ static REDIRECTEE redir;
 %right '|'
 %%
 
-inputunit:     simple_list '\n'
+inputunit:     simple_list simple_list_terminator
                        {
                          /* Case of regular command.  Discard the error
                             safety net,and return the command just parsed. */
                          global_command = $1;
                          eof_encountered = 0;
-                         discard_parser_constructs (0);
+                         /* discard_parser_constructs (0); */
                          YYACCEPT;
                        }
        |       '\n'
@@ -300,7 +344,7 @@ inputunit:  simple_list '\n'
                          /* Error during parsing.  Return NULL command. */
                          global_command = (COMMAND *)NULL;
                          eof_encountered = 0;
-                         discard_parser_constructs (1);
+                         /* discard_parser_constructs (1); */
                          if (interactive)
                            {
                              YYACCEPT;
@@ -368,6 +412,16 @@ redirection:       '>' WORD
                          $$ = make_redirection ($1, r_reading_until, redir);
                          redir_stack[need_here_doc++] = $$;
                        }
+       |       LESS_LESS_LESS WORD
+                       {
+                         redir.filename = $2;
+                         $$ = make_redirection (0, r_reading_string, redir);
+                       }
+       |       NUMBER LESS_LESS_LESS WORD
+                       {
+                         redir.filename = $3;
+                         $$ = make_redirection ($1, r_reading_string, redir);
+                       }
        |       LESS_AND NUMBER
                        {
                          redir.dest = $2;
@@ -592,11 +646,11 @@ select_command:   SELECT WORD newline_list DO list DONE
                        }
        |       SELECT WORD newline_list IN word_list list_terminator newline_list DO list DONE
                        {
-                         $$ = make_select_command ($2, (WORD_LIST *)reverse_list ($5), $9);
+                         $$ = make_select_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9);
                        }
        |       SELECT WORD newline_list IN word_list list_terminator newline_list '{' list '}'
                        {
-                         $$ = make_select_command ($2, (WORD_LIST *)reverse_list ($5), $9);
+                         $$ = make_select_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9);
                        }
        ;
 
@@ -765,6 +819,10 @@ list1:             list1 AND_AND newline_list list1
                        { $$ = $1; }
        ;
 
+simple_list_terminator:        '\n'
+       |       yacc_EOF
+       ;
+
 list_terminator:'\n'
        |       ';'
        |       yacc_EOF
@@ -971,6 +1029,12 @@ init_yy_io (get, unget, type, name, location)
   bash_input.ungetter = unget;
 }
 
+char *
+yy_input_name ()
+{
+  return (bash_input.name ? bash_input.name : "stdin");
+}
+
 /* Call this to get the next character of input. */
 static int
 yy_getc ()
@@ -1399,6 +1463,8 @@ push_string (s, expand, ap)
   shell_input_line_index = 0;
   shell_input_line_terminator = '\0';
   parser_state &= ~PST_ALEXPNEXT;
+
+  set_line_mbstate ();
 }
 
 /*
@@ -1432,6 +1498,8 @@ pop_string ()
 #endif
 
   free ((char *)t);
+
+  set_line_mbstate ();
 }
 
 static void
@@ -1591,9 +1659,46 @@ STRING_INT_ALIST word_token_alist[] = {
   { (char *)NULL, 0}
 };
 
-/* XXX - we should also have an alist with strings for other tokens, so we
-        can give more descriptive error messages.  Look at y.tab.h for the
-        other tokens. */
+/* other tokens that can be returned by read_token() */
+STRING_INT_ALIST other_token_alist[] = {
+  /* Multiple-character tokens with special values */
+  { "-p", TIMEOPT },
+  { "&&", AND_AND },
+  { "||", OR_OR },
+  { ">>", GREATER_GREATER },
+  { "<<", LESS_LESS },
+  { "<&", LESS_AND },
+  { ">&", GREATER_AND },
+  { ";;", SEMI_SEMI },
+  { "<<-", LESS_LESS_MINUS },
+  { "<<<", LESS_LESS_LESS },
+  { "&>", AND_GREATER },
+  { "<>", LESS_GREATER },
+  { ">|", GREATER_BAR },
+  { "EOF", yacc_EOF },
+  /* Tokens whose value is the character itself */
+  { ">", '>' },
+  { "<", '<' },
+  { "-", '-' },
+  { "{", '{' },
+  { "}", '}' },
+  { ";", ';' },
+  { "(", '(' },
+  { ")", ')' },
+  { "|", '|' },
+  { "&", '&' },
+  { "newline", '\n' },
+  { (char *)NULL, 0}
+};
+
+/* others not listed here:
+       WORD                    look at yylval.word
+       ASSIGNMENT_WORD         look at yylval.word
+       NUMBER                  look at yylval.number
+       ARITH_CMD               look at yylval.word_list
+       ARITH_FOR_EXPRS         look at yylval.word_list
+       COND_CMD                look at yylval.command
+*/
 
 /* These are used by read_token_word, but appear up here so that shell_getc
    can use them to decide when to add otherwise blank lines to the history. */
@@ -1735,6 +1840,8 @@ shell_getc (remove_quoted_newline)
       shell_input_line_index = 0;
       shell_input_line_len = i;                /* == strlen (shell_input_line) */
 
+      set_line_mbstate ();
+
 #if defined (HISTORY)
       if (remember_on_history && shell_input_line && shell_input_line[0])
        {
@@ -1765,6 +1872,8 @@ shell_getc (remove_quoted_newline)
              /* We have to force the xrealloc below because we don't know
                 the true allocated size of shell_input_line anymore. */
              shell_input_line_size = shell_input_line_len;
+
+             set_line_mbstate ();
            }
        }
       /* Try to do something intelligent with blank lines encountered while
@@ -1816,6 +1925,8 @@ shell_getc (remove_quoted_newline)
 
          shell_input_line[shell_input_line_len] = '\n';
          shell_input_line[shell_input_line_len + 1] = '\0';
+
+         set_line_mbstate ();
        }
     }
 
@@ -1824,8 +1935,7 @@ shell_getc (remove_quoted_newline)
   if (uc)
     shell_input_line_index++;
 
-  if (uc == '\\' && remove_quoted_newline &&
-      shell_input_line[shell_input_line_index] == '\n')
+  if MBTEST(uc == '\\' && remove_quoted_newline && shell_input_line[shell_input_line_index] == '\n')
     {
        prompt_again ();
        line_number++;
@@ -1862,7 +1972,11 @@ shell_getc (remove_quoted_newline)
   return (uc);
 }
 
-/* Put C back into the input for the shell. */
+/* Put C back into the input for the shell.  This might need changes for
+   HANDLE_MULTIBYTE around EOLs.  Since we (currently) never push back a
+   character different than we read, shell_input_line_property doesn't need
+   to change when manipulating shell_input_line.  The define for
+   last_shell_getc_is_singlebyte should take care of it, though. */
 static void
 shell_ungetc (c)
      int c;
@@ -2034,7 +2148,7 @@ static int open_brace_count;
     /* OK, we have a token.  Let's try to alias expand it, if (and only if)
        it's eligible.
 
-       It is eligible for expansion if the shell is in interactive mode, and
+       It is eligible for expansion if EXPAND_ALIASES is set, and
        the token is unquoted and the last token read was a command
        separator (or expand_next_token is set), and we are currently
        processing an alias (pushed_string_list is non-empty) and this
@@ -2281,10 +2395,7 @@ read_token (command)
       yylval.command = parse_cond_command ();
       if (cond_token != COND_END)
        {
-         if (EOF_Reached && cond_token != COND_ERROR)          /* [[ */
-           parser_error (cond_lineno, "unexpected EOF while looking for `]]'");
-         else if (cond_token != COND_ERROR)
-           parser_error (cond_lineno, "syntax error in conditional expression");
+         cond_error ();
          return (-1);
        }
       token_to_read = COND_END;
@@ -2309,7 +2420,7 @@ read_token (command)
       return (yacc_EOF);
     }
 
-  if (character == '#' && (!interactive || interactive_comments))
+  if MBTEST(character == '#' && (!interactive || interactive_comments))
     {
       /* A comment.  Discard until EOL or EOF, and then return a newline. */
       discard_until ('\n');
@@ -2332,7 +2443,7 @@ read_token (command)
     }
 
   /* Shell meta-characters. */
-  if (shellmeta (character) && ((parser_state & PST_DBLPAREN) == 0))
+  if MBTEST(shellmeta (character) && ((parser_state & PST_DBLPAREN) == 0))
     {
 #if defined (ALIAS)
       /* Turn off alias tokenization iff this character sequence would
@@ -2352,6 +2463,8 @@ read_token (command)
              peek_char = shell_getc (1);
              if (peek_char == '-')
                return (LESS_LESS_MINUS);
+             else if (peek_char == '<')
+               return (LESS_LESS_LESS);
              else
                {
                  shell_ungetc (peek_char);
@@ -2376,74 +2489,23 @@ read_token (command)
 
 #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
            case '(':           /* ) */
-#  if defined (ARITH_FOR_COMMAND)
-             if (last_read_token == FOR)
-               {
-                 int cmdtyp, len;
-                 char *wval, *wv2;
-                 WORD_DESC *wd;
-
-                 arith_for_lineno = line_number;
-                 cmdtyp = parse_arith_cmd (&wval);
-                 if (cmdtyp == 1)
-                   {
-                     /* parse_arith_cmd adds quotes at the beginning and end
-                        of the string it returns; we need to take those out. */
-                     len = strlen (wval);
-                     wv2 = (char *)xmalloc (len);
-                     strncpy (wv2, wval + 1, len - 2);
-                     wv2[len - 2] = '\0';
-                     wd = make_word (wv2);
-                     yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
-                     free (wval);
-                     free (wv2);
-                     return (ARITH_FOR_EXPRS);
-                   }
-                 else
-                   return -1;          /* ERROR */
-               }
-#  endif
-#  if defined (DPAREN_ARITHMETIC)
-             if (reserved_word_acceptable (last_read_token))
-               {
-                 int cmdtyp, sline;
-                 char *wval;
-                 WORD_DESC *wd;
-
-                 sline = line_number;
-                 cmdtyp = parse_arith_cmd (&wval);
-                 if (cmdtyp == 1)      /* arithmetic command */
-                   {
-                     wd = make_word (wval);
-                     wd->flags = W_QUOTED;
-                     yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
-                     free (wval);      /* make_word copies it */
-                     return (ARITH_CMD);
-                   }
-                 else if (cmdtyp == 0) /* nested subshell */
-                   {
-                     push_string (wval, 0, (alias_t *)NULL);
-                     if ((parser_state & PST_CASEPAT) == 0)
-                       parser_state |= PST_SUBSHELL;
-                     return (character);
-                   }
-                 else                  /* ERROR */
-                   return -1;
-               }
-             break;
-#  endif
+             result = parse_dparen (character);
+             if (result == -2)
+               break;
+             else
+               return result;
 #endif
            }
        }
-      else if (character == '<' && peek_char == '&')
+      else if MBTEST(character == '<' && peek_char == '&')
        return (LESS_AND);
-      else if (character == '>' && peek_char == '&')
+      else if MBTEST(character == '>' && peek_char == '&')
        return (GREATER_AND);
-      else if (character == '<' && peek_char == '>')
+      else if MBTEST(character == '<' && peek_char == '>')
        return (LESS_GREATER);
-      else if (character == '>' && peek_char == '|')
+      else if MBTEST(character == '>' && peek_char == '|')
        return (GREATER_BAR);
-      else if (peek_char == '>' && character == '&')
+      else if MBTEST(peek_char == '>' && character == '&')
        return (AND_GREATER);
 
       shell_ungetc (peek_char);
@@ -2451,7 +2513,7 @@ read_token (command)
       /* If we look like we are reading the start of a function
         definition, then let the reader know about it so that
         we will do the right thing with `{'. */
-      if (character == ')' && last_read_token == '(' && token_before_that == WORD)
+      if MBTEST(character == ')' && last_read_token == '(' && token_before_that == WORD)
        {
          parser_state |= PST_ALLOWOPNBRC;
 #if defined (ALIAS)
@@ -2463,26 +2525,25 @@ read_token (command)
       /* case pattern lists may be preceded by an optional left paren.  If
         we're not trying to parse a case pattern list, the left paren
         indicates a subshell. */
-      if (character == '(' && (parser_state & PST_CASEPAT) == 0) /* ) */
+      if MBTEST(character == '(' && (parser_state & PST_CASEPAT) == 0) /* ) */
        parser_state |= PST_SUBSHELL;
       /*(*/
-      else if ((parser_state & PST_CASEPAT) && character == ')')
+      else if MBTEST((parser_state & PST_CASEPAT) && character == ')')
        parser_state &= ~PST_CASEPAT;
       /*(*/
-      else if ((parser_state & PST_SUBSHELL) && character == ')')
+      else if MBTEST((parser_state & PST_SUBSHELL) && character == ')')
        parser_state &= ~PST_SUBSHELL;
 
 #if defined (PROCESS_SUBSTITUTION)
       /* Check for the constructs which introduce process substitution.
         Shells running in `posix mode' don't do process substitution. */
-      if (posixly_correct ||
-         ((character != '>' && character != '<') || peek_char != '('))
+      if MBTEST(posixly_correct || ((character != '>' && character != '<') || peek_char != '(')) /*)*/
 #endif /* PROCESS_SUBSTITUTION */
        return (character);
     }
 
-  /* Hack <&- (close stdin) case. */
-  if (character == '-' && (last_read_token == LESS_AND || last_read_token == GREATER_AND))
+  /* Hack <&- (close stdin) case.  Also <&N- (dup and close). */
+  if MBTEST(character == '-' && (last_read_token == LESS_AND || last_read_token == GREATER_AND))
     return (character);
 
   /* Okay, if we got this far, we have to read a word.  Read one,
@@ -2495,11 +2556,13 @@ read_token (command)
   return result;
 }
 
-/* Match a $(...) or other grouping construct.  This has to handle embedded
-   quoted strings ('', ``, "") and nested constructs.  It also must handle
-   reprompting the user, if necessary, after reading a newline, and returning
-   correct error values if it reads EOF. */
-
+/*
+ * Match a $(...) or other grouping construct.  This has to handle embedded
+ * quoted strings ('', ``, "") and nested constructs.  It also must handle
+ * reprompting the user, if necessary, after reading a newline (unless the
+ * P_NONL flag is passed), and returning correct error values if it reads
+ * EOF.
+ */
 #define P_FIRSTCLOSE   0x01
 #define P_ALLOWESC     0x02
 
@@ -2548,26 +2611,26 @@ parse_matched_pair (qc, open, close, lenp, flags)
            }
 
          RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
-         if (ch == CTLESC || ch == CTLNUL)
+         if MBTEST(ch == CTLESC || ch == CTLNUL)
            ret[retind++] = CTLESC;
          ret[retind++] = ch;
          continue;
        }
-      else if (ch == CTLESC || ch == CTLNUL)   /* special shell escapes */
+      else if MBTEST(ch == CTLESC || ch == CTLNUL)     /* special shell escapes */
        {
          RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
          ret[retind++] = CTLESC;
          ret[retind++] = ch;
          continue;
        }
-      else if (ch == close)            /* ending delimiter */
+      else if MBTEST(ch == close)              /* ending delimiter */
        count--;
 #if 1
       /* handle nested ${...} specially. */
-      else if (open != close && was_dollar && open == '{' && ch == open) /* } */
+      else if MBTEST(open != close && was_dollar && open == '{' && ch == open) /* } */
        count++;
 #endif
-      else if (((flags & P_FIRSTCLOSE) == 0) && ch == open)            /* nested begin */
+      else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && ch == open)      /* nested begin */
        count++;
 
       /* Add this character. */
@@ -2576,21 +2639,21 @@ parse_matched_pair (qc, open, close, lenp, flags)
 
       if (open == '\'')                        /* '' inside grouping construct */
        {
-         if ((flags & P_ALLOWESC) && ch == '\\')
+         if MBTEST((flags & P_ALLOWESC) && ch == '\\')
            pass_next_character++;
          continue;
        }
 
-      if (ch == '\\')                  /* backslashes */
+      if MBTEST(ch == '\\')                    /* backslashes */
        pass_next_character++;
 
       if (open != close)               /* a grouping construct */
        {
-         if (shellquote (ch))
+         if MBTEST(shellquote (ch))
            {
              /* '', ``, or "" inside $(...) or other grouping construct. */
              push_delimiter (dstack, ch);
-             if (was_dollar && ch == '\'')     /* $'...' inside group */
+             if MBTEST(was_dollar && ch == '\'')       /* $'...' inside group */
                nestret = parse_matched_pair (ch, ch, ch, &nestlen, P_ALLOWESC);
              else
                nestret = parse_matched_pair (ch, ch, ch, &nestlen, 0);
@@ -2600,7 +2663,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
                  free (ret);
                  return &matched_pair_error;
                }
-             if (was_dollar && ch == '\'')
+             if MBTEST(was_dollar && ch == '\'')
                {
                  /* Translate $'...' here. */
                  ttrans = ansiexpand (nestret, 0, nestlen - 1, &ttranslen);
@@ -2610,7 +2673,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
                  nestlen = strlen (nestret);
                  retind -= 2;          /* back up before the $' */
                }
-             else if (was_dollar && ch == '"')
+             else if MBTEST(was_dollar && ch == '"')
                {
                  /* Locale expand $"..." here. */
                  ttrans = localeexpand (nestret, 0, nestlen - 1, start_lineno, &ttranslen);
@@ -2624,6 +2687,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
                  nestlen = ttranslen;
                  retind -= 2;          /* back up before the $" */
                }
+
              if (nestlen)
                {
                  RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64);
@@ -2636,7 +2700,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
       /* Parse an old-style command substitution within double quotes as a
         single word. */
       /* XXX - sh and ksh93 don't do this - XXX */
-      else if (open == '"' && ch == '`')
+      else if MBTEST(open == '"' && ch == '`')
        {
          nestret = parse_matched_pair (0, '`', '`', &nestlen, 0);
          if (nestret == &matched_pair_error)
@@ -2652,7 +2716,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
            }
          FREE (nestret);
        }
-      else if (was_dollar && (ch == '(' || ch == '{' || ch == '['))    /* ) } ] */
+      else if MBTEST(was_dollar && (ch == '(' || ch == '{' || ch == '['))      /* ) } ] */
        /* check for $(), $[], or ${} inside quoted string. */
        {
          if (open == ch)       /* undo previous increment */
@@ -2676,7 +2740,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
            }
          FREE (nestret);
        }
-      was_dollar = (ch == '$');
+      was_dollar = MBTEST(ch == '$');
     }
 
   ret[retind] = '\0';
@@ -2686,6 +2750,70 @@ parse_matched_pair (qc, open, close, lenp, flags)
 }
 
 #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
+/* Parse a double-paren construct.  It can be either an arithmetic
+   command, an arithmetic `for' command, or a nested subshell.  Returns
+   the parsed token, -1 on error, or -2 if we didn't do anything and
+   should just go on. */
+static int
+parse_dparen (c)
+     int c;
+{
+  int cmdtyp, len, sline;
+  char *wval, *wv2;
+  WORD_DESC *wd;
+
+#if defined (ARITH_FOR_COMMAND)
+  if (last_read_token == FOR)
+    {
+      arith_for_lineno = line_number;
+      cmdtyp = parse_arith_cmd (&wval);
+      if (cmdtyp == 1)
+       {
+         /* parse_arith_cmd adds quotes at the beginning and end
+            of the string it returns; we need to take those out. */
+         len = strlen (wval);
+         wv2 = (char *)xmalloc (len);
+         strncpy (wv2, wval + 1, len - 2);
+         wv2[len - 2] = '\0';
+         wd = make_word (wv2);
+         yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
+         free (wval);
+         free (wv2);
+         return (ARITH_FOR_EXPRS);
+       }
+      else
+       return -1;              /* ERROR */
+    }
+#endif
+
+#if defined (DPAREN_ARITHMETIC)
+  if (reserved_word_acceptable (last_read_token))
+    {
+      sline = line_number;
+      cmdtyp = parse_arith_cmd (&wval);
+      if (cmdtyp == 1) /* arithmetic command */
+       {
+         wd = make_word (wval);
+         wd->flags = W_QUOTED;
+         yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
+         free (wval);  /* make_word copies it */
+         return (ARITH_CMD);
+       }
+      else if (cmdtyp == 0)    /* nested subshell */
+       {
+         push_string (wval, 0, (alias_t *)NULL);
+         if ((parser_state & PST_CASEPAT) == 0)
+           parser_state |= PST_SUBSHELL;
+         return (c);
+       }
+      else                     /* ERROR */
+       return -1;
+    }
+#endif
+
+  return -2;                   /* XXX */
+}
+
 /* We've seen a `(('.  Look for the matching `))'.  If we get it, return 1.
    If not, assume it's a nested subshell for backwards compatibility and
    return 0.  In any case, put the characters we've consumed into a locally-
@@ -2706,7 +2834,8 @@ parse_arith_cmd (ep)
     return -1;
   /* Check that the next character is the closing right paren.  If
      not, this is a syntax error. ( */
-  if ((c = shell_getc (0)) != ')')
+  c = shell_getc (0);
+  if MBTEST(c != ')')
     rval = 0;
 
   tokstr = (char *)xmalloc (ttoklen + 4);
@@ -2732,6 +2861,25 @@ parse_arith_cmd (ep)
 #endif /* DPAREN_ARITHMETIC || ARITH_FOR_COMMAND */
 
 #if defined (COND_COMMAND)
+static void
+cond_error ()
+{
+  char *etext;
+
+  if (EOF_Reached && cond_token != COND_ERROR)         /* [[ */
+    parser_error (cond_lineno, "unexpected EOF while looking for `]]'");
+  else if (cond_token != COND_ERROR)
+    {
+      if (etext = error_token_from_token (cond_token))
+       {
+         parser_error (cond_lineno, "syntax error in conditional expression: unexpected token `%s'", etext);
+         free (etext);
+       }
+      else
+       parser_error (cond_lineno, "syntax error in conditional expression");
+    }
+}
+
 static COND_COM *
 cond_expr ()
 {
@@ -2786,6 +2934,7 @@ cond_term ()
   WORD_DESC *op;
   COND_COM *term, *tleft, *tright;
   int tok, lineno;
+  char *etext;
 
   /* Read a token.  It can be a left paren, a `!', a unary operator, or a
      word that should be the first argument of a binary operator.  Start by
@@ -2803,7 +2952,13 @@ cond_term ()
        {
          if (term)
            dispose_cond_node (term);           /* ( */
-         parser_error (lineno, "expected `)'");
+         if (etext = error_token_from_token (cond_token))
+           {
+             parser_error (lineno, "unexpected token `%s', expected `)'", etext);
+             free (etext);
+           }
+         else
+           parser_error (lineno, "expected `)'");
          COND_RETURN_ERROR ();
        }
       term = make_cond_node (COND_EXPR, (WORD_DESC *)NULL, term, (COND_COM *)NULL);
@@ -2829,7 +2984,13 @@ cond_term ()
       else
        {
          dispose_word (op);
-         parser_error (line_number, "unexpected argument to conditional unary operator");
+         if (etext = error_token_from_token (tok))
+           {
+             parser_error (line_number, "unexpected argument `%s' to conditional unary operator", etext);
+             free (etext);
+           }
+         else
+           parser_error (line_number, "unexpected argument to conditional unary operator");
          COND_RETURN_ERROR ();
        }
 
@@ -2860,7 +3021,13 @@ cond_term ()
        }
       else
        {
-         parser_error (line_number, "conditional binary operator expected");
+         if (etext = error_token_from_token (tok))
+           {
+             parser_error (line_number, "unexpected token `%s', conditional binary operator expected", etext);
+             free (etext);
+           }
+         else
+           parser_error (line_number, "conditional binary operator expected");
          dispose_cond_node (tleft);
          COND_RETURN_ERROR ();
        }
@@ -2874,7 +3041,13 @@ cond_term ()
        }
       else
        {
-         parser_error (line_number, "unexpected argument to conditional binary operator");
+         if (etext = error_token_from_token (tok))
+           {
+             parser_error (line_number, "unexpected argument `%s' to conditional binary operator", etext);
+             free (etext);
+           }
+         else
+           parser_error (line_number, "unexpected argument to conditional binary operator");
          dispose_cond_node (tleft);
          dispose_word (op);
          COND_RETURN_ERROR ();
@@ -2886,6 +3059,11 @@ cond_term ()
     {
       if (tok < 256)
        parser_error (line_number, "unexpected token `%c' in conditional command", tok);
+      else if (etext = error_token_from_token (tok))
+       {
+         parser_error (line_number, "unexpected token `%s' in conditional command", etext);
+         free (etext);
+       }
       else
        parser_error (line_number, "unexpected token %d in conditional command", tok);
       COND_RETURN_ERROR ();
@@ -2905,6 +3083,40 @@ parse_cond_command ()
 }
 #endif
 
+#if defined (ARRAY_VARS)
+/* When this is called, it's guaranteed that we don't care about anything
+   in t beyond i.  We do save and restore the chars, though. */
+static int
+token_is_assignment (t, i)
+     char *t;
+     int i;
+{
+  unsigned char c, c1;
+  int r;
+
+  c = t[i]; c1 = t[i+1];
+  t[i] = '='; t[i+1] = '\0';
+  r = assignment (t);
+  t[i] = c; t[i+1] = c1;
+  return r;
+}
+
+static int
+token_is_ident (t, i)
+     char *t;
+     int i;
+{
+  unsigned char c;
+  int r;
+
+  c = t[i];
+  t[i] = '\0';
+  r = legal_identifier (t);
+  t[i] = c;
+  return r;
+}
+#endif
+
 static int
 read_token_word (character)
      int character;
@@ -2933,7 +3145,7 @@ read_token_word (character)
   int result, peek_char;
   char *ttok, *ttrans;
   int ttoklen, ttranslen;
-  long lvalue;
+  intmax_t lvalue;
 
   if (token_buffer_size < TOKEN_DEFAULT_INITIAL_SIZE)
     token = (char *)xrealloc (token, token_buffer_size = TOKEN_DEFAULT_INITIAL_SIZE);
@@ -2957,7 +3169,7 @@ read_token_word (character)
 
       /* Handle backslashes.  Quote lots of things when not inside of
         double-quotes, quote some things inside of double-quotes. */
-      if (character == '\\')
+      if MBTEST(character == '\\')
        {
          peek_char = shell_getc (0);
 
@@ -2983,7 +3195,7 @@ read_token_word (character)
        }
 
       /* Parse a matched pair of quote characters. */
-      if (shellquote (character))
+      if MBTEST(shellquote (character))
        {
          push_delimiter (dstack, character);
          ttok = parse_matched_pair (character, character, character, &ttoklen, 0);
@@ -3007,7 +3219,7 @@ read_token_word (character)
       if (extended_glob && PATTERN_CHAR (character))
        {
          peek_char = shell_getc (1);
-         if (peek_char == '(')         /* ) */
+         if MBTEST(peek_char == '(')           /* ) */
            {
              push_delimiter (dstack, peek_char);
              ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
@@ -3036,7 +3248,7 @@ read_token_word (character)
        {
          peek_char = shell_getc (1);
          /* $(...), <(...), >(...), $((...)), ${...}, and $[...] constructs */
-         if (peek_char == '(' ||
+         if MBTEST(peek_char == '(' || \
                ((peek_char == '{' || peek_char == '[') && character == '$'))   /* ) ] } */
            {
              if (peek_char == '{')             /* } */
@@ -3069,7 +3281,7 @@ read_token_word (character)
              goto next_character;
            }
          /* This handles $'...' and $"..." new-style quoted strings. */
-         else if (character == '$' && (peek_char == '\'' || peek_char == '"'))
+         else if MBTEST(character == '$' && (peek_char == '\'' || peek_char == '"'))
            {
              int first_line;
 
@@ -3121,7 +3333,7 @@ read_token_word (character)
            }
          /* This could eventually be extended to recognize all of the
             shell's single-character parameter expansions, and set flags.*/
-         else if (character == '$' && peek_char == '$')
+         else if MBTEST(character == '$' && peek_char == '$')
            {
              ttok = (char *)xmalloc (3);
              ttok[0] = ttok[1] = '$';
@@ -3141,27 +3353,42 @@ read_token_word (character)
        }
 
 #if defined (ARRAY_VARS)
+      /* Identify possible array subscript assignment; match [...] */
+      else if MBTEST(character == '[' && token_index > 0 && assignment_acceptable (last_read_token) && token_is_ident (token, token_index))    /* ] */
+        {
+         ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
+         if (ttok == &matched_pair_error)
+           return -1;          /* Bail immediately. */
+         RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
+                                 token_buffer_size,
+                                 TOKEN_DEFAULT_GROW_SIZE);
+         token[token_index++] = character;
+         strcpy (token + token_index, ttok);
+         token_index += ttoklen;
+         FREE (ttok);
+         all_digit_token = 0;
+         goto next_character;
+        }
       /* Identify possible compound array variable assignment. */
-      else if (character == '=' && token_index > 0)
+      else if MBTEST(character == '=' && token_index > 0 && token_is_assignment (token, token_index))
        {
          peek_char = shell_getc (1);
-         if (peek_char == '(')         /* ) */
+         if MBTEST(peek_char == '(')           /* ) */
            {
-             ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
-             if (ttok == &matched_pair_error)
-               return -1;              /* Bail immediately. */
-             if (ttok[0] == '(')       /* ) */
-               {
-                 FREE (ttok);
-                 return -1;
-               }
-             RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
+             ttok = parse_compound_assignment (&ttoklen);
+
+             RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 4,
                                      token_buffer_size,
                                      TOKEN_DEFAULT_GROW_SIZE);
-             token[token_index++] = character;
-             token[token_index++] = peek_char;
-             strcpy (token + token_index, ttok);
-             token_index += ttoklen;
+
+             token[token_index++] = '=';
+             token[token_index++] = '(';
+             if (ttok)
+               {
+                 strcpy (token + token_index, ttok);
+                 token_index += ttoklen;
+               }
+             token[token_index++] = ')';
              FREE (ttok);
              all_digit_token = 0;
              goto next_character;
@@ -3173,7 +3400,7 @@ read_token_word (character)
 
       /* When not parsing a multi-character word construct, shell meta-
         characters break words. */
-      if (shellbreak (character))
+      if MBTEST(shellbreak (character))
        {
          shell_ungetc (character);
          goto got_token;
@@ -3194,7 +3421,7 @@ read_token_word (character)
 
     next_character:
       if (character == '\n' && interactive &&
-       (bash_input.type == st_stdin || bash_input.type == st_stream))
+          (bash_input.type == st_stdin || bash_input.type == st_stream))
        prompt_again ();
 
       /* We want to remove quoted newlines (that is, a \<newline> pair)
@@ -3212,8 +3439,8 @@ got_token:
      is a `<', or a `&', or the character which ended this token is
      a '>' or '<', then, and ONLY then, is this input token a NUMBER.
      Otherwise, it is just a word, and should be returned as such. */
-  if (all_digit_token && (character == '<' || character == '>' ||
-                   last_read_token == LESS_AND ||
+  if MBTEST(all_digit_token && (character == '<' || character == '>' || \
+                   last_read_token == LESS_AND || \
                    last_read_token == GREATER_AND))
       {
        if (legal_number (token, &lvalue) && (int)lvalue == lvalue)
@@ -3224,7 +3451,7 @@ got_token:
       }
 
   /* Check for special case tokens. */
-  result = special_case_tokens (token);
+  result = (last_shell_getc_is_singlebyte) ? special_case_tokens (token) : -1;
   if (result >= 0)
     return result;
 
@@ -3232,7 +3459,7 @@ got_token:
   /* Posix.2 does not allow reserved words to be aliased, so check for all
      of them, including special cases, before expanding the current token
      as an alias. */
-  if (posixly_correct)
+  if MBTEST(posixly_correct)
     CHECK_FOR_RESERVED_WORD (token);
 
   /* Aliases are expanded iff EXPAND_ALIASES is non-zero, and quoting
@@ -3248,7 +3475,7 @@ got_token:
 
   /* If not in Posix.2 mode, check for reserved words after alias
      expansion. */
-  if (posixly_correct == 0)
+  if MBTEST(posixly_correct == 0)
 #endif
     CHECK_FOR_RESERVED_WORD (token);
 
@@ -3285,172 +3512,45 @@ got_token:
   return (result);
 }
 
-/* $'...' ANSI-C expand the portion of STRING between START and END and
-   return the result.  The result cannot be longer than the input string. */
-static char *
-ansiexpand (string, start, end, lenp)
-     char *string;
-     int start, end, *lenp;
-{
-  char *temp, *t;
-  int len, tlen;
-
-  temp = (char *)xmalloc (end - start + 1);
-  for (tlen = 0, len = start; len < end; )
-    temp[tlen++] = string[len++];
-  temp[tlen] = '\0';
-
-  if (*temp)
-    {
-      t = ansicstr (temp, tlen, 0, (int *)NULL, lenp);
-      free (temp);
-      return (t);
-    }
-  else
-    {
-      if (lenp)
-       *lenp = 0;
-      return (temp);
-    }
-}
-
-/* Change a bash string into a string suitable for inclusion in a `po' file.
-   This backslash-escapes `"' and `\' and changes newlines into \\\n"\n". */
-static char *
-mk_msgstr (string, foundnlp)
-     char *string;
-     int *foundnlp;
-{
-  register int c, len;
-  char *result, *r, *s;
-
-  for (len = 0, s = string; s && *s; s++)
-    {
-      len++;
-      if (*s == '"' || *s == '\\')
-       len++;
-      else if (*s == '\n')
-       len += 5;
-    }
-  
-  r = result = (char *)xmalloc (len + 3);
-  *r++ = '"';
-
-  for (s = string; s && (c = *s); s++)
-    {
-      if (c == '\n')   /* <NL> -> \n"<NL>" */
-       {
-         *r++ = '\\';
-         *r++ = 'n';
-         *r++ = '"';
-         *r++ = '\n';
-         *r++ = '"';
-         if (foundnlp)
-           *foundnlp = 1;
-         continue;
-       }
-      if (c == '"' || c == '\\')
-       *r++ = '\\';
-      *r++ = c;
-    }
-
-  *r++ = '"';
-  *r++ = '\0';
-
-  return result;
-}
-
-/* $"..." -- Translate the portion of STRING between START and END
-   according to current locale using gettext (if available) and return
-   the result.  The caller will take care of leaving the quotes intact.
-   The string will be left without the leading `$' by the caller.
-   If translation is performed, the translated string will be double-quoted
-   by the caller.  The length of the translated string is returned in LENP,
-   if non-null. */
-static char *
-localeexpand (string, start, end, lineno, lenp)
-     char *string;
-     int start, end, lineno, *lenp;
-{
-  int len, tlen, foundnl;
-  char *temp, *t, *t2;
-
-  temp = (char *)xmalloc (end - start + 1);
-  for (tlen = 0, len = start; len < end; )
-    temp[tlen++] = string[len++];
-  temp[tlen] = '\0';
-
-  /* If we're just dumping translatable strings, don't do anything with the
-     string itself, but if we're dumping in `po' file format, convert it into a form more palatable to gettext(3)
-     and friends by quoting `"' and `\' with backslashes and converting <NL>
-     into `\n"<NL>"'.  If we find a newline in TEMP, we first output a
-     `msgid ""' line and then the translated string; otherwise we output the
-     `msgid' and translated string all on one line. */
-  if (dump_translatable_strings)
-    {
-      if (dump_po_strings)
-       {
-         foundnl = 0;
-         t = mk_msgstr (temp, &foundnl);
-         t2 = foundnl ? "\"\"\n" : "";
-
-         printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
-                 (bash_input.name ? bash_input.name : "stdin"), lineno, t2, t);
-         free (t);
-       }
-      else
-       printf ("\"%s\"\n", temp);
-
-      if (lenp)
-       *lenp = tlen;
-      return (temp);
-    }
-  else if (*temp)
-    {
-      t = localetrans (temp, tlen, &len);
-      free (temp);
-      if (lenp)
-       *lenp = len;
-      return (t);
-    }
-  else
-    {
-      if (lenp)
-       *lenp = 0;
-      return (temp);
-    }
-}
-
 /* Return 1 if TOKSYM is a token that after being read would allow
    a reserved word to be seen, else 0. */
 static int
 reserved_word_acceptable (toksym)
      int toksym;
 {
-  if (toksym == '\n' || toksym == ';' || toksym == '(' || toksym == ')' ||
-      toksym == '|' || toksym == '&' || toksym == '{' ||
-      toksym == '}' ||                 /* XXX */
-      toksym == AND_AND ||
-      toksym == BANG ||
-      toksym == TIME || toksym == TIMEOPT ||
-      toksym == DO ||
-      toksym == ELIF ||
-      toksym == ELSE ||
-      toksym == FI ||
-      toksym == IF ||
-      toksym == OR_OR ||
-      toksym == SEMI_SEMI ||
-      toksym == THEN ||
-      toksym == UNTIL ||
-      toksym == WHILE ||
-      toksym == DONE ||                /* XXX these two are experimental */
-      toksym == ESAC ||
-      toksym == 0)
-    return (1);
-  else
-    return (0);
+  switch (toksym)
+    {
+    case '\n':
+    case ';':
+    case '(':
+    case ')':
+    case '|':
+    case '&':
+    case '{':
+    case '}':          /* XXX */
+    case AND_AND:
+    case BANG:
+    case DO:
+    case DONE:
+    case ELIF:
+    case ELSE:
+    case ESAC:
+    case FI:
+    case IF:
+    case OR_OR:
+    case SEMI_SEMI:
+    case THEN:
+    case TIME:
+    case TIMEOPT:
+    case UNTIL:
+    case WHILE:
+    case 0:
+      return 1;
+    default:
+      return 0;
+    }
 }
-
+    
 /* Return the index of TOKEN in the alist of reserved words, or -1 if
    TOKEN is not a shell reserved word. */
 int
@@ -3625,24 +3725,27 @@ print_prompt ()
    may contain special characters which are decoded as follows:
 
        \a      bell (ascii 07)
-       \e      escape (ascii 033)
        \d      the date in Day Mon Date format
+       \e      escape (ascii 033)
        \h      the hostname up to the first `.'
        \H      the hostname
        \j      the number of active jobs
        \l      the basename of the shell's tty device name
        \n      CRLF
+       \r      CR
        \s      the name of the shell
        \t      the time in 24-hour hh:mm:ss format
        \T      the time in 12-hour hh:mm:ss format
-       \@      the time in 12-hour am/pm format
+       \@      the time in 12-hour hh:mm am/pm format
+       \A      the time in 24-hour hh:mm format
+       \D{fmt} the result of passing FMT to strftime(3)
+       \u      your username
        \v      the version of bash (e.g., 2.00)
        \V      the release of bash, version + patchlevel (e.g., 2.00.0)
        \w      the current working directory
        \W      the last element of $PWD
-       \u      your username
-       \#      the command number of this command
        \!      the history number of this command
+       \#      the command number of this command
        \$      a $ or a # if you are root
        \nnn    character code nnn in octal
        \\      a backslash
@@ -3662,7 +3765,10 @@ decode_prompt_string (string)
   int result_size, result_index;
   int c, n;
   char *temp, octal_string[4];
+  struct tm *tm;  
   time_t the_time;
+  char timebuf[128];
+  char *timefmt;
 
   result = (char *)xmalloc (result_size = PROMPT_GROWTH);
   result[result_index = 0] = 0;
@@ -3728,52 +3834,64 @@ decode_prompt_string (string)
              for (c = 0; n != -1 && c < 3 && ISOCTAL (*string); c++)
                string++;
 
-             c = 0;
+             c = 0;            /* tested at add_string: */
              goto add_string;
 
-           case 't':
            case 'd':
+           case 't':
            case 'T':
            case '@':
            case 'A':
              /* Make the current time/date into a string. */
-             the_time = time (0);
-             temp = ctime (&the_time);
+             (void) time (&the_time);
+             tm = localtime (&the_time);
+
+             if (c == 'd')
+               n = strftime (timebuf, sizeof (timebuf), "%a %b %d", tm);
+             else if (c == 't')
+               n = strftime (timebuf, sizeof (timebuf), "%H:%M:%S", tm);
+             else if (c == 'T')
+               n = strftime (timebuf, sizeof (timebuf), "%I:%M:%S", tm);
+             else if (c == '@')
+               n = strftime (timebuf, sizeof (timebuf), "%I:%M %p", tm);
+             else if (c == 'A')
+               n = strftime (timebuf, sizeof (timebuf), "%H:%M", tm);
+
+             timebuf[sizeof(timebuf) - 1] = '\0';
+             temp = savestring (timebuf);
+             goto add_string;
 
-             temp = (c != 'd') ? savestring (temp + 11) : savestring (temp);
-             temp[(c != 'd') ? 8 : 10] = '\0';
-             temp[(c != 'A') ? 10 : 5] = '\0';
+           case 'D':           /* strftime format */
+             if (string[1] != '{')             /* } */
+               goto not_escape;
 
-             /* quick and dirty conversion to 12-hour time */
-             if (c == 'T' || c == '@')
+             (void) time (&the_time);
+             tm = localtime (&the_time);
+             string += 2;                      /* skip { */
+             timefmt = xmalloc (strlen (string) + 3);
+             for (t = timefmt; *string && *string != '}'; )
+               *t++ = *string++;
+             *t = '\0';
+             c = *string;      /* tested at add_string */
+             if (timefmt[0] == '\0')
                {
-                 if (c == '@')
-                   {
-                     temp[5] = 'a';    /* am/pm format */
-                     temp[6] = 'm';
-                     temp[7] = '\0';
-                   }
-                 c = temp[2];
-                 temp[2] = '\0';
-                 n = atoi (temp);
-                 temp[2] = c;
-                 n -= 12;
-                 if (n > 0)
-                   {
-                     temp[0] = (n / 10) + '0';
-                     temp[1] = (n % 10) + '0';
-                   }
-                 if (n >= 0 && temp[5] == 'a')
-                   temp[5] = 'p';
+                 timefmt[0] = '%';
+                 timefmt[1] = 'X';     /* locale-specific current time */
+                 timefmt[2] = '\0';
                }
+             n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
+             free (timefmt);
+
+             timebuf[sizeof(timebuf) - 1] = '\0';
+             if (promptvars || posixly_correct)
+               /* Make sure that expand_prompt_string is called with a
+                  second argument of Q_DOUBLE_QUOTES if we use this
+                  function here. */
+               temp = sh_backslash_quote_for_double_quotes (timebuf);
+             else
+               temp = savestring (timebuf);
              goto add_string;
-
-           case 'r':
-             temp = (char *)xmalloc (2);
-             temp[0] = '\r';
-             temp[1] = '\0';
-             goto add_string;
-
+             
            case 'n':
              temp = (char *)xmalloc (3);
              temp[0] = no_line_editing ? '\n' : '\r';
@@ -3788,7 +3906,7 @@ decode_prompt_string (string)
 
            case 'v':
            case 'V':
-             temp = (char *)xmalloc (8);
+             temp = (char *)xmalloc (16);
              if (c == 'v')
                strcpy (temp, dist_version);
              else
@@ -3843,7 +3961,7 @@ decode_prompt_string (string)
                   quote the directory name. */
                if (promptvars || posixly_correct)
                  /* Make sure that expand_prompt_string is called with a
-                    second argument of Q_DOUBLE_QUOTE if we use this
+                    second argument of Q_DOUBLE_QUOTES if we use this
                     function here. */
                  temp = sh_backslash_quote_for_double_quotes (t_string);
                else
@@ -3910,19 +4028,23 @@ decode_prompt_string (string)
 #endif /* READLINE */
 
            case '\\':
-             temp = (char *)xmalloc (2);
-             temp[0] = c;
-             temp[1] = '\0';
-             goto add_string;
-
            case 'a':
            case 'e':
+           case 'r':
              temp = (char *)xmalloc (2);
-             temp[0] = (c == 'a') ? '\07' : '\033';
+             if (c == 'a')
+               temp[0] = '\07';
+             else if (c == 'e')
+               temp[0] = '\033';
+             else if (c == 'r')
+               temp[0] = '\r';
+             else                      /* (c == '\\') */
+               temp[0] = c;
              temp[1] = '\0';
              goto add_string;
 
            default:
+not_escape:
              temp = (char *)xmalloc (3);
              temp[0] = '\\';
              temp[1] = c;
@@ -3979,6 +4101,12 @@ decode_prompt_string (string)
   return (result);
 }
 
+/************************************************
+ *                                             *
+ *             ERROR HANDLING                  *
+ *                                             *
+ ************************************************/
+
 /* Report a syntax error, and restart the parser.  Call here for fatal
    errors. */
 int
@@ -3990,6 +4118,103 @@ yyerror (msg)
   return (0);
 }
 
+static char *
+error_token_from_token (token)
+     int token;
+{
+  char *t;
+
+  if (t = find_token_in_alist (token, word_token_alist, 0))
+    return t;
+
+  if (t = find_token_in_alist (token, other_token_alist, 0))
+    return t;
+
+  t = (char *)NULL;
+  /* This stuff is dicy and needs closer inspection */
+  switch (current_token)
+    {
+    case WORD:
+    case ASSIGNMENT_WORD:
+      if (yylval.word)
+       t = savestring (yylval.word->word);
+      break;
+    case NUMBER:
+      t = itos (yylval.number);
+      break;
+    case ARITH_CMD:
+      if (yylval.word_list)
+        t = string_list (yylval.word_list);
+      break;
+    case ARITH_FOR_EXPRS:
+      if (yylval.word_list)
+       t = string_list_internal (yylval.word_list, " ; ");
+      break;
+    case COND_CMD:
+      t = (char *)NULL;                /* punt */
+      break;
+    }
+
+  return t;
+}
+
+static char *
+error_token_from_text ()
+{
+  char *msg, *t;
+  int token_end, i;
+
+  t = shell_input_line;
+  i = shell_input_line_index;
+  token_end = 0;
+  msg = (char *)NULL;
+
+  if (i && t[i] == '\0')
+    i--;
+
+  while (i && (whitespace (t[i]) || t[i] == '\n'))
+    i--;
+
+  if (i)
+    token_end = i + 1;
+
+  while (i && (member (t[i], " \n\t;|&") == 0))
+    i--;
+
+  while (i != token_end && (whitespace (t[i]) || t[i] == '\n'))
+    i++;
+
+  /* Return our idea of the offending token. */
+  if (token_end || (i == 0 && token_end == 0))
+    {
+      if (token_end)
+       msg = substring (t, i, token_end);
+      else     /* one-character token */
+       {
+         msg = (char *)xmalloc (2);
+         msg[0] = t[i];
+         msg[1] = '\0';
+       }
+    }
+
+  return (msg);
+}
+
+static void
+print_offending_line ()
+{
+  char *msg;
+  int token_end;
+
+  msg = savestring (shell_input_line);
+  token_end = strlen (msg);
+  while (token_end && msg[token_end - 1] == '\n')
+    msg[--token_end] = '\0';
+
+  parser_error (line_number, "`%s'", msg);
+  free (msg);
+}
+
 /* Report a syntax error with line numbers, etc.
    Call here for recoverable errors.  If you have a message to print,
    then place it in MESSAGE, otherwise pass NULL and this will figure
@@ -3998,9 +4223,7 @@ static void
 report_syntax_error (message)
      char *message;
 {
-  char *msg, *t;
-  int token_end, i;
-  char msg2[2];
+  char *msg;
 
   if (message)
     {
@@ -4012,57 +4235,35 @@ report_syntax_error (message)
     }
 
   /* If the line of input we're reading is not null, try to find the
-     objectionable token. */
-  if (shell_input_line && *shell_input_line)
+     objectionable token.  First, try to figure out what token the
+     parser's complaining about by looking at current_token. */
+  if (current_token != 0 && EOF_Reached == 0 && (msg = error_token_from_token (current_token)))
     {
-      t = shell_input_line;
-      i = shell_input_line_index;
-      token_end = 0;
-
-      if (i && t[i] == '\0')
-       i--;
-
-      while (i && (whitespace (t[i]) || t[i] == '\n'))
-       i--;
+      parser_error (line_number, "syntax error near unexpected token `%s'", msg);
+      free (msg);
 
-      if (i)
-       token_end = i + 1;
-
-      while (i && (member (t[i], " \n\t;|&") == 0))
-       i--;
+      if (interactive == 0)
+       print_offending_line ();
 
-      while (i != token_end && (whitespace (t[i]) || t[i] == '\n'))
-       i++;
+      last_command_exit_value = EX_USAGE;
+      return;
+    }
 
-      /* Print the offending token. */
-      if (token_end || (i == 0 && token_end == 0))
+  /* If looking at the current token doesn't prove fruitful, try to find the
+     offending token by analyzing the text of the input line near the current
+     input line index and report what we find. */
+  if (shell_input_line && *shell_input_line)
+    {
+      msg = error_token_from_text ();
+      if (msg)
        {
-         if (token_end)
-           msg = substring (t, i, token_end);
-         else  /* one-character token */
-           {
-             msg2[0] = t[i];
-             msg2[1] = '\0';
-             msg = msg2;
-           }
-
-         parser_error (line_number, "syntax error near unexpected token `%s'", msg);
-
-         if (msg != msg2)
-           free (msg);
+         parser_error (line_number, "syntax error near `%s'", msg);
+         free (msg);
        }
 
       /* If not interactive, print the line containing the error. */
       if (interactive == 0)
-       {
-         msg = savestring (shell_input_line);
-         token_end = strlen (msg);
-         while (token_end && msg[token_end - 1] == '\n')
-           msg[--token_end] = '\0';
-
-         parser_error (line_number, "`%s'", msg);
-         free (msg);
-       }
+        print_offending_line ();
     }
   else
     {
@@ -4074,6 +4275,7 @@ report_syntax_error (message)
       if (interactive && EOF_Reached)
        EOF_Reached = 0;
     }
+
   last_command_exit_value = EX_USAGE;
 }
 
@@ -4081,13 +4283,19 @@ report_syntax_error (message)
    created during parsing.  In the case of error, we want to return
    allocated objects to the memory pool.  In the case of no error, we want
    to throw away the information about where the allocated objects live.
-   (dispose_command () will actually free the command. */
+   (dispose_command () will actually free the command.) */
 static void
 discard_parser_constructs (error_p)
      int error_p;
 {
 }
 
+/************************************************
+ *                                             *
+ *             EOF HANDLING                    *
+ *                                             *
+ ************************************************/
+
 /* Do that silly `type "bye" to exit' stuff.  You know, "ignoreeof". */
 
 /* A flag denoting whether or not ignoreeof is set. */
@@ -4124,10 +4332,11 @@ handle_eof_input_unit ()
              fprintf (stderr, "Use \"%s\" to leave the shell.\n",
                       login_shell ? "logout" : "exit");
              eof_encountered++;
+             /* Reset the parsing state. */
+             last_read_token = current_token = '\n';
              /* Reset the prompt string to be $PS1. */
              prompt_string_pointer = (char **)NULL;
              prompt_again ();
-             last_read_token = current_token = '\n';
              return;
            }
        }
@@ -4143,6 +4352,15 @@ handle_eof_input_unit ()
     }
 }
 
+/************************************************
+ *                                             *
+ *     STRING PARSING FUNCTIONS                *
+ *                                             *
+ ************************************************/
+
+/* It's very important that these two functions treat the characters
+   between ( and ) identically. */
+
 static WORD_LIST parse_string_error;
 
 /* Take a string and run it through the shell parser, returning the
@@ -4153,8 +4371,9 @@ parse_string_to_word_list (s, whom)
      const char *whom;
 {
   WORD_LIST *wl;
-  int tok, orig_line_number, orig_input_terminator;
+  int tok, orig_current_token, orig_line_number, orig_input_terminator;
   int orig_line_count;
+  int old_echo_input, old_expand_aliases;
 #if defined (HISTORY)
   int old_remember_on_history, old_history_expansion_inhibited;
 #endif
@@ -4170,10 +4389,13 @@ parse_string_to_word_list (s, whom)
   orig_line_number = line_number;
   orig_line_count = current_command_line_count;
   orig_input_terminator = shell_input_line_terminator;
+  old_echo_input = echo_input_at_read;
+  old_expand_aliases = expand_aliases;
 
   push_stream (1);
-  last_read_token = '\n';
+  last_read_token = WORD;              /* WORD to allow reserved words here */
   current_command_line_count = 0;
+  echo_input_at_read = expand_aliases = 0;
 
   with_input_from_string (s, whom);
   wl = (WORD_LIST *)NULL;
@@ -4186,7 +4408,10 @@ parse_string_to_word_list (s, whom)
       if (tok != WORD && tok != ASSIGNMENT_WORD)
        {
          line_number = orig_line_number + line_number - 1;
+         orig_current_token = current_token;
+         current_token = tok;
          yyerror ((char *)NULL);       /* does the right thing */
+         current_token = orig_current_token;
          if (wl)
            dispose_words (wl);
          wl = &parse_string_error;
@@ -4205,6 +4430,9 @@ parse_string_to_word_list (s, whom)
 #  endif /* BANG_HISTORY */
 #endif /* HISTORY */
 
+  echo_input_at_read = old_echo_input;
+  expand_aliases = old_expand_aliases;
+
   current_command_line_count = orig_line_count;
   shell_input_line_terminator = orig_input_terminator;
 
@@ -4219,3 +4447,126 @@ parse_string_to_word_list (s, whom)
 
   return (REVERSE_LIST (wl, WORD_LIST *));
 }
+
+static char *
+parse_compound_assignment (retlenp)
+     int *retlenp;
+{
+  WORD_LIST *wl, *rl;
+  int tok, orig_line_number, orig_token_size;
+  char *saved_token, *ret;
+
+  saved_token = token;
+  orig_token_size = token_buffer_size;
+  orig_line_number = line_number;
+
+  last_read_token = WORD;      /* WORD to allow reserved words here */
+
+  token = (char *)NULL;
+  token_buffer_size = 0;
+
+  wl = (WORD_LIST *)NULL;      /* ( */
+  while ((tok = read_token (READ)) != ')')
+    {
+      if (tok == '\n')                 /* Allow newlines in compound assignments */
+       continue;
+      if (tok != WORD && tok != ASSIGNMENT_WORD)
+       {
+         current_token = tok;  /* for error reporting */
+         if (tok == yacc_EOF)  /* ( */
+           parser_error (orig_line_number, "unexpected EOF while looking for matching `)'");
+         else
+           yyerror ((char *)NULL);     /* does the right thing */
+         if (wl)
+           dispose_words (wl);
+         wl = &parse_string_error;
+         break;
+       }
+      wl = make_word_list (yylval.word, wl);
+    }
+
+  FREE (token);
+  token = saved_token;
+  token_buffer_size = orig_token_size;
+
+  if (wl == &parse_string_error)
+    {
+      last_command_exit_value = EXECUTION_FAILURE;
+      last_read_token = '\n';  /* XXX */
+      if (interactive_shell == 0 && posixly_correct)
+       jump_to_top_level (FORCE_EOF);
+      else
+       jump_to_top_level (DISCARD);
+    }
+
+  last_read_token = WORD;
+  if (wl)
+    {
+      rl = REVERSE_LIST (wl, WORD_LIST *);
+      ret = string_list (rl);
+      dispose_words (rl);
+    }
+  else
+    ret = (char *)NULL;
+
+  if (retlenp)
+    *retlenp = (ret && *ret) ? strlen (ret) : 0;
+  return ret;
+}
+
+/************************************************
+ *                                             *
+ *     MULTIBYTE CHARACTER HANDLING            *
+ *                                             *
+ ************************************************/
+
+#if defined (HANDLE_MULTIBYTE)
+static void
+set_line_mbstate ()
+{
+  int i, previ, len;
+  mbstate_t mbs, prevs;
+  size_t mbclen;
+
+  if (shell_input_line == NULL)
+    return;
+  len = strlen (shell_input_line);     /* XXX - shell_input_line_len ? */
+  FREE (shell_input_line_property);
+  shell_input_line_property = (char *)xmalloc (len + 1);
+
+  memset (&prevs, '\0', sizeof (mbstate_t));
+  for (i = previ = 0; i < len; i++)
+    {
+      mbs = prevs;
+
+      if (shell_input_line[i] == EOF)
+       {
+         int j;
+         for (j = i; j < len; j++)
+           shell_input_line_property[j] = 1;
+         break;
+       }
+
+      mbclen = mbrlen (shell_input_line + previ, i - previ + 1, &mbs);
+      if (mbclen == 1 || mbclen == (size_t)-1)
+       {
+         mbclen = 1;
+         previ = i + 1;
+       }
+      else if (mbclen == (size_t)-2)
+        mbclen = 0;
+      else if (mbclen > 1)
+       {
+         mbclen = 0;
+         previ = i + 1;
+         prevs = mbs;
+       }
+      else
+       {
+         /* mbrlen doesn't return any other values */
+       }
+
+      shell_input_line_property[i] = mbclen;
+    }
+}
+#endif /* HANDLE_MULTIBYTE */
index f371cab501222ba395f6024eb4c396808da61baf..565b03991b3be1103caa3eb8bd48da96c3d496f7 100644 (file)
@@ -1,3 +1,7 @@
+#ifndef BISON_Y_TAB_H
+# define BISON_Y_TAB_H
+
+#ifndef YYSTYPE
 typedef union {
   WORD_DESC *word;             /* the word that we read. */
   int number;                  /* the number that we read. */
@@ -6,46 +10,51 @@ typedef union {
   REDIRECT *redirect;
   ELEMENT element;
   PATTERN_LIST *pattern;
-} YYSTYPE;
-#define        IF      257
-#define        THEN    258
-#define        ELSE    259
-#define        ELIF    260
-#define        FI      261
-#define        CASE    262
-#define        ESAC    263
-#define        FOR     264
-#define        SELECT  265
-#define        WHILE   266
-#define        UNTIL   267
-#define        DO      268
-#define        DONE    269
-#define        FUNCTION        270
-#define        COND_START      271
-#define        COND_END        272
-#define        COND_ERROR      273
-#define        IN      274
-#define        BANG    275
-#define        TIME    276
-#define        TIMEOPT 277
-#define        WORD    278
-#define        ASSIGNMENT_WORD 279
-#define        NUMBER  280
-#define        ARITH_CMD       281
-#define        ARITH_FOR_EXPRS 282
-#define        COND_CMD        283
-#define        AND_AND 284
-#define        OR_OR   285
-#define        GREATER_GREATER 286
-#define        LESS_LESS       287
-#define        LESS_AND        288
-#define        GREATER_AND     289
-#define        SEMI_SEMI       290
-#define        LESS_LESS_MINUS 291
-#define        AND_GREATER     292
-#define        LESS_GREATER    293
-#define        GREATER_BAR     294
-#define        yacc_EOF        295
+} yystype;
+# define YYSTYPE yystype
+#endif
+# define       IF      257
+# define       THEN    258
+# define       ELSE    259
+# define       ELIF    260
+# define       FI      261
+# define       CASE    262
+# define       ESAC    263
+# define       FOR     264
+# define       SELECT  265
+# define       WHILE   266
+# define       UNTIL   267
+# define       DO      268
+# define       DONE    269
+# define       FUNCTION        270
+# define       COND_START      271
+# define       COND_END        272
+# define       COND_ERROR      273
+# define       IN      274
+# define       BANG    275
+# define       TIME    276
+# define       TIMEOPT 277
+# define       WORD    278
+# define       ASSIGNMENT_WORD 279
+# define       NUMBER  280
+# define       ARITH_CMD       281
+# define       ARITH_FOR_EXPRS 282
+# define       COND_CMD        283
+# define       AND_AND 284
+# define       OR_OR   285
+# define       GREATER_GREATER 286
+# define       LESS_LESS       287
+# define       LESS_AND        288
+# define       LESS_LESS_LESS  289
+# define       GREATER_AND     290
+# define       SEMI_SEMI       291
+# define       LESS_LESS_MINUS 292
+# define       AND_GREATER     293
+# define       LESS_GREATER    294
+# define       GREATER_BAR     295
+# define       yacc_EOF        296
 
 
 extern YYSTYPE yylval;
+
+#endif /* not BISON_Y_TAB_H */
index aae09a7051fead8bac8d014f4e3a30814935a583..a498672f51ec668c266fb581a0a637b726b913c2 100644 (file)
--- a/pathexp.c
+++ b/pathexp.c
@@ -1,6 +1,6 @@
 /* pathexp.c -- The shell interface to the globbing library. */
 
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 #include "pathexp.h"
 #include "flags.h"
 
+#include "shmbutil.h"
+
 #include <glob/strmatch.h>
 
+static int glob_name_is_acceptable __P((const char *));
+static void ignore_globbed_names __P((char **, sh_ignore_func_t *));
+               
 #if defined (USE_POSIX_GLOB_LIBRARY)
 #  include <glob.h>
 typedef int posix_glob_errfunc_t __P((const char *, int));
@@ -54,9 +59,14 @@ unquoted_glob_pattern_p (string)
      register char *string;
 {
   register int c;
+  char *send;
   int open;
 
+  DECLARE_MBSTATE;
+
   open = 0;
+  send = string + strlen (string);
+
   while (c = *string++)
     {
       switch (c)
@@ -86,6 +96,16 @@ unquoted_glob_pattern_p (string)
          if (*string++ == '\0')
            return (0);
        }
+
+      /* Advance one fewer byte than an entire multibyte character to
+        account for the auto-increment in the loop above. */
+#ifdef HANDLE_MULTIBYTE
+      string--;
+      ADVANCE_CHAR_P (string, send - string);
+      string++;
+#else
+      ADVANCE_CHAR_P (string, send - string);
+#endif
     }
   return (0);
 }
@@ -123,9 +143,11 @@ quote_string_for_globbing (pathname, qflags)
          if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
            continue;
          temp[j++] = '\\';
+         i++;
+         if (pathname[i] == '\0')
+           break;
        }
-      else
-       temp[j++] = pathname[i];
+      temp[j++] = pathname[i];
     }
   temp[j] = '\0';
 
@@ -136,9 +158,14 @@ char *
 quote_globbing_chars (string)
      char *string;
 {
-  char *temp, *s, *t;
+  size_t slen;
+  char *temp, *s, *t, *send;
+  DECLARE_MBSTATE;
+
+  slen = strlen (string);
+  send = string + slen;
 
-  temp = (char *)xmalloc (strlen (string) * 2 + 1);
+  temp = (char *)xmalloc (slen * 2 + 1);
   for (t = temp, s = string; *s; )
     {
       switch (*s)
@@ -157,7 +184,10 @@ quote_globbing_chars (string)
            *t++ = '\\';
          break;
        }
-      *t++ = *s++;
+
+      /* Copy a single (possibly multibyte) character from s to t,
+         incrementing both. */
+      COPY_CHAR_P (t, s, send);
     }
   *t = '\0';
   return temp;
@@ -204,7 +234,7 @@ shell_glob_filename (pathname)
       if (should_ignore_glob_matches ())
        ignore_glob_matches (results);
       if (results && results[0])
-       sort_char_array (results);
+       strvec_sort (results);
       else
        {
          FREE (results);
@@ -221,8 +251,7 @@ shell_glob_filename (pathname)
   noglob_dot_filenames = glob_dot_filenames == 0;
 
   temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
-
-  results = glob_filename (temp);
+  results = glob_filename (temp, 0);
   free (temp);
 
   if (results && ((GLOB_FAILED (results)) == 0))
@@ -230,7 +259,7 @@ shell_glob_filename (pathname)
       if (should_ignore_glob_matches ())
        ignore_glob_matches (results);
       if (results && results[0])
-       sort_char_array (results);
+       strvec_sort (results);
       else
        {
          FREE (results);
@@ -314,7 +343,7 @@ ignore_globbed_names (names, name_func)
 
   for (i = 0; names[i]; i++)
     ;
-  newnames = alloc_array (i + 1);
+  newnames = strvec_create (i + 1);
 
   for (n = i = 0; names[i]; i++)
     {
index 17d37d51ba07213843d7358994664415e45ee67f..181135129aecd4d19a415f1294994dfe96931832 100644 (file)
@@ -1,7 +1,7 @@
 /* pcomplete.c - functions to generate lists of matches for programmable
                 completion. */
 
-/* Copyright (C) 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -35,9 +35,7 @@
 #if defined (PREFER_STDARG)
 #  include <stdarg.h>
 #else
-#  if defined (PREFER_VARARGS)
-#    include <varargs.h>
-#  endif
+#  include <varargs.h>
 #endif
 
 #include <stdio.h>
@@ -83,9 +81,11 @@ extern int array_needs_making;
 extern STRING_INT_ALIST word_token_alist[];
 extern char *signal_names[];
 
-#if defined(PREFER_STDARG)
+#if defined (DEBUG)
+#if defined (PREFER_STDARG)
 static void debug_printf (const char *, ...)  __attribute__((__format__ (printf, 1, 2)));
 #endif
+#endif /* DEBUG */
 
 static int it_init_joblist __P((ITEMLIST *, int));
 
@@ -132,7 +132,9 @@ static void unbind_compfunc_variables __P((int));
 static WORD_LIST *build_arg_list __P((char *, const char *, WORD_LIST *, int));
 static WORD_LIST *command_line_to_word_list __P((char *, int, int, int *, int *));
 
+#ifdef DEBUG
 static int progcomp_debug = 0;
+#endif
 
 int prog_completion_enabled = 1;
 
@@ -146,34 +148,23 @@ ITEMLIST it_directories = { LIST_DYNAMIC };       /* unused */
 ITEMLIST it_disabled = { 0, it_init_disabled, (STRINGLIST *)0 };
 ITEMLIST it_enabled = { 0, it_init_enabled, (STRINGLIST *)0 };
 ITEMLIST it_exports  = { LIST_DYNAMIC, it_init_exported, (STRINGLIST *)0 };
-ITEMLIST it_files = { LIST_DYNAMIC };  /* unused */
+ITEMLIST it_files = { LIST_DYNAMIC };          /* unused */
 ITEMLIST it_functions  = { 0, it_init_functions, (STRINGLIST *)0 };
 ITEMLIST it_hostnames  = { LIST_DYNAMIC, it_init_hostnames, (STRINGLIST *)0 };
-ITEMLIST it_groups = { LIST_DYNAMIC }; /* unused */
+ITEMLIST it_groups = { LIST_DYNAMIC };         /* unused */
 ITEMLIST it_jobs = { LIST_DYNAMIC, it_init_jobs, (STRINGLIST *)0 };
 ITEMLIST it_keywords = { 0, it_init_keywords, (STRINGLIST *)0 };
 ITEMLIST it_running = { LIST_DYNAMIC, it_init_running, (STRINGLIST *)0 };
+ITEMLIST it_services = { LIST_DYNAMIC };       /* unused */
 ITEMLIST it_setopts = { 0, it_init_setopts, (STRINGLIST *)0 };
 ITEMLIST it_shopts = { 0, it_init_shopts, (STRINGLIST *)0 };
 ITEMLIST it_signals = { 0, it_init_signals, (STRINGLIST *)0 };
 ITEMLIST it_stopped = { LIST_DYNAMIC, it_init_stopped, (STRINGLIST *)0 };
-ITEMLIST it_users = { LIST_DYNAMIC };  /* unused */
+ITEMLIST it_users = { LIST_DYNAMIC };          /* unused */
 ITEMLIST it_variables = { LIST_DYNAMIC, it_init_variables, (STRINGLIST *)0 };
 
+#ifdef DEBUG
 /* Debugging code */
-#if !defined (USE_VARARGS)
-static void
-debug_printf (format, arg1, arg2, arg3, arg4, arg5)
-     char *format;
-{
-  if (progcomp_debug == 0)
-    return;
-
-  fprintf (stdout, format, arg1, arg2, arg3, arg4, arg5);
-  fprintf (stdout, "\n");
-  rl_on_new_line ();
-}
-#else
 static void
 #if defined (PREFER_STDARG)
 debug_printf (const char *format, ...)
@@ -188,11 +179,7 @@ debug_printf (format, va_alist)
   if (progcomp_debug == 0)
     return;
 
-#if defined (PREFER_STDARG)
-  va_start (args, format);
-#else
-  va_start (args);
-#endif
+  SH_VA_START (args, format);
 
   fprintf (stdout, "DEBUG: ");
   vfprintf (stdout, format, args);
@@ -202,7 +189,7 @@ debug_printf (format, va_alist)
 
   va_end (args);
 }
-#endif /* USE_VARARGS */
+#endif
 
 /* Functions to manage the item lists */
 
@@ -232,7 +219,7 @@ clean_itemlist (itp)
   if (sl)
     {
       if ((itp->flags & (LIST_DONTFREEMEMBERS|LIST_DONTFREE)) == 0)
-       free_array_members (sl->list);
+       strvec_flush (sl->list);
       if ((itp->flags & LIST_DONTFREE) == 0)
        free (sl->list);
       free (sl);
@@ -294,7 +281,7 @@ filter_stringlist (sl, filterpat, text)
   not = (npat[0] == '!');
   t = not ? npat + 1 : npat;
 
-  ret = alloc_stringlist (sl->list_size);
+  ret = strlist_create (sl->list_size);
   for (i = 0; i < sl->list_len; i++)
     {
       m = strmatch (t, sl->list[i], FNMATCH_EXTFLAG);
@@ -321,8 +308,8 @@ completions_to_stringlist (matches)
   STRINGLIST *sl;
   int mlen, i, n;
 
-  mlen = (matches == 0) ? 0 : array_len (matches);
-  sl = alloc_stringlist (mlen + 1);
+  mlen = (matches == 0) ? 0 : strvec_len (matches);
+  sl = strlist_create (mlen + 1);
 
   if (matches == 0 || matches[0] == 0)
     return sl;
@@ -362,7 +349,7 @@ it_init_aliases (itp)
     }
   for (n = 0; alias_list[n]; n++)
     ;
-  sl = alloc_stringlist (n+1);
+  sl = strlist_create (n+1);
   for (i = 0; i < n; i++)
     sl->list[i] = STRDUP (alias_list[i]->name);
   sl->list[n] = (char *)NULL;
@@ -386,7 +373,7 @@ init_itemlist_from_varlist (itp, svfunc)
   vlist = (*svfunc) ();
   for (n = 0; vlist[n]; n++)
     ;
-  sl = alloc_stringlist (n+1);
+  sl = strlist_create (n+1);
   for (i = 0; i < n; i++)
     sl->list[i] = savestring (vlist[i]->name);
   sl->list[sl->list_len = n] = (char *)NULL;
@@ -414,10 +401,10 @@ it_init_bindings (itp)
 
   /* rl_funmap_names allocates blist, but not its members */
   blist = (char **)rl_funmap_names (); /* XXX fix const later */
-  sl = alloc_stringlist (0);
+  sl = strlist_create (0);
   sl->list = blist;
   sl->list_size = 0;
-  sl->list_len = array_len (sl->list);
+  sl->list_len = strvec_len (sl->list);
   itp->flags |= LIST_DONTFREEMEMBERS;
   itp->slist = sl;
 
@@ -431,7 +418,7 @@ it_init_builtins (itp)
   STRINGLIST *sl;
   register int i, n;
 
-  sl = alloc_stringlist (num_shell_builtins);
+  sl = strlist_create (num_shell_builtins);
   for (i = n = 0; i < num_shell_builtins; i++)
     if (shell_builtins[i].function)
       sl->list[n++] = shell_builtins[i].name;
@@ -448,7 +435,7 @@ it_init_enabled (itp)
   STRINGLIST *sl;
   register int i, n;
 
-  sl = alloc_stringlist (num_shell_builtins);
+  sl = strlist_create (num_shell_builtins);
   for (i = n = 0; i < num_shell_builtins; i++)
     {
       if (shell_builtins[i].function && (shell_builtins[i].flags & BUILTIN_ENABLED))
@@ -467,7 +454,7 @@ it_init_disabled (itp)
   STRINGLIST *sl;
   register int i, n;
 
-  sl = alloc_stringlist (num_shell_builtins);
+  sl = strlist_create (num_shell_builtins);
   for (i = n = 0; i < num_shell_builtins; i++)
     {
       if (shell_builtins[i].function && ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
@@ -501,9 +488,9 @@ it_init_hostnames (itp)
 {
   STRINGLIST *sl;
 
-  sl = alloc_stringlist (0);
+  sl = strlist_create (0);
   sl->list = get_hostname_list ();
-  sl->list_len = sl->list ? array_len (sl->list) : 0;
+  sl->list_len = sl->list ? strvec_len (sl->list) : 0;
   sl->list_size = sl->list_len;
   itp->slist = sl;
   itp->flags |= LIST_DONTFREEMEMBERS|LIST_DONTFREE;
@@ -527,7 +514,7 @@ it_init_joblist (itp, jstate)
   else if (jstate == 1)
     js = JSTOPPED;
 
-  sl = alloc_stringlist (job_slots);
+  sl = strlist_create (job_slots);
   for (i = job_slots - 1; i >= 0; i--)
     {
       if (jobs[i] == 0)
@@ -579,7 +566,7 @@ it_init_keywords (itp)
 
   for (n = 0; word_token_alist[n].word; n++)
     ;
-  sl = alloc_stringlist (n);
+  sl = strlist_create (n);
   for (i = 0; i < n; i++)
     sl->list[i] = word_token_alist[i].word;
   sl->list[sl->list_len = i] = (char *)NULL;
@@ -594,9 +581,9 @@ it_init_signals (itp)
 {
   STRINGLIST *sl;
 
-  sl = alloc_stringlist (0);
+  sl = strlist_create (0);
   sl->list = signal_names;
-  sl->list_len = array_len (sl->list);
+  sl->list_len = strvec_len (sl->list);
   itp->flags |= LIST_DONTFREE;
   itp->slist = sl;
   return 0;
@@ -616,9 +603,9 @@ it_init_setopts (itp)
 {
   STRINGLIST *sl;
 
-  sl = alloc_stringlist (0);
+  sl = strlist_create (0);
   sl->list = get_minus_o_opts ();
-  sl->list_len = array_len (sl->list);
+  sl->list_len = strvec_len (sl->list);
   itp->slist = sl;
   itp->flags |= LIST_DONTFREEMEMBERS;
   return 0;
@@ -630,9 +617,9 @@ it_init_shopts (itp)
 {
   STRINGLIST *sl;
 
-  sl = alloc_stringlist (0);
+  sl = strlist_create (0);
   sl->list = get_shopt_options ();
-  sl->list_len = array_len (sl->list);
+  sl->list_len = strvec_len (sl->list);
   itp->slist = sl;
   itp->flags |= LIST_DONTFREEMEMBERS;
   return 0;
@@ -660,7 +647,7 @@ gen_matches_from_itemlist (itp, text)
     }
   if (itp->slist == 0)
     return ((STRINGLIST *)NULL);
-  ret = alloc_stringlist (itp->slist->list_len+1);
+  ret = strlist_create (itp->slist->list_len+1);
   sl = itp->slist;
   tlen = STRLEN (text);
   for (i = n = 0; i < sl->list_len; i++)
@@ -705,8 +692,8 @@ pcomp_filename_completion_function (text, state)
        tlist = gen_matches_from_itemlist (it, text); \
        if (tlist) \
          { \
-           glist = append_stringlist (glist, tlist); \
-           free_stringlist (tlist); \
+           glist = strlist_append (glist, tlist); \
+           strlist_dispose (tlist); \
          } \
       } \
   } while (0)
@@ -717,9 +704,9 @@ pcomp_filename_completion_function (text, state)
       { \
        cmatches = rl_completion_matches (text, func); \
        tlist = completions_to_stringlist (cmatches); \
-       glist = append_stringlist (glist, tlist); \
-       free_array (cmatches); \
-       free_stringlist (tlist); \
+       glist = strlist_append (glist, tlist); \
+       strvec_dispose (cmatches); \
+       strlist_dispose (tlist); \
       } \
   } while (0)
 
@@ -759,15 +746,17 @@ gen_action_completions (cs, text)
   GEN_XCOMPS(flags, CA_FILE, text, pcomp_filename_completion_function, cmatches, ret, tmatches);
   GEN_XCOMPS(flags, CA_USER, text, rl_username_completion_function, cmatches, ret, tmatches);
   GEN_XCOMPS(flags, CA_GROUP, text, bash_groupname_completion_function, cmatches, ret, tmatches);
+  GEN_XCOMPS(flags, CA_SERVICE, text, bash_servicename_completion_function, cmatches, ret, tmatches);
 
   /* And lastly, the special case for directories */
   if (flags & CA_DIRECTORY)
     {
+      rl_completion_mark_symlink_dirs = 1;     /* override user preference */
       cmatches = bash_directory_completion_matches (text);
       tmatches = completions_to_stringlist (cmatches);
-      ret = append_stringlist (ret, tmatches);
-      free_array (cmatches);
-      free_stringlist (tmatches);
+      ret = strlist_append (ret, tmatches);
+      strvec_dispose (cmatches);
+      strlist_dispose (tmatches);
     }
 
   return ret;
@@ -785,12 +774,12 @@ gen_globpat_matches (cs, text)
 {
   STRINGLIST *sl;
 
-  sl = alloc_stringlist (0);
-  sl->list = glob_filename (cs->globpat);
+  sl = strlist_create (0);
+  sl->list = glob_filename (cs->globpat, 0);
   if (GLOB_FAILED (sl->list))
     sl->list = (char **)NULL;
   if (sl->list)
-    sl->list_len = sl->list_size = array_len (sl->list);
+    sl->list_len = sl->list_size = strvec_len (sl->list);
   return sl;
 }
 
@@ -820,7 +809,7 @@ gen_wordlist_matches (cs, text)
   dispose_words (l);
 
   nw = list_length (l2);
-  sl = alloc_stringlist (nw + 1);
+  sl = strlist_create (nw + 1);
   tlen = STRLEN (text);
 
   for (nw = 0, l = l2; l; l = l->next)
@@ -893,11 +882,11 @@ static void
 unbind_compfunc_variables (exported)
      int exported;
 {
-  makunbound ("COMP_LINE", shell_variables);
-  makunbound ("COMP_POINT", shell_variables);
+  unbind_variable ("COMP_LINE");
+  unbind_variable ("COMP_POINT");
 #ifdef ARRAY_VARS
-  makunbound ("COMP_WORDS", shell_variables);
-  makunbound ("COMP_CWORD", shell_variables);
+  unbind_variable ("COMP_WORDS");
+  unbind_variable ("COMP_CWORD");
 #endif
   if (exported)
     array_needs_making = 1;
@@ -1015,13 +1004,13 @@ gen_shell_function_matches (cs, text, line, ind, lwords, nw, cw)
     {
       /* XXX - should we filter the list of completions so only those matching
         TEXT are returned?  Right now, we do not. */
-      sl = alloc_stringlist (0);
+      sl = strlist_create (0);
       sl->list = array_to_argv (a);
       sl->list_len = sl->list_size = array_num_elements (a);
     }
 
   /* XXX - should we unbind COMPREPLY here? */
-  makunbound ("COMPREPLY", shell_variables);
+  unbind_variable ("COMPREPLY");
 
   return (sl);
 #endif
@@ -1094,7 +1083,7 @@ gen_command_matches (cs, text, line, ind, lwords, nw, cw)
 
   /* Now break CSBUF up at newlines, with backslash allowed to escape a
      newline, and put the individual words into a STRINGLIST. */
-  sl = alloc_stringlist (16);
+  sl = strlist_create (16);
   for (ws = 0; csbuf[ws]; )
     {
       we = ws;
@@ -1106,7 +1095,7 @@ gen_command_matches (cs, text, line, ind, lwords, nw, cw)
        }
       t = substring (csbuf, ws, we);
       if (sl->list_len >= sl->list_size - 1)
-       realloc_stringlist (sl, sl->list_size + 16);
+       strlist_resize (sl, sl->list_size + 16);
       sl->list[sl->list_len++] = t;
       while (csbuf[we] == '\n') we++;
       ws = we;
@@ -1144,15 +1133,19 @@ gen_compspec_completions (cs, cmd, word, start, end)
   int llen, nw, cw;
   WORD_LIST *lwords;
 
-  debug_printf ("programmable_completions (%s, %s, %d, %d)", cmd, word, start, end);
-  debug_printf ("programmable_completions: %s -> %p", cmd, cs);
+#ifdef DEBUG
+  debug_printf ("gen_compspec_completions (%s, %s, %d, %d)", cmd, word, start, end);
+  debug_printf ("gen_compspec_completions: %s -> %p", cmd, cs);
+#endif
   ret = gen_action_completions (cs, word);
+#ifdef DEBUG
   if (ret && progcomp_debug)
     {
       debug_printf ("gen_action_completions (%p, %s) -->", cs, word);
-      print_stringlist (ret, "\t");
+      strlist_print (ret, "\t");
       rl_on_new_line ();
     }
+#endif
 
   /* Now we start generating completions based on the other members of CS. */
   if (cs->globpat)
@@ -1160,14 +1153,16 @@ gen_compspec_completions (cs, cmd, word, start, end)
       tmatches = gen_globpat_matches (cs, word);
       if (tmatches)
        {
+#ifdef DEBUG
          if (progcomp_debug)
            {
              debug_printf ("gen_globpat_matches (%p, %s) -->", cs, word);
-             print_stringlist (tmatches, "\t");
+             strlist_print (tmatches, "\t");
              rl_on_new_line ();
            }
-         ret = append_stringlist (ret, tmatches);
-         free_stringlist (tmatches);
+#endif
+         ret = strlist_append (ret, tmatches);
+         strlist_dispose (tmatches);
          rl_filename_completion_desired = 1;
        }
     }
@@ -1177,14 +1172,16 @@ gen_compspec_completions (cs, cmd, word, start, end)
       tmatches = gen_wordlist_matches (cs, word);
       if (tmatches)
        {
+#ifdef DEBUG
          if (progcomp_debug)
            {
              debug_printf ("gen_wordlist_matches (%p, %s) -->", cs, word);
-             print_stringlist (tmatches, "\t");
+             strlist_print (tmatches, "\t");
              rl_on_new_line ();
            }
-         ret = append_stringlist (ret, tmatches);
-         free_stringlist (tmatches);
+#endif
+         ret = strlist_append (ret, tmatches);
+         strlist_dispose (tmatches);
        }
     }
 
@@ -1198,9 +1195,12 @@ gen_compspec_completions (cs, cmd, word, start, end)
       line = substring (rl_line_buffer, start, end);
       llen = end - start;
 
+#ifdef DEBUG
       debug_printf ("command_line_to_word_list (%s, %d, %d, %p, %p)",
                line, llen, rl_point - start, &nw, &cw);
+#endif
       lwords = command_line_to_word_list (line, llen, rl_point - start, &nw, &cw);
+#ifdef DEBUG
       if (lwords == 0 && llen > 0)
        debug_printf ("ERROR: command_line_to_word_list returns NULL");
       else if (progcomp_debug)
@@ -1212,6 +1212,7 @@ gen_compspec_completions (cs, cmd, word, start, end)
          fflush(stdout);
          rl_on_new_line ();
        }
+#endif
     }
 
   if (cs->funcname)
@@ -1219,14 +1220,16 @@ gen_compspec_completions (cs, cmd, word, start, end)
       tmatches = gen_shell_function_matches (cs, word, line, rl_point - start, lwords, nw, cw);
       if (tmatches)
        {
+#ifdef DEBUG
          if (progcomp_debug)
            {
              debug_printf ("gen_shell_function_matches (%p, %s, %p, %d, %d) -->", cs, word, lwords, nw, cw);
-             print_stringlist (tmatches, "\t");
+             strlist_print (tmatches, "\t");
              rl_on_new_line ();
            }
-         ret = append_stringlist (ret, tmatches);
-         free_stringlist (tmatches);
+#endif
+         ret = strlist_append (ret, tmatches);
+         strlist_dispose (tmatches);
        }
     }
 
@@ -1235,14 +1238,16 @@ gen_compspec_completions (cs, cmd, word, start, end)
       tmatches = gen_command_matches (cs, word, line, rl_point - start, lwords, nw, cw);
       if (tmatches)
        {
+#ifdef DEBUG
          if (progcomp_debug)
            {
              debug_printf ("gen_command_matches (%p, %s, %p, %d, %d) -->", cs, word, lwords, nw, cw);
-             print_stringlist (tmatches, "\t");
+             strlist_print (tmatches, "\t");
              rl_on_new_line ();
            }
-         ret = append_stringlist (ret, tmatches);
-         free_stringlist (tmatches);
+#endif
+         ret = strlist_append (ret, tmatches);
+         strlist_dispose (tmatches);
        }
     }
 
@@ -1256,12 +1261,14 @@ gen_compspec_completions (cs, cmd, word, start, end)
   if (cs->filterpat)
     {
       tmatches = filter_stringlist (ret, cs->filterpat, word);
+#ifdef DEBUG
       if (progcomp_debug)
        {
          debug_printf ("filter_stringlist (%p, %s, %s) -->", ret, cs->filterpat, word);
-         print_stringlist (tmatches, "\t");
+         strlist_print (tmatches, "\t");
          rl_on_new_line ();
        }
+#endif
       if (ret && ret != tmatches)
        {
          FREE (ret->list);
@@ -1271,7 +1278,7 @@ gen_compspec_completions (cs, cmd, word, start, end)
     }
 
   if (cs->prefix || cs->suffix)
-    ret = prefix_suffix_stringlist (ret, cs->prefix, cs->suffix);
+    ret = strlist_prefix_suffix (ret, cs->prefix, cs->suffix);
 
   /* If no matches have been generated and the user has specified that
       directory completion should be done as a default, call
@@ -1281,10 +1288,10 @@ gen_compspec_completions (cs, cmd, word, start, end)
     {
       COMPSPEC *dummy;
 
-      dummy = alloc_compspec ();
+      dummy = compspec_create ();
       dummy->actions = CA_DIRECTORY;
       ret = gen_action_completions (dummy, word);
-      free_compspec (dummy);
+      compspec_dispose (dummy);
     }
 
   return (ret);
@@ -1305,12 +1312,12 @@ programmable_completions (cmd, word, start, end, foundp)
 
   /* We look at the basename of CMD if the full command does not have
      an associated COMPSPEC. */
-  cs = find_compspec (cmd);
+  cs = progcomp_search (cmd);
   if (cs == 0)
     {
       t = strrchr (cmd, '/');
       if (t)
-       cs = find_compspec (++t);
+       cs = progcomp_search (++t);
     }
   if (cs == 0)
     {
index e37645f7c0feb03e9315cadd8f193ede76bafaf0..9353fe1ef5891c129f49902620efb1a454a2a91f 100644 (file)
@@ -1,7 +1,7 @@
 /* pcomplete.h - structure definitions and other stuff for programmable
                 completion. */
 
-/* Copyright (C) 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -57,18 +57,20 @@ typedef struct compspec {
 #define CA_JOB         (1<<14)
 #define CA_KEYWORD     (1<<15)
 #define CA_RUNNING     (1<<16)
-#define CA_SETOPT      (1<<17)
-#define CA_SHOPT       (1<<18)
-#define CA_SIGNAL      (1<<19)
-#define CA_STOPPED     (1<<20)
-#define CA_USER                (1<<21)
-#define CA_VARIABLE    (1<<22)
+#define CA_SERVICE     (1<<17)
+#define CA_SETOPT      (1<<18)
+#define CA_SHOPT       (1<<19)
+#define CA_SIGNAL      (1<<20)
+#define CA_STOPPED     (1<<21)
+#define CA_USER                (1<<22)
+#define CA_VARIABLE    (1<<23)
 
 /* Values for COMPSPEC options field. */
 #define COPT_RESERVED  (1<<0)          /* reserved for other use */
 #define COPT_DEFAULT   (1<<1)
 #define COPT_FILENAMES (1<<2)
 #define COPT_DIRNAMES  (1<<3)
+#define COPT_NOSPACE   (1<<4)
 
 /* List of items is used by the code that implements the programmable
    completions. */
@@ -112,6 +114,7 @@ extern ITEMLIST it_hostnames;
 extern ITEMLIST it_jobs;
 extern ITEMLIST it_keywords;
 extern ITEMLIST it_running;
+extern ITEMLIST it_services;
 extern ITEMLIST it_setopts;
 extern ITEMLIST it_shopts;
 extern ITEMLIST it_signals;
@@ -120,24 +123,22 @@ extern ITEMLIST it_users;
 extern ITEMLIST it_variables;
 
 /* Functions from pcomplib.c */
-typedef void sh_csprint_func_t __P((char *, COMPSPEC *));
+extern COMPSPEC *compspec_create __P((void));
+extern void compspec_dispose __P((COMPSPEC *));
+extern COMPSPEC *compspec_copy __P((COMPSPEC *));
 
-extern COMPSPEC *alloc_compspec __P((void));
-extern void free_compspec __P((COMPSPEC *));
+extern void progcomp_create __P((void));
+extern void progcomp_flush __P((void));
+extern void progcomp_dispose __P((void));
 
-extern COMPSPEC *copy_compspec __P((COMPSPEC *));
+extern int progcomp_size __P((void));
 
-extern void initialize_progcomp __P((void));
-extern void clear_progcomps __P((void));
+extern int progcomp_insert __P((char *, COMPSPEC *));
+extern int progcomp_remove __P((char *));
 
-extern int remove_progcomp __P((char *));
-extern int add_progcomp __P((char *, COMPSPEC *));
+extern COMPSPEC *progcomp_search __P((const char *));
 
-extern int num_progcomps __P((void));
-
-extern COMPSPEC *find_compspec __P((const char *));
-
-extern void print_all_compspecs __P((sh_csprint_func_t *));
+extern void progcomp_walk __P((hash_wfunc *));
 
 /* Functions from pcomplete.c */
 extern void set_itemlist_dirty __P((ITEMLIST *));
index 845f6ac1263097de977138b8151af62c941a6b9f..aa08fa5da452a4dcd166d19db70bba4a728c2352 100644 (file)
@@ -1,6 +1,6 @@
 /* pcomplib.c - library functions for programmable completion. */
 
-/* Copyright (C) 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -35,7 +35,7 @@
 #include "shell.h"
 #include "pcomplete.h"
 
-#define COMPLETE_HASH_BUCKETS  29      /* for testing */
+#define COMPLETE_HASH_BUCKETS  32      /* must be power of two */
 
 #define STRDUP(x)      ((x) ? savestring (x) : (char *)NULL)
 
@@ -43,10 +43,8 @@ HASH_TABLE *prog_completes = (HASH_TABLE *)NULL;
 
 static void free_progcomp __P((PTR_T));
 
-static int progcomp_initialized = 0;
-
 COMPSPEC *
-alloc_compspec ()
+compspec_create ()
 {
   COMPSPEC *ret;
 
@@ -68,7 +66,7 @@ alloc_compspec ()
 }
 
 void
-free_compspec (cs)
+compspec_dispose (cs)
      COMPSPEC *cs;
 {
   cs->refcount--;
@@ -87,7 +85,7 @@ free_compspec (cs)
 }
 
 COMPSPEC *
-copy_compspec (cs)
+compspec_copy (cs)
      COMPSPEC *cs;
 {
   COMPSPEC *new;
@@ -110,21 +108,16 @@ copy_compspec (cs)
 }
 
 void
-initialize_progcomp ()
+progcomp_create ()
 {
-  if (progcomp_initialized == 0)
-    {
-      prog_completes = make_hash_table (COMPLETE_HASH_BUCKETS);
-      progcomp_initialized = 1;
-    }
+  if (prog_completes == 0)
+    prog_completes = hash_create (COMPLETE_HASH_BUCKETS);
 }
 
 int
-num_progcomps ()
+progcomp_size ()
 {
-  if (progcomp_initialized == 0 || prog_completes == 0)
-    return (0);
-  return (prog_completes->nentries);
+  return (HASH_ENTRIES (prog_completes));
 }
 
 static void
@@ -134,18 +127,26 @@ free_progcomp (data)
   COMPSPEC *cs;
 
   cs = (COMPSPEC *)data;
-  free_compspec (cs);
+  compspec_dispose (cs);
 }
   
 void
-clear_progcomps ()
+progcomp_flush ()
+{
+  if (prog_completes)
+    hash_flush (prog_completes, free_progcomp);
+}
+
+void
+progcomp_dispose ()
 {
   if (prog_completes)
-    flush_hash_table (prog_completes, free_progcomp);
+    hash_dispose (prog_completes);
+  prog_completes = (HASH_TABLE *)NULL;
 }
 
 int
-remove_progcomp (cmd)
+progcomp_remove (cmd)
      char *cmd;
 {
   register BUCKET_CONTENTS *item;
@@ -153,10 +154,11 @@ remove_progcomp (cmd)
   if (prog_completes == 0)
     return 1;
 
-  item = remove_hash_item (cmd, prog_completes);
+  item = hash_remove (cmd, prog_completes, 0);
   if (item)
     {
-      free_progcomp (item->data);
+      if (item->data)
+       free_progcomp (item->data);
       free (item->key);
       free (item);
       return (1);
@@ -165,30 +167,30 @@ remove_progcomp (cmd)
 }
 
 int
-add_progcomp (cmd, cs)
+progcomp_insert (cmd, cs)
       char *cmd;
       COMPSPEC *cs;
 {
   register BUCKET_CONTENTS *item;
 
-  if (progcomp_initialized == 0 || prog_completes == 0)
-    initialize_progcomp ();
-
   if (cs == NULL)
-    programming_error ("add_progcomp: %s: NULL COMPSPEC", cmd);
+    programming_error ("progcomp_insert: %s: NULL COMPSPEC", cmd);
+
+  if (prog_completes == 0)
+    progcomp_create ();
 
-  item = add_hash_item (cmd, prog_completes);
+  item = hash_insert (cmd, prog_completes, 0);
   if (item->data)
     free_progcomp (item->data);
   else
     item->key = savestring (cmd);
-  item->data = (char *)cs;
+  item->data = cs;
   cs->refcount++;
   return 1;
 }
 
 COMPSPEC *
-find_compspec (cmd)
+progcomp_search (cmd)
      const char *cmd;
 {
   register BUCKET_CONTENTS *item;
@@ -197,7 +199,7 @@ find_compspec (cmd)
   if (prog_completes == 0)
     return ((COMPSPEC *)NULL);
 
-  item = find_hash_item (cmd, prog_completes);
+  item = hash_search (cmd, prog_completes, 0);
 
   if (item == NULL)
     return ((COMPSPEC *)NULL);
@@ -208,28 +210,13 @@ find_compspec (cmd)
 }
 
 void
-print_all_compspecs (pfunc)
-     sh_csprint_func_t *pfunc;
+progcomp_walk (pfunc)
+     hash_wfunc *pfunc;
 {
-  BUCKET_CONTENTS *item_list;
-  int bucket;
-  COMPSPEC *cs;
-
-  if (prog_completes == 0 || pfunc == 0)
+  if (prog_completes == 0 || pfunc == 0 || HASH_ENTRIES (prog_completes) == 0)
     return;
 
-  for (bucket = 0; bucket < prog_completes->nbuckets; bucket++)
-    {
-      item_list = get_hash_bucket (bucket, prog_completes);
-      if (item_list == 0)
-       continue;
-
-      for ( ; item_list; item_list = item_list->next)
-       {
-         cs = (COMPSPEC *)item_list->data;
-         (*pfunc) (item_list->key, cs);
-       }
-    }
+  hash_walk (prog_completes, pfunc);
 }
 
 #endif /* PROGRAMMABLE_COMPLETION */
index 4aee8d3c52830346d954b47f40fc8a7e44f651af..9429472eff691ba24cd7bcd8a3babf44cf377aae 100644 (file)
@@ -31,22 +31,22 @@ Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
 #if defined (PREFER_STDARG)
 #  include <stdarg.h>
 #else
-#  if defined (PREFER_VARARGS)
-#    include <varargs.h>
-#  endif
+#  include <varargs.h>
 #endif
 
 #include "bashansi.h"
 
 #include "shell.h"
+#include "flags.h"
 #include <y.tab.h>     /* use <...> so we pick it up from the build directory */
-#include "stdc.h"
 #include "builtins/common.h"
 
 #if !HAVE_DECL_PRINTF
 extern int printf __P((const char *, ...));    /* Yuck.  Double yuck. */
 #endif
 
+extern int indirection_level;
+
 static int indentation;
 static int indentation_amount = 4;
 
@@ -112,6 +112,9 @@ static int was_heredoc;
    includes the group command that is a function body. */
 static int group_command_nesting;
 
+/* A buffer to indicate the indirection level (PS4) when set -x is enabled. */
+static char indirection_string[100];
+
 /* Print COMMAND (a command tree) on standard output. */
 void
 print_command (command)
@@ -314,6 +317,35 @@ print_word_list (list, separator)
   _print_word_list (list, separator, xprintf);
 }
 
+/* Return a string denoting what our indirection level is. */
+
+char *
+indirection_level_string ()
+{
+  register int i, j;
+  char *ps4;
+
+  indirection_string[0] = '\0';
+  ps4 = get_string_value ("PS4");
+
+  if (ps4 == 0 || *ps4 == '\0')
+    return (indirection_string);
+
+  change_flag ('x', FLAG_OFF);
+  ps4 = decode_prompt_string (ps4);
+  change_flag ('x', FLAG_ON);
+
+  for (i = 0; *ps4 && i < indirection_level && i < 99; i++)
+    indirection_string[i] = *ps4;
+
+  for (j = 1; *ps4 && ps4[j] && i < 99; i++, j++)
+    indirection_string[i] = ps4[j];
+
+  indirection_string[i] = '\0';
+  free (ps4);
+  return (indirection_string);
+}
+
 /* A function to print the words of a simple command when set -x is on. */
 void
 xtrace_print_word_list (list)
@@ -334,6 +366,12 @@ xtrace_print_word_list (list)
          fprintf (stderr, "%s%s", x, w->next ? " " : "");
          free (x);
        }
+      else if (ansic_shouldquote (t))
+       {
+         x = ansic_quote (t, 0, (int *)0);
+         fprintf (stderr, "%s%s", x, w->next ? " " : "");
+         free (x);
+       }
       else
        fprintf (stderr, "%s%s", t, w->next ? " " : "");
     }
@@ -763,6 +801,20 @@ print_redirection (redirect)
               redirect->redirectee.filename->word, redirect->here_doc_eof);
       break;
 
+    case r_reading_string:
+      if (redirector != 0)
+       cprintf ("%d", redirector);
+      if (ansic_shouldquote (redirect->redirectee.filename->word))
+       {
+         char *x;
+         x = ansic_quote (redirect->redirectee.filename->word, 0, (int *)0);
+         cprintf ("<<< %s", x);
+         free (x);
+       }
+      else
+       cprintf ("<<< %s", redirect->redirectee.filename->word);
+      break;
+
     case r_duplicating_input:
       cprintf ("%d<&%d", redirector, redir_fd);
       break;
@@ -779,6 +831,22 @@ print_redirection (redirect)
       cprintf ("%d>&%s", redirector, redirectee->word);
       break;
 
+    case r_move_input:
+      cprintf ("%d<&%d-", redirector, redir_fd);
+      break;
+
+    case r_move_output:
+      cprintf ("%d>&%d-", redirector, redir_fd);
+      break;
+
+    case r_move_input_word:
+      cprintf ("%d<&%s-", redirector, redirectee->word);
+      break;
+
+    case r_move_output_word:
+      cprintf ("%d>&%s-", redirector, redirectee->word);
+      break;
+
     case r_close_this:
       cprintf ("%d>&-", redirector);
       break;
@@ -970,99 +1038,13 @@ indent (amount)
 static void
 semicolon ()
 {
-  if (command_string_index > 0 && the_printed_command[command_string_index - 1] == '&')
+  if (command_string_index > 0 &&
+       (the_printed_command[command_string_index - 1] == '&' ||
+        the_printed_command[command_string_index - 1] == '\n'))
     return;
   cprintf (";");
 }
 
-#if !defined (USE_VARARGS)
-/* How to make the string. */
-static void
-cprintf (format, arg1, arg2)
-     const char *format;
-     char *arg1, *arg2;
-{
-  register const char *s;
-  char char_arg[2], *argp, *args[2], intbuf[INT_STRLEN_BOUND(int) + 1];
-  int arg_len, c, arg_index, digit_arg;
-
-  args[arg_index = 0] = arg1;
-  args[1] = arg2;
-
-  arg_len = strlen (format);
-  the_printed_command_resize (arg_len + 1);
-
-  char_arg[1] = '\0';
-  s = format;
-  while (s && *s)
-    {
-      int free_argp = 0;
-      c = *s++;
-      if (c != '%' || !*s)
-       {
-         char_arg[0] = c;
-         argp = char_arg;
-         arg_len = 1;
-       }
-      else
-       {
-         c = *s++;
-         switch (c)
-           {
-           case '%':
-             char_arg[0] = c;
-             argp = char_arg;
-             arg_len = 1;
-             break;
-
-           case 's':
-             argp = (char *)args[arg_index++];
-             arg_len = strlen (argp);
-             break;
-
-           case 'd':
-             /* Represent an out-of-range file descriptor with an out-of-range
-                integer value.  We can do this because the only use of `%d' in
-                the calls to cprintf is to output a file descriptor number for
-                a redirection. */
-             digit_arg = pointer_to_int (args[arg_index]);
-             if (digit_arg < 0)
-               {
-                 sprintf (intbuf, "%u", (unsigned)-1);
-                 argp = intbuf;
-               }
-             else
-               argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
-             arg_index++;
-             arg_len = strlen (argp);
-             break;
-
-           case 'c':
-             char_arg[0] = pointer_to_int (args[arg_index]);
-             arg_index++;
-             argp = char_arg;
-             arg_len = 1;
-             break;
-
-           default:
-             programming_error ("cprintf: bad `%%' argument (%c)", c);
-           }
-       }
-      if (argp)
-       {
-         the_printed_command_resize (arg_len + 1);
-         FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
-         command_string_index += arg_len;
-         if (free_argp)
-           free (argp);
-       }
-    }
-
-  the_printed_command[command_string_index] = '\0';
-}
-
-#else /* We have support for varargs. */
-
 /* How to make the string. */
 static void
 #if defined (PREFER_STDARG)
@@ -1078,11 +1060,7 @@ cprintf (control, va_alist)
   int digit_arg, arg_len, c;
   va_list args;
 
-#if defined (PREFER_STDARG)
-  va_start (args, control);
-#else
-  va_start (args);
-#endif
+  SH_VA_START (args, control);
 
   arg_len = strlen (control);
   the_printed_command_resize (arg_len + 1);
@@ -1091,8 +1069,6 @@ cprintf (control, va_alist)
   s = control;
   while (s && *s)
     {
-      int free_argp;
-      free_argp = 0;
       c = *s++;
       argp = (char *)NULL;
       if (c != '%' || !*s)
@@ -1150,14 +1126,11 @@ cprintf (control, va_alist)
          the_printed_command_resize (arg_len + 1);
          FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
          command_string_index += arg_len;
-         if (free_argp)
-           free (argp);
        }
     }
 
   the_printed_command[command_string_index] = '\0';
 }
-#endif /* HAVE_VARARGS_H */
 
 /* Ensure that there is enough space to stuff LENGTH characters into
    THE_PRINTED_COMMAND. */
@@ -1199,11 +1172,7 @@ xprintf (format, va_alist)
 {
   va_list args;
 
-#if defined (PREFER_STDARG)
-  va_start (args, format);
-#else
-  va_start (args);
-#endif
+  SH_VA_START (args, format);
 
   vfprintf (stdout, format, args);
   va_end (args);
diff --git a/redir.c b/redir.c
index 6fdcc94fc0d4417364fe80ad2cbb9eb014d84feb..e4200110a776c180e936a1cdfdddae98ccb12b87 100644 (file)
--- a/redir.c
+++ b/redir.c
@@ -1,6 +1,6 @@
 /* redir.c -- Functions to perform input and output redirection. */
 
-/* Copyright (C) 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1997-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -66,14 +66,15 @@ static int stdin_redirection __P((enum r_instruction, int));
 static int do_redirection_internal __P((REDIRECT *, int, int, int));
 
 static int write_here_document __P((int, WORD_DESC *));
-static int here_document_to_fd __P((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));
 
-/* Spare redirector used when translating [N]>&WORD or [N]<&WORD to a new
-   redirection and when creating the redirection undo list. */
+/* 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.
@@ -95,7 +96,23 @@ redirection_error (temp, error)
     filename = "file descriptor out of range";
 #ifdef EBADF
   else if (temp->redirector >= 0 && errno == EBADF)
-    filename = allocname = itos (temp->redirector);
+    {
+      /* 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;
+       default:
+         filename = allocname = itos (temp->redirector);
+         break;
+        }
+    }
 #endif
   else if (expandable_redirection_filename (temp))
     {
@@ -197,6 +214,8 @@ expandable_redirection_filename (redirect)
     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:
@@ -235,6 +254,34 @@ redirection_expand (word)
   return (result);
 }
 
+static int
+write_here_string (fd, redirectee)
+     int fd;
+     WORD_DESC *redirectee;
+{
+  char *herestr;
+  int herelen, n, e;
+
+  herestr = expand_string_to_string (redirectee->word, 0);
+  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. */
@@ -316,8 +363,9 @@ write_here_document (fd, redirectee)
    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)
+here_document_to_fd (redirectee, ri)
      WORD_DESC *redirectee;
+     enum r_instruction ri;
 {
   char *filename;
   int r, fd, fd2;
@@ -334,7 +382,8 @@ here_document_to_fd (redirectee)
   errno = r = 0;               /* XXX */
   /* write_here_document returns 0 on success, errno on failure. */
   if (redirectee->word)
-    r = write_here_document (fd, redirectee);
+    r = (ri != r_reading_string) ? write_here_document (fd, redirectee)
+                                : write_here_string (fd, redirectee);
 
   if (r)
     {
@@ -416,7 +465,7 @@ redir_special_open (spec, filename, flags, mode, ri)
 {
   int fd;
 #if !defined (HAVE_DEV_FD)
-  long lfd;
+  intmax_t lfd;
 #endif
 
   fd = -1;
@@ -562,7 +611,7 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
 {
   WORD_DESC *redirectee;
   int redir_fd, fd, redirector, r, oflags;
-  long lfd;
+  intmax_t lfd;
   char *redirectee_word;
   enum r_instruction ri;
   REDIRECT *new_redirect;
@@ -572,12 +621,14 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
   redirector = redirect->redirector;
   ri = redirect->instruction;
 
-  if (ri == r_duplicating_input_word || ri == r_duplicating_output_word)
+  if (TRANSLATE_REDIRECT (ri))
     {
-      /* We have [N]>&WORD or [N]<&WORD.  Expand WORD, then translate
+      /* We have [N]>&WORD[-] or [N]<&WORD[-].  Expand 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')
@@ -591,11 +642,21 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
            rd.dest = lfd;
          else
            rd.dest = -1;       /* XXX */
-         new_redirect = make_redirection (redirector,
-                                          (ri == r_duplicating_input_word
-                                               ? r_duplicating_input
-                                               : r_duplicating_output),
-                                          rd);         
+         switch (ri)
+           {
+           case r_duplicating_input_word:
+             new_redirect = make_redirection (redirector, r_duplicating_input, rd);
+             break;
+           case r_duplicating_output_word:
+             new_redirect = make_redirection (redirector, r_duplicating_output, rd);
+             break;
+           case r_move_input_word:
+             new_redirect = make_redirection (redirector, r_move_input, rd);
+             break;
+           case r_move_output_word:
+             new_redirect = make_redirection (redirector, r_move_output, rd);
+             break;
+           }
        }
       else if (ri == r_duplicating_output_word && redirector == 1)
        {
@@ -744,11 +805,12 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
 
     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);
+         fd = here_document_to_fd (redirectee, ri);
 
          if (fd < 0)
            {
@@ -796,6 +858,8 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
 
     case r_duplicating_input:
     case r_duplicating_output:
+    case r_move_input:
+    case r_move_output:
       if (for_real && (redir_fd != redirector))
        {
          if (remembering)
@@ -815,7 +879,7 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
            return (errno);
 
 #if defined (BUFFERED_INPUT)
-         if (ri == r_duplicating_input)
+         if (ri == r_duplicating_input || ri == r_move_input)
            duplicate_buffered_stream (redir_fd, redirector);
 #endif /* BUFFERED_INPUT */
 
@@ -829,6 +893,10 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
          if (((fcntl (redir_fd, F_GETFD, 0) == 1) || set_clexec) &&
               (redirector > 2))
            SET_CLOSE_ON_EXEC (redirector);
+
+         /* dup-and-close redirection */
+         if (ri == r_move_input || ri == r_move_output)
+           close (redir_fd);
        }
       break;
 
@@ -946,6 +1014,7 @@ stdin_redirection (ri, redirector)
     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:
diff --git a/shell.c b/shell.c
index 98d8303c0685c24e6c3387121432cf9ab61d564c..a4298e7cc653bb4bf64621b15b158d31a39cf76b 100644 (file)
--- a/shell.c
+++ b/shell.c
@@ -1,6 +1,6 @@
 /* shell.c -- GNU's idea of the POSIX shell specification. */
 
-/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 #include "execute_cmd.h"
 #include "findcmd.h"
 
+#if defined (USING_BASH_MALLOC) && defined (DEBUG) && !defined (DISABLE_MALLOC_WRAPPERS)
+#  include <malloc/shmalloc.h>
+#endif
+
 #if defined (HISTORY)
 #  include "bashhist.h"
 #  include <readline/history.h>
@@ -115,7 +119,7 @@ char *current_host_name = (char *)NULL;
    Specifically:
    0 = not login shell.
    1 = login shell from getty (or equivalent fake out)
-  -1 = login shell from "--login" flag.
+  -1 = login shell from "--login" (or -l) flag.
   -2 = both from getty, and from flag.
  */
 int login_shell = 0;
@@ -136,6 +140,7 @@ int hup_on_exit = 0;
        0 = non-interactive shell script
        1 = interactive
        2 = -c command
+       3 = wordexp evaluation
    This is a superset of the information provided by interactive_shell.
 */
 int startup_state = 0;
@@ -240,6 +245,8 @@ int default_buffered_input = -1;
 int read_from_stdin;           /* -s flag supplied */
 int want_pending_command;      /* -c flag supplied */
 
+int malloc_trace_at_exit = 0;
+
 static int shell_reinitialized = 0;
 static char *local_pending_command;
 
@@ -263,7 +270,6 @@ static int run_one_command __P((char *));
 static int run_wordexp __P((char *));
 
 static int uidget __P((void));
-static int isnetconn __P((int));
 
 static void init_interactive __P((void));
 static void init_noninteractive __P((void));
@@ -330,12 +336,8 @@ main (argc, argv, env)
   if (code)
     exit (2);
 
-#if defined (USING_BASH_MALLOC) && defined (DEBUG)
-#  if 0                /* memory tracing */
-  malloc_set_trace(1);
-#  endif
-
-#  if 0
+#if defined (USING_BASH_MALLOC) && defined (DEBUG) && !defined (DISABLE_MALLOC_WRAPPERS)
+#  if 1
   malloc_set_register (1);
 #  endif
 #endif
@@ -417,7 +419,12 @@ main (argc, argv, env)
       exit (EXECUTION_SUCCESS);
     }
 
-  /* If user supplied the "--login" flag, then set and invert LOGIN_SHELL. */
+  /* All done with full word options; do standard shell option parsing.*/
+  this_command_name = shell_name;      /* for error reporting */
+  arg_index = parse_shell_options (argv, arg_index, argc);
+
+  /* If user supplied the "--login" (or -l) flag, then set and invert
+     LOGIN_SHELL. */
   if (make_login_shell)
     {
       login_shell++;
@@ -426,10 +433,6 @@ main (argc, argv, env)
 
   set_login_shell (login_shell != 0);
 
-  /* All done with full word options; do standard shell option parsing.*/
-  this_command_name = shell_name;      /* for error reporting */
-  arg_index = parse_shell_options (argv, arg_index, argc);
-
   if (dump_po_strings)
     dump_translatable_strings = 1;
 
@@ -447,13 +450,15 @@ main (argc, argv, env)
       local_pending_command = argv[arg_index];
       if (local_pending_command == 0)
        {
-         report_error ("option `-c' requires an argument");
+         report_error ("-c: option requires an argument");
          exit (EX_USAGE);
        }
       arg_index++;
     }
   this_command_name = (char *)NULL;
 
+  cmd_init();          /* initialize the command object caches */
+
   /* First, let the outside world know about our interactive status.
      A shell is interactive if the `-i' flag was given, or if all of
      the following conditions are met:
@@ -490,8 +495,8 @@ main (argc, argv, env)
     }
 #endif /* CLOSE_FDS_AT_LOGIN */
 
-  /* If we're in a strict Posix.2 mode, turn on interactive comments and
-     other Posix.2 things. */
+  /* If we're in a strict Posix.2 mode, turn on interactive comments,
+     alias expansion in non-interactive shells, and other Posix.2 things. */
   if (posixly_correct)
     {
       bind_variable ("POSIXLY_CORRECT", "y");
@@ -517,6 +522,7 @@ main (argc, argv, env)
       term = getenv ("EMACS");
       running_under_emacs = term ? ((strmatch ("*term*", term, 0) == 0) ? 2 : 1)
                                 : 0;
+      no_line_editing |= term && term[0] == 't' && term[1] == '\0';
     }
 
   top_level_arg_index = arg_index;
@@ -549,10 +555,13 @@ main (argc, argv, env)
 
   if (interactive_shell == 0)
     {
-      makunbound ("PS1", shell_variables);
-      makunbound ("PS2", shell_variables);
+      unbind_variable ("PS1");
+      unbind_variable ("PS2");
       interactive = 0;
+#if 0
+      /* This has already been done by init_noninteractive */
       expand_aliases = posixly_correct;
+#endif
     }
   else
     {
@@ -649,7 +658,10 @@ main (argc, argv, env)
 #if defined (HISTORY)
       /* Initialize the interactive history stuff. */
       bash_initialize_history ();
-      if (shell_initialized == 0)
+      /* Don't load the history from the history file if we've already
+        saved some lines in this session (e.g., by putting `history -s xx'
+        into one of the startup files). */
+      if (shell_initialized == 0 && history_lines_this_session == 0)
        load_history ();
 #endif /* HISTORY */
 
@@ -698,8 +710,7 @@ parse_long_options (argv, arg_start, arg_end)
                *long_args[i].int_value = 1;
              else if (argv[++arg_index] == 0)
                {
-                 report_error ("option `%s' requires an argument",
-                               long_args[i].name);
+                 report_error ("%s: option requires an argument", long_args[i].name);
                  exit (EX_USAGE);
                }
              else
@@ -712,7 +723,7 @@ parse_long_options (argv, arg_start, arg_end)
        {
          if (longarg)
            {
-             report_error ("%s: unrecognized option", argv[arg_index]);
+             report_error ("%s: invalid option", argv[arg_index]);
              show_shell_usage (stderr, 0);
              exit (EX_USAGE);
            }
@@ -759,6 +770,10 @@ parse_shell_options (argv, arg_start, arg_end)
              want_pending_command = 1;
              break;
 
+           case 'l':
+             make_login_shell = 1;
+             break;
+
            case 's':
              read_from_stdin = 1;
              break;
@@ -797,7 +812,7 @@ parse_shell_options (argv, arg_start, arg_end)
            default:
              if (change_flag (arg_character, on_or_off) == FLAG_ERROR)
                {
-                 report_error ("%c%c: unrecognized option", on_or_off, arg_character);
+                 report_error ("%c%c: invalid option", on_or_off, arg_character);
                  show_shell_usage (stderr, 0);
                  exit (EX_USAGE);
                }
@@ -845,19 +860,22 @@ exit_shell (s)
 #endif /* JOB_CONTROL */
 
   /* Always return the exit status of the last command to our parent. */
-  exit (s);
+  sh_exit (s);
 }
 
-#ifdef INCLUDE_UNUSED
 /* A wrapper for exit that (optionally) can do other things, like malloc
    statistics tracing. */
 void
 sh_exit (s)
      int s;
 {
+#if defined (MALLOC_DEBUG) && defined (USING_BASH_MALLOC)
+  if (malloc_trace_at_exit)
+    trace_malloc_stats (get_name_for_error (), (char *)NULL);
+#endif
+
   exit (s);
 }
-#endif
 
 /* Source the bash startup files.  If POSIXLY_CORRECT is non-zero, we obey
    the Posix.2 startup file rules:  $ENV is expanded, and if the file it
@@ -943,8 +961,8 @@ run_startup_files ()
 
   sourced_login = 0;
 
-  /* A shell begun with the --login flag that is not in posix mode runs
-     the login shell startup files, no matter whether or not it is
+  /* A shell begun with the --login (or -l) flag that is not in posix mode
+     runs the login shell startup files, no matter whether or not it is
      interactive.  If NON_INTERACTIVE_LOGIN_SHELLS is defined, run the
      startup files if argv[0][0] == '-' as well. */
 #if defined (NON_INTERACTIVE_LOGIN_SHELLS)
@@ -1063,7 +1081,7 @@ maybe_make_restricted (name)
 {
   char *temp;
 
-  temp = base_pathname (shell_name);
+  temp = base_pathname (name);
   if (restricted || (STREQ (temp, RESTRICTED_SHELL_NAME)))
     {
       set_var_read_only ("PATH");
@@ -1435,8 +1453,13 @@ set_shell_name (argv0)
   /* Here's a hack.  If the name of this shell is "sh", then don't do
      any startup files; just try to be more like /bin/sh. */
   shell_name = base_pathname (argv0);
+
   if (*shell_name == '-')
-    shell_name++;
+    {
+      shell_name++;
+      login_shell++;
+    }
+
   if (shell_name[0] == 's' && shell_name[1] == 'h' && shell_name[2] == '\0')
     act_like_sh++;
   if (shell_name[0] == 's' && shell_name[1] == 'u' && shell_name[2] == '\0')
@@ -1446,12 +1469,6 @@ set_shell_name (argv0)
   FREE (dollar_vars[0]);
   dollar_vars[0] = savestring (shell_name);
 
-  if (*shell_name == '-')
-    {
-      shell_name++;
-      login_shell++;
-    }
-
   /* A program may start an interactive shell with
          "execl ("/bin/bash", "-", NULL)".
      If so, default the name of this shell to our name. */
@@ -1473,7 +1490,7 @@ init_noninteractive ()
   bash_history_reinit (0);
 #endif /* HISTORY */
   interactive_shell = startup_state = interactive = 0;
-  expand_aliases = 0;
+  expand_aliases = posixly_correct;    /* XXX - was 0 not posixly_correct */
   no_line_editing = 1;
 #if defined (JOB_CONTROL)
   set_job_control (0);
@@ -1530,7 +1547,7 @@ shell_initialize ()
      for restoring the original default signal handlers.  That function
      is called when we make a new child. */
   initialize_traps ();
-  initialize_signals ();
+  initialize_signals (0);
 
   /* It's highly unlikely that this will change. */
   if (current_host_name == 0)
@@ -1560,17 +1577,14 @@ shell_initialize ()
   initialize_shell_variables (shell_environment, privileged_mode||running_setuid);
 #endif
 
-#if 0
-  /* Initialize filename hash tables. */
-  initialize_filename_hashing ();
-#endif
-
   /* Initialize the data structures for storing and running jobs. */
   initialize_job_control (0);
 
   /* Initialize input streams to null. */
   initialize_bash_input ();
 
+  initialize_flags ();
+
   /* Initialize the shell options.  Don't import the shell options
      from the environment variable $SHELLOPTS if we are running in
      privileged or restricted mode or if the shell is running setuid. */
@@ -1620,7 +1634,7 @@ shell_reinitialize ()
 
   /* Delete all variables and functions.  They will be reinitialized when
      the environment is parsed. */
-  delete_all_variables (shell_variables);
+  delete_all_contexts (shell_variables);
   delete_all_variables (shell_functions);
 
   shell_reinitialized = 1;
@@ -1650,12 +1664,12 @@ show_shell_usage (fp, extra)
       set_opts = savestring (shell_builtins[i].short_doc);
   if (set_opts)
     {
-      s = strchr (set_opts, '[');
+      s = xstrchr (set_opts, '[');
       if (s == 0)
        s = set_opts;
       while (*++s == '-')
        ;
-      t = strchr (s, ']');
+      t = xstrchr (s, ']');
       if (t)
        *t = '\0';
       fprintf (fp, "\t-%s or -o option\n", s);
@@ -1697,51 +1711,3 @@ run_shopt_alist ()
   shopt_alist = 0;
   shopt_ind = shopt_len = 0;
 }
-
-/* The second and subsequent conditions must match those used to decide
-   whether or not to call getpeername() in isnetconn(). */
-#if defined (HAVE_SYS_SOCKET_H) && defined (HAVE_GETPEERNAME) && !defined (SVR4_2)
-#  include <sys/socket.h>
-#endif
-
-/* Is FD a socket or network connection? */
-static int
-isnetconn (fd)
-     int fd;
-{
-#if defined (HAVE_GETPEERNAME) && !defined (SVR4_2) && !defined (__BEOS__)
-  int rv;
-  socklen_t l;
-  struct sockaddr sa;
-
-  l = sizeof(sa);
-  rv = getpeername(fd, &sa, &l);
-  /* Solaris 2.5 getpeername() returns EINVAL if the fd is not a socket. */
-  return ((rv < 0 && (errno == ENOTSOCK || errno == EINVAL)) ? 0 : 1);
-#else /* !HAVE_GETPEERNAME || SVR4_2 || __BEOS__ */
-#  if defined (SVR4) || defined (SVR4_2)
-  /* Sockets on SVR4 and SVR4.2 are character special (streams) devices. */
-  struct stat sb;
-
-  if (isatty (fd))
-    return (0);
-  if (fstat (fd, &sb) < 0)
-    return (0);
-#    if defined (S_ISFIFO)
-  if (S_ISFIFO (sb.st_mode))
-    return (0);
-#    endif /* S_ISFIFO */
-  return (S_ISCHR (sb.st_mode));
-#  else /* !SVR4 && !SVR4_2 */
-#    if defined (S_ISSOCK) && !defined (__BEOS__)
-  struct stat sb;
-
-  if (fstat (fd, &sb) < 0)
-    return (0);
-  return (S_ISSOCK (sb.st_mode));
-#    else /* !S_ISSOCK || __BEOS__ */
-  return (0);
-#    endif /* !S_ISSOCK || __BEOS__ */
-#  endif /* !SVR4 && !SVR4_2 */
-#endif /* !HAVE_GETPEERNAME || SVR4_2 || __BEOS__ */
-}
diff --git a/shell.h b/shell.h
index b79d267bb074cb1cadf37b575b11f03985312cb8..0cc3a9270b092b5602d5f016cf50895894cb8ae7 100644 (file)
--- a/shell.h
+++ b/shell.h
@@ -35,6 +35,7 @@
 #include "unwind_prot.h"
 #include "dispose_cmd.h"
 #include "make_cmd.h"
+#include "ocache.h"
 #include "subst.h"
 #include "sig.h"
 #include "pathnames.h"
@@ -86,6 +87,7 @@ extern WORD_LIST *rest_of_args;
 /* Generalized global variables. */
 extern int executing, login_shell;
 extern int interactive, interactive_shell;
+extern int startup_state;
 
 /* Structure to pass around that holds a bitmap of file descriptors
    to close, and the size of that structure.  Used in execute_cmd.c. */
@@ -112,7 +114,7 @@ extern struct user_info current_user;
 
 /* Force gcc to not clobber X on a longjmp().  Old versions of gcc mangle
    this badly. */
-#if __GNUC__ == 2 && __GNUC_MINOR__ > 8
+#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ > 8)
 #  define USE_VAR(x)   ((void) &(x))
 #else
 #  define USE_VAR(x)
diff --git a/sig.c b/sig.c
index 646d6822e6789a95509683b269bd3d02956c45ba..21a57ae1001833da37467561959326db6010188d 100644 (file)
--- a/sig.c
+++ b/sig.c
@@ -54,7 +54,6 @@ extern int last_command_exit_value;
 extern int return_catch_flag;
 extern int loop_level, continuing, breaking;
 extern int parse_and_execute_level, shell_initialized;
-extern int startup_state;
 
 /* Non-zero after SIGINT. */
 int interrupt_state;
@@ -74,22 +73,17 @@ int interrupt_immediately = 0;
 static void initialize_shell_signals __P((void));
 
 void
-initialize_signals ()
+initialize_signals (reinit)
+     int reinit;
 {
   initialize_shell_signals ();
   initialize_job_signals ();
 #if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
-  initialize_siglist ();
+  if (reinit == 0)
+    initialize_siglist ();
 #endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
 }
 
-void
-reinitialize_signals ()
-{
-  initialize_shell_signals ();
-  initialize_job_signals ();
-}
-
 /* 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. */
@@ -225,6 +219,10 @@ initialize_terminating_signals ()
     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;
       /* Don't do anything with signals that are ignored at shell entry
@@ -244,6 +242,10 @@ initialize_terminating_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), termination_unwind_protect);
       /* Don't do anything with signals that are ignored at shell entry
         if the shell is not interactive. */
diff --git a/sig.h b/sig.h
index ed634ed7ce6c04101bd3c9583db216e3075cc8ca..2b4c115183416a044d8aab160f4640bd8f600485 100644 (file)
--- a/sig.h
+++ b/sig.h
@@ -30,7 +30,7 @@
 #endif
 
 #define sighandler RETSIGTYPE
-typedef RETSIGTYPE SigHandler ();
+typedef RETSIGTYPE SigHandler __P((int));
 
 #if defined (VOID_SIGHANDLER)
 #  define SIGRETURN(n) return
@@ -44,7 +44,7 @@ typedef RETSIGTYPE SigHandler ();
 #if !defined (HAVE_POSIX_SIGNALS)
 #  define set_signal_handler(sig, handler) (SigHandler *)signal (sig, handler)
 #else
-extern SigHandler *set_signal_handler ();      /* in sig.c */
+extern SigHandler *set_signal_handler __P((int, SigHandler *));        /* in sig.c */
 #endif /* _POSIX_VERSION */
 
 /* Definitions used by the job control code. */
@@ -89,10 +89,12 @@ extern SigHandler *set_signal_handler ();   /* in sig.c */
 /* These definitions are used both in POSIX and non-POSIX implementations. */
 
 #define BLOCK_SIGNAL(sig, nvar, ovar) \
+do { \
   sigemptyset (&nvar); \
   sigaddset (&nvar, sig); \
   sigemptyset (&ovar); \
-  sigprocmask (SIG_BLOCK, &nvar, &ovar)
+  sigprocmask (SIG_BLOCK, &nvar, &ovar); \
+} while (0)
 
 #if defined (HAVE_POSIX_SIGNALS)
 #  define BLOCK_CHILD(nvar, ovar) \
@@ -109,8 +111,7 @@ extern SigHandler *set_signal_handler ();   /* in sig.c */
 /* Functions from sig.c. */
 extern sighandler termination_unwind_protect __P((int));
 extern sighandler sigint_sighandler __P((int));
-extern void initialize_signals __P((void));
-extern void reinitialize_signals __P((void));
+extern void initialize_signals __P((int));
 extern void initialize_terminating_signals __P((void));
 extern void reset_terminating_signals __P((void));
 extern void throw_to_top_level __P((void));
index db8f15b3b1d6ec43d7b73cc3362f51a1f95e963c..97280cf5a843c957be9aa7b63401f26d43e4d995 100644 (file)
@@ -1,7 +1,6 @@
 /* stringlib.c - Miscellaneous string functions. */
 
-/* Copyright (C) 1996
-   Free Software Foundation, Inc.
+/* Copyright (C) 1996-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 /*                                                                 */
 /* **************************************************************** */
 
-/* Cons up a new array of words.  The words are taken from LIST,
-   which is a WORD_LIST *.  If COPY is true, everything is malloc'ed,
-   so you should free everything in this array when you are done.
-   The array is NULL terminated.  If IP is non-null, it gets the
-   number of words in the returned array.  STARTING_INDEX says where
-   to start filling in the returned array; it can be used to reserve
-   space at the beginning of the array. */
-char **
-word_list_to_argv (list, copy, starting_index, ip)
-     WORD_LIST *list;
-     int copy, starting_index, *ip;
+/* Find STRING in ALIST, a list of string key/int value pairs.  If FLAGS
+   is 1, STRING is treated as a pattern and matched using strmatch. */
+int
+find_string_in_alist (string, alist, flags)
+     char *string;
+     STRING_INT_ALIST *alist;
+     int flags;
 {
-  int count;
-  char **array;
-
-  count = list_length (list);
-  array = (char **)xmalloc ((1 + count + starting_index) * sizeof (char *));
+  register int i;
+  int r;
 
-  for (count = 0; count < starting_index; count++)
-    array[count] = (char *)NULL;
-  for (count = starting_index; list; count++, list = list->next)
-    array[count] = copy ? savestring (list->word->word) : list->word->word;
-  array[count] = (char *)NULL;
+  for (i = r = 0; alist[i].word; i++)
+    {
+#if defined (EXTENDED_GLOB)
+      if (flags)
+       r = strmatch (alist[i].word, string, FNM_EXTMATCH) != FNM_NOMATCH;
+      else
+#endif
+       r = STREQ (string, alist[i].word);
 
-  if (ip)
-    *ip = count;
-  return (array);
+      if (r)
+       return (alist[i].token);
+    }
+  return -1;
 }
 
-/* Convert an array of strings into the form used internally by the shell.
-   COPY means to copy the values in ARRAY into the returned list rather
-   than allocate new storage.  STARTING_INDEX says where in ARRAY to begin. */
-WORD_LIST *
-argv_to_word_list (array, copy, starting_index)
-     char **array;
-     int copy, starting_index;
+/* Find TOKEN in ALIST, a list of string/int value pairs.  Return the
+   corresponding string.  Allocates memory for the returned
+   string.  FLAGS is currently ignored, but reserved. */
+char *
+find_token_in_alist (token, alist, flags)
+     int token;
+     STRING_INT_ALIST *alist;
+     int flags;
 {
-  WORD_LIST *list;
-  WORD_DESC *w;
-  int i, count;
-
-  if (array == 0 || array[0] == 0)
-    return (WORD_LIST *)NULL;
-
-  for (count = 0; array[count]; count++)
-    ;
+  register int i;
 
-  for (i = starting_index, list = (WORD_LIST *)NULL; i < count; i++)
+  for (i = 0; alist[i].word; i++)
     {
-      w = make_bare_word (copy ? "" : array[i]);
-      if (copy)
-       {
-         free (w->word);
-         w->word = array[i];
-       }
-      list = make_word_list (w, list);
+      if (alist[i].token == token)
+        return (savestring (alist[i].word));
     }
-  return (REVERSE_LIST(list, WORD_LIST *));
+  return ((char *)NULL);
 }
 
-/* Find STRING in ALIST, a list of string key/int value pairs.  If FLAGS
-   is 1, STRING is treated as a pattern and matched using strmatch. */
 int
-find_string_in_alist (string, alist, flags)
+find_index_in_alist (string, alist, flags)
      char *string;
      STRING_INT_ALIST *alist;
      int flags;
@@ -127,8 +109,9 @@ find_string_in_alist (string, alist, flags)
        r = STREQ (string, alist[i].word);
 
       if (r)
-       return (alist[i].token);
+       return (i);
     }
+
   return -1;
 }
 
@@ -138,6 +121,23 @@ find_string_in_alist (string, alist, flags)
 /*                                                                 */
 /* **************************************************************** */
 
+/* Cons a new string from STRING starting at START and ending at END,
+   not including END. */
+char *
+substring (string, start, end)
+     char *string;
+     int start, end;
+{
+  register int len;
+  register char *result;
+
+  len = end - start;
+  result = (char *)xmalloc (len + 1);
+  strncpy (result, string + start, len);
+  result[len] = '\0';
+  return (result);
+}
+
 /* Replace occurrences of PAT with REP in STRING.  If GLOBAL is non-zero,
    replace all occurrences, otherwise replace only the first.
    This returns a new string; the caller should free it. */
diff --git a/subst.c b/subst.c
index 4670e41a31e708bdc45f4b3bef174c9f208078ca..9ebc465a4bfa7b77ec76dec18c4356f1bb8aa440 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -4,7 +4,7 @@
 /* ``Have a little faith, there's magic in the night.  You ain't a
      beauty, but, hey, you're alright.'' */
 
-/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -47,6 +47,8 @@
 #include "pathexp.h"
 #include "mailcheck.h"
 
+#include "shmbutil.h"
+
 #include "builtins/getopt.h"
 #include "builtins/common.h"
 
@@ -70,6 +72,12 @@ extern int errno;
 /* 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 string extraction functions. */
+#define EX_NOALLOC     0x01    /* just skip; don't return substring */
+#define EX_VARNAME     0x02    /* variable name; for string_extract () */
 
 /* These defs make it easier to use the editor. */
 #define LBRACE         '{'
@@ -89,8 +97,7 @@ extern int errno;
 
 /* Evaluates to 1 if C is one of the OP characters that follows the parameter
    in ${parameter[:]OPword}. */
-#define VALID_PARAM_EXPAND_CHAR(c) \
-  ((c) == '-' || (c) == '=' || (c) == '?' || (c) == '+')
+#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) \
@@ -107,9 +114,16 @@ typedef WORD_LIST *EXPFUNC __P((char *, int));
 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];
+unsigned char ifs_firstc;
+
 /* Extern functions and variables from different files. */
 extern int last_command_exit_value;
-extern int subshell_environment, startup_state;
+extern int subshell_environment;
+extern int eof_encountered;
 extern int return_catch_flag, return_catch_value;
 extern pid_t dollar_dollar_pid;
 extern int posixly_correct;
@@ -151,7 +165,8 @@ WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL;
 static WORD_LIST *garglist = (WORD_LIST *)NULL;
 
 static char *quoted_substring __P((char *, int, int));
-static inline char *quoted_strchr __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 *));
@@ -160,12 +175,13 @@ 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 char *remove_quoted_escapes __P((char *));
 static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
+static char *dequote_escapes __P((char *));
 static char *make_quoted_char __P((int));
 static WORD_LIST *quote_list __P((WORD_LIST *));
 static WORD_LIST *dequote_list __P((WORD_LIST *));
-static void remove_quoted_nulls __P((char *));
+static char *remove_quoted_escapes __P((char *));
+static char *remove_quoted_nulls __P((char *));
 
 static int unquoted_substring __P((char *, char *));
 static int unquoted_member __P((int, char *));
@@ -175,13 +191,12 @@ static int do_assignment_internal __P((const char *, int));
 static char *string_extract_verbatim __P((char *, int *, char *));
 static char *string_extract __P((char *, int *, char *, int));
 static char *string_extract_double_quoted __P((char *, int *, int));
-static char *string_extract_single_quoted __P((char *, int *));
-static inline int skip_single_quoted __P((char *, int));
-static int skip_double_quoted __P((char *, int));
-static char *extract_delimited_string __P((char *, int *, char *, char *, char *));
-static char *extract_dollar_brace_string __P((char *, int *, int));
+static inline char *string_extract_single_quoted __P((char *, int *));
+static inline int skip_single_quoted __P((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 char *string_list_internal __P((WORD_LIST *, char *));
 static char *pos_params __P((char *, int, int, int));
 
 static char *remove_pattern __P((char *, char *, int));
@@ -189,12 +204,13 @@ static int match_pattern_char __P((char *, char *));
 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 *parameter_brace_remove_pattern __P((char *, 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((char *, int, int, int));
+static char *parameter_list_remove_pattern __P((int, char *, int, int));
 #ifdef ARRAY_VARS
-static char *array_remove_pattern __P((char *, char *, char *, int, int));
+static char *array_remove_pattern __P((ARRAY *, char *, int, char *, int));
 #endif
+static char *parameter_brace_remove_pattern __P((char *, char *, char *, int, int));
 
 static char *process_substitute __P((char *, int));
 
@@ -211,10 +227,10 @@ static char *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, in
 static void parameter_brace_expand_error __P((char *, char *));
 
 static int valid_length_expression __P((char *));
-static long parameter_brace_expand_length __P((char *));
+static intmax_t parameter_brace_expand_length __P((char *));
 
 static char *skiparith __P((char *, int));
-static int verify_substring_values __P((char *, char *, int, long *, long *));
+static int verify_substring_values __P((char *, char *, int, intmax_t *, intmax_t *));
 static int get_var_and_type __P((char *, char *, SHELL_VAR **, char **));
 static char *parameter_brace_substring __P((char *, char *, char *, int));
 
@@ -227,7 +243,6 @@ static char *param_expand __P((char *, int *, int, int *, int *, int *, int *, i
 
 static WORD_LIST *expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
 
-static char *getifs __P((void));
 static WORD_LIST *word_list_split __P((WORD_LIST *));
 
 static WORD_LIST *separate_out_assignments __P((WORD_LIST *));
@@ -244,23 +259,7 @@ static WORD_LIST *expand_word_list_internal __P((WORD_LIST *, int));
 /*                                                                 */
 /* **************************************************************** */
 
-/* Cons a new string from STRING starting at START and ending at END,
-   not including END. */
-char *
-substring (string, start, end)
-     char *string;
-     int start, end;
-{
-  register int len;
-  register char *result;
-
-  len = end - start;
-  result = (char *)xmalloc (len + 1);
-  strncpy (result, string + start, len);
-  result[len] = '\0';
-  return (result);
-}
-
+#ifdef INCLUDE_UNUSED
 static char *
 quoted_substring (string, start, end)
      char *string;
@@ -300,12 +299,38 @@ quoted_substring (string, start, end)
   *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 inline char *
+static char *
 quoted_strchr (s, c, flags)
      char *s;
      int c, flags;
@@ -329,15 +354,19 @@ quoted_strchr (s, c, flags)
 }
 
 /* Return 1 if CHARACTER appears in an unquoted portion of
-   STRING.  Return 0 otherwise. */
+   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;
 
-  for (sindex = 0; c = string[sindex]; )
+  slen = strlen (string);
+  sindex = 0;
+  while (c = string[sindex])
     {
       if (c == character)
        return (1);
@@ -345,21 +374,21 @@ unquoted_member (character, string)
       switch (c)
        {
        default:
-         sindex++;
+         ADVANCE_CHAR (string, slen, sindex);
          break;
 
        case '\\':
          sindex++;
          if (string[sindex])
-           sindex++;
+           ADVANCE_CHAR (string, slen, sindex);
          break;
 
        case '\'':
-         sindex = skip_single_quoted (string, ++sindex);
+         sindex = skip_single_quoted (string, slen, ++sindex);
          break;
 
        case '"':
-         sindex = skip_double_quoted (string, ++sindex);
+         sindex = skip_double_quoted (string, slen, ++sindex);
          break;
        }
     }
@@ -371,11 +400,14 @@ 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]; )
     {
@@ -388,19 +420,19 @@ unquoted_substring (substr, string)
          sindex++;
 
          if (string[sindex])
-           sindex++;
+           ADVANCE_CHAR (string, slen, sindex);
          break;
 
        case '\'':
-         sindex = skip_single_quoted (string, ++sindex);
+         sindex = skip_single_quoted (string, slen, ++sindex);
          break;
 
        case '"':
-         sindex = skip_double_quoted (string, ++sindex);
+         sindex = skip_double_quoted (string, slen, ++sindex);
          break;
 
        default:
-         sindex++;
+         ADVANCE_CHAR (string, slen, sindex);
          break;
        }
     }
@@ -419,7 +451,7 @@ unquoted_substring (substr, string)
    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 *
+INLINE char *
 sub_append_string (source, target, indx, size)
      char *source, *target;
      int *indx, *size;
@@ -451,7 +483,7 @@ sub_append_string (source, target, indx, size)
    INDX and SIZE are as in SUB_APPEND_STRING. */
 char *
 sub_append_number (number, target, indx, size)
-     long number;
+     intmax_t number;
      int *indx, *size;
      char *target;
 {
@@ -465,28 +497,36 @@ sub_append_number (number, target, indx, size)
 /* 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 VARNAME is non-zero,
-   and array variables have been compiled into the shell, everything
-   between a `[' and a corresponding `]' is skipped over. */
+   Understand about backslashes in the string.  If (flags & EX_VARNAME)
+   is non-zero, and array variables have been compiled into the shell,
+   everything between a `[' and a corresponding `]' is skipped over.
+   If (flags & EX_NOALLOC) is non-zero, don't return the substring, just
+   update SINDEX. */
 static char *
-string_extract (string, sindex, charlist, varname)
+string_extract (string, sindex, charlist, flags)
      char *string;
      int *sindex;
      char *charlist;
-     int varname;
+     int flags;
 {
   register int c, i;
+  size_t slen;
   char *temp;
+  DECLARE_MBSTATE;
 
-  for (i = *sindex; c = string[i]; i++)
+  slen = strlen (string + *sindex) + *sindex;
+  i = *sindex;
+  while (c = string[i])
     {
       if (c == '\\')
-       if (string[i + 1])
-         i++;
-       else
-         break;
+       {
+         if (string[i + 1])
+           i++;
+         else
+           break;
+       }
 #if defined (ARRAY_VARS)
-      else if (varname && c == '[')
+      else if ((flags & EX_VARNAME) && c == '[')
        {
          int ni;
          /* If this is an array subscript, skip over it and continue. */
@@ -497,9 +537,11 @@ string_extract (string, sindex, charlist, varname)
 #endif
       else if (MEMBER (c, charlist))
          break;
+
+      ADVANCE_CHAR (string, slen, i);
     }
 
-  temp = substring (string, *sindex, i);
+  temp = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
   *sindex = i;
   return (temp);
 }
@@ -511,21 +553,29 @@ string_extract (string, sindex, charlist, varname)
    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 inline char *
+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 + strlen (string) - *sindex);
+  temp = (char *)xmalloc (1 + slen - *sindex);
 
-  for (j = 0, i = *sindex; c = string[i]; i++)
+  j = 0;
+  i = *sindex;
+  while (c = string[i])
     {
       /* Process a character that was quoted by a backslash. */
       if (pass_next)
@@ -534,7 +584,7 @@ string_extract_double_quoted (string, sindex, stripdq)
 
             ``The backslash shall retain its special meaning as an escape
             character only when followed by one of the characters:
-               $       `       "       \       <newline>''.
+               $       `       "       \       <newline>''.
 
             If STRIPDQ is zero, we handle the double quotes here and let
             expand_word_internal handle the rest.  If STRIPDQ is non-zero,
@@ -555,8 +605,10 @@ string_extract_double_quoted (string, sindex, stripdq)
          if ((stripdq == 0 && c != '"') ||
              (stripdq && ((dquote && (sh_syntaxtab[c] & CBSDQUOTE)) || dquote == 0)))
            temp[j++] = '\\';
-         temp[j++] = c;
          pass_next = 0;
+
+add_one_character:
+         COPY_CHAR_I (temp, j, string, send, i);
          continue;
        }
 
@@ -566,6 +618,7 @@ string_extract_double_quoted (string, sindex, stripdq)
       if (c == '\\')
        {
          pass_next++;
+         i++;
          continue;
        }
 
@@ -578,6 +631,7 @@ string_extract_double_quoted (string, sindex, stripdq)
          if (c == '`')
            backquote = 0;
          temp[j++] = c;
+         i++;
          continue;
        }
 
@@ -585,6 +639,7 @@ string_extract_double_quoted (string, sindex, stripdq)
        {
          temp[j++] = c;
          backquote++;
+         i++;
          continue;
        }
 
@@ -594,9 +649,9 @@ string_extract_double_quoted (string, sindex, stripdq)
        {
          si = i + 2;
          if (string[i + 1] == LPAREN)
-           ret = extract_delimited_string (string, &si, "$(", "(", ")"); /*)*/
+           ret = extract_delimited_string (string, &si, "$(", "(", ")", 0); /*)*/
          else
-           ret = extract_dollar_brace_string (string, &si, 1);
+           ret = extract_dollar_brace_string (string, &si, 1, 0);
 
          temp[j++] = '$';
          temp[j++] = string[i + 1];
@@ -605,7 +660,7 @@ string_extract_double_quoted (string, sindex, stripdq)
            temp[j] = ret[t];
          temp[j++] = string[si];
 
-         i = si;
+         i = si + 1;
          free (ret);
          continue;
        }
@@ -613,15 +668,13 @@ string_extract_double_quoted (string, sindex, stripdq)
       /* Add any character but a double quote to the quoted string we're
         accumulating. */
       if (c != '"')
-       {
-         temp[j++] = c;
-         continue;
-       }
+       goto add_one_character;
 
       /* c == '"' */
       if (stripdq)
        {
          dquote ^= 1;
+         i++;
          continue;
        }
 
@@ -639,53 +692,61 @@ string_extract_double_quoted (string, sindex, stripdq)
 
 /* This should really be another option to string_extract_double_quoted. */
 static int
-skip_double_quoted (string, sind)
+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;
-
-  for (i = sind; c = string[i]; i++)
+  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_delimited_string (string, &si, "$(", "(", ")");
+           ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC);
          else
-           ret = extract_dollar_brace_string (string, &si, 0);
+           ret = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
 
-         i = si;
-         free (ret);
+         i = si + 1;
          continue;
        }
       else if (c != '"')
-       continue;
+       {
+         ADVANCE_CHAR (string, slen, i);
+         continue;
+       }
       else
        break;
     }
@@ -706,10 +767,14 @@ string_extract_single_quoted (string, sindex)
      int *sindex;
 {
   register int i;
+  size_t slen;
   char *t;
+  DECLARE_MBSTATE;
 
-  for (i = *sindex; string[i] && string[i] != '\''; i++)
-    ;
+  slen = strlen (string + *sindex) + *sindex;
+  i = *sindex;
+  while (string[i] && string[i] != '\'')
+    ADVANCE_CHAR (string, slen, i);
 
   t = substring (string, *sindex, i);
 
@@ -721,14 +786,18 @@ string_extract_single_quoted (string, sindex)
 }
 
 static inline int
-skip_single_quoted (string, sind)
+skip_single_quoted (string, slen, sind)
      char *string;
+     size_t slen;
      int sind;
 {
   register int c;
+  DECLARE_MBSTATE;
+
+  c = sind;
+  while (string[c] && string[c] != '\'')
+    ADVANCE_CHAR (string, slen, c);
 
-  for (c = sind; string[c] && string[c] != '\''; c++)
-    ;
   if (string[c])
     c++;
   return c;
@@ -779,7 +848,7 @@ extract_command_subst (string, sindex)
      char *string;
      int *sindex;
 {
-  return (extract_delimited_string (string, sindex, "$(", "(", ")"));
+  return (extract_delimited_string (string, sindex, "$(", "(", ")", 0));
 }
 
 /* Extract the $[ construct in STRING, and return a new string. (])
@@ -790,7 +859,7 @@ extract_arithmetic_subst (string, sindex)
      char *string;
      int *sindex;
 {
-  return (extract_delimited_string (string, sindex, "$[", "[", "]")); /*]*/
+  return (extract_delimited_string (string, sindex, "$[", "[", "]", 0)); /*]*/
 }
 
 #if defined (PROCESS_SUBSTITUTION)
@@ -803,7 +872,7 @@ extract_process_subst (string, starter, sindex)
      char *starter;
      int *sindex;
 {
-  return (extract_delimited_string (string, sindex, starter, "(", ")"));
+  return (extract_delimited_string (string, sindex, starter, "(", ")", 0));
 }
 #endif /* PROCESS_SUBSTITUTION */
 
@@ -813,7 +882,7 @@ extract_array_assignment_list (string, sindex)
      char *string;
      int *sindex;
 {
-  return (extract_delimited_string (string, sindex, "(", (char *)NULL, ")"));
+  return (extract_delimited_string (string, sindex, "(", (char *)NULL, ")", 0));
 }
 #endif
 
@@ -826,16 +895,20 @@ extract_array_assignment_list (string, sindex)
    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)
+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;
   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);
@@ -855,18 +928,11 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer)
       if (pass_character)      /* previous char was backslash */
        {
          pass_character = 0;
-         i++;
-         continue;
-       }
-
-      if (c == CTLESC)
-       {
-         pass_character++;
-         i++;
+         ADVANCE_CHAR (string, slen, i);
          continue;
        }
 
-      if (c == '\\')
+      if (c == CTLESC || c == '\\')
        {
          pass_character++;
          i++;
@@ -877,9 +943,8 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer)
       if (STREQN (string + i, opener, len_opener))
        {
          si = i + len_opener;
-         t = extract_delimited_string (string, &si, opener, alt_opener, closer);
+         t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|EX_NOALLOC);
          i = si + 1;
-         FREE (t);
          continue;
        }
 
@@ -887,9 +952,8 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer)
       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);
+         t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|EX_NOALLOC);
          i = si + 1;
-         FREE (t);
          continue;
        }
 
@@ -897,7 +961,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer)
         the nesting level. */
       if (STREQN (string + i, closer, len_closer))
        {
-         i += len_closer - 1;  /* move to last char of the closer */
+         i += len_closer - 1;  /* move to last byte of the closer */
          nesting_level--;
          if (nesting_level == 0)
            break;
@@ -907,36 +971,25 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer)
       if (c == '`')
        {
          si = i + 1;
-         t = string_extract (string, &si, "`", 0);
+         t = string_extract (string, &si, "`", flags|EX_NOALLOC);
          i = si + 1;
-         FREE (t);
          continue;
        }
 
-      /* Pass single-quoted strings through verbatim. */
-      if (c == '\'')
-       {
-         si = i + 1;
-         i = skip_single_quoted (string, si);
-         continue;
-       }
-
-      /* Pass embedded double-quoted strings through verbatim as well. */
-      if (c == '"')
+      /* Pass single-quoted and double-quoted strings through verbatim. */
+      if (c == '\'' || c == '"')
        {
          si = i + 1;
-         i = skip_double_quoted (string, si);
+         i = (c == '\'') ? skip_single_quoted (string, slen, si)
+                         : skip_double_quoted (string, slen, si);
          continue;
        }
 
-      i++;     /* move past this character, which was not special. */
+      /* move past this character, which was not special. */
+      ADVANCE_CHAR (string, slen, i);
     }
 
-#if 0
-  if (c == 0 && nesting_level)
-#else
   if (c == 0 && nesting_level && no_longjmp_on_fatal_error == 0)
-#endif
     {
       report_error ("bad substitution: no `%s' in %s", closer, string);
       last_command_exit_value = EXECUTION_FAILURE;
@@ -944,9 +997,14 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer)
     }
 
   si = i - *sindex - len_closer + 1;
-  result = (char *)xmalloc (1 + si);
-  strncpy (result, string + *sindex, si);
-  result[si] = '\0';
+  if (flags & EX_NOALLOC)
+    result = (char *)NULL;
+  else    
+    {
+      result = (char *)xmalloc (1 + si);
+      strncpy (result, string + *sindex, si);
+      result[si] = '\0';
+    }
   *sindex = i;
 
   return (result);
@@ -961,23 +1019,27 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer)
    occurs inside double quotes. */
 /* XXX -- this is very similar to extract_delimited_string -- XXX */
 static char *
-extract_dollar_brace_string (string, sindex, quoted)
+extract_dollar_brace_string (string, sindex, quoted, flags)
      char *string;
-     int *sindex, quoted;
+     int *sindex, quoted, flags;
 {
   register int i, c;
+  size_t slen;
   int pass_character, nesting_level, si;
   char *result, *t;
+  DECLARE_MBSTATE;
 
   pass_character = 0;
-
   nesting_level = 1;
+  slen = strlen (string + *sindex) + *sindex;
 
-  for (i = *sindex; (c = string[i]); i++)
+  i = *sindex;
+  while (c = string[i])
     {
       if (pass_character)
        {
          pass_character = 0;
+         ADVANCE_CHAR (string, slen, i);
          continue;
        }
 
@@ -985,13 +1047,14 @@ extract_dollar_brace_string (string, sindex, quoted)
       if (c == CTLESC || c == '\\')
        {
          pass_character++;
+         i++;
          continue;
        }
 
       if (string[i] == '$' && string[i+1] == LBRACE)
        {
          nesting_level++;
-         i++;
+         i += 2;
          continue;
        }
 
@@ -1000,6 +1063,7 @@ extract_dollar_brace_string (string, sindex, quoted)
          nesting_level--;
          if (nesting_level == 0)
            break;
+         i++;
          continue;
        }
 
@@ -1008,9 +1072,8 @@ extract_dollar_brace_string (string, sindex, quoted)
       if (c == '`')
        {
          si = i + 1;
-         t = string_extract (string, &si, "`", 0);
-         i = si;
-         free (t);
+         t = string_extract (string, &si, "`", flags|EX_NOALLOC);
+         i = si + 1;
          continue;
        }
 
@@ -1019,9 +1082,8 @@ extract_dollar_brace_string (string, sindex, quoted)
       if (string[i] == '$' && string[i+1] == LPAREN)
        {
          si = i + 2;
-         t = extract_delimited_string (string, &si, "$(", "(", ")"); /*)*/
-         i = si;
-         free (t);
+         t = extract_delimited_string (string, &si, "$(", "(", ")", flags|EX_NOALLOC); /*)*/
+         i = si + 1;
          continue;
        }
 
@@ -1030,12 +1092,14 @@ extract_dollar_brace_string (string, sindex, quoted)
       if (c == '\'' || c == '"')
        {
          si = i + 1;
-         i = (c == '\'') ? skip_single_quoted (string, si)
-                         : skip_double_quoted (string, si);
+         i = (c == '\'') ? skip_single_quoted (string, slen, si)
+                         : skip_double_quoted (string, slen, si);
          /* skip_XXX_quoted leaves index one past close quote */
-         i--;
          continue;
        }
+
+      /* move past this character, which was not special. */
+      ADVANCE_CHAR (string, slen, i);
     }
 
   if (c == 0 && nesting_level && no_longjmp_on_fatal_error == 0)
@@ -1045,7 +1109,7 @@ extract_dollar_brace_string (string, sindex, quoted)
       jump_to_top_level (DISCARD);
     }
 
-  result = substring (string, *sindex, i);
+  result = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
   *sindex = i;
 
   return (result);
@@ -1057,12 +1121,28 @@ char *
 de_backslash (string)
      char *string;
 {
-  register int i, l;
+  register size_t slen;
+  register int i, j, prev_i;
+  DECLARE_MBSTATE;
 
-  for (i = 0, l = strlen (string); i < l; i++)
-    if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
+  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] == '$'))
-      strcpy (string + i, string + i + 1);     /* XXX - should be memmove */
+       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);
 }
 
@@ -1096,7 +1176,9 @@ unquote_bang (string)
    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. */
+   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. */
 
 #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
 
@@ -1105,32 +1187,43 @@ char_is_quoted (string, eindex)
      char *string;
      int eindex;
 {
-  int i, pass_next;
+  int i, pass_next, c;
+  size_t slen;
+  DECLARE_MBSTATE;
 
+  slen = strlen (string);
   no_longjmp_on_fatal_error = 1;
-  for (i = pass_next = 0; i <= eindex; i++)
+  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 (string[i] == '\'' || string[i] == '"')
-       {
-         i = (string[i] == '\'') ? skip_single_quoted (string, ++i)
-                                 : skip_double_quoted (string, ++i);
-         if (i > eindex)
-           CQ_RETURN(1);
-         i--;  /* the skip functions increment past the closing quote. */
-       }
-      else if (string[i] == '\\')
+      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);
 }
 
@@ -1141,34 +1234,42 @@ unclosed_pair (string, eindex, openstr)
      char *openstr;
 {
   int i, pass_next, openc, olen;
+  size_t slen;
+  DECLARE_MBSTATE;
 
+  slen = strlen (string);
   olen = strlen (openstr);
-  for (i = pass_next = openc = 0; i <= eindex; i++)
+  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 - 1;
+         i += olen;
        }
       else if (string[i] == '\'' || string[i] == '"')
        {
-         i = (string[i] == '\'') ? skip_single_quoted (string, i)
-                                 : skip_double_quoted (string, i);
+         i = (string[i] == '\'') ? skip_single_quoted (string, slen, i)
+                                 : skip_double_quoted (string, slen, i);
          if (i > eindex)
            return 0;
        }
-      else if (string[i] == '\\')
-       {
-         pass_next = 1;
-         continue;
-       }
+      else
+       ADVANCE_CHAR (string, slen, i);
     }
   return (openc);
 }
@@ -1185,60 +1286,72 @@ skip_to_delim (string, start, delims)
      int start;
      char *delims;
 {
-  int i, pass_next, backq, si;
+  int i, pass_next, backq, si, c;
+  size_t slen;
   char *temp;
+  DECLARE_MBSTATE;
 
+  slen = strlen (string + start) + start;
   no_longjmp_on_fatal_error = 1;
-  for (i = start, pass_next = backq = 0; string[i]; i++)
+  i = start;
+  pass_next = backq = 0;
+  while (c = string[i])
     {
       if (pass_next)
        {
          pass_next = 0;
-         if (string[i] == 0)
+         if (c == 0)
            CQ_RETURN(i);
+         ADVANCE_CHAR (string, slen, i);
          continue;
        }
-      else if (string[i] == '\\')
+      else if (c == '\\')
        {
          pass_next = 1;
+         i++;
          continue;
        }
       else if (backq)
        {
-         if (string[i] == '`')
+         if (c == '`')
            backq = 0;
+         ADVANCE_CHAR (string, slen, i);
          continue;
        }
-      else if (string[i] == '`')
+      else if (c == '`')
        {
          backq = 1;
+         i++;
          continue;
        }
-      else if (string[i] == '\'' || string[i] == '"')
+      else if (c == '\'' || c == '"')
        {
-         i = (string[i] == '\'') ? skip_single_quoted (string, ++i)
-                                 : skip_double_quoted (string, ++i);
-         i--;  /* the skip functions increment past the closing quote. */
+         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 (string[i] == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
+      else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
        {
          si = i + 2;
          if (string[si] == '\0')
            CQ_RETURN(si);
 
          if (string[i+1] == LPAREN)
-           temp = extract_delimited_string (string, &si, "$(", "(", ")"); /* ) */
+           temp = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC); /* ) */
          else
-           temp = extract_dollar_brace_string (string, &si, 0);
+           temp = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
          i = si;
-         free (temp);
          if (string[i] == '\0')        /* don't increment i past EOS in loop */
            break;
+         i++;
          continue;
        }
-      else if (member (string[i], delims))
+      else if (member (c, delims))
        break;
+      else
+       ADVANCE_CHAR (string, slen, i);
     }
+
   CQ_RETURN(i);
 }
 
@@ -1269,7 +1382,7 @@ split_at_delims (string, slen, delims, sentinel, nwp, cwp)
       return ((WORD_LIST *)NULL);
     }
 
-  d = (delims == 0) ? getifs () : delims;
+  d = (delims == 0) ? ifs_value : delims;
 
   /* Make d2 the non-whitespace characters in delims */
   d2 = 0;
@@ -1286,7 +1399,7 @@ split_at_delims (string, slen, delims, sentinel, nwp, cwp)
 
   ret = (WORD_LIST *)NULL;
 
-  for (i = 0; member (string[i], d) && (whitespace(string[i]) || string[i] == '\n'); i++)
+  for (i = 0; member (string[i], d) && spctabnl(string[i]); i++)
     ;
   if (string[i] == '\0')
     return (ret);
@@ -1327,9 +1440,7 @@ split_at_delims (string, slen, delims, sentinel, nwp, cwp)
         the word we just added, and set the current word to that one. */
       if (cwp && cw == -1 && sentinel < ts)
        {
-         tl = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
-         tl->word = make_word ("");
-         tl->next = ret->next;
+         tl = make_word_list (make_word (""), ret->next);
          ret->next = tl;
          cw = nw;
          nw++;
@@ -1339,7 +1450,7 @@ split_at_delims (string, slen, delims, sentinel, nwp, cwp)
        break;
 
       i = te /* + member (string[te], d) */;
-      while (member (string[i], d) && whitespace(string[i]))
+      while (member (string[i], d) && spctabnl(string[i]))
        i++;
 
       if (string[i])
@@ -1398,7 +1509,7 @@ assignment_name (string)
 
 /* 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. */
-static char *
+char *
 string_list_internal (list, sep)
      WORD_LIST *list;
      char *sep;
@@ -1463,11 +1574,9 @@ char *
 string_list_dollar_star (list)
      WORD_LIST *list;
 {
-  char *ifs, sep[2];
+  char sep[2];
 
-  ifs = get_string_value ("IFS");
-
-  sep[0] = (ifs == 0) ? ' ' : *ifs;
+  sep[0] = ifs_firstc;
   sep[1] = '\0';
 
   return (string_list_internal (list, sep));
@@ -1490,7 +1599,8 @@ string_list_dollar_at (list, quoted)
   char *ifs, sep[2];
   WORD_LIST *tlist;
 
-  ifs = get_string_value ("IFS");
+  /* XXX this could just be ifs = ifs_value; */
+  ifs = ifs_var ? value_cell (ifs_var) : (char *)0;
 
   sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
   sep[1] = '\0';
@@ -1528,7 +1638,11 @@ string_list_dollar_at (list, quoted)
 
 /* This performs word splitting and quoted null character removal on
    STRING. */
-#define issep(c)       (member ((c), separators))
+#if 0
+#define issep(c)       ((separators)[1] ? (member ((c), separators)) : (c) == (separators)[0])
+#else
+#define issep(c)       ((separators)[1] ? isifs(c) : (c) == (separators)[0])
+#endif
 
 WORD_LIST *
 list_string (string, separators, quoted)
@@ -1543,8 +1657,10 @@ list_string (string, separators, quoted)
   if (!string || !*string)
     return ((WORD_LIST *)NULL);
 
-  sh_style_split =
-    separators && *separators && (STREQ (separators, " \t\n"));
+  sh_style_split = separators && separators[0] == ' ' &&
+                                separators[1] == '\t' &&
+                                separators[2] == '\n' &&
+                                separators[3] == '\0';
 
   /* Remove sequences of whitespace at the beginning of STRING, as
      long as those characters appear in IFS.  Do not do this if
@@ -1561,8 +1677,8 @@ list_string (string, separators, quoted)
 
   /* 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
+       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. */
   for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
     {
@@ -1617,10 +1733,10 @@ list_string (string, separators, quoted)
       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 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++;
     }
@@ -1629,7 +1745,9 @@ list_string (string, separators, quoted)
 
 /* 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.
+   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 *
@@ -1645,14 +1763,16 @@ get_word_from_string (stringp, separators, endptr)
 
   s = *stringp;
 
-  sh_style_split =
-    separators && *separators && (STREQ (separators, " \t\n"));
+  sh_style_split = separators && separators[0] == ' ' &&
+                                separators[1] == '\t' &&
+                                separators[2] == '\n' &&
+                                separators[3] == '\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) && issep (*s); s++);
+      for (; *s && spctabnl (*s) && isifs (*s); s++);
 
       /* If the string is nothing but whitespace, update it and return. */
       if (!*s)
@@ -1686,14 +1806,14 @@ get_word_from_string (stringp, separators, endptr)
 
   /* Now skip sequences of space, tab, or newline characters if they are
      in the list of separators. */
-  while (s[sindex] && spctabnl (s[sindex]) && issep (s[sindex]))
+  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 && issep (s[sindex]) && !spctabnl (s[sindex]))
+  if (s[sindex] && whitesep && isifs (s[sindex]) && !spctabnl (s[sindex]))
     sindex++;
 
   /* Update STRING to point to the next field. */
@@ -1714,7 +1834,7 @@ strip_trailing_ifs_whitespace (string, separators, saw_escape)
   char *s;
 
   s = string + STRLEN (string) - 1;
-  while (s > string && ((spctabnl (*s) && issep (*s)) ||
+  while (s > string && ((spctabnl (*s) && isifs (*s)) ||
                        (saw_escape && *s == CTLESC && spctabnl (s[1]))))
     s--;
   *++s = '\0';
@@ -1731,6 +1851,7 @@ list_string_with_quotes (string)
 {
   WORD_LIST *list;
   char *token, *s;
+  size_t s_len;
   int c, i, tokstart, len;
 
   for (s = string; s && *s && spctabnl (*s); s++)
@@ -1738,6 +1859,7 @@ list_string_with_quotes (string)
   if (s == 0 || *s == 0)
     return ((WORD_LIST *)NULL);
 
+  s_len = strlen (s);
   tokstart = i = 0;
   list = (WORD_LIST *)NULL;
   while (1)
@@ -1750,9 +1872,9 @@ list_string_with_quotes (string)
            i++;
        }
       else if (c == '\'')
-       i = skip_single_quoted (s, ++i);
+       i = skip_single_quoted (s, s_len, ++i);
       else if (c == '"')
-       i = skip_double_quoted (s, ++i);
+       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
@@ -1810,10 +1932,10 @@ do_assignment_internal (string, expand)
       temp = name + offset + 1;
 
 #if defined (ARRAY_VARS)
-      if (expand && temp[0] == LPAREN && strchr (temp, RPAREN))
+      if (expand && temp[0] == LPAREN && xstrchr (temp, RPAREN))
        {
          assign_list = ni = 1;
-         value = extract_delimited_string (temp, &ni, "(", (char *)NULL, ")");
+         value = extract_delimited_string (temp, &ni, "(", (char *)NULL, ")", 0);
        }
       else
 #endif
@@ -1821,8 +1943,8 @@ do_assignment_internal (string, expand)
       /* Perform tilde expansion. */
       if (expand && temp[0])
        {
-         temp = (strchr (temp, '~') && unquoted_member ('~', temp))
-                       ? bash_tilde_expand (temp)
+         temp = (xstrchr (temp, '~') && unquoted_member ('~', temp))
+                       ? bash_tilde_expand (temp, 1)
                        : savestring (temp);
 
          value = expand_string_if_necessary (temp, 0, expand_string_unsplit);
@@ -1851,7 +1973,7 @@ do_assignment_internal (string, expand)
 #define ASSIGN_RETURN(r)       do { FREE (value); free (name); return (r); } while (0)
 
 #if defined (ARRAY_VARS)
-  if (t = strchr (name, '['))  /*]*/
+  if (t = xstrchr (name, '[')) /*]*/
     {
       if (assign_list)
        {
@@ -1935,7 +2057,7 @@ number_of_args ()
 /* Return the value of a positional parameter.  This handles values > 10. */
 char *
 get_dollar_var_value (ind)
-     long ind;
+     intmax_t ind;
 {
   char *temp;
   WORD_LIST *p;
@@ -1970,7 +2092,9 @@ string_rest_of_args (dollar_star)
 
 /* 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. */
+   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;
@@ -2000,7 +2124,7 @@ pos_params (string, start, end, quoted)
 
   t->next = (WORD_LIST *)NULL;
   if (string[0] == '*')
-    ret = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (h) : string_list (h);
+    ret = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (quote_list (h)) : string_list (h);
   else
     ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
   if (t != params)
@@ -2032,15 +2156,20 @@ expand_string_if_necessary (string, quoted, func)
      EXPFUNC *func;
 {
   WORD_LIST *list;
+  size_t slen;
   int i, saw_quote;
   char *ret;
+  DECLARE_MBSTATE;
 
-  for (i = saw_quote = 0; string[i]; i++)
+  slen = strlen (string);
+  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])
@@ -2058,6 +2187,7 @@ expand_string_if_necessary (string, quoted, func)
     ret = string_quote_removal (string, quoted);
   else
     ret = savestring (string);
+
   return ret;
 }
 
@@ -2140,9 +2270,9 @@ cond_expand_word (w, special)
   if (w->word == 0 || w->word[0] == '\0')
     return ((char *)NULL);
 
-  if (strchr (w->word, '~') && unquoted_member ('~', w->word))
+  if (xstrchr (w->word, '~') && unquoted_member ('~', w->word))
     {
-      p = bash_tilde_expand (w->word);
+      p = bash_tilde_expand (w->word, 0);
       free (w->word);
       w->word = p;
     }
@@ -2361,40 +2491,6 @@ expand_string (string, quoted)
      A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
      The parser passes CTLNUL as CTLESC 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.
-   Here we remove doubled CTLESC characters inside quoted strings before
-   quoting the entire string, so we do not double the number of CTLESC
-   characters. */
-static char *
-remove_quoted_escapes (string)
-     char *string;
-{
-  register char *s;
-  int docopy;
-  char *t, *t1;
-
-  if (string == NULL)
-    return (string);
-
-  t1 = t = (char *)xmalloc (strlen (string) + 1);
-  for (docopy = 0, s = string; *s; s++, t1++)
-    {
-      if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
-       {
-         s++;
-         docopy = 1;
-       }
-      *t1 = *s;
-    }
-  *t1 = '\0';
-  if (docopy)
-    strcpy (string, t);
-  free (t);
-  return (string);
-}
-
 /* 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. */
@@ -2403,14 +2499,21 @@ quote_escapes (string)
      char *string;
 {
   register char *s, *t;
-  char *result;
+  size_t slen;
+  char *result, *send;
+  DECLARE_MBSTATE; 
 
-  result = (char *)xmalloc ((strlen (string) * 2) + 1);
-  for (s = string, t = result; *s; )
+  slen = strlen (string);
+  send = string + slen;
+
+  t = result = (char *)xmalloc ((slen * 2) + 1);
+  s = string;
+
+  while (*s)
     {
       if (*s == CTLESC || *s == CTLNUL)
        *t++ = CTLESC;
-      *t++ = *s++;
+      COPY_CHAR_P (t, s, send);
     }
   *t = '\0';
   return (result);
@@ -2432,17 +2535,39 @@ list_quote_escapes (list)
   return list;
 }
 
-#if 0
-/* UNUSED */
+/* 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. */
 static char *
 dequote_escapes (string)
      char *string;
 {
   register char *s, *t;
-  char *result;
+  size_t slen;
+  char *result, *send;
+  DECLARE_MBSTATE;
 
-  result = (char *)xmalloc (strlen (string) + 1);
-  for (s = string, t = result; *s; )
+  if (string == 0)
+    return string;
+
+  slen = strlen (string);
+  send = string + slen;
+
+  t = result = (char *)xmalloc (slen + 1);
+  s = string;
+
+  if (strchr (string, CTLESC) == 0)
+    return (strcpy (result, s));
+
+  while (*s)
     {
       if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
        {
@@ -2450,28 +2575,11 @@ dequote_escapes (string)
          if (*s == '\0')
            break;
        }
-      *t++ = *s++;
+      COPY_CHAR_P (t, s, send);
     }
   *t = '\0';
   return result;
 }
-#endif
-
-static 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);
-      free (tlist->word->word);
-      tlist->word->word = s;
-    }
-  return list;
-}
 
 /* Return a new string with the quoted representation of character C. */
 static char *
@@ -2501,7 +2609,8 @@ quote_string (string)
      char *string;
 {
   register char *t;
-  char *result;
+  size_t slen;
+  char *result, *send;
 
   if (*string == 0)
     {
@@ -2511,12 +2620,17 @@ quote_string (string)
     }
   else
     {
-      result = (char *)xmalloc ((strlen (string) * 2) + 1);
+      DECLARE_MBSTATE;
 
-      for (t = result; *string; )
+      slen = strlen (string);
+      send = string + slen;
+
+      result = (char *)xmalloc ((slen * 2) + 1);
+
+      for (t = result; string < send; )
        {
          *t++ = CTLESC;
-         *t++ = *string++;
+         COPY_CHAR_P (t, string, send);
        }
       *t = '\0';
     }
@@ -2528,10 +2642,14 @@ char *
 dequote_string (string)
      char *string;
 {
-  register char *t;
-  char *result;
+  register char *s, *t;
+  size_t slen;
+  char *result, *send;
+  DECLARE_MBSTATE;
 
-  result = (char *)xmalloc (strlen (string) + 1);
+  slen = strlen (string);
+
+  t = result = (char *)xmalloc (slen + 1);
 
   if (QUOTED_NULL (string))
     {
@@ -2541,23 +2659,20 @@ dequote_string (string)
 
   /* 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)         /* XXX */
-    {                                          /* XXX */
-      strcpy (result, string);                 /* XXX */
-      return (result);                         /* XXX */
-    }
+  if (strchr (string, CTLESC) == NULL)
+    return (strcpy (result, string));
 
-  for (t = result; *string; string++, t++)
+  send = string + slen;
+  s = string;
+  while (*s)
     {
-      if (*string == CTLESC)
+      if (*s == CTLESC)
        {
-         string++;
-
-         if (!*string)
+         s++;
+         if (*s == '\0')
            break;
        }
-
-      *t = *string;
+      COPY_CHAR_P (t, s, send);
     }
 
   *t = '\0';
@@ -2582,40 +2697,82 @@ quote_list (list)
   return list;
 }
 
+static 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);
+      free (tlist->word->word);
+      tlist->word->word = s;
+    }
+  return list;
+}
+
+/* Remove CTLESC protecting a CTLESC or CTLNUL in place.  Return the passed
+   string. */
+static 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. */
-/*
-#define remove_quoted_nulls(string) \
-  do { if (QUOTED_NULL (string)) string[0] ='\0'; } while (0)
-*/
-static void
+static char *
 remove_quoted_nulls (string)
      char *string;
 {
-  char *nstr, *s, *p;
+  register size_t slen;
+  register int i, j, prev_i;
+  DECLARE_MBSTATE;
+
+  if (strchr (string, CTLNUL) == 0)            /* XXX */
+    return string;                             /* XXX */
 
-  nstr = savestring (string);
-  nstr[0] = '\0';
-  for (p = nstr, s = string; *s; s++)
+  slen = strlen (string);
+  i = j = 0;
+
+  while (i < slen)
     {
-      if (*s == CTLESC)
+      if (string[i] == CTLESC)
+        {
+          i++; j++;
+          if (i == slen)
+            break;
+        }
+      else if (string[i] == CTLNUL)
+        i++;
+
+      prev_i = i;
+      ADVANCE_CHAR (string, slen, i);
+      if (j < prev_i)
        {
-         *p++ = *s++;  /* CTLESC */
-         if (*s == 0)
-           break;
-         *p++ = *s;    /* quoted char */
-         continue;
+         do string[j++] = string[prev_i++]; while (prev_i < i);
        }
-      if (*s == CTLNUL)
-       continue;
-      *p++ = *s;
+      else
+       j = i;
     }
-  *p = '\0';
-  strcpy (string, nstr);
-  free (nstr);
+  string[j] = '\0';
+
+  return (string);
 }
 
 /* Perform quoted null character removal on each element of LIST.
@@ -2856,10 +3013,14 @@ getpattern (value, quoted, expandpat)
   WORD_LIST *l;
   int i;
 
-  tword = strchr (value, '~') ? bash_tilde_expand (value) : savestring (value);
+  tword = xstrchr (value, '~') ? bash_tilde_expand (value, 0) : savestring (value);
 
-  /* expand_string_internal () leaves WORD quoted and does not perform
-     word splitting. */
+  /* 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;
@@ -2867,16 +3028,13 @@ getpattern (value, quoted, expandpat)
       free (tword);
       tword = pat;
     }
+#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? */
-#if 0
-  l = *tword ? expand_string_for_rhs (tword, quoted, (int *)NULL, (int *)NULL)
-#else
+  /* expand_string_for_rhs () leaves WORD quoted and does not perform
+     word splitting. */
   l = *tword ? expand_string_for_rhs (tword,
-                                     (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_NOQUOTE : quoted,
+                                     (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_PATQUOTE : quoted,
                                      (int *)NULL, (int *)NULL)
-#endif
             : (WORD_LIST *)0;
   free (tword);
   pat = string_list (l);
@@ -2890,33 +3048,27 @@ getpattern (value, quoted, expandpat)
   return (pat);
 }
 
+#if 0
 /* Handle removing a pattern from a string as a result of ${name%[%]value}
    or ${name#[#]value}. */
 static char *
-parameter_brace_remove_pattern (value, temp, c, quoted)
-     char *value, *temp;
-     int c, quoted;
+variable_remove_pattern (value, pattern, patspec, quoted)
+     char *value, *pattern;
+     int patspec, quoted;
 {
-  int patspec;
-  char *pattern, *tword;
-
-  patspec = getpatspec (c, value);
-  if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
-    value++;
-
-  pattern = getpattern (value, quoted, 1);
+  char *tword;
 
-  tword = remove_pattern (temp, pattern, patspec);
+  tword = remove_pattern (value, pattern, patspec);
 
-  FREE (pattern);
   return (tword);
 }
+#endif
 
 static char *
-list_remove_pattern (list, pattern, patspec, type, quoted)
+list_remove_pattern (list, pattern, patspec, itype, quoted)
      WORD_LIST *list;
      char *pattern;
-     int patspec, type, quoted;
+     int patspec, itype, quoted;
 {
   WORD_LIST *new, *l;
   WORD_DESC *w;
@@ -2931,7 +3083,7 @@ list_remove_pattern (list, pattern, patspec, type, quoted)
     }
 
   l = REVERSE_LIST (new, WORD_LIST *);
-  if (type == '*')
+  if (itype == '*')
     tword = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (l) : string_list (l);
   else
     tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
@@ -2941,77 +3093,114 @@ list_remove_pattern (list, pattern, patspec, type, quoted)
 }
 
 static char *
-parameter_list_remove_pattern (value, type, c, quoted)
-     char *value;
-     int type, c, quoted;
+parameter_list_remove_pattern (itype, pattern, patspec, quoted)
+     int itype;
+     char *pattern;
+     int patspec, quoted;
 {
-  int patspec;
-  char *pattern, *ret;
+  char *ret;
   WORD_LIST *list;
 
-  patspec = getpatspec (c, value);
-  if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
-    value++;
-
-  pattern = getpattern (value, quoted, 1);
-
   list = list_rest_of_args ();
-  ret = list_remove_pattern (list, pattern, patspec, type, quoted);
+  if (list == 0)
+    return ((char *)NULL);
+  ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
   dispose_words (list);
-  FREE (pattern);
   return (ret);
 }
 
 #if defined (ARRAY_VARS)
 static char *
-array_remove_pattern (value, aspec, aval, c, quoted)
-     char *value, *aspec, *aval;       /* AVAL == evaluated ASPEC */
-     int c, quoted;
+array_remove_pattern (a, pattern, patspec, varname, quoted)
+     ARRAY *a;
+     char *pattern;
+     int patspec;
+     char *varname;    /* so we can figure out how it's indexed */
+     int quoted;
 {
-  SHELL_VAR *var;
-  int len, patspec;
-  char *ret, *t, *pattern;
-  WORD_LIST *l;
+  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];
+
+  list = array_to_word_list (a);
+  if (list == 0)
+   return ((char *)NULL);
+  ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
+  dispose_words (list);
 
-  var = array_variable_part (aspec, &t, &len);
-  if (var == 0)
+  return ret;
+}
+#endif /* ARRAY_VARS */
+
+static char *
+parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
+     char *varname, *value, *patstr;
+     int rtype, quoted;
+{
+  int vtype, patspec;
+  char *temp1, *val, *pattern;
+  SHELL_VAR *v;
+
+  if (value == 0)
+    return ((char *)NULL);
+
+  this_command_name = varname;
+
+  vtype = get_var_and_type (varname, value, &v, &val);
+  if (vtype == -1)
     return ((char *)NULL);
 
-  patspec = getpatspec (c, value);
+  patspec = getpatspec (rtype, patstr);
   if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
-    value++;
+    patstr++;
 
-  pattern = getpattern (value, quoted, 1);
+  pattern = getpattern (patstr, quoted, 1);
 
-  if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
+  temp1 = (char *)NULL;                /* shut up gcc */
+  switch (vtype)
     {
-      if (array_p (var) == 0)
+    case VT_VARIABLE:
+    case VT_ARRAYMEMBER:
+      temp1 = remove_pattern (val, pattern, patspec);
+      if (vtype == VT_VARIABLE)
+       FREE (val);
+      if (temp1)
        {
-         report_error ("%s: bad array subscript", aspec);
-         FREE (pattern);
-         return ((char *)NULL);
+         val = quote_escapes (temp1);
+         free (temp1);
+         temp1 = val;
        }
-      l = array_to_word_list (array_cell (var));
-      if (l == 0)
-       return ((char *)NULL);
-      ret = list_remove_pattern (l, pattern, patspec, t[0], quoted);
-      dispose_words (l);
-    }
-  else
-    {
-      ret = remove_pattern (aval, pattern, patspec);
-      if (ret)
+      break;
+#if defined (ARRAY_VARS)
+    case VT_ARRAYVAR:
+      temp1 = array_remove_pattern (array_cell (v), pattern, patspec, varname, quoted);
+      if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
        {
-         t = quote_escapes (ret);
-         free (ret);
-         ret = t;
+         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 ret;
-}
-#endif /* ARRAY_VARS */
+  return temp1;
+}    
 
 /*******************************************
  *                                        *
@@ -3049,7 +3238,7 @@ expand_word_unsplit (word, quoted)
   expand_no_split_dollar_star = 1;
   result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
   expand_no_split_dollar_star = 0;
-  
+
   return (result ? dequote_list (result) : result);
 }
 
@@ -3114,13 +3303,13 @@ unlink_fifo_list ()
     {
       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;
+         unlink (fifo_list[i].file);
+         free (fifo_list[i].file);
+         fifo_list[i].file = (char *)NULL;
+         fifo_list[i].proc = -1;
        }
       else
-        saved++;
+       saved++;
     }
 
   /* If we didn't remove some of the FIFOs, compact the list. */
@@ -3181,7 +3370,7 @@ add_fifo_list (fd)
        totfds = fd + 2;
 
       dev_fd_list = (char *)xrealloc (dev_fd_list, totfds);
-      bzero (dev_fd_list + ofds, totfds - ofds);
+      memset (dev_fd_list + ofds, '\0', totfds - ofds);
     }
 
   dev_fd_list[fd] = 1;
@@ -3557,7 +3746,7 @@ command_substitute (string, quoted)
   /* Pipe the output of executing STRING into the current shell. */
   if (pipe (fildes) < 0)
     {
-      sys_error ("cannot make pipes for command substitution");
+      sys_error ("cannot make pipe for command substitution");
       goto error_exit;
     }
 
@@ -3628,7 +3817,7 @@ command_substitute (string, quoted)
       subshell_environment |= SUBSHELL_COMSUB;
 
       /* When not in POSIX mode, command substitution does not inherit
-         the -e flag. */
+        the -e flag. */
       if (posixly_correct == 0)
        exit_immediately_on_error = 0;
 
@@ -3724,7 +3913,7 @@ array_length_reference (s)
     {
       c = *--t;
       *t = '\0';
-      report_error ("%s: unbound variable", s);
+      err_unboundvar (s);
       *t = c;
       return (-1);
     }
@@ -3743,7 +3932,7 @@ array_length_reference (s)
   ind = array_expand_index (t, len);
   if (ind < 0)
     {
-      report_error ("%s: bad array subscript", t);
+      err_badarraysub (t);
       return (-1);
     }
 
@@ -3787,42 +3976,40 @@ parameter_brace_expand_word (name, var_is_special, quoted)
      int var_is_special, quoted;
 {
   char *temp, *tt;
-  long arg_index;
+  intmax_t arg_index;
   SHELL_VAR *var;
-#if 0
-  WORD_LIST *l;
-#endif
+  int atype;
 
   /* Handle multiple digit arguments, as in ${11}. */
   
   if (legal_number (name, &arg_index))
-    temp = get_dollar_var_value (arg_index);
+    {
+      tt = get_dollar_var_value (arg_index);
+      temp = tt ? quote_escapes (tt) : (char *)NULL;
+      FREE (tt);
+    }
   else if (var_is_special)      /* ${@} */
     {
       int sindex;
       tt = (char *)xmalloc (2 + strlen (name));
       tt[sindex = 0] = '$';
       strcpy (tt + 1, name);
-#if 0
-      l = expand_string_leave_quoted (tt, quoted);
-      free (tt);
-      temp = string_list (l);
-      dispose_words (l);
-#else
+
       temp = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
                           (int *)NULL, (int *)NULL, 0);
       free (tt);
-#endif
     }
 #if defined (ARRAY_VARS)
   else if (valid_array_reference (name))
     {
-      temp = array_value (name, quoted);
+      temp = array_value (name, quoted, &atype);
+      if (atype == 0 && temp)
+       temp = quote_escapes (temp);
     }
 #endif
   else if (var = find_variable (name))
     {
-      if (var && invisible_p (var) == 0)
+      if (var_isset (var) && invisible_p (var) == 0)
        {
 #if defined (ARRAY_VARS)
          temp = array_p (var) ? array_reference (array_cell (var), 0) : value_cell (var);
@@ -3832,9 +4019,6 @@ parameter_brace_expand_word (name, var_is_special, quoted)
 
          if (temp)
            temp = quote_escapes (temp);
-
-         if (tempvar_p (var))
-           dispose_variable (var);
        }
       else
        temp = (char *)NULL;
@@ -3857,11 +4041,7 @@ parameter_brace_expand_indir (name, var_is_special, quoted)
   t = parameter_brace_expand_word (name, var_is_special, quoted);
   if (t == 0)
     return (t);
-#if 0
-  temp = parameter_brace_expand_word (t, t[0] == '@' && t[1] == '\0', quoted);
-#else
   temp = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted);
-#endif
   free (t);
   return temp;
 }
@@ -3879,9 +4059,13 @@ parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
   char *t, *t1, *temp;
   int hasdol;
 
-  temp = (*value == '~' || (strchr (value, '~') && unquoted_substring ("=~", value)))
-       ? bash_tilde_expand (value)
-       : savestring (value);
+  /* XXX - Should we tilde expand in an assignment context if C is `='? */
+  if (*value == '~')
+    temp = bash_tilde_expand (value, 0);
+  else if (xstrchr (value, '~')  && unquoted_substring ("=~", value))
+    temp = bash_tilde_expand (value, 1);
+  else
+    temp = savestring (value);
 
   /* 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
@@ -3916,8 +4100,8 @@ parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
     {
       /* 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. */
+        it does not expand to anything.  In this case, we want to return
+        a quoted empty string. */
       temp = (char *)xmalloc (2);
       temp[0] = CTLNUL;
       temp[1] = '\0';
@@ -3950,9 +4134,12 @@ parameter_brace_expand_error (name, value)
 
   if (value && *value)
     {
-      temp = (*value == '~' || (strchr (value, '~') && unquoted_substring ("=~", value)))
-               ? bash_tilde_expand (value)
-               : savestring (value);
+      if (*value == '~')
+       temp = bash_tilde_expand (value, 0);
+      else if (xstrchr (value, '~')  && unquoted_substring ("=~", value))
+       temp = bash_tilde_expand (value, 1);
+      else
+       temp = savestring (value);
 
       l = expand_string (temp, 0);
       FREE (temp);
@@ -3987,12 +4174,12 @@ valid_length_expression (name)
 
 /* Handle the parameter brace expansion that requires us to return the
    length of a parameter. */
-static long
+static intmax_t
 parameter_brace_expand_length (name)
      char *name;
 {
   char *t, *newname;
-  long number, arg_index;
+  intmax_t number, arg_index;
   WORD_LIST *list;
 #if defined (ARRAY_VARS)
   SHELL_VAR *var;
@@ -4080,40 +4267,52 @@ skiparith (substr, delim)
      char *substr;
      int delim;
 {
-  int skipcol, pcount;
-  char *t;
+  size_t sublen;
+  int skipcol, pcount, i;
+  DECLARE_MBSTATE;
 
-  for (skipcol = pcount = 0, t = substr; *t; t++)
+  sublen = strlen (substr);
+  i = skipcol = pcount = 0;
+  while (substr[i])
     {
       /* Balance parens */
-      if (*t == '(')
+      if (substr[i] == LPAREN)
        {
          pcount++;
+         i++;
          continue;
        }
-      if (*t == ')' && pcount)
+      if (substr[i] == RPAREN && pcount)
        {
          pcount--;
+         i++;
          continue;
        }
       if (pcount)
-       continue;
+       {
+         ADVANCE_CHAR (substr, sublen, i);
+         continue;
+       }
 
       /* Skip one `:' for each `?' */
-      if (*t == ':' && skipcol)
+      if (substr[i] == ':' && skipcol)
        {
          skipcol--;
+         i++;
          continue;
        }
-      if (*t == delim)
+      if (substr[i] == delim)
        break;
-      if (*t == '?')
+      if (substr[i] == '?')
        {
          skipcol++;
+         i++;
          continue;
        }
+      ADVANCE_CHAR (substr, sublen, i);
     }
-  return t;
+
+  return (substr + i);
 }
 
 /* Verify and limit the start and end of the desired substring.  If
@@ -4126,7 +4325,7 @@ static int
 verify_substring_values (value, substr, vtype, e1p, e2p)
      char *value, *substr;
      int vtype;
-     long *e1p, *e2p;
+     intmax_t *e1p, *e2p;
 {
   char *t, *temp1, *temp2;
   arrayind_t len;
@@ -4138,7 +4337,7 @@ verify_substring_values (value, substr, vtype, e1p, e2p)
   /* duplicate behavior of strchr(3) */
   t = skiparith (substr, ':');
   if (*t && *t == ':')
-    *t = '\0'; 
+    *t = '\0';
   else
     t = (char *)0;
 
@@ -4203,7 +4402,10 @@ verify_substring_values (value, substr, vtype, e1p, e2p)
 
 /* 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). */
+   by VARNAME (value of a variable or a reference to an array element).
+   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, varp, valp)
      char *varname, *value;
@@ -4216,7 +4418,8 @@ get_var_and_type (varname, value, varp, valp)
   SHELL_VAR *v;
 #endif
 
-  vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';      /* VT_POSPARMS */
+  /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
+  vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
   *varp = (SHELL_VAR *)NULL;
 
 #if defined (ARRAY_VARS)
@@ -4233,7 +4436,7 @@ get_var_and_type (varname, value, varp, valp)
          else
            {
              vtype = VT_ARRAYMEMBER;
-             *valp = array_value (varname, 1);
+             *valp = array_value (varname, 1, (int *)NULL);
            }
          *varp = v;
        }
@@ -4242,13 +4445,13 @@ get_var_and_type (varname, value, varp, valp)
     }
   else if ((v = find_variable (varname)) && array_p (v))
     {
-      vtype = VT_VARIABLE;
+      vtype = VT_ARRAYMEMBER;
       *varp = v;
       *valp = array_reference (array_cell (v), 0);
     }
   else
 #endif
-  *valp = value;
+  *valp = (value && vtype == VT_VARIABLE) ? dequote_escapes (value) : value;
 
   return vtype;
 }
@@ -4268,9 +4471,9 @@ parameter_brace_substring (varname, value, substr, quoted)
      char *varname, *value, *substr;
      int quoted;
 {
-  long e1, e2;
+  intmax_t e1, e2;
   int vtype, r;
-  char *temp, *val;
+  char *temp, *val, *tt;
   SHELL_VAR *v;
 
   if (value == 0)
@@ -4284,26 +4487,41 @@ parameter_brace_substring (varname, value, substr, quoted)
 
   r = verify_substring_values (val, substr, vtype, &e1, &e2);
   if (r <= 0)
-    {
-      if (val && vtype == VT_ARRAYMEMBER)
-       free (val);
-      return ((r == 0) ? &expand_param_error : (char *)NULL);
-    }
+    return ((r == 0) ? &expand_param_error : (char *)NULL);
 
   switch (vtype)
     {
     case VT_VARIABLE:
     case VT_ARRAYMEMBER:
-      temp = quoted ? quoted_substring (value, e1, e2) : substring (value, e1, e2);
-      if (val && vtype == VT_ARRAYMEMBER)
-       free (val);
+      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:
-      temp = pos_params (varname, e1, e2, quoted);
+      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:
-      temp = array_subrange (array_cell (v), e1, e2, quoted);
+      tt = array_subrange (array_cell (v), 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;
 #endif
     default:
@@ -4406,7 +4624,7 @@ pos_params_pat_subst (string, pat, rep, mflags)
 {
   WORD_LIST *save, *params;
   WORD_DESC *w;
-  char *ret;
+  char *ret, *tt;
 
   save = params = list_rest_of_args ();
   if (save == 0)
@@ -4437,7 +4655,7 @@ parameter_brace_patsub (varname, value, patsub, quoted)
      int quoted;
 {
   int vtype, mflags;
-  char *val, *temp, *pat, *rep, *p, *lpatsub;
+  char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
   SHELL_VAR *v;
 
   if (value == 0)
@@ -4455,8 +4673,9 @@ parameter_brace_patsub (varname, value, patsub, quoted)
       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. */
+
+  /* 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))
@@ -4473,11 +4692,7 @@ parameter_brace_patsub (varname, value, patsub, quoted)
   /* Expand PAT and REP for command, variable and parameter, arithmetic,
      and process substitution.  Also perform quote removal.  Do not
      perform word splitting or filename generation. */
-#if 0
-  pat = expand_string_if_necessary (lpatsub, quoted, expand_string_unsplit);
-#else
   pat = expand_string_if_necessary (lpatsub, (quoted & ~Q_DOUBLE_QUOTES), expand_string_unsplit);
-#endif
 
   if (rep)
     {
@@ -4504,26 +4719,50 @@ parameter_brace_patsub (varname, value, patsub, quoted)
   /* 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. */
+     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 = 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 = array_pat_subst (array_cell (v), p, rep, mflags);
+      temp = array_patsub (array_cell (v), p, rep, mflags);
+      if (temp && (mflags & MATCH_QUOTED) == 0)
+       {
+         tt = quote_escapes (temp);
+         free (temp);
+         temp = tt;
+       }
       break;
 #endif
     }
 
-  if (val && v && array_p (v) && vtype == VT_ARRAYMEMBER)
-    free (val);
-
   FREE (pat);
   FREE (rep);
   free (lpatsub);
@@ -4547,7 +4786,7 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
   int want_substring, want_indir, want_patsub;
   char *name, *value, *temp, *temp1;
   int t_index, sindex, c;
-  long number;
+  intmax_t number;
 
   value = (char *)NULL;
   var_is_set = var_is_null = var_is_special = check_nullness = 0;
@@ -4555,7 +4794,7 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
 
   sindex = *indexp;
   t_index = ++sindex;
-  name = string_extract (string, &t_index, "#%:-=?+/}", 1);
+  name = string_extract (string, &t_index, "#%:-=?+/}", EX_VARNAME);
 
   /* If the name really consists of a special variable, then make sure
      that we have the entire name.  We don't allow indirect references
@@ -4633,7 +4872,7 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
      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]));
+                                       || VALID_INDIR_PARAM (name[1]));
 
   /* Determine the value of this variable. */
 
@@ -4684,7 +4923,7 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
       number = strlen (temp1);
       temp1[number - 1] = '\0';
       x = all_variables_matching_prefix (temp1);
-      xlist = argv_to_word_list (x, 1, 0);
+      xlist = strvec_to_word_list (x, 0, 0);
       if (string[sindex - 2] == '*')
        temp = string_list_dollar_star (xlist);
       else
@@ -4718,10 +4957,10 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
 #if defined (ARRAY_VARS)
   if (valid_array_reference (name))
     {
-      temp1 = strchr (name, '[');
+      temp1 = xstrchr (name, '[');
       if (temp1 && temp1[1] == '@' && temp1[2] == ']')
        {
-         if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
+         if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
            *quoted_dollar_atp = 1;
          if (contains_dollar_at)
            *contains_dollar_at = 1;
@@ -4744,7 +4983,7 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
     {
       /* Extract the contents of the ${ ... } expansion
         according to the Posix.2 rules. */
-      value = extract_dollar_brace_string (string, &sindex, quoted);
+      value = extract_dollar_brace_string (string, &sindex, quoted, 0);
       if (string[sindex] == RBRACE)
        sindex++;
       else
@@ -4788,7 +5027,7 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
     case RBRACE:
       if (var_is_set == 0 && unbound_vars_is_error)
        {
-         report_error ("%s: unbound variable", name);
+         err_unboundvar (name);
          FREE (value);
          FREE (temp);
          free (name);
@@ -4804,14 +5043,7 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
          FREE (value);
          break;
        }
-      if ((name[0] == '@' || name[0] == '*') && name[1] == '\0')
-       temp1 = parameter_list_remove_pattern (value, name[0], c, quoted);
-#if defined (ARRAY_VARS)
-      else if (valid_array_reference (name))
-       temp1 = array_remove_pattern (value, name, temp, c, quoted);
-#endif
-      else
-       temp1 = parameter_brace_remove_pattern (value, temp, c, quoted);
+      temp1 = parameter_brace_remove_pattern (name, temp, value, c, quoted);
       free (temp);
       free (value);
       temp = temp1;
@@ -4904,10 +5136,10 @@ param_expand (string, sindex, quoted, expanded_something,
      int *sindex, quoted, *expanded_something, *contains_dollar_at;
      int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
 {
-  char *temp, *temp1;
+  char *temp, *temp1, uerror[3];
   int zindex, t_index, expok;
   unsigned char c;
-  long number;
+  intmax_t number;
   SHELL_VAR *var;
   WORD_LIST *list;
 
@@ -4933,11 +5165,14 @@ param_expand (string, sindex, quoted, expanded_something,
       temp1 = dollar_vars[TODIGIT (c)];
       if (unbound_vars_is_error && temp1 == (char *)NULL)
        {
-         report_error ("$%c: unbound variable", c);
+         uerror[0] = '$';
+         uerror[1] = c;
+         uerror[2] = '\0';
+         err_unboundvar (uerror);
          last_command_exit_value = EXECUTION_FAILURE;
          return (interactive_shell ? &expand_param_error : &expand_param_fatal);
        }
-      temp = temp1 ? savestring (temp1) : (char *)NULL;
+      temp = temp1 ? quote_escapes (temp1) : (char *)NULL;
       break;
 
     /* $$ -- pid of the invoking shell. */
@@ -4972,7 +5207,10 @@ param_expand (string, sindex, quoted, expanded_something,
          temp = (char *)NULL;
          if (unbound_vars_is_error)
            {
-             report_error ("$%c: unbound variable", c);
+             uerror[0] = '$';
+             uerror[1] = c;
+             uerror[2] = '\0';
+             err_unboundvar (uerror);
              last_command_exit_value = EXECUTION_FAILURE;
              return (interactive_shell ? &expand_param_error : &expand_param_fatal);
            }
@@ -5160,7 +5398,7 @@ comsub:
       /* If the variable exists, return its value cell. */
       var = find_variable (temp1);
 
-      if (var && invisible_p (var) == 0 && value_cell (var))
+      if (var && invisible_p (var) == 0 && var_isset (var))
        {
 #if defined (ARRAY_VARS)
          if (array_p (var))
@@ -5173,18 +5411,14 @@ comsub:
 #endif
          temp = quote_escapes (value_cell (var));
          free (temp1);
-         if (tempvar_p (var))          /* XXX */
-           {
-             dispose_variable (var);   /* XXX */
-             var = (SHELL_VAR *)NULL;
-           }
+
          goto return0;
        }
 
       temp = (char *)NULL;
 
       if (unbound_vars_is_error)
-       report_error ("%s: unbound variable", temp1);
+       err_unboundvar (temp1);
       else
        {
          free (temp1);
@@ -5257,6 +5491,9 @@ expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_somethin
   /* The text of WORD. */
   register char *string;
 
+  /* The size of STRING. */
+  size_t string_size;
+
   /* The index into STRING. */
   int sindex;
 
@@ -5273,12 +5510,12 @@ expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_somethin
   int tflag;
 
   register unsigned char c;    /* Current character. */
-  unsigned char uc;
   int t_index;                 /* For calls to string_extract_xxx. */
 
-  char ifscmap[256];
   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;
@@ -5287,27 +5524,11 @@ expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_somethin
   string = word->word;
   if (string == 0)
     goto finished_with_string;
+  string_size = strlen (string);
 
   if (contains_dollar_at)
     *contains_dollar_at = 0;
 
-  /* Cache a bitmap of characters in IFS for quoting IFS characters that are
-     not part of an expansion.  POSIX.2 says this is a must. */
-  temp = getifs ();
-  bzero (ifscmap, sizeof (ifscmap));
-  for (temp1 = temp; temp1 && *temp1; temp1++)
-#if 0
-    /* This check compensates for what I think is a parsing problem -- the
-       end brace matching algorithms for ${...} expressions differ between
-       parse.y and subst.c.  For instance, the parser passes
-       ${abc:-G { I } K } as one word when it should be three. */
-    if (*temp1 != ' ' && *temp1 != '\t' && *temp1 != '\n')
-#endif
-      {
-       uc = *temp1;
-        ifscmap[uc] = 1;
-      }
-
   /* Begin the expansion. */
 
   for (sindex = 0; ;)
@@ -5321,10 +5542,39 @@ expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_somethin
          goto finished_with_string;
 
        case CTLESC:
-         temp = (char *)xmalloc (3);
-         temp[0] = CTLESC;
-         temp[1] = c = string[++sindex];
-         temp[2] = '\0';
+         sindex++;
+#if HANDLE_MULTIBYTE
+         if (MB_CUR_MAX > 1 && string[sindex])
+           {
+             int i;
+             mbstate_t state_bak;
+             size_t mblength;
+
+             state_bak = state;
+             mblength = mbrlen (string + sindex, string_size - sindex, &state);
+             if (mblength == (size_t)-1 || mblength == (size_t)-2)
+               {
+                 state = state_bak;
+                 mblength = 1;
+               }
+             if (mblength < 1)
+               mblength = 1;
+             temp = (char *)xmalloc (mblength + 2);
+             temp[0] = CTLESC;
+             for (i = 0; i < mblength; i++)
+               temp[i+1] = string[sindex++];
+             temp[mblength + 1] = '\0';
+
+             goto add_string;
+           }
+         else
+#endif
+           {
+             temp = (char *)xmalloc (3);
+             temp[0] = CTLESC;
+             temp[1] = c = string[sindex];
+             temp[2] = '\0';
+           }
 
 dollar_add_string:
          if (string[sindex])
@@ -5419,11 +5669,9 @@ add_string:
          else
            tflag = 0;
 
-
          if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
            {
-             twochars[0] = '\\';
-             twochars[1] = c;
+             SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
            }
          else if (c == 0)
            {
@@ -5433,8 +5681,7 @@ add_string:
            }
          else
            {
-             twochars[0] = CTLESC;
-             twochars[1] = c;
+             SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
            }
 
          sindex++;
@@ -5449,7 +5696,11 @@ add_twochars:
          break;
 
        case '"':
-         if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_NOQUOTE))
+#if 0
+         if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_PATQUOTE))
+#else
+         if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+#endif
            goto add_character;
 
          t_index = ++sindex;
@@ -5459,7 +5710,7 @@ add_twochars:
             whole word was quoted. */
          quoted_state = (t_index == 1 && string[sindex] == '\0')
                            ? WHOLLY_QUOTED
-                           : PARTIALLY_QUOTED;
+                           : PARTIALLY_QUOTED;
 
          if (temp && *temp)
            {
@@ -5551,7 +5802,11 @@ add_twochars:
                     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. */                   
+                    the $* should expand into nothing. */
+                 /* HOWEVER, this fails if the string contains a literal
+                    CTLNUL or CTLNUL is contained in the (non-null) expansion
+                    of some variable.  I'm not sure what to do about this
+                    yet. */
                  if (QUOTED_NULL (temp) == 0)
                    remove_quoted_nulls (temp); /* XXX */
 #endif
@@ -5585,7 +5840,11 @@ add_twochars:
          /* break; */
 
        case '\'':
-         if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_NOQUOTE))
+#if 0
+         if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_PATQUOTE))
+#else
+         if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+#endif
            goto add_character;
 
          t_index = ++sindex;
@@ -5595,7 +5854,7 @@ add_twochars:
             then the string is wholly quoted. */
          quoted_state = (t_index == 1 && string[sindex] == '\0')
                            ? WHOLLY_QUOTED
-                           : PARTIALLY_QUOTED;
+                           : PARTIALLY_QUOTED;
 
          /* If all we had was '', it is a null expansion. */
          if (*temp == '\0')
@@ -5604,7 +5863,7 @@ add_twochars:
              temp = (char *)NULL;
            }
          else
-           remove_quoted_escapes (temp);
+           remove_quoted_escapes (temp);       /* ??? */
 
          /* We do not want to add quoted nulls to strings that are only
             partially quoted; such nulls are discarded. */
@@ -5625,7 +5884,7 @@ add_twochars:
 
        default:
          /* This is the fix for " $@ " */
-         if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && ifscmap[c]))
+         if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
            {
              if (string[sindex])       /* from old goto dollar_add_string */
                sindex++;
@@ -5636,12 +5895,45 @@ add_twochars:
                }
              else
                {
-                 twochars[0] = CTLESC;
-                 twochars[1] = c;
-                 goto add_twochars;
+#if HANDLE_MULTIBYTE
+                 /* XXX - I'd like to use SCOPY_CHAR_I here. */
+                 if (MB_CUR_MAX > 1)
+                   {
+                     int i;
+                     mbstate_t state_bak;
+                     size_t mblength;
+
+                     sindex--;
+                     state_bak = state;
+                     mblength = mbrlen (string + sindex, string_size - sindex, &state);
+                     if (mblength == (size_t)-1 || mblength == (size_t)-2)
+                       {
+                         state = state_bak;
+                         mblength = 1;
+                       }
+                     if (mblength < 1)
+                       mblength = 1;
+
+                     temp = (char *)xmalloc (mblength + 2);
+                     temp[0] = CTLESC;
+                     for (i = 0; i < mblength; i++)
+                       temp[i + 1] = string[sindex++];
+                     temp[mblength + 1] = '\0';
+
+                     goto add_string;
+                   }
+                 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);
@@ -5724,7 +6016,7 @@ finished_with_string:
     {
       char *ifs_chars;
 
-      ifs_chars = (quoted_dollar_at || has_dollar_at) ? getifs () : (char *)NULL;
+      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
@@ -5758,18 +6050,23 @@ finished_with_string:
 /* **************************************************************** */
 
 /* Perform quote removal on STRING.  If QUOTED > 0, assume we are obeying the
-   backslash quoting rules for within double quotes. */
+   backslash quoting rules for within double quotes or a here document. */
 char *
 string_quote_removal (string, quoted)
      char *string;
      int quoted;
 {
-  char *r, *result_string, *temp;
+  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. */
-  r = result_string = (char *)xmalloc (strlen (string) + 1);
+  slen = strlen (string);
+  send = string + slen;
+
+  r = result_string = (char *)xmalloc (slen + 1);
 
   for (dquote = sindex = 0; c = string[sindex];)
     {
@@ -5782,8 +6079,7 @@ string_quote_removal (string, quoted)
          /* FALLTHROUGH */
 
        default:
-         *r++ = c;
-         sindex++;
+         SCOPY_CHAR_M (r, string, send, sindex);
          break;
 
        case '\'':
@@ -5844,9 +6140,7 @@ word_list_quote_removal (list, quoted)
 
   for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
     {
-      tresult = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
-      tresult->word = word_quote_removal (t->word, quoted);
-      tresult->next = (WORD_LIST *)NULL;
+      tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
       result = (WORD_LIST *) list_append (result, tresult);
     }
   return (result);
@@ -5859,40 +6153,49 @@ word_list_quote_removal (list, quoted)
  *                                        *
  *******************************************/
 
-static char *
-getifs ()
+void
+setifs (v)
+     SHELL_VAR *v;
 {
-  SHELL_VAR *ifs;
+  char *t;
+  unsigned char uc;
 
-  ifs = find_variable ("IFS");
-  /* If IFS is unset, it defaults to " \t\n". */
-  return (ifs ? value_cell (ifs) : " \t\n");
+  ifs_var = v;
+  ifs_value = v ? value_cell (v) : " \t\n";
+
+  /* Should really merge ifs_cmap with sh_syntaxtab. */
+  memset (ifs_cmap, '\0', sizeof (ifs_cmap));
+  for (t = ifs_value ; t && *t; t++)
+    {
+      uc = *t;
+      ifs_cmap[uc] = 1;
+    }
+
+  ifs_firstc = ifs_value ? *ifs_value : 0;
+}
+
+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)
+word_split (w, ifs_chars)
      WORD_DESC *w;
+     char *ifs_chars;
 {
   WORD_LIST *result;
-  SHELL_VAR *ifs;
-  char *ifs_chars;
 
   if (w)
     {
-      ifs = find_variable ("IFS");
-      /* If IFS is unset, it defaults to " \t\n". */
-      ifs_chars = ifs ? value_cell (ifs) : " \t\n";
-
-      if ((w->flags & W_QUOTED) || !ifs_chars)
-       ifs_chars = "";
-
-      result = list_string (w->word, ifs_chars, w->flags & W_QUOTED);
+      char *xifs;
 
-      if (ifs && tempvar_p (ifs))      /* XXX */
-       dispose_variable (ifs);         /* XXX */
+      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;
@@ -5910,7 +6213,7 @@ word_list_split (list)
 
   for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
     {
-      tresult = word_split (t->word);
+      tresult = word_split (t->word, ifs_value);
       result = (WORD_LIST *) list_append (result, tresult);
     }
   return (result);
@@ -5949,8 +6252,8 @@ separate_out_assignments (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
+       lp = list of words left after assignment statements skipped
+       tlist = original list of words
   */
   while (lp && (lp->word->flags & W_ASSIGNMENT))
     {
@@ -6088,7 +6391,7 @@ glob_expand_word_list (tlist, eflags)
         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
+        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;
@@ -6153,7 +6456,7 @@ glob_expand_word_list (tlist, eflags)
          PREPEND_LIST (tlist, output_list);
        }
 
-      free_array (glob_array);
+      strvec_dispose (glob_array);
       glob_array = (char **)NULL;
 
       tlist = next;
@@ -6187,11 +6490,11 @@ brace_expand_word_list (tlist, eflags)
       /* 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 `strchr', and then what is
+        degenerate to a bunch of calls to `xstrchr', 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
+        by a call to REVERSE_LIST () on BRACES when the end of TLIST
         is reached. */
-      if (strchr (tlist->word->word, LBRACE))
+      if (xstrchr (tlist->word->word, LBRACE))
        {
          expansions = brace_expand (tlist->word->word);
 
@@ -6244,17 +6547,25 @@ shell_expand_word_list (tlist, eflags)
       next = tlist->next;
 
       /* Posix.2 section 3.6.1 says that tildes following `=' in words
-        which are not assignment statements are not expanded.  We do
-        this only if POSIXLY_CORRECT is enabled.  Essentially, we do
-        tilde expansion on unquoted assignment statements (flags include
-        W_ASSIGNMENT but not W_QUOTED). */
-      if (temp_string[0] == '~' ||
-           (((tlist->word->flags & (W_ASSIGNMENT|W_QUOTED)) == W_ASSIGNMENT) &&
-            posixly_correct == 0 &&
-            strchr (temp_string, '~') &&
-            (unquoted_substring ("=~", temp_string) || unquoted_substring (":~", temp_string))))
-       {
-         tlist->word->word = bash_tilde_expand (temp_string);
+        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 (((tlist->word->flags & (W_ASSIGNMENT|W_QUOTED)) == W_ASSIGNMENT) &&
+            (posixly_correct == 0 || (tlist->word->flags & W_TILDEEXP)) &&
+            (unquoted_substring ("=~", temp_string) || unquoted_substring (":~", temp_string)))
+       {
+         tlist->word->word = bash_tilde_expand (temp_string, 1);
+         free (temp_string);
+       }
+      else if (temp_string[0] == '~')
+       {
+         tlist->word->word = bash_tilde_expand (temp_string, 0);
          free (temp_string);
        }
 
diff --git a/subst.h b/subst.h
index 56de477c26f4bef5d69f088de93563432eec8fd6..0acfdd7c6a4a4f5eb46e801c2abd9ac26efcb361 100644 (file)
--- a/subst.h
+++ b/subst.h
@@ -1,6 +1,6 @@
 /* subst.h -- Names of externally visible functions in subst.c. */
 
-/* Copyright (C) 1993 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
    slashify_in_quotes () to decide whether the backslash should be
    retained.  Q_HERE_DOCUMENT means slashify_in_here_document () to
    decide whether to retain the backslash.  Q_KEEP_BACKSLASH means
-   to unconditionally retain the backslash. */
+   to unconditionally retain the backslash.  Q_PATQUOTE means that we're
+   expanding a pattern ${var%#[#%]pattern} in an expansion surrounded
+   by double quotes. */
 #define Q_DOUBLE_QUOTES  0x1
 #define Q_HERE_DOCUMENT  0x2
 #define Q_KEEP_BACKSLASH 0x4
-#define Q_NOQUOTE       0x8
+#define Q_PATQUOTE      0x8
 #define Q_QUOTED        0x10
 #define Q_ADDEDQUOTES   0x20
 #define Q_QUOTEDNULL    0x40
 
-/* Cons a new string from STRING starting at START and ending at END,
-   not including END. */
-extern char *substring __P((char *, int, int));
-
 /* Remove backslashes which are quoting backquotes from STRING.  Modifies
    STRING, and returns a pointer to it. */
 extern char * de_backslash __P((char *));
@@ -68,6 +66,10 @@ extern char *extract_process_subst __P((char *, char *, int *));
 /* Extract the name of the variable to bind to from the assignment string. */
 extern char *assignment_name __P((char *));
 
+/* Return a single string of all the words present in LIST, separating
+   each word with SEP. */
+extern char *string_list_internal __P((WORD_LIST *, char *));
+
 /* Return a single string of all the words present in LIST, separating
    each word with a space. */
 extern char *string_list __P((WORD_LIST *));
@@ -105,7 +107,7 @@ extern char *sub_append_string __P((char *, char *, int *, int *));
 
 /* Append the textual representation of NUMBER to TARGET.
    INDEX and SIZE are as in SUB_APPEND_STRING. */
-extern char *sub_append_number __P((long, char *, int *, int *));
+extern char *sub_append_number __P((intmax_t, char *, int *, int *));
 
 /* Return the word list that corresponds to `$*'. */
 extern WORD_LIST *list_rest_of_args __P((void));
@@ -155,7 +157,7 @@ extern WORD_LIST *expand_word_unsplit __P((WORD_DESC *, int));
 extern WORD_LIST *expand_word_leave_quoted __P((WORD_DESC *, int));
 
 /* Return the value of a positional parameter.  This handles values > 10. */
-extern char *get_dollar_var_value __P((long));
+extern char *get_dollar_var_value __P((intmax_t));
 
 /* Quote a string to protect it from word splitting. */
 extern char *quote_string __P((char *));
@@ -177,10 +179,16 @@ extern WORD_DESC *word_quote_removal __P((WORD_DESC *, int));
    double quotes.  Return a new list, or NULL if LIST is NULL. */
 extern WORD_LIST *word_list_quote_removal __P((WORD_LIST *, int));
 
+/* Called when IFS is changed to maintain some private variables. */
+extern void setifs __P((SHELL_VAR *));
+
+/* Return the value of $IFS, or " \t\n" if IFS is unset. */
+extern char *getifs __P((void));
+
 /* 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. */
-extern WORD_LIST *word_split __P((WORD_DESC *));
+extern WORD_LIST *word_split __P((WORD_DESC *, char *));
 
 /* 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
@@ -219,6 +227,15 @@ extern int skip_to_delim __P((char *, int, char *));
 extern WORD_LIST *split_at_delims __P((char *, int, char *, int, int *, int *));
 #endif
 
+/* Variables used to keep track of the characters in IFS. */
+extern SHELL_VAR *ifs_var;
+extern char *ifs_value;
+extern unsigned char ifs_cmap[];
+extern unsigned char ifs_firstc;
+
+/* Evaluates to 1 if C is a character in $IFS. */
+#define isifs(c)       (ifs_cmap[(unsigned char)(c)] != 0)
+
 /* How to determine the quoted state of the character C. */
 #define QUOTED_CHAR(c)  ((c) == CTLESC)
 
index c7e411202a82997a1687ee8ce638b683391280ce..e437c69594bbd280d2b5408f85d72e6df93de52f 100644 (file)
@@ -43,27 +43,34 @@ EXEEXT = @EXEEXT@
 # Compiler options:
 #
 PROFILE_FLAGS = @PROFILE_FLAGS@
+
 CFLAGS = @CFLAGS@
-LOCAL_CFLAGS = @LOCAL_CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
 CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+LOCAL_CFLAGS = @LOCAL_CFLAGS@
 DEFS = @DEFS@
 LOCAL_DEFS = @LOCAL_DEFS@
-LDFLAGS = @LDFLAGS@ $(LOCAL_LDFLAGS) $(CFLAGS)
+
 LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
 LIBS = @LIBS@
+LDFLAGS = @LDFLAGS@ $(LOCAL_LDFLAGS) $(CFLAGS)
+LDFLAGS_FOR_BUILD = $(LDFLAGS)
 
 INCLUDES = -I${BUILD_DIR} -I${topdir}
 
-#
-CCFLAGS = ${PROFILE_FLAGS} $(DEFS) $(LOCAL_DEFS) $(SYSTEM_FLAGS) $(CPPFLAGS) \
-         ${INCLUDES} $(LOCAL_CFLAGS) $(CFLAGS)
+BASE_CCFLAGS = ${PROFILE_FLAGS} $(DEFS) $(LOCAL_DEFS) $(SYSTEM_FLAGS) \
+         ${INCLUDES} $(LOCAL_CFLAGS)
+
+CCFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(CFLAGS)
+CCFLAGS_FOR_BUILD = $(BASE_CCFLAGS) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD)
 
 SRC1 = man2html.c
 OBJ1 = man2html.o
 
 .c.o:
        $(RM) $@
-       $(CC) -c $(CCFLAGS) $<
+       $(CC_FOR_BUILD) -c $(CCFLAGS_FOR_BUILD) $<
 
 all: man2html$(EXEEXT)
 
index 60eaeb9b9732f8912f783381cf51d0a14d4ed577..ceb4afaf603b489560d904d082f2f2c5db784c97 100644 (file)
@@ -6,6 +6,23 @@
 # with status `devel', `alpha', `beta', or `rc' mail bug reports to
 # chet@po.cwru.edu and, optionally, to bash-testers@po.cwru.edu.
 # Other versions send mail to bug-bash@gnu.org.
+#
+# Copyright (C) 1996-2002 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.
+
 #
 # configuration section:
 #      these variables are filled in by the make target in Makefile
index b95fe104a93ca62865b6e40182b04bc4dfdff374..abf1aa8dfcf8514413073fdab3758b5197baa090 100644 (file)
 #include "stdc.h"
 
 #include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
 #include "bashansi.h"
 
 #include "version.h"
index cd219563c7fe4522cf6e7c682eed7a61277f72da..56681081e215f51aefe95bd7099864116c47c0ae 100755 (executable)
@@ -1,7 +1,10 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
-#   Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
-#
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002 Free Software Foundation, Inc.
+
+timestamp='2002-03-20'
+
 # This file 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 of the License, or
 # configuration script generated by Autoconf, you may include it under
 # the same distribution terms that you use for the rest of that program.
 
-# Written by Per Bothner <bothner@cygnus.com>.
-# The master version of this file is at the FSF in /home/gd/gnu/lib.
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
 #
 # This script attempts to guess a canonical system name similar to
 # config.sub.  If it succeeds, it prints the system name on stdout, and
 # exits with 0.  Otherwise, it exits with 1.
 #
 # The plan is that this can be called by configure scripts if you
-# don't specify an explicit system type (host/target name).
-#
-# Only a few systems have been added to this list; please add others
-# (but try to keep the structure clean).
-#
-
-# Use $HOST_CC if defined. $CC may point to a cross-compiler
-if test x"$CC_FOR_BUILD" = x; then
-  if test x"$HOST_CC" != x; then
-    CC_FOR_BUILD="$HOST_CC"
-  else
-    if test x"$CC" != x; then
-      CC_FOR_BUILD="$CC"
-    else
-      CC_FOR_BUILD=cc
-    fi
-  fi
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
 fi
 
+
+dummy=dummy-$$
+trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script.
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int dummy(){}" > $dummy.c ;
+       for c in cc gcc c89 c99 ; do
+         ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ;
+         if test $? = 0 ; then
+            CC_FOR_BUILD="$c"; break ;
+         fi ;
+       done ;
+       rm -f $dummy.c $dummy.o $dummy.rel ;
+       if test x"$CC_FOR_BUILD" = x ; then
+         CC_FOR_BUILD=no_compiler_found ;
+       fi
+       ;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac'
+
 # This is needed to find uname on a Pyramid OSx when run in the BSD universe.
-# (ghazi@noc.rutgers.edu 8/24/94.)
+# (ghazi@noc.rutgers.edu 1994-08-24)
 if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
        PATH=$PATH:/.attbin ; export PATH
-elif (test -f /usr/5bin/uname) >/dev/null 2>&1 ; then
+elif (test -f /usr/5bin/uname) >/dev/null 2>&1 ; then  # bash
        PATH=$PATH:/usr/5bin
 fi
 
-UNAME=`(uname) 2>/dev/null` || UNAME=unknown
+UNAME=`(uname) 2>/dev/null` || UNAME=unknown   # bash
 UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
 UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
-UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
 UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
 
-RELEASE=`expr "$UNAME_RELEASE" : '[^0-9]*\([0-9]*\)'` # 4
-case "$RELEASE" in
-"")    RELEASE=0 ;;
-*)     RELEASE=`expr "$RELEASE" + 0` ;;
-esac
-REL_LEVEL=`expr "$UNAME_RELEASE" : '[^0-9]*[0-9]*.\([0-9]*\)'`    # 1
-REL_SUBLEVEL=`expr "$UNAME_RELEASE" : '[^0-9]*[0-9]*.[0-9]*.\([0-9]*\)'` # 2
-
-dummy=dummy-$$
-trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15
-
-# Some versions of i386 SVR4.2 make `uname' equivalent to `uname -n', which
-# is contrary to all other versions of uname
-if [ -n "$UNAME" ] && [ "$UNAME_S" != "$UNAME" ] && [ "$UNAME_S" = UNIX_SV ]; then
-       UNAME=UNIX_SV
-fi
-
 # Note: order is significant - the case branches are not exclusive.
 
 case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
-    # Begin cases added for Bash
-    alpha:NetBSD:*:*)
-       echo alpha-dec-netbsd${UNAME_RELEASE}
-       exit 0 ;;
-    alpha:OpenBSD:*:*)
-       echo alpha-dec-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    i?86:NetBSD:*:*)
-       echo ${UNAME_MACHINE}-pc-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
-       exit 0 ;;
-    i?86:OpenBSD:*:*)
-       echo ${UNAME_MACHINE}-pc-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
-       exit 0 ;;
-    sparc:NetBSD:*:*)
-       echo sparc-unknown-netbsd${UNAME_RELEASE}
-       exit 0 ;;
-    sparc:OpenBSD:*:*)
-       echo sparc-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    vax:NetBSD:*:*)
-       echo vax-dec-netbsd${UNAME_RELEASE}
-       exit 0 ;;
-    vax:OpenBSD:*:*)
-       echo vax-dec-openbsd${UNAME_RELEASE}
-       exit 0 ;;
+    # NOTE -- begin cases added for bash (mostly legacy) -- NOTE
     mac68k:machten:*:*)
        echo mac68k-apple-machten${UNAME_RELEASE}
        exit 0 ;;
@@ -132,20 +156,14 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     mips:4.4BSD:*:*)
        echo mips-mips-bsd4.4
        exit 0 ;;
-    MIServer-S:SMP_DC.OSx:*:dcosx)
-       echo mips-pyramid-sysv4
+    MIS*:SMP_DC.OSx:*:dcosx)   # not the same as below
+       echo pyramid-pyramid-sysv4
        exit 0 ;;
     news*:NEWS*:*:*)
        echo mips-sony-newsos${UNAME_RELEASE}
        exit 0 ;;
-    i?86:NEXTSTEP:*:*)
-       echo i386-next-nextstep${RELEASE}
-       exit 0 ;;
-    *680?0:NEXTSTEP:*:*)
-       echo m68k-next-nextstep${RELEASE}
-       exit 0 ;;    
     *370:AIX:*:*)
-       echo ibm370-ibm-aix
+       echo ibm370-ibm-aix${UNAME_RELEASE}
        exit 0 ;;
     ksr1:OSF*1:*:*)
        echo ksr1-ksr-osf1
@@ -159,118 +177,190 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     *3b2*:*:*:*)
        echo we32k-att-sysv3
        exit 0 ;;
-    *:QNX:*:42*)
-       echo i386-qssl-qnx`echo ${UNAME_VERSION}`
-       exit 0 ;;
-    Alpha*:Windows:NT:*:SP*)
+    Alpha*:Windows_NT:*:SP*)
        echo alpha-pc-opennt
        exit 0 ;;
-    *:Windows:NT:*:SP*)
-       echo intel-pc-opennt
+    *:Windows_NT:*:SP*)
+       echo i386-pc-opennt
        exit 0 ;;
-    *:NonStop-UX:*:*)
-       echo mips-compaq-nonstopux
+
+    # NOTE -- end legacy cases added for bash -- NOTE
+    *:NetBSD:*:*)
+       # NetBSD (nbsd) targets should (where applicable) match one or
+       # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+       # *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+       # switched to ELF, *-*-netbsd* would select the old
+       # object file format.  This provides both forward
+       # compatibility and a consistent mechanism for selecting the
+       # object file format.
+       #
+       # Note: NetBSD doesn't particularly care about the vendor
+       # portion of the name.  We always set it to "unknown".
+       sysctl="sysctl -n hw.machine_arch"
+       UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+           /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+       case "${UNAME_MACHINE_ARCH}" in
+           arm*) machine=arm-unknown ;;
+           sh3el) machine=shl-unknown ;;
+           sh3eb) machine=sh-unknown ;;
+           *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+       esac
+       # The Operating System including object format, if it has switched
+       # to ELF recently, or will in the future.
+       case "${UNAME_MACHINE_ARCH}" in
+           arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+               eval $set_cc_for_build
+               if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+                       | grep __ELF__ >/dev/null
+               then
+                   # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+                   # Return netbsd for either.  FIX?
+                   os=netbsd
+               else
+                   os=netbsdelf
+               fi
+               ;;
+           *)
+               os=netbsd
+               ;;
+       esac
+       # The OS release
+       release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+       # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+       # contains redundant information, the shorter form:
+       # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+       echo "${machine}-${os}${release}"
+       exit 0 ;;
+    amiga:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    arc:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    hp300:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mac68k:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    macppc:OpenBSD:*:*)
+       echo powerpc-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+       echo m88k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvmeppc:OpenBSD:*:*)
+       echo powerpc-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    pmax:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sgi:OpenBSD:*:*)
+       echo mipseb-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sun3:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    vax:OpenBSD:*:*)   # bash
+       echo vax-dec-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    *:OpenBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
        exit 0 ;;
-    # end cases added for Bash
     alpha:OSF1:*:*)
-       # TEST CHANGED FOR BASH to handle `letter version' releases
-       UNAME_MAJOR=`echo "$UNAME_RELEASE" | sed -e 's/^.\([0-9]\).*/\1/'`
-       if test X"$UNAME_MAJOR" != X"" && test $UNAME_MAJOR = 4 ; then
+       if test $UNAME_RELEASE = "V4.0"; then
                UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
-       elif test X"$UNAME_MAJOR" != X"" && test $UNAME_MAJOR -gt 4 ; then
-               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`           
        fi
        # A Vn.n version is a released version.
        # A Tn.n version is a released field test version.
        # A Xn.n version is an unreleased experimental baselevel.
        # 1.2 uses "1.2" for uname -r.
        cat <<EOF >$dummy.s
+       .data
+\$Lformat:
+       .byte 37,100,45,37,120,10,0     # "%d-%x\n"
+
+       .text
        .globl main
+       .align 4
        .ent main
 main:
-       .frame \$30,0,\$26,0
-       .prologue 0
-       .long 0x47e03d80 # implver $0
-       lda \$2,259
-       .long 0x47e20c21 # amask $2,$1
-       srl \$1,8,\$2
-       sll \$2,2,\$2
-       sll \$0,3,\$0
-       addl \$1,\$0,\$0
-       addl \$2,\$0,\$0
-       ret \$31,(\$26),1
+       .frame \$30,16,\$26,0
+       ldgp \$29,0(\$27)
+       .prologue 1
+       .long 0x47e03d80 # implver \$0
+       lda \$2,-1
+       .long 0x47e20c21 # amask \$2,\$1
+       lda \$16,\$Lformat
+       mov \$0,\$17
+       not \$1,\$18
+       jsr \$26,printf
+       ldgp \$29,0(\$26)
+       mov 0,\$16
+       jsr \$26,exit
        .end main
 EOF
+       eval $set_cc_for_build
        $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
        if test "$?" = 0 ; then
-               ./$dummy
-               case "$?" in
-                       7)
+               case `./$dummy` in
+                       0-0)
                                UNAME_MACHINE="alpha"
                                ;;
-                       15)
+                       1-0)
                                UNAME_MACHINE="alphaev5"
                                ;;
-                       14)
+                       1-1)
                                UNAME_MACHINE="alphaev56"
                                ;;
-                       10)
+                       1-101)
                                UNAME_MACHINE="alphapca56"
                                ;;
-                       16)
+                       2-303)
                                UNAME_MACHINE="alphaev6"
                                ;;
+                       2-307)
+                               UNAME_MACHINE="alphaev67"
+                               ;;
+                       2-1307)
+                               UNAME_MACHINE="alphaev68"
+                               ;;
                esac
        fi
        rm -f $dummy.s $dummy
        echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
        exit 0 ;;
     Alpha\ *:Windows_NT*:*)
-        # How do we know it's Interix rather than the generic POSIX subsystem?
-        # Should we change UNAME_MACHINE based on the output of uname instead
-        # of the specific Alpha model?
-        echo alpha-pc-interix
-        exit 0 ;;
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # Should we change UNAME_MACHINE based on the output of uname instead
+       # of the specific Alpha model?
+       echo alpha-pc-interix
+       exit 0 ;;
     21064:Windows_NT:50:3)
        echo alpha-dec-winnt3.5
        exit 0 ;;
     Amiga*:UNIX_System_V:4.0:*)
-       echo m68k-cbm-sysv4
+       echo m68k-unknown-sysv4
        exit 0;;
-    amiga:NetBSD:*:*)
-       echo m68k-cbm-netbsd${UNAME_RELEASE}
-       exit 0 ;;
-    amiga:OpenBSD:*:*)
-       echo m68k-cbm-openbsd${UNAME_RELEASE}
-       exit 0 ;;
     *:[Aa]miga[Oo][Ss]:*:*)
        echo ${UNAME_MACHINE}-unknown-amigaos
        exit 0 ;;
-    arc64:OpenBSD:*:*)
-       echo mips64el-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    arc:OpenBSD:*:*)
-       echo mipsel-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    hkmips:OpenBSD:*:*)
-       echo mips-unknown-openbsd${UNAME_RELEASE}
+    *:[Mm]orph[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-morphos
        exit 0 ;;
-    pmax:OpenBSD:*:*)
-       echo mipsel-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    sgi:OpenBSD:*:*)
-       echo mips-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    wgrisc:OpenBSD:*:*)
-       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+    *:OS/390:*:*)
+       echo i370-ibm-openedition
        exit 0 ;;
     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
        echo arm-acorn-riscix${UNAME_RELEASE}
        exit 0;;
-    arm32:NetBSD:*:*)
-       echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
-       exit 0 ;;
-    SR2?01:HI-UX/MPP:*:*)
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
        echo hppa1.1-hitachi-hiuxmpp
        exit 0;;
     Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
@@ -281,12 +371,12 @@ EOF
                echo pyramid-pyramid-bsd
        fi
        exit 0 ;;
-    NILE:*:*:*:dcosx)
+    NILE*:*:*:dcosx)
        echo pyramid-pyramid-svr4
        exit 0 ;;
     sun4H:SunOS:5.*:*)
-        echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-        exit 0 ;;
+       echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
     sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
        echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
        exit 0 ;;
@@ -312,7 +402,7 @@ EOF
        echo m68k-sun-sunos${UNAME_RELEASE}
        exit 0 ;;
     sun*:*:4.2BSD:*)
-       UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+       UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
        test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
        case "`/bin/arch`" in
            sun3)
@@ -326,29 +416,23 @@ EOF
     aushp:SunOS:*:*)
        echo sparc-auspex-sunos${UNAME_RELEASE}
        exit 0 ;;
-    atari*:NetBSD:*:*)
-       echo m68k-atari-netbsd${UNAME_RELEASE}
-       exit 0 ;;
-    atari*:OpenBSD:*:*)
-       echo m68k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
     # The situation for MiNT is a little confusing.  The machine name
     # can be virtually everything (everything which is not
-    # "atarist" or "atariste" at least should have a processor 
+    # "atarist" or "atariste" at least should have a processor
     # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
     # to the lowercase version "mint" (or "freemint").  Finally
     # the system name "TOS" denotes a system which is actually not
     # MiNT.  But MiNT is downward compatible to TOS, so this should
     # be no problem.
     atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
-       echo m68k-atari-mint${UNAME_RELEASE}
-       exit 0 ;;
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit 0 ;;
     atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
-       echo m68k-atari-mint${UNAME_RELEASE}
-       exit 0 ;;
+       echo m68k-atari-mint${UNAME_RELEASE}
+        exit 0 ;;
     *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
-       echo m68k-atari-mint${UNAME_RELEASE}
-       exit 0 ;;
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit 0 ;;
     milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
         echo m68k-milan-mint${UNAME_RELEASE}
         exit 0 ;;
@@ -358,33 +442,9 @@ EOF
     *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
         echo m68k-unknown-mint${UNAME_RELEASE}
         exit 0 ;;
-    sun3*:NetBSD:*:*)
-       echo m68k-sun-netbsd${UNAME_RELEASE}
-       exit 0 ;;
-    sun3*:OpenBSD:*:*)
-       echo m68k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    mac68k:NetBSD:*:*)
-       echo m68k-apple-netbsd${UNAME_RELEASE}
-       exit 0 ;;
-    mac68k:OpenBSD:*:*)
-       echo m68k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    mvme68k:OpenBSD:*:*)
-       echo m68k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    mvme88k:OpenBSD:*:*)
-       echo m88k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    *:"Mac OS":*:*)
-       echo `uname -p`-apple-macos${UNAME_RELEASE}
-       exit 0 ;;
     powerpc:machten:*:*)
        echo powerpc-apple-machten${UNAME_RELEASE}
        exit 0 ;;
-    macppc:NetBSD:*:*)
-        echo powerpc-apple-netbsd${UNAME_RELEASE}
-        exit 0 ;;
     RISC*:Mach:*:*)
        echo mips-dec-mach_bsd4.3
        exit 0 ;;
@@ -398,8 +458,10 @@ EOF
        echo clipper-intergraph-clix${UNAME_RELEASE}
        exit 0 ;;
     mips:*:*:UMIPS | mips:*:*:RISCos)
+       eval $set_cc_for_build
        sed 's/^        //' << EOF >$dummy.c
 #ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
        int main (int argc, char *argv[]) {
 #else
        int main (argc, argv) int argc; char *argv[]; {
@@ -420,10 +482,13 @@ EOF
 EOF
        $CC_FOR_BUILD $dummy.c -o $dummy \
          && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
-         && rm $dummy.c $dummy && exit 0
+         && rm -f $dummy.c $dummy && exit 0
        rm -f $dummy.c $dummy
        echo mips-mips-riscos${UNAME_RELEASE}
        exit 0 ;;
+    Motorola:PowerMAX_OS:*:*)
+       echo powerpc-motorola-powermax
+       exit 0 ;;
     Night_Hawk:Power_UNIX:*:*)
        echo powerpc-harris-powerunix
        exit 0 ;;
@@ -437,17 +502,19 @@ EOF
        echo m88k-motorola-sysv3
        exit 0 ;;
     AViiON:dgux:*:*)
-       # DG/UX returns AViiON for all architectures
-       UNAME_PROCESSOR=`/usr/bin/uname -p`
-       if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
-         if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
-            -o ${TARGET_BINARY_INTERFACE}x = x ] ; then
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+       if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+       then
+           if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+              [ ${TARGET_BINARY_INTERFACE}x = x ]
+           then
                echo m88k-dg-dgux${UNAME_RELEASE}
-         else
+           else
                echo m88k-dg-dguxbcs${UNAME_RELEASE}
-         fi
+           fi
        else
-         echo i586-dg-dgux${UNAME_RELEASE}
+           echo i586-dg-dgux${UNAME_RELEASE}
        fi
        exit 0 ;;
     M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
@@ -469,11 +536,20 @@ EOF
     ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
        echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
        exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
-    i?86:AIX:*:*)
+    i*86:AIX:*:*)
        echo i386-ibm-aix
        exit 0 ;;
+    ia64:AIX:*:*)
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+       exit 0 ;;
     *:AIX:2:3)
        if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+               eval $set_cc_for_build
                sed 's/^                //' << EOF >$dummy.c
                #include <sys/systemcfg.h>
 
@@ -485,7 +561,7 @@ EOF
                        exit(0);
                        }
 EOF
-               $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
+               $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
                rm -f $dummy.c $dummy
                echo rs6000-ibm-aix3.2.5
        elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
@@ -494,21 +570,17 @@ EOF
                echo rs6000-ibm-aix3.2
        fi
        exit 0 ;;
-    *:AIX:*:4)
-       IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
-       if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then
+    *:AIX:*:[45])
+       IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+       if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
                IBM_ARCH=rs6000
        else
                IBM_ARCH=powerpc
        fi
        if [ -x /usr/bin/oslevel ] ; then
                IBM_REV=`/usr/bin/oslevel`
-       elif grep bos410 /usr/include/stdio.h >/dev/null 2>&1; then
-               IBM_REV=4.1
-       elif grep bos411 /usr/include/stdio.h >/dev/null 2>&1; then
-               IBM_REV=4.1.1
        else
-               IBM_REV=4.${UNAME_RELEASE}
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
        fi
        echo ${IBM_ARCH}-ibm-aix${IBM_REV}
        exit 0 ;;
@@ -518,7 +590,7 @@ EOF
     ibmrt:4.4BSD:*|romp-ibm:BSD:*)
        echo romp-ibm-bsd4.4
        exit 0 ;;
-    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC NetBSD and
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
        echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
        exit 0 ;;                           # report: romp-ibm BSD 4.3
     *:BOSX:*:*)
@@ -534,11 +606,30 @@ EOF
        echo m68k-hp-bsd4.4
        exit 0 ;;
     9000/[34678]??:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
        case "${UNAME_MACHINE}" in
-           9000/31? )          HP_ARCH=m68000 ;;
-           9000/[34]?? )       HP_ARCH=m68k ;;
+           9000/31? )            HP_ARCH=m68000 ;;
+           9000/[34]?? )         HP_ARCH=m68k ;;
            9000/[678][0-9][0-9])
-              sed 's/^              //' << EOF >$dummy.c
+               if [ -x /usr/bin/getconf ]; then
+                   sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+                         '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+               fi
+               if [ "${HP_ARCH}" = "" ]; then
+                   eval $set_cc_for_build
+                   sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
               #include <stdlib.h>
               #include <unistd.h>
 
@@ -569,13 +660,19 @@ EOF
                   exit (0);
               }
 EOF
-       ($CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
-       rm -f $dummy.c $dummy
+                   (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy`
+                   if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
+                   rm -f $dummy.c $dummy
+               fi ;;
        esac
-       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
        echo ${HP_ARCH}-hp-hpux${HPUX_REV}
        exit 0 ;;
+    ia64:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       echo ia64-hp-hpux${HPUX_REV}
+       exit 0 ;;
     3050*:HI-UX:*:*)
+       eval $set_cc_for_build
        sed 's/^        //' << EOF >$dummy.c
        #include <unistd.h>
        int
@@ -601,7 +698,7 @@ EOF
          exit (0);
        }
 EOF
-       $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
+       $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
        rm -f $dummy.c $dummy
        echo unknown-hitachi-hiuxwe2
        exit 0 ;;
@@ -611,16 +708,16 @@ EOF
     9000/8??:4.3bsd:*:*)
        echo hppa1.0-hp-bsd
        exit 0 ;;
-    *9??*:MPE/iX:*:*)
-        echo hppa1.0-hp-mpeix
-        exit 0 ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+       echo hppa1.0-hp-mpeix
+       exit 0 ;;
     hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
        echo hppa1.1-hp-osf
        exit 0 ;;
     hp8??:OSF1:*:*)
        echo hppa1.0-hp-osf
        exit 0 ;;
-    i?86:OSF1:*:*)
+    i*86:OSF1:*:*)
        if [ -x /usr/sbin/sysversion ] ; then
            echo ${UNAME_MACHINE}-unknown-osf1mk
        else
@@ -630,9 +727,6 @@ EOF
     parisc*:Lites*:*:*)
        echo hppa1.1-hp-lites
        exit 0 ;;
-    hppa*:OpenBSD:*:*)
-        echo hppa-unknown-openbsd
-        exit 0 ;;
     C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
        echo c1-convex-bsd
         exit 0 ;;
@@ -651,63 +745,44 @@ EOF
     C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
        echo c4-convex-bsd
         exit 0 ;;
-    CRAY*X-MP:*:*:*)
-       echo xmp-cray-unicos
-        exit 0 ;;
     CRAY*Y-MP:*:*:*)
-       echo ymp-cray-unicos${UNAME_RELEASE}
+       echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
        exit 0 ;;
     CRAY*[A-Z]90:*:*:*)
        echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
        | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
+             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+             -e 's/\.[^.]*$/.X/'
        exit 0 ;;
     CRAY*TS:*:*:*)
-       echo t90-cray-unicos${UNAME_RELEASE}
+       echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
        exit 0 ;;
-    CRAY*T3E:*:*:*)
-        echo alpha-cray-unicosmk${UNAME_RELEASE}
-        exit 0 ;;
-    CRAY-2:*:*:*)
-       echo cray2-cray-unicos
-        exit 0 ;;
-    F300:UNIX_System_V:*:*)
-       FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-       FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
-       echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+    CRAY*T3D:*:*:*)
+       echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
        exit 0 ;;
-    F301:UNIX_System_V:*:*)
-       echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
+    CRAY*T3E:*:*:*)
+       echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
        exit 0 ;;
-    hp3[0-9][05]:NetBSD:*:*)
-       echo m68k-hp-netbsd${UNAME_RELEASE}
+    CRAY*SV1:*:*:*)
+       echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
        exit 0 ;;
-    hp300:OpenBSD:*:*)
-        echo m68k-unknown-openbsd${UNAME_RELEASE}
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+       FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
         exit 0 ;;
-    i?86:BSD/386:*:* | i?86:BSD/OS:*:*)
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
        echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
        exit 0 ;;
     sparc*:BSD/OS:*:*)
-        echo sparc-unknown-bsdi${UNAME_RELEASE}
-        exit 0 ;;
-    *:BSD/OS:*:*)
-        echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
-        exit 0 ;;
-    *:FreeBSD:*:*)
-#      if test -x /usr/bin/objformat; then
-#          if test "elf" = "`/usr/bin/objformat`"; then
-#              echo ${UNAME_MACHINE}-unknown-freebsdelf`echo ${UNAME_RELEASE}|sed -e 's/[-_].*//'`
-#              exit 0
-#          fi
-#      fi
-       echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-=(].*//'`
+       echo sparc-unknown-bsdi${UNAME_RELEASE}
        exit 0 ;;
-    *:NetBSD:*:*)
-       echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+    *:BSD/OS:*:*)
+       echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
        exit 0 ;;
-    *:OpenBSD:*:*)
-       echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+    *:FreeBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
        exit 0 ;;
     i*:CYGWIN*:*)
        echo ${UNAME_MACHINE}-pc-cygwin
@@ -715,225 +790,190 @@ EOF
     i*:MINGW*:*)
        echo ${UNAME_MACHINE}-pc-mingw32
        exit 0 ;;
+    i*:PW*:*)
+       echo ${UNAME_MACHINE}-pc-pw32
+       exit 0 ;;
+    x86:Interix*:3*)
+       echo i386-pc-interix3
+       exit 0 ;;
     i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
-        # How do we know it's Interix rather than the generic POSIX subsystem?
-        # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
-        # UNAME_MACHINE based on the output of uname instead of i386?
-        echo i386-pc-interix
-        exit 0 ;;
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+       # UNAME_MACHINE based on the output of uname instead of i386?
+       echo i386-pc-interix
+       exit 0 ;;
     i*:UWIN*:*)
-        echo ${UNAME_MACHINE}-pc-uwin
-        exit 0 ;;
+       echo ${UNAME_MACHINE}-pc-uwin
+       exit 0 ;;
     p*:CYGWIN*:*)
        echo powerpcle-unknown-cygwin
-       exit 0 ;;    
+       exit 0 ;;
     prep*:SunOS:5.*:*)
        echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
        exit 0 ;;
     *:GNU:*:*)
        echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
        exit 0 ;;
-    *:Linux:*:*)
-        # uname on the ARM produces all sorts of strangeness, and we need to
-        # filter it out.
-        case "$UNAME_MACHINE" in
-          armv*)                      UNAME_MACHINE=$UNAME_MACHINE ;;
-          arm* | sa110*)              UNAME_MACHINE="arm" ;;
+    i*86:Minix:*:*)
+       echo ${UNAME_MACHINE}-pc-minix
+       exit 0 ;;
+    arm*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    ia64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    m68*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    mips:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef mips
+       #undef mipsel
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=mipsel
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=mips
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+       rm -f $dummy.c
+       test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0
+       ;;
+    ppc:Linux:*:*)
+       echo powerpc-unknown-linux-gnu
+       exit 0 ;;
+    ppc64:Linux:*:*)
+       echo powerpc64-unknown-linux-gnu
+       exit 0 ;;
+    alpha:Linux:*:*)
+       case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+         EV5)   UNAME_MACHINE=alphaev5 ;;
+         EV56)  UNAME_MACHINE=alphaev56 ;;
+         PCA56) UNAME_MACHINE=alphapca56 ;;
+         PCA57) UNAME_MACHINE=alphapca56 ;;
+         EV6)   UNAME_MACHINE=alphaev6 ;;
+         EV67)  UNAME_MACHINE=alphaev67 ;;
+         EV68*) UNAME_MACHINE=alphaev68 ;;
         esac
-
+       objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+       if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+       echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+       exit 0 ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+       # Look for CPU level
+       case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+         PA7*) echo hppa1.1-unknown-linux-gnu ;;
+         PA8*) echo hppa2.0-unknown-linux-gnu ;;
+         *)    echo hppa-unknown-linux-gnu ;;
+       esac
+       exit 0 ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+       echo hppa64-unknown-linux-gnu
+       exit 0 ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+       echo ${UNAME_MACHINE}-ibm-linux
+       exit 0 ;;
+    sh*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    x86_64:Linux:*:*)
+       echo x86_64-unknown-linux-gnu
+       exit 0 ;;
+    i*86:Linux:*:*)
        # The BFD linker knows what the default object file format is, so
-       # first see if it will tell us.  cd to the root directory to prevent
+       # first see if it will tell us. cd to the root directory to prevent
        # problems with other programs or directories called `ld' in the path.
-       ld_help_string=`cd /; ld --help 2>&1`
-       ld_supported_emulations=`echo $ld_help_string \
-                        | sed -ne '/supported emulations:/!d
+       # Set LC_ALL=C to ensure ld outputs messages in English.
+       ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+                        | sed -ne '/supported targets:/!d
                                    s/[         ][      ]*/ /g
-                                   s/.*supported emulations: *//
+                                   s/.*supported targets: *//
                                    s/ .*//
                                    p'`
-       case "$ld_supported_emulations" in
-         *ia64)      echo "${UNAME_MACHINE}-unknown-linux"         ; exit 0 ;;
-         i?86linux)  echo "${UNAME_MACHINE}-pc-linux-gnuaout"      ; exit 0 ;;
-         i?86coff)   echo "${UNAME_MACHINE}-pc-linux-gnucoff"      ; exit 0 ;;
-         sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
-         armlinux)   echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
-         m68klinux)  echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
-         elf32ppc | elf32ppclinux)
-               # Determine Lib Version
-               cat >$dummy.c <<EOF
-#include <features.h>
-#if defined(__GLIBC__)
-extern char __libc_version[];
-extern char __libc_release[];
-#endif
-main(argc, argv)
-     int argc;
-     char *argv[];
-{
-#if defined(__GLIBC__)
-  printf("%s %s\n", __libc_version, __libc_release);
-#else
-  printf("unkown\n");
-#endif
-  return 0;
-}
-EOF
-               LIBC=""
-               $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null
-               if test "$?" = 0 ; then
-                       ./$dummy | grep 1\.99 > /dev/null
-                       if test "$?" = 0 ; then
-                               LIBC="libc1"
-                       fi
-               fi      
-               rm -f $dummy.c $dummy
-               echo powerpc-unknown-linux-gnu${LIBC} ; exit 0 ;;
-       esac
-
-       if test "${UNAME_MACHINE}" = "alpha" ; then
-               sed 's/^        //'  <<EOF >$dummy.s
-               .globl main
-               .ent main
-       main:
-               .frame \$30,0,\$26,0
-               .prologue 0
-               .long 0x47e03d80 # implver $0
-               lda \$2,259
-               .long 0x47e20c21 # amask $2,$1
-               srl \$1,8,\$2
-               sll \$2,2,\$2
-               sll \$0,3,\$0
-               addl \$1,\$0,\$0
-               addl \$2,\$0,\$0
-               ret \$31,(\$26),1
-               .end main
-EOF
-               LIBC=""
-               $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
-               if test "$?" = 0 ; then
-                       ./$dummy
-                       case "$?" in
-                       7)
-                               UNAME_MACHINE="alpha"
-                               ;;
-                       15)
-                               UNAME_MACHINE="alphaev5"
-                               ;;
-                       14)
-                               UNAME_MACHINE="alphaev56"
-                               ;;
-                       10)
-                               UNAME_MACHINE="alphapca56"
-                               ;;
-                       16)
-                               UNAME_MACHINE="alphaev6"
-                               ;;
-                       esac
-
-                       objdump --private-headers $dummy | \
-                         grep ld.so.1 > /dev/null
-                       if test "$?" = 0 ; then
-                               LIBC="libc1"
-                       fi
-               fi
-               rm -f $dummy.s $dummy
-               echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
-       elif test "${UNAME_MACHINE}" = "mips" ; then
-         cat >$dummy.c <<EOF
-#ifdef __cplusplus
-int main (int argc, char *argv[]) {
-#else
-int main (argc, argv) int argc; char *argv[]; {
-#endif
-#ifdef __MIPSEB__
-  printf ("%s-unknown-linux-gnu\n", argv[1]);
-#endif
-#ifdef __MIPSEL__
-  printf ("%sel-unknown-linux-gnu\n", argv[1]);
-#endif
-  return 0;
-}
-EOF
-         $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
-         rm -f $dummy.c $dummy
-       else
-         # Either a pre-BFD a.out linker (linux-gnuoldld)
-         # or one that does not give us useful --help.
-         # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout.
-         # If ld does not provide *any* "supported emulations:"
-         # that means it is gnuoldld.
-         echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:"
-         test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
-
-         case "${UNAME_MACHINE}" in
-         i?86)
-           VENDOR=pc;
-           ;;
-         *)
-           VENDOR=unknown;
-           ;;
-         esac
-         # Determine whether the default compiler is a.out or elf
-         cat >$dummy.c <<EOF
-#include <features.h>
-#ifdef __cplusplus
-       int main (int argc, char *argv[]) {
-#else
-       int main (argc, argv) int argc; char *argv[]; {
-#endif
-#ifdef __ELF__
-# ifdef __GLIBC__
-#  if __GLIBC__ >= 2
-    printf ("%s-${VENDOR}-linux-gnu\n", argv[1]);
-#  else
-    printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
-#  endif
-# else
-   printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
-# endif
-#else
-  printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]);
-#endif
-  return 0;
-}
+        case "$ld_supported_targets" in
+         elf32-i386)
+               TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+               ;;
+         a.out-i386-linux)
+               echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+               exit 0 ;;               
+         coff-i386)
+               echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+               exit 0 ;;
+         "")
+               # Either a pre-BFD a.out linker (linux-gnuoldld) or
+               # one that does not give us useful --help.
+               echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+               exit 0 ;;
+       esac
+       # Determine whether the default compiler is a.out or elf
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <features.h>
+       #ifdef __ELF__
+       # ifdef __GLIBC__
+       #  if __GLIBC__ >= 2
+       LIBC=gnu
+       #  else
+       LIBC=gnulibc1
+       #  endif
+       # else
+       LIBC=gnulibc1
+       # endif
+       #else
+       #ifdef __INTEL_COMPILER
+       LIBC=gnu
+       #else
+       LIBC=gnuaout
+       #endif
+       #endif
 EOF
-         ${CC-cc} $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
-         rm -f $dummy.c $dummy
-       fi ;;
-# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.  earlier versions
-# are messed up and put the nodename in both sysname and nodename.
-    i?86:DYNIX/ptx:4*:*)
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+       rm -f $dummy.c
+       test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+       test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+       ;;
+    i*86:DYNIX/ptx:4*:*)
+       # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+       # earlier versions are messed up and put the nodename in both
+       # sysname and nodename.
        echo i386-sequent-sysv4
        exit 0 ;;
-# added by chet for bash based on usenet posting from <hops@sco.com> and
-# documentation on SCO's web site -- UnixWare 7 (SVR5)
-#    i?86:UnixWare:5*:*)
-#      echo ${UNAME_MACHINE}-pc-sysv5uw${UNAME_VERSION}
-#      exit 0 ;;
-    i?86:UNIX_SV:4.2MP:2.*)
-       # Unixware is an offshoot of SVR4, but it has its own version
-       # number series starting with 2...
-       # I am not positive that other SVR4 systems won't match this,
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
        # I just have to hope.  -- rms.
-       # Use sysv4.2uw... so that sysv4* matches it.
+        # Use sysv4.2uw... so that sysv4* matches it.
        echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
        exit 0 ;;
-    i?86:*:4.*:* | i?86:SYSTEM_V:4.*:* | i?86:UNIX_SV:4.*:*)
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+       UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
        if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
-               echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
+               echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
        else
-               echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
+               echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
        fi
        exit 0 ;;
-    i?86:*:5:7*)
-        UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
-        (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
-        (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) && UNAME_MACHINE=i586
-        (/bin/uname -X|egrep '^Machine.*Pent.*II' >/dev/null) && UNAME_MACHINE=i686
-        (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) && UNAME_MACHINE=i585
-        echo ${UNAME_MACHINE}-${UNAME_SYSTEM}${UNAME_VERSION}-sysv${UNAME_RELEASE}
-        exit 0 ;;
-    i?86:*:3.2:*)
+    i*86:*:5:[78]*)
+       case `/bin/uname -X | grep "^Machine"` in
+           *486*)           UNAME_MACHINE=i486 ;;
+           *Pentium)        UNAME_MACHINE=i586 ;;
+           *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+       esac
+       echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+       exit 0 ;;
+    i*86:*:3.2:*)
        if test -f /usr/options/cb.name; then
                UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
                echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
@@ -951,11 +991,15 @@ EOF
                echo ${UNAME_MACHINE}-pc-sysv32
        fi
        exit 0 ;;
+    i*86:*DOS:*:*)
+       echo ${UNAME_MACHINE}-pc-msdosdjgpp
+       exit 0 ;;
     pc:*:*:*)
-       # uname -m prints for DJGPP always 'pc', but it prints nothing about
-       # the processor, so we play safe by assuming i386.
+       # Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
        echo i386-pc-msdosdjgpp
-       exit 0 ;;
+        exit 0 ;;
     Intel:Mach:3*:*)
        echo i386-pc-mach3
        exit 0 ;;
@@ -975,7 +1019,7 @@ EOF
        exit 0 ;;
     M68*:*:R3V[567]*:*)
        test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
-    3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
+    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0)
        OS_REL=''
        test -r /etc/.relid \
        && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
@@ -984,30 +1028,33 @@ EOF
        /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
          && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
     3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
-       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-         && echo i486-ncr-sysv4 && exit 0 ;;
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
     mc68030:UNIX_System_V:4.*:*)
        echo m68k-atari-sysv4
        exit 0 ;;
-    m68*:LynxOS:2.*:*)
-       echo m68k-unknown-lynxos${UNAME_RELEASE}
-       exit 0 ;;
-    i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*)
-       echo i386-pc-lynxos${UNAME_RELEASE}
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
        exit 0 ;;
     TSUNAMI:LynxOS:2.*:*)
        echo sparc-unknown-lynxos${UNAME_RELEASE}
        exit 0 ;;
-    rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
+    rs6000:LynxOS:2.*:*)
        echo rs6000-unknown-lynxos${UNAME_RELEASE}
        exit 0 ;;
-    *:LynxOS:*:*)
-       echo ${UNAME_MACHINE}-unknown-lynxos${UNAME_RELEASE}
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+       echo powerpc-unknown-lynxos${UNAME_RELEASE}
        exit 0 ;;
     SM[BE]S:UNIX_SV:*:*)
        echo mips-dde-sysv${UNAME_RELEASE}
        exit 0 ;;
-    RM*:SINIX-*:*:* | RM*:ReliantUNIX-*:*:*)
+    RM*:ReliantUNIX-*:*:*)
+       echo mips-sni-sysv4
+       exit 0 ;;
+    RM*:SINIX-*:*:*)
        echo mips-sni-sysv4
        exit 0 ;;
     *:SINIX-*:*:*)
@@ -1018,10 +1065,10 @@ EOF
                echo ns32k-sni-sysv
        fi
        exit 0 ;;
-    PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
-                          # says <Richard.M.Bartel@ccMail.Census.GOV>
-       echo i586-unisys-sysv4
-       exit 0 ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
     *:UNIX_System_V:4*:FTX*)
        # From Gerald Hewes <hewes@openmarket.com>.
        # How about differentiating between stratus architectures? -djm
@@ -1030,27 +1077,31 @@ EOF
     *:*:*:FTX*)
        # From seanf@swdc.stratus.com.
        echo i860-stratus-sysv4
-       exit 0 ;;              
+       exit 0 ;;
+    *:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo hppa1.1-stratus-vos
+       exit 0 ;;
     mc68*:A/UX:*:*)
        echo m68k-apple-aux${UNAME_RELEASE}
        exit 0 ;;
-    news*:NEWS-OS:*:6*)
+    news*:NEWS-OS:6*:*)
        echo mips-sony-newsos6
        exit 0 ;;
-    R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
        if [ -d /usr/nec ]; then
-               echo mips-nec-sysv${UNAME_RELEASE}
+               echo mips-nec-sysv${UNAME_RELEASE}
        else
-               echo mips-unknown-sysv${UNAME_RELEASE}
+               echo mips-unknown-sysv${UNAME_RELEASE}
        fi
+        exit 0 ;;
+    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
+       echo powerpc-be-beos
        exit 0 ;;
-    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
-       echo powerpc-apple-beos
-       exit 0 ;;
-    BeMac:BeOS:*:*)
+    BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
        echo powerpc-apple-beos
        exit 0 ;;
-    BePC:BeOS:*:*)
+    BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
        echo i586-pc-beos
        exit 0 ;;
     SX-4:SUPER-UX:*:*)
@@ -1065,17 +1116,78 @@ EOF
     *:Rhapsody:*:*)
        echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
        exit 0 ;;
-    Power*:Darwin:*:*)
-       echo powerpc-apple-darwin${UNAME_RELEASE}
-       exit 0 ;;
     *:Darwin:*:*)
-       echo ${UNAME_MACHINE}-apple-darwin${UNAME_RELEASE}
+       echo `uname -p`-apple-darwin${UNAME_RELEASE}
+       exit 0 ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+       UNAME_PROCESSOR=`uname -p`
+       if test "$UNAME_PROCESSOR" = "x86"; then
+               UNAME_PROCESSOR=i386
+               UNAME_MACHINE=pc
+       fi
+       echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+       exit 0 ;;
+    *:QNX:*:4*)
+       echo i386-pc-qnx
+       exit 0 ;;
+    NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*)
+       echo nsr-tandem-nsk${UNAME_RELEASE}
+       exit 0 ;;
+    *:NonStop-UX:*:*)
+       echo mips-compaq-nonstopux
+       exit 0 ;;
+    BS2000:POSIX*:*:*)
+       echo bs2000-siemens-sysv
+       exit 0 ;;
+    DS/*:UNIX_System_V:*:*)
+       echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+       exit 0 ;;
+    *:Plan9:*:*)
+       # "uname -m" is not consistent, so use $cputype instead. 386
+       # is converted to i386 for consistency with other x86
+       # operating systems.
+       if test "$cputype" = "386"; then
+           UNAME_MACHINE=i386
+       else
+           UNAME_MACHINE="$cputype"
+       fi
+       echo ${UNAME_MACHINE}-unknown-plan9
+       exit 0 ;;
+    i*86:OS/2:*:*)
+       # If we were able to find `uname', then EMX Unix compatibility
+       # is probably installed.
+       echo ${UNAME_MACHINE}-pc-os2-emx
+       exit 0 ;;
+    *:TOPS-10:*:*)
+       echo pdp10-unknown-tops10
+       exit 0 ;;
+    *:TENEX:*:*)
+       echo pdp10-unknown-tenex
+       exit 0 ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+       echo pdp10-dec-tops20
+       exit 0 ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+       echo pdp10-xkl-tops20
+       exit 0 ;;
+    *:TOPS-20:*:*)
+       echo pdp10-unknown-tops20
+       exit 0 ;;
+    *:ITS:*:*)
+       echo pdp10-unknown-its
+       exit 0 ;;
+    i*86:XTS-300:*:STOP)
+       echo ${UNAME_MACHINE}-unknown-stop
+       exit 0 ;;
+    i*86:atheos:*:*)
+       echo ${UNAME_MACHINE}-unknown-atheos
        exit 0 ;;
 esac
 
 #echo '(No uname command or uname output not recognized.)' 1>&2
 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
 
+eval $set_cc_for_build
 cat >$dummy.c <<EOF
 #ifdef _SEQUENT_
 # include <sys/types.h>
@@ -1101,11 +1213,7 @@ main ()
 #endif
 
 #if defined (__arm) && defined (__acorn) && defined (__unix)
-  printf ("arm-acorn-riscix\n"); exit (0);
-#endif
-
-#if defined (hp9000) && !defined (hpux)
-  printf ("m68k-hp-bsd\n"); exit (0);
+  printf ("arm-acorn-riscix"); exit (0);
 #endif
 
 #if defined (hp300) && !defined (hpux)
@@ -1166,129 +1274,35 @@ main ()
 #endif
 
 #if defined (vax)
-#if !defined (ultrix)
-  printf ("vax-dec-bsd\n"); exit (0);
-#else
-  printf ("vax-dec-ultrix\n"); exit (0);
-#endif
-#endif
-
-#if defined (alliant) && defined (i860)
-  printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
-/* Begin cases added for Bash */
-#if defined (tahoe)
-  printf ("tahoe-cci-bsd\n"); exit (0);
-#endif
-
-#if defined (nec_ews)
-#  if defined (SYSTYPE_SYSV)
-  printf ("ews4800-nec-sysv4\n"); exit 0;
-#  else
-  printf ("ews4800-nec-bsd\n"); exit (0);
-#  endif
-#endif
-
-#if defined (sony)
-#  if defined (SYSTYPE_SYSV)
-  printf ("mips-sony-sysv4\n"); exit 0;
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
 #  else
-  printf ("mips-sony-bsd\n"); exit (0);
+    printf ("vax-dec-bsd\n"); exit (0);
 #  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
 #endif
 
-#if defined (ardent)
-  printf ("titan-ardent-bsd\n"); exit (0);
-#endif
-
-#if defined (stardent)
-  printf ("stardent-stardent-sysv\n"); exit (0);
-#endif
-
-#if defined (ibm032)
-  printf ("ibmrt-ibm-bsd4.3\n"); exit (0);
-#endif
-
-#if defined (sequent) && defined (i386)
-  printf ("i386-sequent-bsd\n"); exit (0);
-#endif
-
-#if defined (qnx) && defined (i386)
-  printf ("i386-pc-qnx\n"); exit (0);
-#endif
-
-#if defined (gould)
-  printf ("gould-gould-bsd\n"); exit (0);
-#endif
-
-#if defined (unixpc)
-  printf ("unixpc-att-sysv\n"); exit (0);
-#endif
-
-#if defined (att386)
-  printf ("i386-att-sysv3\n"); exit (0);
-#endif
-
-#if defined (__m88k) && defined (__UMAXV__)
-  printf ("m88k-encore-sysv3\n"); exit (0);
-#endif
-
-#if defined (drs6000)
-  printf ("drs6000-icl-sysv4.2\n"); exit (0);
-#endif
-
-#if defined (clipper)
-  printf ("clipper-orion-bsd\n"); exit (0);
-#endif
-
-#if defined (is68k)
-  printf ("m68k-isi-bsd\n"); exit (0);
-#endif
-
-#if defined (luna88k)
-  printf ("luna88k-omron-bsd\n"); exit (0);
-#endif
-
-#if defined (butterfly) && defined (BFLY1)
-  printf ("butterfly-bbn-mach\n"); exit (0);
-#endif
-
-#if defined (tower32)
-  printf ("tower32-ncr-sysv4\n"); exit (0);
-#endif
-
-#if defined (MagicStation)
-  printf ("magicstation-unknown-bsd\n"); exit (0);
-#endif
-
-#if defined (scs)
-  printf ("symmetric-scs-bsd4.2\n"); exit (0);
-#endif
-
-#if defined (tandem)
-  printf ("tandem-tandem-sysv\n"); exit (0);
-#endif
-
-#if defined (cadmus)
-  printf ("cadmus-pcs-sysv\n"); exit (0);
-#endif
-
-#if defined (masscomp)
-  printf ("masscomp-masscomp-sysv3\n"); exit (0);
-#endif
-
-#if defined (hbullx20)
-  printf ("hbullx20-bull-sysv3\n"); exit (0);
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
 #endif
 
-/* End cases added for Bash */
-
   exit (1);
 }
 EOF
 
-${CC-cc} $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0
+$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0
 rm -f $dummy.c $dummy
 
 # Apollos put the system type in the environment.
@@ -1321,21 +1335,59 @@ then
     esac
 fi
 
-# Begin cases added for Bash
+# NOTE -- Begin fallback cases added for bash -- NOTE
 case "$UNAME" in
 uts) echo uts-amdahl-sysv${UNAME_RELEASE}; exit 0 ;;
 esac
 
-if [ -d /usr/amiga ]; then
-       echo m68k-cbm-sysv${UNAME_RELEASE}; exit 0;
-fi
-
 if [ -f /bin/fxc.info ]; then
        echo fxc-alliant-concentrix
        exit 0
 fi
-# end cases added for Bash
+# NOTE -- End fallback cases added for bash -- NOTE
 
-#echo '(Unable to guess system type)' 1>&2
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+    ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
 
 exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
old mode 100755 (executable)
new mode 100644 (file)
index 6cc1150..538dc09
@@ -1,6 +1,10 @@
 #! /bin/sh
-# Configuration validation subroutine script, version 1.1.
-#   Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002 Free Software Foundation, Inc.
+
+timestamp='2002-03-07'
+
 # This file is (in principle) common to ALL GNU software.
 # The presence of a machine in this file suggests that SOME GNU software
 # can handle that machine.  It does not imply ALL GNU software can.
@@ -25,6 +29,9 @@
 # configuration script generated by Autoconf, you may include it under
 # the same distribution terms that you use for the rest of that program.
 
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
 # Configuration subroutine to validate and canonicalize a configuration type.
 # Supply the specified configuration type as an argument.
 # If it is invalid, we print an error message on stderr and exit with code 1.
 #      CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
 # It is wrong to echo any other type of specification.
 
-if [ x$1 = x ]
-then
-       echo Configuration name missing. 1>&2
-       echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
-       echo "or     $0 ALIAS" 1>&2
-       echo where ALIAS is a recognized configuration type. 1>&2
-       exit 1
-fi
+me=`echo "$0" | sed -e 's,.*/,,'`
 
-# First pass through any local machine types.
-case $1 in
-       *local*)
-               echo $1
-               exit 0
-               ;;
-       *)
-       ;;
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit 0;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
 esac
 
 # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
 # Here we must recognize all the valid KERNEL-OS combinations.
 maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
-  linux-gnu*)
+  nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*)
     os=-$maybe_os
     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
     ;;
@@ -94,7 +144,7 @@ case $os in
        -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
        -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
        -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-       -apple )
+       -apple | -axis)
                os=
                basic_machine=$1
                ;;
@@ -105,9 +155,17 @@ case $os in
        -scout)
                ;;
        -wrs)
-               os=vxworks
+               os=-vxworks
                basic_machine=$1
                ;;
+       -chorusos*)
+               os=-chorusos
+               basic_machine=$1
+               ;;
+       -chorusrdb)
+               os=-chorusrdb
+               basic_machine=$1
+               ;;
        -hiux*)
                os=-hiuxwe2
                ;;
@@ -156,33 +214,60 @@ case $os in
        -psos*)
                os=-psos
                ;;
+       -mint | -mint[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
 esac
 
 # Decode aliases for certain CPU-COMPANY combinations.
 case $basic_machine in
        # Recognize the basic CPU types without company name.
        # Some are omitted here because they have special meanings below.
-       tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
-               | arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \
-               | 580 | i960 | h8300 \
-               | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
-               | alpha | alphaev[4-7] | alphaev56 | alphapca5[67] \
-               | we32k | ns16k | clipper | i370 | sh | powerpc | powerpcle \
-               | 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \
-               | mips64orion | mips64orionel | mipstx39 | mipstx39el \
-               | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
-               | mips64vr5000 | miprs64vr5000el | mcore \
-               | sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \
-               | thumb | d10v | s390)
+       1750a | 580 \
+       | a29k \
+       | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+       | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+       | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+       | c4x | clipper \
+       | d10v | d30v | dsp16xx \
+       | fr30 \
+       | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+       | i370 | i860 | i960 | ia64 \
+       | m32r | m68000 | m68k | m88k | mcore \
+       | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \
+       | mips64vr4100 | mips64vr4100el | mips64vr4300 \
+       | mips64vr4300el | mips64vr5000 | mips64vr5000el \
+       | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \
+       | mipsisa32 | mipsisa64 \
+       | mn10200 | mn10300 \
+       | ns16k | ns32k \
+       | openrisc | or32 \
+       | pdp10 | pdp11 | pj | pjl \
+       | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+       | pyramid \
+       | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \
+       | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+       | strongarm \
+       | tahoe | thumb | tic80 | tron \
+       | v850 | v850e \
+       | we32k \
+       | x86 | xscale | xstormy16 | xtensa \
+       | z8k)
+               basic_machine=$basic_machine-unknown
+               ;;
+       m6811 | m68hc11 | m6812 | m68hc12)
+               # Motorola 68HC11/12.
                basic_machine=$basic_machine-unknown
+               os=-none
                ;;
-       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65)
+       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
                ;;
 
        # We use `pc' rather than `unknown'
        # because (1) that's what they normally are, and
        # (2) the word "unknown" tends to confuse beginning users.
-       i[34567]86)
+       i*86 | x86_64)
          basic_machine=$basic_machine-pc
          ;;
        # Object if more than one company name word.
@@ -191,33 +276,54 @@ case $basic_machine in
                exit 1
                ;;
        # Recognize the basic CPU types with company name.
-       # FIXME: clean up the formatting here.
-       vax-* | tahoe-* | i[34567]86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \
-             | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
-             | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
-             | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
-             | xmp-* | ymp-* \
-             | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* | hppa2.0n-* \
-             | alpha-* | alphaev[4-7]-* | alphaev56-* | alphapca5[67]-* \
-             | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
-             | clipper-* | orion-* \
-             | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
-             | sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \
-             | mips64el-* | mips64orion-* | mips64orionel-* \
-             | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
-             | mipstx39-* | mipstx39el-* | mcore-* \
-             | f301-* | armv*-* | t3e-* \
-             | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
-             | thumb-* | v850-* | d30v-* | tic30-* | c30-* )
-               ;;
-       # BEGIN cases added for Bash
-       butterfly-bbn* | cadmus-* | ews*-nec | ibmrt-ibm* | masscomp-masscomp \
-             | tandem-* | symmetric-* | drs6000-icl | *-*ardent | gould-gould \
-             | concurrent-* | ksr1-* | esa-ibm | fxc-alliant | *370-amdahl \
-             | *-convex | sx[45]*-nec )
-               ;;
-       # END cases added for Bash
+       580-* \
+       | a29k-* \
+       | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+       | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+       | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+       | arm-*  | armbe-* | armle-* | armv*-* \
+       | avr-* \
+       | bs2000-* \
+       | c[123]* | c30-* | [cjt]90-* | c54x-* \
+       | clipper-* | cydra-* \
+       | d10v-* | d30v-* \
+       | elxsi-* \
+       | f30[01]-* | f700-* | fr30-* | fx80-* \
+       | h8300-* | h8500-* \
+       | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+       | i*86-* | i860-* | i960-* | ia64-* \
+       | m32r-* \
+       | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+       | m88110-* | m88k-* | mcore-* \
+       | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \
+       | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \
+       | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \
+       | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \
+       | none-* | np1-* | ns16k-* | ns32k-* \
+       | orion-* \
+       | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+       | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+       | pyramid-* \
+       | romp-* | rs6000-* \
+       | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \
+       | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+       | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+       | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
+       | v850-* | v850e-* | vax-* \
+       | we32k-* \
+       | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+       | xtensa-* \
+       | ymp-* \
+       | z8k-*)
+               ;;
 
+       # NOTE -- BEGIN cases added for Bash -- NOTE
+       butterfly-bbn* | cadmus-* | ews*-nec | masscomp-masscomp \
+       | tandem-* | symmetric-* | drs6000-icl | *-*ardent | concurrent-* \
+       | ksr1-* | esa-ibm | fxc-alliant | *370-amdahl | sx[45]*-nec )
+               ;;
+       # NOTE -- END cases added for Bash -- NOTE
+       
        # Recognize the various machine names and aliases which stand
        # for a CPU type and a company and sometimes even an OS.
        386bsd)
@@ -253,15 +359,14 @@ case $basic_machine in
                os=-sysv
                ;;
        amiga | amiga-*)
-#              basic_machine=m68k-cbm
                basic_machine=m68k-unknown
                ;;
        amigaos | amigados)
-               basic_machine=m68k-cbm
+               basic_machine=m68k-unknown
                os=-amigaos
                ;;
        amigaunix | amix)
-               basic_machine=m68k-cbm
+               basic_machine=m68k-unknown
                os=-sysv4
                ;;
        apollo68)
@@ -280,6 +385,10 @@ case $basic_machine in
                basic_machine=ns32k-sequent
                os=-dynix
                ;;
+       c90)
+               basic_machine=c90-cray
+               os=-unicos
+               ;;
        convex-c1)
                basic_machine=c1-convex
                os=-bsd
@@ -300,27 +409,30 @@ case $basic_machine in
                basic_machine=c38-convex
                os=-bsd
                ;;
-       cray | ymp)
-               basic_machine=ymp-cray
-               os=-unicos
-               ;;
-       cray2)
-               basic_machine=cray2-cray
-               os=-unicos
-               ;;
-       [ctj]90-cray)
-               basic_machine=c90-cray
+       cray | j90)
+               basic_machine=j90-cray
                os=-unicos
                ;;
        crds | unos)
                basic_machine=m68k-crds
                ;;
+       cris | cris-* | etrax*)
+               basic_machine=cris-axis
+               ;;
        da30 | da30-*)
                basic_machine=m68k-da30
                ;;
        decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
                basic_machine=mips-dec
                ;;
+       decsystem10* | dec10*)
+               basic_machine=pdp10-dec
+               os=-tops10
+               ;;
+       decsystem20* | dec20*)
+               basic_machine=pdp10-dec
+               os=-tops20
+               ;;
        delta | 3300 | motorola-3300 | motorola-delta \
              | 3300-motorola | delta-motorola)
                basic_machine=m68k-motorola
@@ -337,9 +449,6 @@ case $basic_machine in
                basic_machine=m68k-bull
                os=-sysv3
                ;;
-       hbullx20-bull)
-               basic_machine=m68k-bull
-               ;;
        ebmon29k)
                basic_machine=a29k-amd
                os=-ebmon
@@ -348,7 +457,7 @@ case $basic_machine in
                basic_machine=elxsi-elxsi
                os=-bsd
                ;;
-       encore | umax | mmax | multimax)
+       encore | umax | mmax | multimax)        # bash
                basic_machine=ns32k-encore
                ;;
        es1800 | OSE68k | ose68k | ose | OSE)
@@ -365,6 +474,10 @@ case $basic_machine in
                basic_machine=tron-gmicro
                os=-sysv
                ;;
+       go32)
+               basic_machine=i386-pc
+               os=-go32
+               ;;
        h3050r* | hiux*)
                basic_machine=hppa1.1-hitachi
                os=-hiuxwe2
@@ -385,6 +498,9 @@ case $basic_machine in
                basic_machine=m88k-harris
                os=-sysv3
                ;;
+       hbullx20-bull)
+               basic_machine=m68k-bull         # bash
+               ;;
        hp300-*)
                basic_machine=m68k-hp
                ;;
@@ -437,29 +553,36 @@ case $basic_machine in
                os=-proelf
                ;;
        ibm032-*)
-               basic_machine=ibmrt-ibm
+               basic_machine=ibmrt-ibm         # bash
                ;;
        i370-ibm* | ibm*)
                basic_machine=i370-ibm
-               os=-mvs
                ;;
 # I'm not sure what "Sysv32" means.  Should this be sysv3.2?
-       i[34567]86v32)
+       i*86v32)
                basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
                os=-sysv32
                ;;
-       i[34567]86v4*)
+       i*86v4*)
                basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
                os=-sysv4
                ;;
-       i[34567]86v)
+       i*86v)
                basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
                os=-sysv
                ;;
-       i[34567]86sol2)
+       i*86sol2)
                basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
                os=-solaris2
                ;;
+       i386-go32)
+               basic_machine=i386-pc           # bash
+               os=-go32
+               ;;
+       i386-mingw32)
+               basic_machine=i386-pc           # bash
+               os=-mingw32
+               ;;
        i386mach)
                basic_machine=i386-mach
                os=-mach
@@ -468,14 +591,6 @@ case $basic_machine in
                basic_machine=i386-unknown
                os=-vsta
                ;;
-       i386-go32 | go32)
-               basic_machine=i386-unknown
-               os=-go32
-               ;;
-       i386-mingw32 | mingw32)
-               basic_machine=i386-unknown
-               os=-mingw32
-               ;;
        iris | iris4d)
                basic_machine=mips-sgi
                case $os in
@@ -490,11 +605,11 @@ case $basic_machine in
                basic_machine=m68k-isi
                os=-sysv
                ;;
-       luna88k-omron* | m88k-omron*)
+       luna88k-omron* | m88k-omron*)           # bash
                basic_machine=m88k-omron
                ;;
        magicstation*)
-               basic_machine=magicstation-unknown
+               basic_machine=magicstation-unknown      # bash
                ;;
        magnum | m3230)
                basic_machine=mips-mips
@@ -504,35 +619,43 @@ case $basic_machine in
                basic_machine=ns32k-utek
                os=-sysv
                ;;
+       mingw32)
+               basic_machine=i386-pc
+               os=-mingw32
+               ;;
        miniframe)
                basic_machine=m68000-convergent
                ;;
-       *mint | *MiNT)
+       *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
                basic_machine=m68k-atari
                os=-mint
                ;;
-       mipsel*-linux*)
-               basic_machine=mipsel-unknown
-               os=-linux-gnu
-               ;;
-       mips*-linux*)
-               basic_machine=mips-unknown
-               os=-linux-gnu
-               ;;
        mips3*-*)
                basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
                ;;
        mips3*)
                basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
                ;;
+       mmix*)
+               basic_machine=mmix-knuth
+               os=-mmixware
+               ;;
        monitor)
                basic_machine=m68k-rom68k
                os=-coff
                ;;
+       morphos)
+               basic_machine=powerpc-unknown
+               os=-morphos
+               ;;
        msdos)
-               basic_machine=i386-unknown
+               basic_machine=i386-pc
                os=-msdos
                ;;
+       mvs)
+               basic_machine=i370-ibm
+               os=-mvs
+               ;;
        ncr3000)
                basic_machine=i486-ncr
                os=-sysv4
@@ -542,7 +665,7 @@ case $basic_machine in
                os=-netbsd
                ;;
        netwinder)
-               basic_machine=armv4l-corel
+               basic_machine=armv4l-rebel
                os=-linux
                ;;
        news | news700 | news800 | news900)
@@ -557,10 +680,10 @@ case $basic_machine in
                basic_machine=mips-sony
                os=-newsos
                ;;
-        necv70)
-                basic_machine=v70-nec
-                os=-sysv
-                ;;
+       necv70)
+               basic_machine=v70-nec
+               os=-sysv
+               ;;
        next | m*-next )
                basic_machine=m68k-next
                case $os in
@@ -586,33 +709,44 @@ case $basic_machine in
                basic_machine=i960-intel
                os=-nindy
                ;;
-        mon960)
-                basic_machine=i960-intel
-                os=-mon960
-                ;;
+       mon960)
+               basic_machine=i960-intel
+               os=-mon960
+               ;;
+       nonstopux)
+               basic_machine=mips-compaq
+               os=-nonstopux
+               ;;
        np1)
                basic_machine=np1-gould
                ;;
-       osr5 | sco5)    # SCO Open Server
-               basic_machine=i386-pc
-               os=-sco3.2v5
+       nsr-tandem)
+               basic_machine=nsr-tandem
                ;;
        odt | odt3 | odt4)      # SCO Open Desktop
-               basic_machine=i386-pc
+               basic_machine=i386-pc           # bash
                os=-sco3.2v4
                ;;
-        op50n-* | op60c-*)
-                basic_machine=hppa1.1-oki
-                os=-proelf
-                ;;
-        OSE68000 | ose68000)
-                basic_machine=m68000-ericsson
-                os=-ose
-                ;;
-        os68k)
-                basic_machine=m68k-none
-                os=-os68k
-                ;;
+       op50n-* | op60c-*)
+               basic_machine=hppa1.1-oki
+               os=-proelf
+               ;;
+       or32 | or32-*)
+               basic_machine=or32-unknown
+               os=-coff
+               ;;
+       OSE68000 | ose68000)
+               basic_machine=m68000-ericsson
+               os=-ose
+               ;;
+       osr5 | sco5)            # SCO Open Server
+               basic_machine=i386-pc           # bash
+               os=-sco3.2v5
+               ;;
+       os68k)
+               basic_machine=m68k-none
+               os=-os68k
+               ;;
        pa-hitachi)
                basic_machine=hppa1.1-hitachi
                os=-hiuxwe2
@@ -627,63 +761,79 @@ case $basic_machine in
        pbb)
                basic_machine=m68k-tti
                ;;
-       pc532 | pc532-*)
+        pc532 | pc532-*)
                basic_machine=ns32k-pc532
                ;;
-       pentium | p5 | k5 | k6 | nexen)
-               basic_machine=i586-intel
+       pentium | p5 | k5 | k6 | nexgen | viac3)
+               basic_machine=i586-pc
+               ;;
+       pentiumpro | p6 | 6x86 | athlon)
+               basic_machine=i686-pc
                ;;
-        pentiumpro | p6 | 6x86)
-                basic_machine=i686-pc
-                ;;
        pentiumii | pentium2)
-               basic_machine=i786-pc
+               basic_machine=i686-pc
                ;;
-       pentium-* | p5-* | k5-* | k6-* | nexen-*)
+       pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
                basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
                ;;
-       pentiumpro-* | p6-* | 6x86*)
+       pentiumpro-* | p6-* | 6x86-* | athlon-*)
                basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
                ;;
        pentiumii-* | pentium2-*)
-               basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
                ;;
        pn)
                basic_machine=pn-gould
                ;;
-       power)  basic_machine=rs6000-ibm
+       power)  basic_machine=power-ibm
                ;;
        ppc)    basic_machine=powerpc-unknown
-               ;;
+               ;;
        ppc-*)  basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
                ;;
        ppcle | powerpclittle | ppc-le | powerpc-little)
                basic_machine=powerpcle-unknown
-               ;;
+               ;;
        ppcle-* | powerpclittle-*)
                basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
                ;;
+       ppc64)  basic_machine=powerpc64-unknown
+               ;;
+       ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+               basic_machine=powerpc64le-unknown
+               ;;
+       ppc64le-* | powerpc64little-*)
+               basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
        ps2)
                basic_machine=i386-ibm
                ;;
-        rom68k)
-                basic_machine=m68k-rom68k
-                os=-coff
-                ;;
+       pw32)
+               basic_machine=i586-unknown
+               os=-pw32
+               ;;
+       rom68k)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
        rm[46]00)
                basic_machine=mips-siemens
                ;;
        rtpc | rtpc-*)
                basic_machine=romp-ibm
                ;;
-       s390-*)
+       s390 | s390-*)
                basic_machine=s390-ibm
-               os=-linux
                ;;
-        sa29200)
-                basic_machine=a29k-amd
-                os=-udi
-                ;;
+       s390x | s390x-*)
+               basic_machine=s390x-ibm
+               ;;
+       sa29200)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
        sequent)
                basic_machine=i386-sequent
                ;;
@@ -691,10 +841,10 @@ case $basic_machine in
                basic_machine=sh-hitachi
                os=-hms
                ;;
-        sparclite-wrs)
-                basic_machine=sparclite-wrs
-                os=-vxworks
-                ;;
+       sparclite-wrs | simso-wrs)
+               basic_machine=sparclite-wrs
+               os=-vxworks
+               ;;
        sps7)
                basic_machine=m68k-bull
                os=-sysv2
@@ -702,13 +852,13 @@ case $basic_machine in
        spur)
                basic_machine=spur-unknown
                ;;
-        st2000)
-                basic_machine=m68k-tandem
-                ;;
-        stratus)
-                basic_machine=i860-stratus
-                os=-sysv4
-                ;;
+       st2000)
+               basic_machine=m68k-tandem
+               ;;
+       stratus)
+               basic_machine=i860-stratus
+               os=-sysv4
+               ;;
        sun2)
                basic_machine=m68000-sun
                ;;
@@ -749,20 +899,40 @@ case $basic_machine in
        sun386 | sun386i | roadrunner)
                basic_machine=i386-sun
                ;;
+        sv1)
+               basic_machine=sv1-cray
+               os=-unicos
+               ;;
        symmetry)
                basic_machine=i386-sequent
                os=-dynix
                ;;
-        t3e)
-                basic_machine=t3e-cray
-                os=-unicos
-                ;;
-        tx39)
-                basic_machine=mipstx39-unknown
-                ;;
-        tx39el)
-                basic_machine=mipstx39el-unknown
-                ;;
+       t3d)
+               basic_machine=alpha-cray
+               os=-unicos
+               ;;
+       t3e)
+               basic_machine=alphaev5-cray
+               os=-unicos
+               ;;
+       t90)
+               basic_machine=t90-cray
+               os=-unicos
+               ;;
+       tic54x | c54x*)
+               basic_machine=tic54x-unknown
+               os=-coff
+               ;;
+       tx39)
+               basic_machine=mipstx39-unknown
+               ;;
+       tx39el)
+               basic_machine=mipstx39el-unknown
+               ;;
+       toad1)
+               basic_machine=pdp10-xkl
+               os=-tops20
+               ;;
        tower | tower-32)
                basic_machine=m68k-ncr
                ;;
@@ -774,18 +944,18 @@ case $basic_machine in
                basic_machine=a29k-nyu
                os=-sym1
                ;;
-       uw2 | unixware | unixware2)
+       uw2 | unixware | unixware2)             # bash
                basic_machine=i386-pc
                os=-sysv4.2uw2.1
                ;;
-       uw7 | unixware7)
+       uw7 | unixware7)                        # bash
                basic_machine=i386-pc
                os=-sysv5uw7
                ;;
-        v810 | necv810)
-                basic_machine=v810-nec
-                os=-none
-                ;;
+       v810 | necv810)
+               basic_machine=v810-nec
+               os=-none
+               ;;
        vaxv)
                basic_machine=vax-dec
                os=-sysv
@@ -795,8 +965,8 @@ case $basic_machine in
                os=-vms
                ;;
        vpp*|vx|vx-*)
-               basic_machine=f301-fujitsu
-               ;;
+               basic_machine=f301-fujitsu
+               ;;
        vxworks960)
                basic_machine=i960-wrs
                os=-vxworks
@@ -809,25 +979,29 @@ case $basic_machine in
                basic_machine=a29k-wrs
                os=-vxworks
                ;;
-        w65*)
-                basic_machine=w65-wdc
-                os=-none
-                ;;
-        w89k-*)
-                basic_machine=hppa1.1-winbond
-                os=-proelf
-                ;;
-       xmp)
-               basic_machine=xmp-cray
-               os=-unicos
+       w65*)
+               basic_machine=w65-wdc
+               os=-none
+               ;;
+       w89k-*)
+               basic_machine=hppa1.1-winbond
+               os=-proelf
                ;;
-       xps | xps100)
+       windows32)
+               basic_machine=i386-pc
+               os=-windows32-msvcrt
+               ;;
+        xps | xps100)
                basic_machine=xps100-honeywell
                ;;
-        z8k-*-coff)
-                basic_machine=z8k-unknown
-                os=-sim
-                ;;
+       ymp)
+               basic_machine=ymp-cray
+               os=-unicos
+               ;;
+       z8k-*-coff)
+               basic_machine=z8k-unknown
+               os=-sim
+               ;;
        none)
                basic_machine=none-none
                os=-none
@@ -835,21 +1009,14 @@ case $basic_machine in
 
 # Here we handle the default manufacturer of certain CPU types.  It is in
 # some cases the only manufacturer, in others, it is the most popular.
-        w89k)
-                basic_machine=hppa1.1-winbond
-                ;;
-        op50n)
-                basic_machine=hppa1.1-oki
-                ;;
-        op60c)
-                basic_machine=hppa1.1-oki
-                ;;
-       mips)
-               if test "x$os" = "x-linux-gnu" ; then
-                       basic_machine=mips-unknown
-               else
-                       basic_machine=mips-mips
-               fi
+       w89k)
+               basic_machine=hppa1.1-winbond
+               ;;
+       op50n)
+               basic_machine=hppa1.1-oki
+               ;;
+       op60c)
+               basic_machine=hppa1.1-oki
                ;;
        romp)
                basic_machine=romp-ibm
@@ -860,16 +1027,26 @@ case $basic_machine in
        vax)
                basic_machine=vax-dec
                ;;
+       pdp10)
+               # there are many clones, so DEC is not a safe bet
+               basic_machine=pdp10-unknown
+               ;;
        pdp11)
                basic_machine=pdp11-dec
                ;;
        we32k)
                basic_machine=we32k-att
                ;;
-       sparc | sparcv9)
+       sh3 | sh4 | sh3eb | sh4eb)
+               basic_machine=sh-unknown
+               ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
+       sparc | sparcv9 | sparcv9b)
                basic_machine=sparc-sun
                ;;
-       cydra)
+        cydra)
                basic_machine=cydra-cydrome
                ;;
        orion)
@@ -878,16 +1055,19 @@ case $basic_machine in
        orion105)
                basic_machine=clipper-highlevel
                ;;
-        mac | mpw | mac-mpw)
-                basic_machine=m68k-apple
-                ;;
-        pmac | pmac-mpw)
-                basic_machine=powerpc-apple
-                ;;
-        c4x*)
-                basic_machine=c4x-none
-                os=-coff
-                ;;
+       mac | mpw | mac-mpw)
+               basic_machine=m68k-apple
+               ;;
+       pmac | pmac-mpw)
+               basic_machine=powerpc-apple
+               ;;
+       c4x*)
+               basic_machine=c4x-none
+               os=-coff
+               ;;
+       *-unknown)
+               # Make sure to match an already-canonicalized machine name.
+               ;;
        *)
                echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
                exit 1
@@ -911,8 +1091,8 @@ esac
 if [ x"$os" != x"" ]
 then
 case $os in
-       # First match some system type aliases
-       # that might get confused with valid system types.
+        # First match some system type aliases
+        # that might get confused with valid system types.
        # -solaris* is a basic system type, with this one exception.
        -solaris1 | -solaris1.*)
                os=`echo $os | sed -e 's|solaris1|sunos4|'`
@@ -923,14 +1103,11 @@ case $os in
        -svr4*)
                os=-sysv4
                ;;
-       -unixware | -uw | -unixware2* | -uw2*)
-               os=-sysv4.2uw2.1
-               ;;
-       -unixware7* | -uw7*)
+       -unixware7*)                    # bash
                os=-sysv5uw7
                ;;
-        -unixware*)
-                os=-sysv4.2uw
+       -unixware*)
+               os=-sysv4.2uw
                ;;
        -gnu/linux*)
                os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
@@ -950,23 +1127,39 @@ case $os in
              | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
              | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
              | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+             | -chorusos* | -chorusrdb* \
              | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
              | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
-             | -interix* | -uwin* | -rhapsody* | -openstep* | -oskit*)
+             | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
+             | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+             | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+             | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+             | -morphos* | -superux* | -rtmk* | -rtmk-nova*)
        # Remember, each alternative MUST END IN *, to match a version number.
                ;;
-       # BEGIN CASES ADDED FOR Bash
-       -qnx* | -powerux* | -superux* | -darwin* | -nonstopux*)
-               ;;
-       # END CASES ADDED FOR Bash
-        -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
-              | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
-              | -macos* | -mpw* | -magic* | -mon960* | -lnews*)
-                ;;
-        -mac*)
-                os=`echo $os | sed -e 's|mac|macos|'`
-                ;;
-
+       # NOTE -- BEGIN CASES ADDED FOR Bash -- NOTE
+       -powerux* | -superux*)
+               ;;
+       # NOTE -- END CASES ADDED FOR Bash -- NOTE
+       -qnx*)
+               case $basic_machine in
+                   x86-* | i*86-*)
+                       ;;
+                   *)
+                       os=-nto$os
+                       ;;
+               esac
+               ;;
+       -nto*)
+               os=-nto-qnx
+               ;;
+       -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+             | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+             | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+               ;;
+       -mac*)
+               os=`echo $os | sed -e 's|mac|macos|'`
+               ;;
        -linux*)
                os=`echo $os | sed -e 's|linux|linux-gnu|'`
                ;;
@@ -976,6 +1169,12 @@ case $os in
        -sunos6*)
                os=`echo $os | sed -e 's|sunos6|solaris3|'`
                ;;
+       -opened*)
+               os=-openedition
+               ;;
+       -wince*)
+               os=-wince
+               ;;
        -osfrose*)
                os=-osfrose
                ;;
@@ -991,14 +1190,23 @@ case $os in
        -acis*)
                os=-aos
                ;;
-        -386bsd)
-                os=-bsd
-                ;;
+       -atheos*)
+               os=-atheos
+               ;;
+       -386bsd)
+               os=-bsd
+               ;;
        -ctix* | -uts*)
                os=-sysv
                ;;
+       -nova*)
+               os=-rtmk-nova
+               ;;
        -ns2 )
-               os=-nextstep2
+               os=-nextstep2
+               ;;
+       -nsk*)
+               os=-nsk
                ;;
        # Preserve the version number of sinix5.
        -sinix5.*)
@@ -1022,24 +1230,24 @@ case $os in
        -sysvr4)
                os=-sysv4
                ;;
-       -sysvr5)
+       -sysvr5)                                # bash
                os=-sysv5
                ;;
-       # This must come after -sysvr[45].
+       # This must come after -sysvr4.
        -sysv*)
                ;;
-        -ose*)
-                os=-ose
-                ;;
-        -es1800*)
-                os=-ose
-                ;;
+       -ose*)
+               os=-ose
+               ;;
+       -es1800*)
+               os=-ose
+               ;;
        -xenix)
                os=-xenix
                ;;
-        -*mint | -*MiNT)
-                os=-mint
-                ;;
+        -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+               os=-mint
+               ;;
        -none)
                ;;
        *)
@@ -1065,10 +1273,17 @@ case $basic_machine in
        *-acorn)
                os=-riscix1.2
                ;;
+       arm*-rebel)
+               os=-linux
+               ;;
        arm*-semi)
                os=-aout
                ;;
-       pdp11-*)
+       # This must come before the *-dec entry.
+       pdp10-*)
+               os=-tops20
+               ;;
+        pdp11-*)
                os=-none
                ;;
        *-dec | vax-*)
@@ -1086,15 +1301,18 @@ case $basic_machine in
                # default.
                # os=-sunos4
                ;;
-        m68*-cisco)
-                os=-aout
-                ;;
-        mips*-cisco)
-                os=-elf
-                ;;
-        mips*-*)
-                os=-elf
-                ;;
+       m68*-cisco)
+               os=-aout
+               ;;
+       mips*-cisco)
+               os=-elf
+               ;;
+       mips*-*)
+               os=-elf
+               ;;
+       or32-*)
+               os=-coff
+               ;;
        *-tti)  # must be before sparc entry or we get the wrong os.
                os=-sysv3
                ;;
@@ -1107,15 +1325,15 @@ case $basic_machine in
        *-ibm)
                os=-aix
                ;;
-        *-wec)
-                os=-proelf
-                ;;
-        *-winbond)
-                os=-proelf
-                ;;
-        *-oki)
-                os=-proelf
-                ;;
+       *-wec)
+               os=-proelf
+               ;;
+       *-winbond)
+               os=-proelf
+               ;;
+       *-oki)
+               os=-proelf
+               ;;
        *-hp)
                os=-hpux
                ;;
@@ -1158,39 +1376,39 @@ case $basic_machine in
        *-next)
                os=-nextstep3
                ;;
-       *-gould)
+        *-gould)
                os=-sysv
                ;;
-       *-highlevel)
+        *-highlevel)
                os=-bsd
                ;;
        *-encore)
                os=-bsd
                ;;
-       *-sgi)
+        *-sgi)
                os=-irix
                ;;
-       *-siemens)
+        *-siemens)
                os=-sysv4
                ;;
        *-masscomp)
                os=-rtu
                ;;
-       f301-fujitsu)
+       f30[01]-fujitsu | f700-fujitsu)
                os=-uxpv
                ;;
-        *-rom68k)
-                os=-coff
-                ;;
-        *-*bug)
-                os=-coff
-                ;;
-        *-apple)
-                os=-macos
-                ;;
-        *-atari*)
-                os=-mint
-                ;;
+       *-rom68k)
+               os=-coff
+               ;;
+       *-*bug)
+               os=-coff
+               ;;
+       *-apple)
+               os=-macos
+               ;;
+       *-atari*)
+               os=-mint
+               ;;
        *)
                os=-none
                ;;
@@ -1209,18 +1427,21 @@ case $basic_machine in
                        -sunos*)
                                vendor=sun
                                ;;
-                       -lynxos*)
+                       -lynxos*)                       # bash
                                vendor=lynx
                                ;;
                        -aix*)
                                vendor=ibm
                                ;;
-                        -beos*)
-                                vendor=be
-                                ;;
+                       -beos*)
+                               vendor=be
+                               ;;
                        -hpux*)
                                vendor=hp
                                ;;
+                       -mpeix*)
+                               vendor=hp
+                               ;;
                        -hiux*)
                                vendor=hitachi
                                ;;
@@ -1236,7 +1457,7 @@ case $basic_machine in
                        -genix*)
                                vendor=ns
                                ;;
-                       -mvs*)
+                       -mvs* | -opened*)
                                vendor=ibm
                                ;;
                        -ptx*)
@@ -1248,18 +1469,29 @@ case $basic_machine in
                        -aux*)
                                vendor=apple
                                ;;
-                        -hms*)
-                                vendor=hitachi
-                                ;;
-                        -mpw* | -macos*)
-                                vendor=apple
-                                ;;
-                        -*mint | -*MiNT)
-                                vendor=atari
-                                ;;
+                       -hms*)
+                               vendor=hitachi
+                               ;;
+                       -mpw* | -macos*)
+                               vendor=apple
+                               ;;
+                       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+                               vendor=atari
+                               ;;
+                       -vos*)
+                               vendor=stratus
+                               ;;
                esac
                basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
                ;;
 esac
 
 echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
index 938d9dc5782d06aeedad9acc38432cda7ca6ccca..13a86c8ec08cd1f24e13fabddc01dc54aefcd97a 100755 (executable)
@@ -3,7 +3,21 @@
 # fixlinks - make symlinks in the bash source tree so that there is
 #           exactly one version of any given source file.
 #
+# Copyright (C) 1996-2002 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.
 
 SRCDIR=.
 while [ $# -gt 0 ]; do
index ea88212bb50be7a7edf3447582af0ce18296e181..0cac004e6dce38456fc54e6e7dac614caa662e12 100755 (executable)
@@ -5,6 +5,18 @@
 #
 # $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $
 #
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
 # This script is compatible with the BSD install script, but was written
 # from scratch.
 #
index fa644f8b8e0f0e397e992d8bb3f0061e58e1ffdd..d1ed8bc5451f0224c978b5be7634975a70945f5e 100644 (file)
 
 static char location_base[NULL_TERMINATED(MED_STR_MAX)] = "";
 
-char   *signature = "<HR>\n"
-"This document was created by man2html\n"
-"using the manual pages.<BR>\n"
-"Time: %s\n";
+char   *signature = "<HR>\nThis document was created by man2html from %s.<BR>\nTime: %s\n";
 
 /* timeformat for signature */
-#define TIMEFORMAT "%T GMT, %B %d, %Y"
+#define TIMEFORMAT "%d %B %Y %T %Z"
+
+char *manpage;
 
 /* BSD mandoc Bl/El lists to HTML list types */
 #define BL_DESC_LIST   1
@@ -437,9 +436,9 @@ print_sig(void)
 
        datbuf[0] = '\0';
        clock = time(NULL);
-       timetm = gmtime(&clock);
+       timetm = localtime(&clock);
        strftime(datbuf, MED_STR_MAX, TIMEFORMAT, timetm);
-       printf(signature, datbuf);
+       printf(signature, manpage, datbuf);
 }
 
 static char *
@@ -1964,6 +1963,28 @@ trans_char(char *c, char s, char t)
        }
 }
 
+/* Remove \a from C in place.  Return modified C. */
+static char *
+unescape (char *c)
+{
+       int     i, l;
+
+       l = strlen (c);
+       i = 0;
+       while (i < l && c[i]) {
+               if (c[i] == '\a') {
+                       if (c[i+1])
+                               strcpy(c + i, c + i + 1);       /* should be memmove */
+                       else {
+                               c[i] = '\0';
+                               break;
+                       }
+               }
+               i++;
+       }
+       return c;
+}
+       
 static char *
 fill_words(char *c, char *words[], int *n)
 {
@@ -1978,6 +1999,9 @@ fill_words(char *c, char *words[], int *n)
                        if (*sl == '"') {
                                *sl = '\a';
                                skipspace = !skipspace;
+                       } else if (*sl == '\a') {
+                               /* handle already-translated " */
+                               skipspace = !skipspace;
                        } else if (*sl == escapesym)
                                slash = 1;
                        else if ((*sl == ' ' || *sl == '\t') && !skipspace) {
@@ -2154,7 +2178,7 @@ scan_request(char *c)
                j++;
        if (c[0] == escapesym) {
                /* some pages use .\" .\$1 .\} */
-               /* .\$1 is too difficult/stuppid */
+               /* .\$1 is too difficult/stupid */
                if (c[1] == '$')
                        c = skip_till_newline(c);
                else
@@ -2847,7 +2871,7 @@ scan_request(char *c)
                                        out_html("<TH ALIGN=LEFT>");
                                        out_html(page_and_sec);
                                        out_html("<TH ALIGN=CENTER>");
-                                       out_html(wordlist[2]);
+                                       out_html(unescape(wordlist[2]));
                                        out_html("<TH ALIGN=RIGHT>");
                                        out_html(page_and_sec);
                                        out_html("\n</TABLE>\n");
@@ -3940,7 +3964,7 @@ main(int argc, char **argv)
                usage();
                exit(EXIT_USAGE);
        }
-       h = t = argv[1];
+       manpage = h = t = argv[1];
        i = 0;
 
        buf = read_man_page(h);
index 56caab882c23141be2518e249bc372bfc168782e..10b08c0ed7b8ca6f5c0e298dfc051a8ab7f2facc 100755 (executable)
@@ -4,6 +4,22 @@
 #          file in the target directory ($1).  Directories specified in
 #          MANIFEST are created in the target directory
 #
+# Copyright (C) 1996-2002 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.
+#
 prog=`basename $0`
 
 SRCDIR=src
index 0da4288c08d031c7e9998b95360cda9cd138fe6f..ec52614d7998538a80fe2d2629432e07d7ad7030 100755 (executable)
 # Chet Ramey
 # chet@po.cwru.edu
 
+# Copyright (C) 1996-2002 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.
+
 PROG=`basename $0`
 
 # defaults
@@ -62,4 +78,3 @@ if [ -n "$verbose" ]; then
 fi
 
 exit 0
-
index b79d9716f464b54db8828aee413878154382d0bd..ce4fb235db79fb980a0a477881fa60e2f97a9a04 100755 (executable)
@@ -5,6 +5,22 @@
 # Chet Ramey
 # chet@po.cwru.edu
 
+# Copyright (C) 1996-2002 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.
+
 for dir
 do
 
index cbaaab264a6ba21130caf11325548338e279b7d5..798a9a401677ae5aa0eeefe9595d18b61f1ad90e 100644 (file)
@@ -19,7 +19,7 @@
    with Bash; see the file COPYING.  If not, write to the Free Software
    Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
 
-#include "config.h"
+#include <config.h>
 
 #include <stdio.h>
 #include <sys/types.h>
index d641cf060cdb2331322e955cbeda6bf12e94845e..509a4548352f6cde34a21e2ff3bffc5438d383f3 100755 (executable)
@@ -5,6 +5,22 @@
 # in the makefile.  This creates a file named by the -o option,
 # otherwise everything is echoed to the standard output.
 
+# Copyright (C) 1996-2002 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.
+
 PROGNAME=`basename $0`
 USAGE="$PROGNAME [-b] [-S srcdir] -d version -p patchlevel [-s status] [-o outfile]"
 
index 0355f857def43a8a83522e1c387c64f6b8b9ae83..29629b345a91d738f6c44443bc049fcf9f1f29c9 100644 (file)
@@ -6,6 +6,24 @@
    chet@po.cwru.edu
 */
 
+/* Copyright (C) 1997-2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 extern char **environ;
 
 int
index 8aebd437cc74fef001d2e289c660b17a08a5a2de..b3a716c7ced88d889969053a0a67766eb4d7c30b 100755 (executable)
@@ -1,5 +1,21 @@
 #! /bin/sh -
 
+# Copyright (C) 1996-2002 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.
+
 if [ $# -eq 0 ]; then
        env
        exit
index 141c763c1baa7486d7f64c921b12794845348dec..c622582e8c83be0033dbad1e88aef3bb2df879c3 100644 (file)
@@ -1,3 +1,29 @@
+/*
+   recho -- really echo args, bracketed with <> and with invisible chars
+           made visible.
+
+   Chet Ramey
+   chet@po.cwru.edu
+*/
+
+/* Copyright (C) 2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 #include <stdio.h>
 
 void strprint();
@@ -21,9 +47,9 @@ void
 strprint(str)
 char   *str;
 {
-       register char *s;
+       register unsigned char *s;
 
-       for (s = str; s && *s; s++) {
+       for (s = (unsigned char *)str; s && *s; s++) {
                if (*s < ' ') {
                        putchar('^');
                        putchar(*s+64);
index a6d751f38d1c955f78fe0bb1e914c662bd8354ba..b3de8feb0ebc22dabe18ee61be2468c343a37dc2 100755 (executable)
@@ -4,6 +4,22 @@
 #             using locally-installed readline libraries
 #
 
+# Copyright (C) 1996-2002 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.
+
 PROGNAME=`basename $0`
 
 : ${TMPDIR:=/tmp}
index a7c58104b96b155816b7d9e20dcfd61c54ea9563..6bd7fb120cac0fea75d2d15f44a55b7f29b43515 100755 (executable)
 # Chet Ramey
 # chet@po.cwru.edu
 
+# Copyright (C) 1996-2002 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.
+
 #
 # defaults
 #
@@ -62,7 +78,10 @@ sunos4*)
 sunos5*-*gcc*|solaris2*-*gcc*)
        SHOBJ_CFLAGS=-fpic
        SHOBJ_LD='${CC}'
+       # This line works for the Solaris linker in /usr/ccs/bin/ld
        SHOBJ_LDFLAGS='-shared -Wl,-i -Wl,-h,$@'
+       # This line works for the GNU ld
+#      SHOBJ_LDFLAGS='-shared -Wl,-h,$@'
 
 #      SHLIB_XLDFLAGS='-R $(libdir)'
        SHLIB_LIBVERSION='$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)'
index 85655638be5423eec30c2d2b8e8c3369345b948f..58e84194f0f8f84dc6a51d58bbd2cd7d105f055c 100755 (executable)
 #      make
 #      CC="cc -x2.3" ./link.sh
 
+# Copyright (C) 1989-2002 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.
+
 set -x
 
 rm -f bash
index 151fac31a5c58fde8ab4c2d1014b5209fe773753..3bc1fbab54b75295acda4f1f6d0eb13c3891b6ff 100644 (file)
@@ -1,5 +1,23 @@
 /* zecho - bare-bones echo */
 
+/* Copyright (C) 1996-2002 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
 #include <stdio.h>
 
 int
index 87938d61fee5ad8dc0d2a5c80a6197beed7788ed..b14427a32f29e67019c285e5c776f95be51204e0 100644 (file)
--- a/syntax.h
+++ b/syntax.h
 #define CXGLOB         0x0200  /* extended globbing characters */
 #define CXQUOTE                0x0400  /* cquote + backslash */
 #define CSPECVAR       0x0800  /* single-character shell variable name */
+#define CSUBSTOP       0x1000  /* values of OP for ${word[:]OPstuff} */
 
 /* Defines for use by the rest of the shell. */
 extern const int sh_syntaxtab[];
 
-#define shellmeta(c)   (sh_syntaxtab[(c)] & CSHMETA)
-#define shellbreak(c)  (sh_syntaxtab[(c)] & CSHBRK)
-#define shellquote(c)  (sh_syntaxtab[(c)] & CQUOTE)
+#define shellmeta(c)   (sh_syntaxtab[(unsigned char)(c)] & CSHMETA)
+#define shellbreak(c)  (sh_syntaxtab[(unsigned char)(c)] & CSHBRK)
+#define shellquote(c)  (sh_syntaxtab[(unsigned char)(c)] & CQUOTE)
+
+#define issyntype(c, t)        ((sh_syntaxtab[(unsigned char)(c)] & (t)) != 0)
+#define notsyntype(c,t) ((sh_syntaxtab[(unsigned char)(c)] & (t)) == 0)
 
 #if defined (PROCESS_SUBSTITUTION)
 #  define shellexp(c)  ((c) == '$' || (c) == '<' || (c) == '>')
diff --git a/test.c b/test.c
index bc791c2b8930175b2ab007a693e286a2dfd38f08..449c5d3b59a680774494146e4e6ae95c3f7ef077 100644 (file)
--- a/test.c
+++ b/test.c
@@ -2,7 +2,7 @@
 
 /* Modified to run with the GNU shell Apr 25, 1988 by bfox. */
 
-/* Copyright (C) 1987, 1988, 1989, 1990, 1991 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -138,12 +138,7 @@ static void
 test_syntax_error (format, arg)
      char *format, *arg;
 {
-  if (interactive_shell == 0)
-    fprintf (stderr, "%s: ", get_name_for_error ());
-  fprintf (stderr, "%s: ", argv[0]);
-  fprintf (stderr, format, arg);
-  fprintf (stderr, "\n");
-  fflush (stderr);
+  builtin_error (format, arg);
   test_exit (TEST_ERREXIT_STATUS);
 }
 
@@ -181,7 +176,7 @@ test_stat (path, finfo)
   if (path[0] == '/' && path[1] == 'd' && strncmp (path, "/dev/fd/", 8) == 0)
     {
 #if !defined (HAVE_DEV_FD)
-      long fd;
+      intmax_t fd;
       int r;
 
       if (legal_number (path + 8, &fd) && fd == (int)fd)
@@ -395,24 +390,23 @@ filecomp (s, t, op)
      int op;
 {
   struct stat st1, st2;
+  int r1, r2;
 
-  if (test_stat (s, &st1) < 0)
+  if ((r1 = test_stat (s, &st1)) < 0)
     {
-      st1.st_mtime = 0;
       if (op == EF)
        return (FALSE);
     }
-  if (test_stat (t, &st2) < 0)
+  if ((r2 = test_stat (t, &st2)) < 0)
     {
-      st2.st_mtime = 0;
       if (op == EF)
        return (FALSE);
     }
   
   switch (op)
     {
-    case OT: return (st1.st_mtime < st2.st_mtime);
-    case NT: return (st1.st_mtime > st2.st_mtime);
+    case OT: return (r1 < r2 || (r2 == 0 && st1.st_mtime < st2.st_mtime));
+    case NT: return (r1 > r2 || (r1 == 0 && st1.st_mtime > st2.st_mtime));
     case EF: return ((st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino));
     }
   return (FALSE);
@@ -423,7 +417,7 @@ arithcomp (s, t, op, flags)
      char *s, *t;
      int op, flags;
 {
-  long l, r;
+  intmax_t l, r;
   int expok;
 
   if (flags & TEST_ARITHEXP)
@@ -558,7 +552,7 @@ static int
 unary_operator ()
 {
   char *op;
-  long r;
+  intmax_t r;
 
   op = argv[pos];
   if (test_unop (op) == 0)
@@ -594,7 +588,7 @@ int
 unary_test (op, arg)
      char *op, *arg;
 {
-  long r;
+  intmax_t r;
   struct stat stat_buf;
      
   switch (op[1])
index 5933620c2853b5ca7e78c632bf5a351f1bd76ae7..6d82f1acd1dc9aef9ca7166a01c80ba70cbc1c15 100644 (file)
@@ -59,7 +59,7 @@
 1,i+=2
 30
 1,j+=2
-./arith.tests: 1 ? 20 : x+=2: attempted assignment to non-variable (error token is "+=2")
+./arith.tests: line 108: 1 ? 20 : x+=2: attempted assignment to non-variable (error token is "+=2")
 20
 6
 6,5,3
 36
 62
 63
-./arith.tests: 3425#56: illegal arithmetic base (error token is "3425#56")
+./arith.tests: line 143: 3425#56: illegal arithmetic base (error token is "3425#56")
 0
-./arith.tests: 7 = 43 : attempted assignment to non-variable (error token is "= 43 ")
-./arith.tests: 2#44: value too great for base (error token is "2#44")
-./arith.tests: 44 / 0 : division by 0 (error token is " ")
-./arith.tests: let: jv += $iv: syntax error: operand expected (error token is "$iv")
-./arith.tests: jv += $iv : syntax error: operand expected (error token is "$iv ")
-./arith.tests: let: rv = 7 + (43 * 6: missing `)' (error token is "6")
-./arith.tests: 0#4: bad number (error token is "0#4")
-./arith.tests: 2#110#11: bad number (error token is "2#110#11")
+./arith.tests: line 149: 7 = 43 : attempted assignment to non-variable (error token is "= 43 ")
+./arith.tests: line 150: 2#44: value too great for base (error token is "2#44")
+./arith.tests: line 151: 44 / 0 : division by 0 (error token is " ")
+./arith.tests: line 152: let: jv += $iv: syntax error: operand expected (error token is "$iv")
+./arith.tests: line 153: jv += $iv : syntax error: operand expected (error token is "$iv ")
+./arith.tests: line 154: let: rv = 7 + (43 * 6: missing `)' (error token is "6")
+./arith.tests: line 158: 0#4: bad number (error token is "0#4")
+./arith.tests: line 159: 2#110#11: bad number (error token is "2#110#11")
 abc
 def
 ghi
@@ -96,15 +96,15 @@ ok
 6
 1
 0
-./arith.tests: 4 + : syntax error: operand expected (error token is " ")
+./arith.tests: line 177: 4 + : syntax error: operand expected (error token is " ")
 16
-./arith.tests: 4 ? : 3 + 5 : expression expected (error token is ": 3 + 5 ")
-./arith.tests: 1 ? 20 : `:' expected for conditional expression (error token is " ")
-./arith.tests: 4 ? 20 : : expression expected (error token is " ")
+./arith.tests: line 182: 4 ? : 3 + 5 : expression expected (error token is ": 3 + 5 ")
+./arith.tests: line 183: 1 ? 20 : `:' expected for conditional expression (error token is " ")
+./arith.tests: line 184: 4 ? 20 : : expression expected (error token is " ")
 9
-./arith.tests: 0 && B=42 : attempted assignment to non-variable (error token is "=42 ")
+./arith.tests: line 190: 0 && B=42 : attempted assignment to non-variable (error token is "=42 ")
 9
-./arith.tests: 1 || B=88 : attempted assignment to non-variable (error token is "=88 ")
+./arith.tests: line 193: 1 || B=88 : attempted assignment to non-variable (error token is "=88 ")
 9
 0
 9
@@ -130,20 +130,20 @@ ok
 4
 4
 7
-./arith.tests: 7-- : syntax error: operand expected (error token is " ")
-./arith.tests: --x=7 : attempted assignment to non-variable (error token is "=7 ")
-./arith.tests: ++x=7 : attempted assignment to non-variable (error token is "=7 ")
-./arith.tests: x++=7 : attempted assignment to non-variable (error token is "=7 ")
-./arith.tests: x--=7 : attempted assignment to non-variable (error token is "=7 ")
+./arith.tests: line 241: 7-- : syntax error: operand expected (error token is " ")
+./arith.tests: line 243: --x=7 : attempted assignment to non-variable (error token is "=7 ")
+./arith.tests: line 244: ++x=7 : attempted assignment to non-variable (error token is "=7 ")
+./arith.tests: line 246: x++=7 : attempted assignment to non-variable (error token is "=7 ")
+./arith.tests: line 247: x--=7 : attempted assignment to non-variable (error token is "=7 ")
 4
 7
 -7
 7
 7
 8 12
-./arith.tests: ((: x=9 y=41 : syntax error in expression (error token is "y=41 ")
-./arith.tests: a b: syntax error in expression (error token is "b")
-./arith.tests: ((: a b: syntax error in expression (error token is "b")
+./arith.tests: line 265: ((: x=9 y=41 : syntax error in expression (error token is "y=41 ")
+./arith.tests: line 269: a b: syntax error in expression (error token is "b")
+./arith.tests: line 270: ((: a b: syntax error in expression (error token is "b")
 42
 42
 42
index b337656180a68cc428a36f7993eae94f00ab38e2..bda49d86e9d5805fa991a8ea0e76f89fab16e6be 100644 (file)
@@ -1,5 +1,6 @@
-./array.tests: array assign: line 10: syntax error near unexpected token `&'
-./array.tests: array assign: line 10: `first & second'
+
+./array.tests: line 15: syntax error near unexpected token `&'
+./array.tests: line 15: `test=(first & second)'
 1
 abcde
 abcde
@@ -20,7 +21,7 @@ hello world
 11
 3
 bdef hello world test expression
-./array.tests: readonly: `a[5]': not a valid identifier
+./array.tests: line 74: readonly: `a[5]': not a valid identifier
 declare -ar a='([1]="" [2]="bdef" [5]="hello world" [6]="test expression")'
 declare -ar c='()'
 declare -ar a='([1]="" [2]="bdef" [5]="hello world" [6]="test expression")'
@@ -35,25 +36,25 @@ declare -ar c='()'
 declare -a d='([1]="" [2]="bdef" [5]="hello world" [6]="test" [9]="ninth element")'
 declare -a e='([0]="test")'
 declare -a f='([0]="" [1]="bdef" [2]="hello world" [3]="test" [4]="ninth element")'
-./array.tests: a: readonly variable
-./array.tests: b[]: bad array subscript
-./array.tests: b[*]: bad array subscript
-./array.tests: ${b[   ]}: bad substitution
-./array.tests: c[-2]: bad array subscript
-./array.tests: c: bad array subscript
+./array.tests: line 98: a: readonly variable
+./array.tests: line 100: b[]: bad array subscript
+./array.tests: line 101: b[*]: bad array subscript
+./array.tests: line 102: ${b[   ]}: bad substitution
+./array.tests: line 104: c[-2]: bad array subscript
+./array.tests: line 105: c: bad array subscript
 
-./array.tests: d[7]: cannot assign list to array member
-./array.tests: []=abcde: bad array subscript
-./array.tests: [*]=last: cannot assign to non-numeric index
-./array.tests: [-65]=negative: bad array subscript
+./array.tests: line 107: d[7]: cannot assign list to array member
+./array.tests: line 109: []=abcde: bad array subscript
+./array.tests: line 109: [*]=last: cannot assign to non-numeric index
+./array.tests: line 109: [-65]=negative: bad array subscript
 declare -a DIRSTACK='()'
 declare -ar a='([1]="" [2]="bdef" [5]="hello world" [6]="test expression")'
 declare -a b='([0]="this" [1]="is" [2]="a" [3]="test" [4]="" [5]="/etc/passwd")'
 declare -ar c='()'
 declare -a d='([1]="test test")'
 declare -a f='([0]="" [1]="bdef" [2]="hello world" [3]="test" [4]="ninth element")'
-./array.tests: unset: ps1: not an array variable
-./array.tests: declare: c: cannot destroy array variables in this way
+./array.tests: line 117: unset: ps1: not an array variable
+./array.tests: line 121: declare: c: cannot destroy array variables in this way
 this of
 this is a test of read using arrays
 this test
@@ -88,6 +89,10 @@ bin bin ucb bin . sbin sbin
 bin
 / / / / / /
 /
+argv[1] = <bin>
+argv[1] = </>
+argv[1] = <sbin>
+argv[1] = </>
 \bin \usr/bin \usr/ucb \usr/local/bin . \sbin \usr/sbin
 \bin \usr\bin \usr\ucb \usr\local\bin . \sbin \usr\sbin
 \bin \usr\bin \usr\ucb \usr\local\bin . \sbin \usr\sbin
@@ -102,7 +107,7 @@ grep [ 123 ] *
 6 7 9 5
 length = 3
 value = new1 new2 new3
-./array.tests: narray: unbound variable
+./array.tests: line 237: narray: unbound variable
 
 a b c d e f g
 for case if then else
@@ -110,19 +115,15 @@ for case if then else
 12 14 16 18 20
 4414758999202
 aaa bbb
-./array.tests: array assign: line 263: syntax error near unexpected token `for'
-./array.tests: array assign: line 263: `a b c for case if then else'
-./array.tests: array assign: line 265: syntax error near unexpected token `for'
-./array.tests: array assign: line 265: `for case if then else'
-./array.tests: array assign: line 267: syntax error near unexpected token `<>'
-./array.tests: array assign: line 267: ` <> < > ! '
-./array.tests: array assign: line 268: syntax error near unexpected token `[1]=<>'
-./array.tests: array assign: line 268: ` [1]=<> [2]=< [3]=> [4]=! '
+./array.tests: line 277: syntax error near unexpected token `<>'
+./array.tests: line 277: `metas=( <> < > ! )'
+./array.tests: line 278: syntax error near unexpected token `<>'
+./array.tests: line 278: `metas=( [1]=<> [2]=< [3]=> [4]=! )'
 abc 3
+case 4
+abc case if then else 5
+abc case if then else 5
 0
-abc 1
-abc 1
-0
-0
-1
-1
+case 4
+case if then else 5
+case if then else 5
index 85dae0d45d6ba21482b86c3182269bc7ae99a749..afa7556a8d3b194d15f8b54e390e586be6c08aca 100644 (file)
@@ -6,6 +6,11 @@ set +a
 # The calls to egrep -v are to filter out builtin array variables that are
 # automatically set and possibly contain values that vary.
 
+# first make sure we handle the basics
+x=()
+echo ${x[@]}
+unset x
+
 # this should be an error
 test=(first & second)
 echo $?
@@ -171,6 +176,10 @@ echo ${xpath[@]##*/}
 echo ${xpath[0]##*/}
 echo ${xpath[@]%%[!/]*}
 echo ${xpath[0]%%[!/]*}
+recho ${xpath##*/}
+recho ${xpath%%[!/]*}
+recho ${xpath[5]##*/}
+recho ${xpath[5]%%[!/]*}
 
 # let's try to make it a DOS-style path
 
@@ -259,11 +268,12 @@ declare -a ddd=(aaa
 bbb)
 echo ${ddd[@]}
 
-# errors
+# errors until post-bash-2.05a; now reserved words are OK
 foo=(a b c for case if then else)
 
 foo=(for case if then else)
 
+# errors
 metas=( <> < > ! )
 metas=( [1]=<> [2]=< [3]=> [4]=! )
 
index 0cb71f9e8fa69c63bdbd836bb8aa4a9cb76b4bc5..9d7bb0ee2aef1d3c4544e367e5c64b94d76e0c01 100644 (file)
@@ -105,9 +105,9 @@ m n o p
 /tmp/bash-dir-a
 /tmp/bash-dir-a
 /tmp/bash-dir-a
-./source5.sub: /tmp/source-notthere: No such file or directory
+./source5.sub: line 10: /tmp/source-notthere: No such file or directory
 after bad source 1
-./source5.sub: /tmp/source-notthere: No such file or directory
+./source5.sub: line 17: /tmp/source-notthere: No such file or directory
 AVAR
 foo
 foo
@@ -118,15 +118,15 @@ AVAR
 foo
 declare -x foo=""
 declare -x FOO="\$\$"
-./builtins.tests: declare: FOO: not found
+./builtins.tests: line 219: declare: FOO: not found
 declare -x FOO="\$\$"
 ok
 ok
-./builtins.tests: kill: bad signal number: 4096
+./builtins.tests: line 251: kill: 4096: invalid signal specification
 1
 a\n\n\nb
 a
 
 
 b
-./builtins.tests: exit: bad non-numeric arg `status'
+./builtins.tests: line 260: exit: status: numeric argument required
index a14ed9e795a65f6d9a0c60760a3399c17a7cac1e..58972ff13548104933080abc768d8beb79ffd114 100644 (file)
@@ -23,7 +23,7 @@ returns: 0
 returns: 1
 returns: 1
 returns: 0
-./cond.tests: [[: 4+: syntax error: operand expected (error token is "+")
+./cond.tests: line 101: [[: 4+: syntax error: operand expected (error token is "+")
 returns: 1
 returns: 0
 returns: 0
index fcd04b8755aed43cd36cbd3bda4a094008c1b3bd..73a006ceb0e44daaf92e5321a322d748f596785e 100644 (file)
@@ -1,13 +1,13 @@
-./dstack.tests: pushd: /tmp/xxx-notthere: No such file or directory
-./dstack.tests: pushd: no other directory
-./dstack.tests: popd: directory stack empty
-./dstack.tests: pushd: -m: bad argument
+./dstack.tests: line 6: pushd: /tmp/xxx-notthere: No such file or directory
+./dstack.tests: line 9: pushd: no other directory
+./dstack.tests: line 10: popd: directory stack empty
+./dstack.tests: line 13: pushd: -m: invalid number
 pushd: usage: pushd [dir | +N | -N] [-n]
-./dstack.tests: popd: -m: bad argument
+./dstack.tests: line 14: popd: -m: invalid number
 popd: usage: popd [+N | -N] [-n]
-./dstack.tests: dirs: -m: bad argument
+./dstack.tests: line 15: dirs: -m: invalid number
 dirs: usage: dirs [-clpv] [+N] [-N]
-./dstack.tests: dirs: unknown option: 7
+./dstack.tests: line 16: dirs: 7: invalid option
 dirs: usage: dirs [-clpv] [+N] [-N]
 /
 ok
@@ -31,12 +31,12 @@ ok
 /tmp
 /usr
 /usr
-./dstack.tests: dirs: 9: bad directory stack index
-./dstack.tests: dirs: 9: bad directory stack index
-./dstack.tests: pushd: +9: bad directory stack index
-./dstack.tests: pushd: -9: bad directory stack index
-./dstack.tests: popd: +9: bad directory stack index
-./dstack.tests: popd: -9: bad directory stack index
+./dstack.tests: line 58: dirs: 9: directory stack index out of range
+./dstack.tests: line 58: dirs: 9: directory stack index out of range
+./dstack.tests: line 59: pushd: +9: directory stack index out of range
+./dstack.tests: line 59: pushd: -9: directory stack index out of range
+./dstack.tests: line 60: popd: +9: directory stack index out of range
+./dstack.tests: line 60: popd: -9: directory stack index out of range
 /tmp /etc /
 /tmp /etc /
 /tmp /etc /
index 8c5a724ec4e139b2c0bf2083a7ba8088a75c16d5..e2e8ad0438b2dbe4659c8a09a1ad46c424ce3fb7 100644 (file)
-./errors.tests: alias: illegal option: -x
+./errors.tests: line 17: alias: -x: invalid option
 alias: usage: alias [-p] [name[=value] ... ]
-./errors.tests: unalias: illegal option: -x
+./errors.tests: line 18: unalias: -x: invalid option
 unalias: usage: unalias [-a] [name ...]
-./errors.tests: alias: `hoowah' not found
-./errors.tests: unalias: `hoowah': not an alias
-./errors.tests: `1': not a valid identifier
+./errors.tests: line 19: alias: hoowah: not found
+./errors.tests: line 20: unalias: hoowah: not found
+./errors.tests: line 23: `1': not a valid identifier
 declare -fr func
-./errors.tests: func: readonly function
-./errors.tests: unset: illegal option: -x
+./errors.tests: line 36: func: readonly function
+./errors.tests: line 39: unset: -x: invalid option
 unset: usage: unset [-f] [-v] [name ...]
-./errors.tests: unset: func: cannot unset: readonly function
-./errors.tests: declare: func: readonly function
-./errors.tests: unset: XPATH: cannot unset: readonly variable
-./errors.tests: unset: `/bin/sh': not a valid identifier
-./errors.tests: unset: cannot simultaneously unset a function and a variable
-./errors.tests: declare: unknown option: `-z'
-declare: usage: declare [-afFrxi] [-p] name[=value] ...
-./errors.tests: declare: `-z': not a valid identifier
-./errors.tests: declare: `/bin/sh': not a valid identifier
-./errors.tests: declare: cannot use `-f' to make functions
-./errors.tests: exec: illegal option: -i
+./errors.tests: line 42: unset: func: cannot unset: readonly function
+./errors.tests: line 45: declare: func: readonly function
+./errors.tests: line 49: unset: XPATH: cannot unset: readonly variable
+./errors.tests: line 52: unset: `/bin/sh': not a valid identifier
+./errors.tests: line 55: unset: cannot simultaneously unset a function and a variable
+./errors.tests: line 58: declare: -z: invalid option
+declare: usage: declare [-afFirtx] [-p] name[=value] ...
+./errors.tests: line 60: declare: `-z': not a valid identifier
+./errors.tests: line 61: declare: `/bin/sh': not a valid identifier
+./errors.tests: line 65: declare: cannot use `-f' to make functions
+./errors.tests: line 68: exec: -i: invalid option
 exec: usage: exec [-cl] [-a name] file [redirection ...]
-./errors.tests: export: XPATH: not a function
-./errors.tests: break: only meaningful in a `for', `while', or `until' loop
-./errors.tests: continue: only meaningful in a `for', `while', or `until' loop
-./errors.tests: shift: bad non-numeric arg `label'
-./errors.tests: shift: too many arguments
-./errors.tests: let: expression expected
-./errors.tests: local: can only be used in a function
-./errors.tests: logout: not login shell: use `exit'
-./errors.tests: hash: notthere: not found
-./errors.tests: hash: illegal option: -v
-hash: usage: hash [-r] [-p pathname] [-t] [name ...]
-./errors.tests: hash: hashing disabled
-./errors.tests: export: `AA[4]': not a valid identifier
-./errors.tests: readonly: `AA[4]': not a valid identifier
-./errors.tests: [-2]: bad array subscript
-./errors.tests: AA: readonly variable
-./errors.tests: AA: readonly variable
-./errors.tests: shift: shift count must be <= $#
-./errors.tests: shift: shift count must be >= 0
-./errors.tests: shopt: no_such_option: unknown shell option name
-./errors.tests: shopt: no_such_option: unknown shell option name
-./errors.tests: umask: `09' is not an octal number from 000 to 777
-./errors.tests: umask: bad character in symbolic mode: :
-./errors.tests: umask: bad symbolic mode operator: :
-./errors.tests: umask: illegal option: -i
+./errors.tests: line 72: export: XPATH: not a function
+./errors.tests: line 75: break: only meaningful in a `for', `while', or `until' loop
+./errors.tests: line 76: continue: only meaningful in a `for', `while', or `until' loop
+./errors.tests: line 79: shift: label: numeric argument required
+./errors.tests: line 84: shift: too many arguments
+./errors.tests: line 90: let: expression expected
+./errors.tests: line 93: local: can only be used in a function
+./errors.tests: line 96: logout: not login shell: use `exit'
+./errors.tests: line 99: hash: notthere: not found
+./errors.tests: line 102: hash: -v: invalid option
+hash: usage: hash [-lr] [-p pathname] [-dt] [name ...]
+./errors.tests: line 106: hash: hashing disabled
+./errors.tests: line 109: export: `AA[4]': not a valid identifier
+./errors.tests: line 110: readonly: `AA[4]': not a valid identifier
+./errors.tests: line 113: [-2]: bad array subscript
+./errors.tests: line 117: AA: readonly variable
+./errors.tests: line 121: AA: readonly variable
+./errors.tests: line 129: shift: 5: shift count out of range
+./errors.tests: line 130: shift: -2: shift count out of range
+./errors.tests: line 133: shopt: no_such_option: invalid shell option name
+./errors.tests: line 134: shopt: no_such_option: invalid shell option name
+./errors.tests: line 137: umask: 09: octal number out of range
+./errors.tests: line 138: umask: `:': invalid symbolic mode character
+./errors.tests: line 139: umask: `:': invalid symbolic mode operator
+./errors.tests: line 142: umask: -i: invalid option
 umask: usage: umask [-p] [-S] [mode]
-./errors.tests: umask: bad character in symbolic mode: u
-./errors.tests: VAR: readonly variable
-./errors.tests: declare: VAR: readonly variable
-./errors.tests: declare: VAR: readonly variable
-./errors.tests: declare: unset: not found
-./errors.tests: VAR: readonly variable
+./errors.tests: line 146: umask: `u': invalid symbolic mode character
+./errors.tests: line 155: VAR: readonly variable
+./errors.tests: line 158: declare: VAR: readonly variable
+./errors.tests: line 159: declare: VAR: readonly variable
+./errors.tests: line 161: declare: unset: not found
+./errors.tests: line 164: VAR: readonly variable
 ./errors.tests: command substitution: line 2: syntax error: unexpected end of file
 ./errors.tests: command substitution: line 1: syntax error near unexpected token `done'
 ./errors.tests: command substitution: line 1: ` for z in 1 2 3; done '
-./errors.tests: cd: HOME not set
-./errors.tests: cd: /tmp/xyz.bash: No such file or directory
-./errors.tests: cd: OLDPWD not set
-./errors.tests: cd: /bin/sh: Not a directory
-./errors.tests: cd: /tmp/cd-notthere: No such file or directory
-./errors.tests: .: filename argument required
+./errors.tests: line 171: cd: HOME not set
+./errors.tests: line 172: cd: /tmp/xyz.bash: No such file or directory
+./errors.tests: line 174: cd: OLDPWD not set
+./errors.tests: line 175: cd: /bin/sh: Not a directory
+./errors.tests: line 177: cd: /tmp/cd-notthere: No such file or directory
+./errors.tests: line 180: .: filename argument required
 .: usage: . filename
-./errors.tests: source: filename argument required
+./errors.tests: line 181: source: filename argument required
 source: usage: source filename
-./errors.tests: .: illegal option: -i
+./errors.tests: line 184: .: -i: invalid option
 .: usage: . filename
-./errors.tests: set: unknown option: q
-./errors.tests: enable: sh: not a shell builtin
-./errors.tests: enable: bash: not a shell builtin
-./errors.tests: shopt: cannot set and unset shell options simultaneously
-./errors.tests: read: var: invalid timeout specification
-./errors.tests: read: `/bin/sh': not a valid identifier
-./errors.tests: VAR: readonly variable
-./errors.tests: readonly: illegal option: -x
-readonly: usage: readonly [-anf] [name ...] or readonly -p
-./errors.tests: eval: illegal option: -i
+./errors.tests: line 187: set: -q: invalid option
+set: usage: set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
+./errors.tests: line 190: enable: sh: not a shell builtin
+./errors.tests: line 190: enable: bash: not a shell builtin
+./errors.tests: line 193: shopt: cannot set and unset shell options simultaneously
+./errors.tests: line 196: read: var: invalid timeout specification
+./errors.tests: line 199: read: `/bin/sh': not a valid identifier
+./errors.tests: line 202: VAR: readonly variable
+./errors.tests: line 205: readonly: -x: invalid option
+readonly: usage: readonly [-anf] [name[=value] ...] or readonly -p
+./errors.tests: line 208: eval: -i: invalid option
 eval: usage: eval [arg ...]
-./errors.tests: command: illegal option: -i
+./errors.tests: line 209: command: -i: invalid option
 command: usage: command [-pVv] command [arg ...]
-./errors.tests: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
-./errors.tests: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
-./errors.tests: trap: NOSIG: not a signal specification
-./errors.tests: trap: illegal option: -s
+./errors.tests: line 1: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
+./errors.tests: line 1: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
+./errors.tests: line 216: trap: NOSIG: invalid signal specification
+./errors.tests: line 219: trap: -s: invalid option
 trap: usage: trap [arg] [signal_spec ...] or trap -l
-./errors.tests: return: can only `return' from a function or sourced script
-./errors.tests: break: loop count must be > 0
-./errors.tests: continue: loop count must be > 0
-./errors.tests: builtin: bash: not a shell builtin
-./errors.tests: bg: no job control
-./errors.tests: fg: no job control
-./errors.tests: kill: -s requires an argument
-./errors.tests: kill: bad signal spec `S'
-./errors.tests: kill: `': not a pid or valid job spec
+./errors.tests: line 225: return: can only `return' from a function or sourced script
+./errors.tests: line 229: break: 0: loop count out of range
+./errors.tests: line 233: continue: 0: loop count out of range
+./errors.tests: line 238: builtin: bash: not a shell builtin
+./errors.tests: line 242: bg: no job control
+./errors.tests: line 243: fg: no job control
+./errors.tests: line 246: kill: -s: option requires an argument
+./errors.tests: line 248: kill: S: invalid signal specification
+./errors.tests: line 250: kill: `': not a pid or valid job spec
 kill: usage: kill [-s sigspec | -n signum | -sigspec] [pid | job]... or kill -l [sigspec]
-./errors.tests: set: trackall: unknown option name
-./errors.tests: `!!': not a valid identifier
+./errors.tests: line 255: set: trackall: invalid option name
+./errors.tests: line 262: `!!': not a valid identifier
index 98fe41ed980beb93c006cd35d5398a095b0a262f..0121ed4b3759ffbdd13e6fe9abfdebbb5ae01ea2 100644 (file)
@@ -4,36 +4,36 @@ aa bb cc dd ee
 after exec1.sub with args: 0
 
 after exec1.sub without args: 0
-./execscript: notthere: command not found
+./execscript: line 20: notthere: command not found
 127
 notthere: notthere: No such file or directory
 127
 /bin/sh: /bin/sh: cannot execute binary file
 126
-./execscript: /: is a directory
+./execscript: line 32: /: is a directory
 126
 /: /: cannot execute binary file
 126
-./execscript: .: /: is a directory
+./execscript: line 39: .: /: is a directory
 1
 127
 0
 this is bashenv
-./exec3.sub: /tmp/bash-notthere: No such file or directory
-./exec3.sub: exec: /tmp/bash-notthere: cannot execute: No such file or directory
+./exec3.sub: line 3: /tmp/bash-notthere: No such file or directory
+./exec3.sub: line 3: exec: /tmp/bash-notthere: cannot execute: No such file or directory
 126
-./execscript: notthere: No such file or directory
+./execscript: line 61: notthere: No such file or directory
 127
-./execscript: notthere: No such file or directory
+./execscript: line 64: notthere: No such file or directory
 127
-./execscript: notthere: No such file or directory
+./execscript: line 67: notthere: No such file or directory
 127
 this is sh
 this is sh
 unset
 ok
 5
-./exec5.sub: exec: bash-notthere: not found
+./exec5.sub: line 4: exec: bash-notthere: not found
 127
 this is ohio-state
 0
index 24d7d485295b62142150a9117e8cb98863955096..92261038ace34b38b310994b736ea3c1c7231409 100644 (file)
@@ -2,7 +2,7 @@ getopts: usage: getopts optstring name [arg]
 2
 getopts: usage: getopts optstring name [arg]
 2
-./getopts.tests: getopts: illegal option: -a
+./getopts.tests: line 10: getopts: -a: invalid option
 getopts: usage: getopts optstring name [arg]
 -a specified
 -b bval specified
@@ -52,5 +52,5 @@ remaining args:
 -a specified
 remaining args: 
 0
-./getopts7.sub: getopts: `opt-var': not a valid identifier
+./getopts7.sub: line 4: getopts: `opt-var': not a valid identifier
 remaining args: 
index f2c4d33450c4bfb01673daccb8ede644e47bb4f5..dfb987ecfc242a1b51ccc2e2037d85a9a61b71ea 100644 (file)
@@ -369,11 +369,10 @@ GLOBIGNORE=
 expect '<man/man1/bash.1>'
 recho */man*/bash.*
 
-builtin cd /
-rm -rf $TESTDIR
-
 # this is for the benefit of pure coverage, so it writes the pcv file
-# in the right place
+# in the right place, and for gprof
 builtin cd $MYDIR
 
+rm -rf $TESTDIR
+
 exit 0
diff --git a/tests/herestr.right b/tests/herestr.right
new file mode 100644 (file)
index 0000000..c20c0a5
--- /dev/null
@@ -0,0 +1,26 @@
+abcde
+yo
+hot damn
+what a fabulous window treatment
+double"quote
+onetwothree
+first second third
+f1 () 
+{ 
+    cat <<< "abcde";
+    cat <<< "yo";
+    cat <<< "$a $b";
+    cat <<< 'what a fabulous window treatment';
+    cat <<< 'double"quote'
+}
+f2 () 
+{ 
+    cat <<< onetwothree
+}
+f3 () 
+{ 
+    cat <<< "$@"
+}
+echo $(echo hi)
+echo ho
+echo off to work we go
diff --git a/tests/herestr.tests b/tests/herestr.tests
new file mode 100644 (file)
index 0000000..4f3ac68
--- /dev/null
@@ -0,0 +1,36 @@
+a=hot
+b=damn
+f1()
+{
+cat <<< "abcde"
+
+cat <<< "yo"
+
+cat <<< "$a $b"
+
+cat <<< 'what a fabulous window treatment'
+
+cat <<< 'double"quote'
+}
+
+f2()
+{
+cat <<< onetwothree
+}
+
+f3()
+{
+cat <<< "$@"
+}
+
+f1
+f2
+f3 first second third
+
+typeset -f
+
+cat <<< 'echo $(echo hi)'
+
+cat <<< "echo ho"
+
+cat <<< "echo $(echo off to work we go)"
index b270a5fa842dbe7403a60309ed0c3db72bdc1cfa..ff6453e5f106c6d97ecfc7ab4168456d3f750b8a 100644 (file)
@@ -1,5 +1,5 @@
 echo $BASH_VERSION
-./histexp.tests: history: !!:z: history expansion failed
+./histexp.tests: line 22: history: !!:z: history expansion failed
     1  for i in one two three; do echo $i; done
     2  /bin/sh -c 'echo this is $0'
     3  ls
index deb6b862b71c8f98edbfa3431d84be474490e738..619d34ca3c1e1addc7dd337d2ad58ab86bf637a7 100644 (file)
@@ -1,7 +1,7 @@
-./history.tests: history: illegal option: -x
+./history.tests: line 4: history: -x: invalid option
 history: usage: history [-c] [-d offset] [n] or history -awrn [filename] or history -ps arg [arg...]
-./history.tests: history: cannot use more than one of -anrw
-./history.tests: fc: illegal option: -v
+./history.tests: line 6: history: cannot use more than one of -anrw
+./history.tests: line 9: fc: -v: invalid option
 fc: usage: fc [-e ename] [-nlr] [first] [last] or fc -s [pat=rep] [cmd]
     1  for i in one two three; do echo $i; done
     2  /bin/sh -c 'echo this is $0'
@@ -97,8 +97,7 @@ line 2 for history
 6       HISTFILE=/tmp/newhistory
 7       echo displaying \$HISTFILE after history -a
 8       cat $HISTFILE
-./history.tests: fc: history specification out of range
-./history.tests: fc: history specification out of range
+./history.tests: line 73: fc: history specification out of range
    14  set -H
    15  echo line 2 for history
    16  unset HISTSIZE
@@ -108,5 +107,5 @@ echo xx xb xc
 xx xb xc
 echo 44 48 4c
 44 48 4c
-./history.tests: fc: no command found
+./history.tests: line 88: fc: no command found
 1
index 4a218c301b7a4837e0de3951fcfe9847f9ee127e..76ea56190e77d3addb3a59e4a8af0cd8a5f116a9 100644 (file)
@@ -70,7 +70,6 @@ unset HISTFILE
 fc -l 4
 fc -l 4 8
 
-fc -l 502
 fc -l one=two three=four 502
 
 history 4
diff --git a/tests/ifs-1.right b/tests/ifs-1.right
deleted file mode 100644 (file)
index af0abb2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-a:b:c
diff --git a/tests/ifs-1.test b/tests/ifs-1.test
deleted file mode 100644 (file)
index a153ce9..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-OIFS="$IFS"
-IFS=":$IFS"
-eval foo="a:b:c"
-IFS="$OIFS"
-echo $foo
diff --git a/tests/ifs-2.right b/tests/ifs-2.right
deleted file mode 100644 (file)
index af0abb2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-a:b:c
diff --git a/tests/ifs-2.test b/tests/ifs-2.test
deleted file mode 100644 (file)
index 3249f1b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-OIFS=$IFS
-IFS=":$IFS"
-foo=$(echo a:b:c)
-IFS=$OIFS
-
-for i in $foo
-do
-       echo $i
-done
diff --git a/tests/ifs-3.right b/tests/ifs-3.right
deleted file mode 100644 (file)
index af0abb2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-a:b:c
diff --git a/tests/ifs-3.test b/tests/ifs-3.test
deleted file mode 100644 (file)
index 4693792..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-OIFS=$IFS
-IFS=":$IFS"
-foo=`echo a:b:c`
-IFS=$OIFS
-
-for i in $foo
-do
-       echo $i
-done
diff --git a/tests/ifs.right b/tests/ifs.right
new file mode 100644 (file)
index 0000000..512f6ee
--- /dev/null
@@ -0,0 +1,10 @@
+a:b:c
+a:b:c
+a:b:c
+a b c d e
+a:b:c:d:e
+a b c d e
+a:b:c:d:e
+a:b:c:d:e
+a b c d e
+a b c d e
diff --git a/tests/ifs.tests b/tests/ifs.tests
new file mode 100644 (file)
index 0000000..763e2a0
--- /dev/null
@@ -0,0 +1,61 @@
+OIFS="$IFS"
+IFS=":$IFS"
+eval foo="a:b:c"
+IFS="$OIFS"
+echo $foo
+
+OIFS=$IFS
+IFS=":$IFS"
+foo=$(echo a:b:c)
+IFS=$OIFS
+
+for i in $foo
+do
+       echo $i
+done
+
+OIFS=$IFS
+IFS=":$IFS"
+foo=`echo a:b:c`
+IFS=$OIFS
+
+for i in $foo
+do
+       echo $i
+done
+
+DEFIFS=$' \t\n'
+
+# local copy of IFS that shadows global version
+function f
+{
+       typeset IFS=:
+
+       echo $1
+}
+
+function ff
+{
+       echo $1
+}
+
+f a:b:c:d:e
+x=a:b:c:d:e
+echo $x
+
+IFS=: ff a:b:c:d:e
+echo $x
+
+# doesn't get word split
+IFS=$DEFIFS
+# variable assignment doesn't use new value for word splitting
+IFS=: echo $x
+# but does this time because of the eval
+IFS=: eval echo \$x
+
+# in posix mode, assignments preceding special builtins and functions are global
+set -o posix
+IFS=: export x
+echo $x
+
+IFS="$DEFIFS"
index 9a10c35c9c388c525115431246c22cd3deaaa00d..12bf8a34aca2f98e9f71b47df207a9bf1df83e88 100644 (file)
@@ -1,4 +1,4 @@
-./jobs2.sub: fg: job %1 started without job control
+./jobs2.sub: line 9: fg: job %1 started without job control
 fg: 1
 Waiting for job 0
 job 0 returns 0
@@ -17,19 +17,19 @@ job 6 returns 0
 Waiting for job 7
 job 7 returns 0
 0
-./jobs.tests: wait: job control not enabled
-./jobs.tests: fg: no job control
+./jobs.tests: line 15: wait: no job control
+./jobs.tests: line 20: fg: no job control
 wait-for-pid
 wait-errors
-./jobs.tests: wait: `1-1' is not a pid or valid job spec
-./jobs.tests: wait: `-4' is not a pid or valid job spec
+./jobs.tests: line 33: wait: `1-1': not a pid or valid job spec
+./jobs.tests: line 34: wait: `-4': not a pid or valid job spec
 wait-for-background-pids
 async list wait-for-background-pids
 async list wait for child
 forked
 wait-when-no-children
 wait-for-job
-./jobs.tests: wait: %2: no such job
+./jobs.tests: line 56: wait: %2: no such job
 127
 async list wait-for-job
 forked
@@ -42,19 +42,19 @@ sleep 5
 fg-bg 4
 sleep 5
 fg-bg 5
-./jobs.tests: fg: %2: no such job
-./jobs.tests: bg: bg background job?
+./jobs.tests: line 83: fg: %2: no such job
+./jobs.tests: line 84: bg: bg background job?
 fg-bg 6
-./jobs.tests: fg: illegal option: -s
+./jobs.tests: line 91: fg: -s: invalid option
 fg: usage: fg [job_spec]
-./jobs.tests: bg: illegal option: -s
+./jobs.tests: line 92: bg: -s: invalid option
 bg: usage: bg [job_spec]
-./jobs.tests: disown: illegal option: -s
+./jobs.tests: line 97: disown: -s: invalid option
 disown: usage: disown [-h] [-ar] [jobspec ...]
-./jobs.tests: disown: %1: no such job
-./jobs.tests: disown: %2: no such job
+./jobs.tests: line 101: disown: %1: no such job
+./jobs.tests: line 104: disown: %2: no such job
 wait-for-non-child
-./jobs.tests: wait: pid 1 is not a child of this shell
+./jobs.tests: line 107: wait: pid 1 is not a child of this shell
 127
 3 -- 1 2 3 -- 1 - 2 - 3
 [1]   Running                 sleep 300 &
@@ -64,8 +64,8 @@ running jobs:
 [1]   Running                 sleep 300 &
 [2]-  Running                 sleep 350 &
 [3]+  Running                 sleep 400 &
-./jobs.tests: kill: %4: no such job
-./jobs.tests: jobs: no such job %4
+./jobs.tests: line 123: kill: %4: no such job
+./jobs.tests: line 125: jobs: %4: no such job
 current job:
 [3]+  Running                 sleep 400 &
 previous job:
index 194fdeb582a9186deffc4dfe3f1cf4afab74e561..a98585656810077ce6b1698acc95a1f31acc6b31 100644 (file)
@@ -41,8 +41,8 @@ argv[1] = <\ $HOME>
 argv[1] = <\ \ $HOME>
 argv[1] = <'bar'>
 argv[1] = <'bar'>
-argv[1] = <*@*>
-argv[1] = <*@*>
+argv[1] = <*@>
+argv[1] = <*@>
 argv[1] = <*@>
 argv[1] = <*@>
 argv[1] = <*@*>
@@ -108,7 +108,7 @@ argv[3] = <c>
 argv[4] = <d>
 argv[5] = <e>
 argv[6] = <f>
-./more-exp.tests: abc=def: command not found
+./more-exp.tests: line 269: abc=def: command not found
 argv[1] = <a b c d e>
 argv[1] = <a>
 argv[2] = <b>
@@ -184,13 +184,13 @@ argv[1] = <1>
 argv[1] = <5>
 argv[1] = <5>
 argv[1] = <0>
-./more-exp.tests: ${#:}: bad substitution
-./more-exp.tests: ${#/}: bad substitution
-./more-exp.tests: ${#%}: bad substitution
-./more-exp.tests: ${#=}: bad substitution
-./more-exp.tests: ${#+}: bad substitution
-./more-exp.tests: ${#1xyz}: bad substitution
-./more-exp.tests: #: %: syntax error: operand expected (error token is "%")
+./more-exp.tests: line 420: ${#:}: bad substitution
+./more-exp.tests: line 422: ${#/}: bad substitution
+./more-exp.tests: line 424: ${#%}: bad substitution
+./more-exp.tests: line 426: ${#=}: bad substitution
+./more-exp.tests: line 428: ${#+}: bad substitution
+./more-exp.tests: line 430: ${#1xyz}: bad substitution
+./more-exp.tests: line 433: #: %: syntax error: operand expected (error token is "%")
 argv[1] = <0>
 argv[1] = <a+b>
 argv[1] = <+>
index a2b7f77c56e5beddfaa50ab4988853b150c6e158..6c821a57257082d0bbdd322b75fdda418cd32bd8 100644 (file)
@@ -96,9 +96,9 @@ expect "<'bar'>"
 recho "${fox='$foo'}"
 
 P='*@*'
-expect '<*@*>'
+expect '<*@>'
 recho "${P%"*"}"
-expect '<*@*>'
+expect '<*@>'
 recho "${P%'*'}"
 
 expect '<*@>'
index db66ab042c8090cc5072aca8c2c0e1cb4dd147e5..95f16d99302f1ec95fc0440224f02240fb5c606c 100644 (file)
@@ -3,7 +3,7 @@ argv[1] = <foo>
 argv[1] = </usr/homes/chet>
 argv[1] = </usr/homes/chet>
 argv[1] = </usr/homes/chet>
-./new-exp.tests: HOME: }: syntax error: operand expected (error token is "}")
+./new-exp.tests: line 24: HOME: }: syntax error: operand expected (error token is "}")
 unset
 argv[1] = </usr/homes/chet>
 argv[1] = </usr/homes/chet>
@@ -12,8 +12,8 @@ argv[1] = </usr/homes/chet>
 argv[1] = </usr/homes/chet>
 argv[1] = </usr/homes/chet>
 argv[1] = </usr/homes/chet>
-argv[1] = <*@*>
-argv[1] = <*@*>
+argv[1] = <*@>
+argv[1] = <*@>
 argv[1] = <@*>
 argv[1] = <)>
 argv[1] = <")">
@@ -59,8 +59,8 @@ argv[1] = <4>
 argv[1] = <op>
 argv[1] = <abcdefghijklmnop>
 argv[1] = <abcdefghijklmnop>
-./new-exp.tests: ABX: unbound variable
-./new-exp.tests: $6: cannot assign in this way
+./new-exp.tests: line 172: ABX: unbound variable
+./new-exp.tests: line 176: $6: cannot assign in this way
 argv[1] = <xxcde>
 argv[1] = <axxde>
 argv[1] = <abxyz>
@@ -162,11 +162,11 @@ lines.
 This-string-has-multiple-lines.
 this is a test of proc subst
 this is test 2
-./new-exp2.sub: /tmp/bashtmp.x*: No such file or directory
-./new-exp2.sub: /tmp/redir-notthere: No such file or directory
+./new-exp2.sub: line 31: /tmp/bashtmp.x*: No such file or directory
+./new-exp2.sub: line 35: /tmp/redir-notthere: No such file or directory
 1
 argv[1] = <6>
-./new-exp.tests: ${#:}: bad substitution
+./new-exp.tests: line 277: ${#:}: bad substitution
 argv[1] = <'>
 argv[1] = <">
 argv[1] = <"hello">
@@ -233,7 +233,7 @@ argv[1] = <oneonetwo>
 argv[1] = <onetwo>
 argv[1] = <two>
 argv[1] = <oneonetwo>
-./new-exp.tests: -2: substring expression < 0
+./new-exp.tests: line 421: -2: substring expression < 0
 argv[1] = <defghi>
 argv[1] = <efghi>
 argv[1] = <e*docrine>
@@ -395,13 +395,13 @@ argv[6] = <w>
 argv[7] = <x>
 argv[8] = <y>
 argv[9] = <z>
-./new-exp.tests: $9: unbound variable
-./new-exp.tests: 9: unbound variable
-./new-exp.tests: UNSET: unbound variable
-./new-exp.tests: UNSET: unbound variable
-./new-exp.tests: UNSET: unbound variable
-./new-exp.tests: UNSET: unbound variable
-./new-exp.tests: UNSET: unbound variable
+./new-exp.tests: line 480: $9: unbound variable
+./new-exp.tests: line 481: 9: unbound variable
+./new-exp.tests: line 482: UNSET: unbound variable
+./new-exp.tests: line 483: UNSET: unbound variable
+./new-exp.tests: line 484: UNSET: unbound variable
+./new-exp.tests: line 485: UNSET: unbound variable
+./new-exp.tests: line 486: UNSET: unbound variable
 argv[1] = <5>
 argv[1] = <#>
 argv[1] = <#>
@@ -419,10 +419,10 @@ argv[4] = <_QUILL>
 argv[5] = <_QUOTA>
 argv[6] = <_QUOTE>
 argv[1] = <_QUANTITY-_QUART-_QUEST-_QUILL-_QUOTA-_QUOTE>
-./new-exp3.sub: ${!_Q* }: bad substitution
-./new-exp3.sub: ${!1*}: bad substitution
-./new-exp3.sub: ${!@*}: bad substitution
-./new-exp.tests: ${$(($#-1))}: bad substitution
+./new-exp3.sub: line 19: ${!_Q* }: bad substitution
+./new-exp3.sub: line 24: ${!1*}: bad substitution
+./new-exp3.sub: line 26: ${!@*}: bad substitution
+./new-exp.tests: line 503: ${$(($#-1))}: bad substitution
 argv[1] = <a>
 argv[2] = <b>
 argv[3] = <c>
@@ -439,5 +439,36 @@ argv[1] = <a>
 argv[1] = <a>
 argv[2] = <b>
 argv[1] = <>
-./new-exp.tests: $(($# - 2)): substring expression < 0
-./new-exp.tests: ABXD: parameter unset
+./new-exp.tests: line 522: $(($# - 2)): substring expression < 0
+argv[1] = <bin>
+argv[2] = <bin>
+argv[3] = <ucb>
+argv[4] = <bin>
+argv[5] = <.>
+argv[6] = <sbin>
+argv[7] = <sbin>
+argv[1] = </>
+argv[2] = </>
+argv[3] = </>
+argv[4] = </>
+argv[5] = </>
+argv[6] = </>
+argv[1] = <bin>
+argv[2] = <usr/bin>
+argv[3] = <usr/ucb>
+argv[4] = <usr/local/bin>
+argv[5] = <.>
+argv[6] = <sbin>
+argv[7] = <usr/sbin>
+argv[1] = </bin>
+argv[2] = </usr/bin>
+argv[3] = </usr/ucb>
+argv[4] = </usr/local/bin>
+argv[5] = <.>
+argv[6] = </sbin>
+argv[7] = </usr/sbin>
+argv[1] = </full/path/to>
+argv[1] = </>
+argv[1] = <full/path/to/x16>
+argv[1] = <x16>
+./new-exp.tests: line 542: ABXD: parameter unset
index 4a33c35498516fba9bba84bdaf2ece31c64cb2aa..89b921361598f58f5a87caad2f7d0a0ac9c9d126 100644 (file)
@@ -44,9 +44,9 @@ expect "<$HOME>"
 recho "$(echo "$(echo "${HOME}")")"
 
 P=*@*
-expect '<*@*>'
+expect '<*@>'
 recho "${P%"*"}"       # 
-expect '<*@*>'
+expect '<*@>'
 recho "${P%'*'}"       # 
 expect '<@*>'
 recho "${P#\*}"                # should be @*
@@ -521,6 +521,22 @@ recho "${*:1:0}"
 set a
 recho ${@:1:$(($# - 2))}
 
+XPATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:.:/sbin:/usr/sbin
+set $( IFS=: ; echo $XPATH ) 
+
+recho ${@##*/}
+recho ${@%%[!/]*}
+
+recho ${@#/*}
+recho ${@%*/}
+
+set /full/path/to/x16 /another/full/path
+
+recho ${1%/*}
+recho ${1%%[!/]*}
+recho ${1#*/}
+recho ${1##*/}
+
 # this must be last!
 expect $0: 'ABXD: parameter unset'
 recho ${ABXD:?"parameter unset"}
diff --git a/tests/nquote1.right b/tests/nquote1.right
new file mode 100644 (file)
index 0000000..26e16b9
--- /dev/null
@@ -0,0 +1,121 @@
+argv[1] = <a>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <1>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <b>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <c>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <d>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <a>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <1>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <b>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <c>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <d>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <a>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <1>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <b>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <c>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <d>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <a>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <1>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <b>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <c>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <d>
+argv[2] = <a^Ab>
+argv[3] = <3>
+argv[1] = <e1>
+argv[2] = <v^A^A>
+argv[1] = <e2>
+argv[2] = <v^A^A>
+argv[1] = <e3>
+argv[2] = <v^A^A>
+argv[1] = <e4>
+argv[2] = <v^A^A>
+argv[1] = <a1>
+argv[2] = <uv^A^A>
+argv[1] = <a2>
+argv[2] = <uv^A^A>
+argv[1] = <a3>
+argv[2] = <uv^A^Awx>
+argv[3] = <uv^A^Awx>
+argv[1] = <a4>
+argv[2] = <uv^A^Awx>
+argv[3] = <uv^A^Awx>
+argv[1] = <p1>
+argv[2] = <uv^A^Awx>
+argv[3] = <uv^A^Awx>
+argv[1] = <p2>
+argv[2] = <uv^A^Awx>
+argv[3] = <uv^A^Awx>
+argv[1] = <p1>
+argv[2] = <uv^A^Awx>
+argv[3] = <uv^A^Awx>
+argv[1] = <p2>
+argv[2] = <uv^A^Awx uv^A^Awx>
+argv[1] = <uv^A^Awx>
+argv[1] = <uv^A^Awx>
+argv[1] = <uv^A^Awx>
+^A
+^A
+^B
+argv[1] = <f1>
+argv[2] = <v^Aw>
+argv[1] = <f2>
+argv[2] = <v^Aw>
+argv[1] = <a1>
+argv[2] = <uv^Aw>
+argv[1] = <a2>
+argv[2] = <uv^Aw>
+argv[1] = <a3>
+argv[2] = <uv^Aw>
+argv[1] = <a4>
+argv[2] = <uv^Aw>
+argv[1] = <e1>
+argv[2] = <uv^Aw>
+argv[1] = <e2>
+argv[2] = <uv^Aw>
+argv[1] = <d1>
+argv[2] = <^Aw>
+argv[1] = <d2>
+argv[2] = <^Aw>
+argv[1] = <@1>
+argv[2] = <uv^Aw^Axy>
+argv[3] = <uv^Aw^Axy>
+argv[1] = <@2>
+argv[2] = <uv^Aw^Axy>
+argv[3] = <uv^Aw^Axy>
diff --git a/tests/nquote1.tests b/tests/nquote1.tests
new file mode 100644 (file)
index 0000000..0970e77
--- /dev/null
@@ -0,0 +1,97 @@
+a=$'a\001b'
+
+set $a
+
+b=$a
+c=$1
+d="$1"
+
+e=$'uv\001\001wx'
+
+recho a $a ${#a}
+recho 1 $1 ${#1}
+recho b $b ${#b}
+recho c $c ${#c}
+recho d $d ${#d}
+
+recho a ${a} ${#a}
+recho 1 ${1} ${#1}
+recho b ${b} ${#b}
+recho c ${c} ${#c}
+recho d ${d} ${#d}
+
+recho a "$a" ${#a}
+recho 1 "$1" ${#1}
+recho b "$b" ${#b}
+recho c "$c" ${#c}
+recho d "$d" ${#d}
+
+recho a "${a}" ${#a}
+recho 1 "${1}" ${#1}
+recho b "${b}" ${#b}
+recho c "${c}" ${#c}
+recho d "${d}" ${#d}
+
+set $e
+
+recho e1 ${e:1:3}
+recho e2 "${e:1:3}"
+recho e3 ${1:1:3}
+recho e4 "${1:1:3}"
+
+arr[0]=$e
+arr[1]=$e
+
+recho a1 ${arr:0:4}
+recho a2 "${arr:0:4}"
+
+recho a3 ${arr[@]:0:2}
+recho a4 "${arr[@]:0:2}"
+
+set $e $e
+
+recho p1 ${@:1:2}
+recho p2 "${@:1:2}"
+
+recho p1 ${*:1:2}
+recho p2 "${*:1:2}"
+
+recho $e
+
+recho 'uv\ 1\ 1wx'
+
+f='uv\ 1\ 1wx'
+
+recho $f
+
+echo -en "\01" | cat -v
+echo
+
+huhu() { echo "$1"; };
+
+huhu $(echo -en "\01") | cat -v
+huhu $(echo -en "\02") | cat -v
+
+f=$'uv\001w\001xy'
+
+set $f $f
+
+recho f1 ${f:1:3}
+recho f2 "${f:1:3}"
+
+arr[0]=$f
+arr[1]=$f
+
+recho a1 ${arr:0:4}
+recho a2 "${arr:0:4}"
+recho a3 ${arr[0]:0:4}
+recho a4 "${arr[0]:0:4}"
+
+recho e1 ${f:0:4}
+recho e2 "${f:0:4}"
+
+recho d1 ${1:2:2}
+recho d2 "${1:2:2}"
+
+recho @1 ${@:1:2}
+recho @2 "${@:1:2}"
diff --git a/tests/nquote2.right b/tests/nquote2.right
new file mode 100644 (file)
index 0000000..e7fb21e
--- /dev/null
@@ -0,0 +1,76 @@
+argv[1] = <a^Ab>
+argv[1] = <uv^A^Awx>
+argv[1] = <aAb>
+argv[1] = <aAb>
+argv[1] = <uvA^Awx>
+argv[1] = <uvA^Awx>
+argv[1] = <a^AB>
+argv[1] = <a^AB>
+argv[1] = <uv^A^AWx>
+argv[1] = <uv^A^AWx>
+argv[1] = <aAb>
+argv[1] = <aAb>
+argv[1] = <uvAAwx>
+argv[1] = <uvAAwx>
+argv[1] = <a^AB>
+argv[1] = <a^AB>
+argv[1] = <uv^A^AWx>
+argv[1] = <uv^A^AWx>
+argv[1] = <uvA^Awx>
+argv[2] = <uvA^Awx>
+argv[1] = <uvA^Awx>
+argv[2] = <uvA^Awx>
+argv[1] = <uv^A^AWx>
+argv[2] = <uv^A^AWx>
+argv[1] = <uv^A^AWx>
+argv[2] = <uv^A^AWx>
+argv[1] = <uvAAwx>
+argv[2] = <uvAAwx>
+argv[1] = <uvAAwx>
+argv[2] = <uvAAwx>
+argv[1] = <uv^A^AWx>
+argv[2] = <uv^A^AWx>
+argv[1] = <uv^A^AWx>
+argv[2] = <uv^A^AWx>
+argv[1] = <a^Ab>
+argv[1] = <uv^A^Awx>
+argv[1] = <aAb>
+argv[1] = <aAb>
+argv[1] = <uvA^Awx>
+argv[1] = <uvA^Awx>
+argv[1] = <a^AB>
+argv[1] = <a^AB>
+argv[1] = <uv^A^AWx>
+argv[1] = <uv^A^AWx>
+argv[1] = <aAb>
+argv[1] = <aAb>
+argv[1] = <uvAAwx>
+argv[1] = <uvAAwx>
+argv[1] = <a^AB>
+argv[1] = <a^AB>
+argv[1] = <uv^A^AWx>
+argv[1] = <uv^A^AWx>
+argv[1] = <aAb>
+argv[2] = <uvA^Awx>
+argv[1] = <aAb>
+argv[2] = <uvA^Awx>
+argv[1] = <a^AB>
+argv[2] = <uv^A^Awx>
+argv[1] = <a^AB>
+argv[2] = <uv^A^Awx>
+argv[1] = <a^Ab>
+argv[2] = <uv^A^AWx>
+argv[1] = <a^Ab>
+argv[2] = <uv^A^AWx>
+argv[1] = <aAb>
+argv[2] = <uvAAwx>
+argv[1] = <aAb>
+argv[2] = <uvAAwx>
+argv[1] = <a^AB>
+argv[2] = <uv^A^Awx>
+argv[1] = <a^AB>
+argv[2] = <uv^A^Awx>
+argv[1] = <a^Ab>
+argv[2] = <uv^A^AWx>
+argv[1] = <a^Ab>
+argv[2] = <uv^A^AWx>
diff --git a/tests/nquote2.tests b/tests/nquote2.tests
new file mode 100644 (file)
index 0000000..c07bd9b
--- /dev/null
@@ -0,0 +1,82 @@
+a=$'a\001b'
+
+e=$'uv\001\001wx'
+
+recho $a
+recho $e
+
+recho ${a/$'\001'/A}
+recho "${a/$'\001'/A}"
+recho ${e/$'\001'/A}
+recho "${e/$'\001'/A}"
+
+recho ${a/b/B}
+recho "${a/b/B}"
+recho ${e/w/W}
+recho "${e/w/W}"
+
+recho ${a//$'\001'/A}
+recho "${a//$'\001'/A}"
+recho ${e//$'\001'/A}
+recho "${e//$'\001'/A}"
+
+recho ${a//b/B}
+recho "${a//b/B}"
+recho ${e//w/W}
+recho "${e//w/W}"
+
+# pos params pat subst
+
+set $e $e
+
+recho ${@/$'\001'/A}
+recho "${@/$'\001'/A}"
+recho ${@/w/W}
+recho "${@/w/W}"
+
+recho ${@//$'\001'/A}
+recho "${@//$'\001'/A}"
+recho ${@//w/W}
+recho "${@//w/W}"
+
+arr[0]=$a
+arr[1]=$e
+
+recho ${arr[0]}
+recho ${arr[1]}
+
+recho ${arr[0]/$'\001'/A}
+recho "${arr[0]/$'\001'/A}"
+recho ${arr[1]/$'\001'/A}
+recho "${arr[1]/$'\001'/A}"
+
+recho ${arr[0]/b/B}
+recho "${arr[0]/b/B}"
+recho ${arr[1]/w/W}
+recho "${arr[1]/w/W}"
+
+recho ${arr[0]//$'\001'/A}
+recho "${arr[0]//$'\001'/A}"
+recho ${arr[1]//$'\001'/A}
+recho "${arr[1]//$'\001'/A}"
+
+recho ${arr[0]//b/B}
+recho "${arr[0]//b/B}"
+recho ${arr[1]//w/W}
+recho "${arr[1]//w/W}"
+
+recho ${arr[@]/$'\001'/A}
+recho "${arr[@]/$'\001'/A}"
+
+recho ${arr[@]/b/B}
+recho "${arr[@]/b/B}"
+recho ${arr[@]/w/W}
+recho "${arr[@]/w/W}"
+
+recho ${arr[@]//$'\001'/A}
+recho "${arr[@]//$'\001'/A}"
+
+recho ${arr[@]//b/B}
+recho "${arr[@]//b/B}"
+recho ${arr[@]//w/W}
+recho "${arr[@]//w/W}"
diff --git a/tests/nquote3.right b/tests/nquote3.right
new file mode 100644 (file)
index 0000000..d01eecc
--- /dev/null
@@ -0,0 +1,60 @@
+argv[1] = <uv^A^A>
+argv[1] = <uv^A^A>
+argv[1] = <uv^A>
+argv[1] = <uv^A>
+argv[1] = <^Ab>
+argv[1] = <^Ab>
+argv[1] = <xy>
+argv[1] = <xy>
+argv[1] = <xy>
+argv[1] = <uv^Aw^Axy>
+argv[1] = <uv^A>
+argv[1] = <uv^A>
+argv[1] = <^Awx>
+argv[1] = <^Awx>
+argv[1] = <xy>
+argv[1] = <xy>
+argv[1] = <xy>
+argv[1] = <uv^Aw^Axy>
+argv[1] = <uv^A>
+argv[1] = <uv^A>
+argv[1] = <^Awx>
+argv[1] = <^Awx>
+argv[1] = <uv^A>
+argv[1] = <uv^A>
+argv[1] = <^Awx>
+argv[1] = <^Awx>
+argv[1] = <xy>
+argv[1] = <xy>
+argv[1] = <xy>
+argv[1] = <xy>
+argv[1] = <uv^Aw^Axy>
+argv[1] = <uv^Aw^Axy>
+argv[1] = <uv^A>
+argv[1] = <uv^A>
+argv[1] = <^Awx>
+argv[1] = <^Awx>
+argv[1] = <uv^A>
+argv[2] = <uv^Aw>
+argv[1] = <uv^A>
+argv[2] = <uv^Aw>
+argv[1] = <^Awx>
+argv[2] = <w^Axy>
+argv[1] = <^Awx>
+argv[2] = <w^Axy>
+argv[1] = <wx>
+argv[2] = <xy>
+argv[1] = <uv^A^Awx>
+argv[2] = <uv^Aw^Axy>
+argv[1] = <uv^A>
+argv[2] = <uv^Aw>
+argv[1] = <uv^A>
+argv[2] = <uv^Aw>
+argv[1] = <^Awx>
+argv[2] = <w^Axy>
+argv[1] = <^Awx>
+argv[2] = <w^Axy>
+argv[1] = <wx>
+argv[2] = <xy>
+argv[1] = <uv^A^Awx>
+argv[2] = <uv^Aw^Axy>
diff --git a/tests/nquote3.tests b/tests/nquote3.tests
new file mode 100644 (file)
index 0000000..a83ff56
--- /dev/null
@@ -0,0 +1,85 @@
+a=$'a\001b'
+
+set $a
+
+b=$a
+c=$1
+d="$1"
+
+e=$'uv\001\001wx'
+f=$'uv\001w\001xy'
+
+set $e $e
+
+recho ${e%%??}
+recho "${e%%??}"
+
+recho ${e%%???}
+recho "${e%%???}"
+
+recho ${a#?}
+recho "${a#?}"
+
+# simple variables
+
+recho ${f##*$'\001'}
+recho "${f##*$'\001'}"
+recho ${f##*'\ 1'}               # literal ^A
+recho "${f##*'^A'}"            # two characters, `^' and `A'
+
+recho ${e%$'\001'*}
+recho "${e%$'\001'*}"
+recho ${e#*$'\001'}
+recho "${e#*$'\001'}"
+
+# array members
+
+arr[0]=$e
+arr[1]=$f
+
+recho ${arr[1]##*$'\001'}
+recho "${arr[1]##*$'\001'}"
+recho ${arr[1]##*'\ 1'}          # literal ^A
+recho "${arr[1]##*'^A'}"       # two characters, `^' and `A'
+
+recho ${arr[0]%$'\001'*}
+recho "${arr[0]%$'\001'*}"
+recho ${arr[0]#*$'\001'}
+recho "${arr[0]#*$'\001'}"
+
+recho ${arr%$'\001'*}
+recho "${arr%$'\001'*}"
+recho ${arr#*$'\001'}
+recho "${arr#*$'\001'}"
+
+# positional parameters
+
+set $e $f
+
+recho ${2##*$'\001'}
+recho "${2##*$'\001'}"
+recho ${2##*'\ 1'}               # literal ^A
+recho "${2##*'\ 1'}"             # literal ^A
+recho ${2##*'^A'}              # two characters, `^' and `A'
+recho "${2##*'^A'}"            # two characters, `^' and `A'
+
+recho ${1%$'\001'*}
+recho "${1%$'\001'*}"
+recho ${1#*$'\001'}
+recho "${1#*$'\001'}"
+
+recho ${@%$'\001'*}
+recho "${@%$'\001'*}"
+recho ${@#*$'\001'}
+recho "${@#*$'\001'}"
+recho ${@##*'\ 1'}               # literal ^A
+recho "${@##*'^A'}"            # two characters, `^' and `A'
+
+# arrays treated as a whole
+
+recho ${arr[@]%$'\001'*}
+recho "${arr[@]%$'\001'*}"
+recho ${arr[@]#*$'\001'}
+recho "${arr[@]#*$'\001'}"
+recho ${arr[@]##*'\ 1'}          # literal ^A
+recho "${arr[@]##*'^A'}"               # two characters, `^' and `A'
index 80d1a7e2e53091a121265bd292fd15a8d44dcf71..d6011f4d5c08039f3f533f0d0b8e8d15915e062c 100644 (file)
Binary files a/tests/printf.right and b/tests/printf.right differ
index b9eeffba1ae7e62fff92b409fdb5e21bcd8d6eb0..dcc869d987617b27efd48e46158377378516ed0d 100644 (file)
@@ -37,11 +37,15 @@ a = abc
 4
 1
 4
-./read2.sub: read: -3: invalid timeout specification
+./read2.sub: line 13: read: -3: invalid timeout specification
 1
 4
 abcde
-./read3.sub: read: -1: invalid number specification
+./read3.sub: line 4: read: -1: invalid number
 abc
 ab
 #
+while read -u 3 var
+do
+echo "$var"
+done 3<$0
index f974324cd92327fdc54bf9efaeed40049246c959..e8b7e8f8173ca7774644f5e9a6383c23310ffe2d 100644 (file)
@@ -87,3 +87,6 @@ ${THIS_SH} ./read2.sub
 
 # test read -n nchars behavior
 ${THIS_SH} ./read3.sub
+
+# test read -u fd behavior
+${THIS_SH} ./read4.sub
diff --git a/tests/read4.sub b/tests/read4.sub
new file mode 100644 (file)
index 0000000..80bc9fc
--- /dev/null
@@ -0,0 +1,4 @@
+while read -u 3 var
+do
+       echo "$var"
+done 3<$0
index 09272fe3d8d899f0902ffd0bb124bc9e73b3c1e8..283bdcdbd9a8063af8bc8b162c64e83053b23efa 100644 (file)
@@ -1,9 +1,9 @@
 abc
-./redir.tests: /tmp/redir-test: cannot overwrite existing file
+./redir.tests: line 13: /tmp/redir-test: cannot overwrite existing file
 abc
 def
 def
-./redir.tests: $z: ambiguous redirect
+./redir.tests: line 29: $z: ambiguous redirect
 Point 1
 Point 2
 to a
@@ -24,8 +24,8 @@ read line3 "cd"
 read line4 "daemon"
 from stdin: aa
 to stdout
-./redir4.sub: $fd: ambiguous redirect
-./redir4.sub: $fd: ambiguous redirect
+./redir4.sub: line 32: $fd: ambiguous redirect
+./redir4.sub: line 33: $fd: ambiguous redirect
 /tmp/err-and-out:
 to stdout
 to stderr
@@ -44,4 +44,47 @@ kl
 ab
 cd
 cd
-./redir.tests: redir1.*: No such file or directory
+./redir.tests: line 152: redir1.*: No such file or directory
+# tests of ksh93-like dup-and-close redirection operators
+exec 9<$0
+
+f()
+{
+exec 5<$0
+
+exec 0<&5-
+
+while read line; do
+echo "$line"
+done
+}
+
+f
+
+typeset -f f
+
+# make sure it was closed
+read -u 5 foo
+echo after read
+
+exec 5<&0
+
+exec <&-
+
+read abcde
+
+exec 0<&9-
+read line
+echo $line
+f () 
+{ 
+    exec 5<$0;
+    exec 0<&5-;
+    while read line; do
+        echo "$line";
+    done
+}
+./redir5.sub: line 20: read: 5: invalid file descriptor: Bad file descriptor
+after read
+./redir5.sub: line 27: read: read error: 0: Bad file descriptor
+# tests of ksh93-like dup-and-close redirection operators
index 3e6e87669e95f9cca25b86b721a49ea8cc04b95e..e80b7309956018b859ed9aef73784ce0359491b6 100644 (file)
@@ -150,3 +150,6 @@ echo $l2
 # a single filename
 set -o posix
 cat < redir1.*
+
+# test ksh93 dup-and-close (move fd) redirections
+${THIS_SH} ./redir5.sub
diff --git a/tests/redir5.sub b/tests/redir5.sub
new file mode 100644 (file)
index 0000000..5d59d39
--- /dev/null
@@ -0,0 +1,31 @@
+# tests of ksh93-like dup-and-close redirection operators
+exec 9<$0
+
+f()
+{
+exec 5<$0
+
+exec 0<&5-
+
+while read line; do
+       echo "$line"
+done
+}
+
+f
+
+typeset -f f
+
+# make sure it was closed
+read -u 5 foo
+echo after read
+
+exec 5<&0
+
+exec <&-
+
+read abcde
+
+exec 0<&9-
+read line
+echo $line
index d5c37ec3102ffe7548bfa7ced77116eb509cafd9..e673b94d494c73411ffbef6f3282c883727dbb31 100644 (file)
@@ -1,13 +1,13 @@
-./rsh.tests: cd: restricted
-./rsh.tests: PATH: readonly variable
-./rsh.tests: SHELL: readonly variable
-./rsh.tests: /bin/sh: restricted: cannot specify `/' in command names
-./rsh.tests: .: ./source.sub3: restricted
-./rsh.tests: /tmp/restricted: restricted: cannot redirect output
-./rsh.tests: /tmp/restricted: restricted: cannot redirect output
-./rsh.tests: command: restricted: cannot use -p
-./rsh.tests: set: unknown option: +r
+./rsh.tests: line 9: cd: restricted
+./rsh.tests: line 10: PATH: readonly variable
+./rsh.tests: line 11: SHELL: readonly variable
+./rsh.tests: line 12: /bin/sh: restricted: cannot specify `/' in command names
+./rsh.tests: line 14: .: ./source.sub3: restricted
+./rsh.tests: line 17: /tmp/restricted: restricted: cannot redirect output
+./rsh.tests: line 21: /tmp/restricted: restricted: cannot redirect output
+./rsh.tests: line 26: command: -p: restricted
+./rsh.tests: line 28: set: +r: invalid option
 set: usage: set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
-./rsh.tests: set: restricted: unknown option name
-./rsh.tests: exec: restricted
+./rsh.tests: line 29: set: restricted: invalid option name
+./rsh.tests: line 31: exec: restricted
 ./rsh.tests: after exec
diff --git a/tests/run-herestr b/tests/run-herestr
new file mode 100644 (file)
index 0000000..8c5b36d
--- /dev/null
@@ -0,0 +1,2 @@
+${THIS_SH} ./herestr.tests > /tmp/xx 2>&1
+diff /tmp/xx herestr.right && rm -f /tmp/xx
diff --git a/tests/run-ifs b/tests/run-ifs
new file mode 100644 (file)
index 0000000..3f9d820
--- /dev/null
@@ -0,0 +1,2 @@
+${THIS_SH} ./ifs.tests > /tmp/xx 2>&1
+diff /tmp/xx ifs.right && rm -f /tmp/xx
diff --git a/tests/run-ifs-tests b/tests/run-ifs-tests
deleted file mode 100644 (file)
index a1c6149..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# show that IFS is only applied to the result of expansions
-#
-${THIS_SH} ifs-1.test > /tmp/xx
-diff /tmp/xx ./ifs-1.right
-
-${THIS_SH} ifs-2.test > /tmp/xx
-diff /tmp/xx ./ifs-2.right
-
-${THIS_SH} ifs-3.test > /tmp/xx
-diff /tmp/xx ./ifs-3.right
-
-rm -f /tmp/xx
diff --git a/tests/run-nquote1 b/tests/run-nquote1
new file mode 100644 (file)
index 0000000..a71740f
--- /dev/null
@@ -0,0 +1,4 @@
+echo "warning: several of these tests will fail if arrays have not" >&2
+echo "warning: been compiled into the shell." >&2
+${THIS_SH} ./nquote1.tests 2>&1 | grep -v '^expect' > /tmp/xx
+diff /tmp/xx nquote1.right && rm -f /tmp/xx
diff --git a/tests/run-nquote2 b/tests/run-nquote2
new file mode 100644 (file)
index 0000000..80d1a8d
--- /dev/null
@@ -0,0 +1,4 @@
+echo "warning: several of these tests will fail if arrays have not" >&2
+echo "warning: been compiled into the shell." >&2
+${THIS_SH} ./nquote2.tests 2>&1 | grep -v '^expect' > /tmp/xx
+diff /tmp/xx nquote2.right && rm -f /tmp/xx
diff --git a/tests/run-nquote3 b/tests/run-nquote3
new file mode 100644 (file)
index 0000000..45ba5f7
--- /dev/null
@@ -0,0 +1,4 @@
+echo "warning: several of these tests will fail if arrays have not" >&2
+echo "warning: been compiled into the shell." >&2
+${THIS_SH} ./nquote3.tests 2>&1 | grep -v '^expect' > /tmp/xx
+diff /tmp/xx nquote3.right && rm -f /tmp/xx
index c7a547576b6ce8ed23d5f3649f13c0b5a3038ea4..2be45dd68e0ab5406bb31a3fb1f8defa245267e1 100644 (file)
@@ -1,6 +1,7 @@
 echo "warning: the text of a system error message may vary between systems and" >&2
 echo "warning: produce diff output." >&2
 echo "warning: if the text of an error message concerning \`redir1.*' not being" >&2
-echo "warning: found produces diff output, please do not consider it a test failure" >&2
+echo "warning: found or messages concerning bad file descriptors produce diff" >&2
+echo "warning: output, please do not consider it a test failure" >&2
 ${THIS_SH} ./redir.tests > /tmp/xx 2>&1
 diff /tmp/xx redir.right && rm -f /tmp/xx
index 0f073e1726ad26b0c34c21719b268b124dca1450..51218f652a31d8f0eb3ea88a2383ca2140da7f10 100644 (file)
@@ -1,4 +1,4 @@
-./shopt.tests: shopt: illegal option: -z
+./shopt.tests: line 2: shopt: -z: invalid option
 shopt: usage: shopt [-pqsu] [-o long-option] optname [optname...]
 --
 shopt -u cdable_vars
@@ -84,124 +84,124 @@ xpg_echo          off
 --
 set +o allexport
 set -o braceexpand
+set -o emacs
 set +o errexit
 set -o hashall
 set -o histexpand
+set -o history
+set +o ignoreeof
+set -o interactive-comments
 set +o keyword
 set -o monitor
 set +o noclobber
 set +o noexec
 set +o noglob
+set +o nolog
 set +o notify
 set +o nounset
 set +o onecmd
 set +o physical
+set +o posix
 set -o privileged
 set +o verbose
-set +o xtrace
-set -o history
-set +o ignoreeof
-set -o interactive-comments
-set +o nolog
-set +o posix
-set -o emacs
 set +o vi
+set +o xtrace
 --
 allexport              off
 braceexpand            on
+emacs                  on
 errexit                off
 hashall                on
 histexpand             on
+history                on
+ignoreeof              off
+interactive-comments   on
 keyword                off
 monitor                on
 noclobber              off
 noexec                 off
 noglob                 off
+nolog                  off
 notify                 off
 nounset                off
 onecmd                 off
 physical               off
+posix                  off
 privileged             on
 verbose                off
-xtrace                 off
-history                on
-ignoreeof              off
-interactive-comments   on
-nolog                  off
-posix                  off
-emacs                  on
 vi                     off
+xtrace                 off
 --
 set +o allexport
 set -o braceexpand
+set -o emacs
 set +o errexit
 set -o hashall
 set -o histexpand
+set -o history
+set +o ignoreeof
+set -o interactive-comments
 set +o keyword
 set -o monitor
 set +o noclobber
 set +o noexec
 set +o noglob
+set +o nolog
 set +o notify
 set +o nounset
 set +o onecmd
 set +o physical
+set +o posix
 set -o privileged
 set +o verbose
-set +o xtrace
-set -o history
-set +o ignoreeof
-set -o interactive-comments
-set +o nolog
-set +o posix
-set -o emacs
 set +o vi
+set +o xtrace
 --
 set -o history
 set +o verbose
 --
 set -o braceexpand
+set -o emacs
 set -o hashall
 set -o histexpand
-set -o monitor
-set -o privileged
 set -o history
 set -o interactive-comments
-set -o emacs
+set -o monitor
+set -o privileged
 --
 set +o allexport
 set +o errexit
+set +o ignoreeof
 set +o keyword
 set +o noclobber
 set +o noexec
 set +o noglob
+set +o nolog
 set +o notify
 set +o nounset
 set +o onecmd
 set +o physical
-set +o verbose
-set +o xtrace
-set +o ignoreeof
-set +o nolog
 set +o posix
+set +o verbose
 set +o vi
+set +o xtrace
 --
 allexport              off
 errexit                off
+ignoreeof              off
 keyword                off
 noclobber              off
 noexec                 off
 noglob                 off
+nolog                  off
 notify                 off
 nounset                off
 onecmd                 off
 physical               off
-verbose                off
-xtrace                 off
-ignoreeof              off
-nolog                  off
 posix                  off
+verbose                off
 vi                     off
+xtrace                 off
 --
-./shopt.tests: shopt: xyz1: unknown shell option name
-./shopt.tests: shopt: xyz1: unknown option name
+./shopt.tests: line 93: shopt: xyz1: invalid shell option name
+./shopt.tests: line 94: shopt: xyz1: invalid option name
index 854e5dc52011114e860915dac18235733de767a3..beb3af6b233a1121d9450f14ff12f55509215e98 100644 (file)
@@ -227,48 +227,48 @@ t -G /tmp/test.group
 t -h /tmp/test.symlink
 0
 t 4+3 -eq 7
-./test.tests: test: 4+3: integer expression expected
+./test.tests: line 13: test: 4+3: integer expression expected
 2
 b 4-5 -eq 7
-./test.tests: [: 4+3: integer expression expected
+./test.tests: line 7: [: 4+3: integer expression expected
 2
 t 9 -eq 4+5
-./test.tests: test: 4+5: integer expression expected
+./test.tests: line 13: test: 4+5: integer expression expected
 2
 b 9 -eq 4+5
-./test.tests: [: 4+5: integer expression expected
+./test.tests: line 7: [: 4+5: integer expression expected
 2
 t A -eq 7
-./test.tests: test: A: integer expression expected
+./test.tests: line 13: test: A: integer expression expected
 2
 b A -eq 7
-./test.tests: [: A: integer expression expected
+./test.tests: line 7: [: A: integer expression expected
 2
 t 9 -eq B
-./test.tests: test: B: integer expression expected
+./test.tests: line 13: test: B: integer expression expected
 2
 b 9 -eq B
-./test.tests: [: B: integer expression expected
+./test.tests: line 7: [: B: integer expression expected
 2
 t ( 1 = 2
-./test.tests: test: `)' expected
+./test.tests: line 13: test: `)' expected
 2
 b ( 1 = 2
-./test.tests: [: `)' expected, found ]
+./test.tests: line 7: [: `)' expected, found ]
 2
-./test.tests: test: a: unary operator expected
+./test.tests: line 13: test: a: unary operator expected
 2
-./test.tests: test: b: binary operator expected
+./test.tests: line 13: test: b: binary operator expected
 2
-./test.tests: test: -A: unary operator expected
+./test.tests: line 13: test: -A: unary operator expected
 2
-./test.tests: test: too many arguments
+./test.tests: line 13: test: too many arguments
 2
-./test.tests: test: too many arguments
+./test.tests: line 13: test: too many arguments
 2
-./test.tests: [: missing `]'
+./test.tests: line 406: [: missing `]'
 2
-./test.tests: test: (: unary operator expected
+./test.tests: line 13: test: (: unary operator expected
 2
 t -t a
 1
index 370d9b7dfe9eb9ca7848cb323b11b1b0e9a04731..6c179d0af2efee695a1fba53effc162787b1a7bc 100644 (file)
@@ -5,8 +5,9 @@ trap -- 'echo aborting' SIGINT
 trap -- 'echo aborting' SIGQUIT
 trap -- 'echo aborting' SIGABRT
 trap -- 'echo aborting' SIGTERM
-debug line
 [20] debug
+debug line
+[22] debug
 trap -- 'echo exiting' EXIT
 trap -- 'echo aborting' SIGHUP
 trap -- 'echo aborting' SIGINT
@@ -14,10 +15,10 @@ trap -- 'echo aborting' SIGQUIT
 trap -- 'echo aborting' SIGABRT
 trap -- 'echo aborting' SIGTERM
 trap -- 'echo [$LINENO] debug' DEBUG
-[22] debug
-funcdebug line
-[2] funcdebug
 [24] debug
+func[16] funcdebug
+funcdebug line
+[26] debug
 trap -- 'echo exiting' EXIT
 trap -- 'echo aborting' SIGHUP
 trap -- 'echo aborting' SIGINT
@@ -25,7 +26,13 @@ trap -- 'echo aborting' SIGQUIT
 trap -- 'echo aborting' SIGABRT
 trap -- 'echo aborting' SIGTERM
 trap -- 'echo [$LINENO] debug' DEBUG
-[26] debug
+[28] debug
+./trap.tests[33] debug
+./trap.tests[34] debug
+func2[31] debug
+func2debug line
+./trap.tests[36] debug
+./trap.tests[38] debug
 trap -- 'echo exiting' EXIT
 trap -- 'echo aborting' SIGHUP
 trap -- 'echo aborting' SIGINT
index f34e8258c7dd7daf07c0f3a68ab862a688873af3..3e2d00dd1d1d8669b5d373d649630d56b2b74e4e 100644 (file)
@@ -12,7 +12,7 @@ trap
 
 func()
 {
-       trap 'echo [$LINENO] funcdebug' DEBUG
+       trap 'echo ${FUNCNAME:-$0}[$LINENO] funcdebug' DEBUG
        echo funcdebug line
 }
 
@@ -25,6 +25,16 @@ func
 
 trap
 
+trap 'echo ${FUNCNAME:-$0}[$LINENO] debug' DEBUG
+func2()
+{
+       echo func2debug line
+}
+declare -ft func2
+func2
+
+unset -f func2
+
 trap '' DEBUG
 
 trap
@@ -74,4 +84,3 @@ trap -p SIGCHLD
 trap SIGINT QUIT TERM
 
 trap
-
index 89b6f53636f319c6d2722bc0dd1fddb496ad9130..30f433ab1350cc159449ab3f27da63e94d0ed541 100644 (file)
@@ -1,7 +1,7 @@
-./type.tests: type: illegal option: -f
-type: usage: type [-apt] name [name ...]
-./type.tests: type: notthere: not found
-./type.tests: command: notthere: not found
+./type.tests: line 9: type: -r: invalid option
+type: usage: type [-afptP] name [name ...]
+./type.tests: line 12: type: notthere: not found
+./type.tests: line 13: command: notthere: not found
 function
 keyword
 alias
@@ -35,12 +35,12 @@ builtin
 builtin is a shell builtin
 /bin/sh
 /bin/sh is /bin/sh
-./type.tests: type: func: not found
-./type.tests: type: m: not found
+./type.tests: line 51: type: func: not found
+./type.tests: line 53: type: m: not found
 /bin/sh
 /tmp/bash
 bash is hashed (/tmp/bash)
 file
 hits   command
-   1   /bin/sh
    3   /tmp/bash
+   1   /bin/sh
index baf55fc51411e91e4c488819565384a1044ab214..706e3be36487209bfd59581cff88f5c9209a29f6 100644 (file)
@@ -6,7 +6,7 @@ unalias -a
 # this should echo nothing
 type
 # this should be a usage error
-type -f ${THIS_SH}
+type -r ${THIS_SH}
 
 # these should behave identically
 type notthere
index d477cebc31a2fe67b9925b7970a7f4728465285b..563411d380ba2e096b27dbfedc0bfd3865ae8e09 100644 (file)
@@ -31,10 +31,23 @@ declare -x ivar="42"
 hB
 braceexpand:hashall:interactive-comments
 hPB
-braceexpand:hashall:physical:interactive-comments
-declare -r SHELLOPTS="braceexpand:hashall:physical:interactive-comments"
+braceexpand:hashall:interactive-comments:physical
+declare -r SHELLOPTS="braceexpand:hashall:interactive-comments:physical"
 abcde
 20
 30
 40
 50
+|0|10|
+10
+|0|10|
+10
+|0|10|
+10
+|4|
+4
+|0|11|
+after fff3: x=4
+|0|12|
+|y|
+|y|
index 0cac0fdbaeaef3bd91678b04a617cca34190040f..d6d763d8433a86f5d42e81d9c44b64f4e537cdc1 100644 (file)
@@ -198,3 +198,6 @@ printenv FOOFOO
 # test out export behavior of variable assignments preceding builtins and
 # functions
 $THIS_SH ./varenv1.sub
+
+# more tests; bugs in bash up to version 2.05a
+$THIS_SH ./varenv2.sub
diff --git a/tests/varenv2.sub b/tests/varenv2.sub
new file mode 100644 (file)
index 0000000..b293572
--- /dev/null
@@ -0,0 +1,44 @@
+fff()
+{
+       typeset i=0 x=10
+       echo "|$i|$x|"
+       export x
+       printenv x
+}
+
+fff2()
+{
+       echo "|$x|"
+       export x
+       printenv x
+}
+
+fff3()
+{
+       typeset i=0 x="${x-10}"
+       echo "|$i|$x|"
+}
+
+fff4()
+{
+       typeset i=0 x
+       x="${x-10}"
+       echo "|$i|$x|"
+}
+
+fff5()
+{
+       z=y typeset z
+       echo "|$z|"
+}
+
+fff
+x=10 fff
+x=1 fff
+x=4 fff2
+x=11 fff3
+echo after fff3: x=$x
+x=12 fff4
+
+fff5
+z=42 fff5
diff --git a/trap.c b/trap.c
index b6850262c35a54084e0a762cfedda1de77a7a7d2..c40baf81ba508f33f856b1e24590d34958e1d7e6 100644 (file)
--- a/trap.c
+++ b/trap.c
@@ -1,7 +1,7 @@
 /* trap.c -- Not the trap command, but useful functions for manipulating
    those objects.  The trap command is in builtins/trap.def. */
 
-/* Copyright (C) 1987, 1991 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -36,7 +36,9 @@
 #include "shell.h"
 #include "input.h"     /* for save_token_state, restore_token_state */
 #include "signames.h"
+#include "builtins.h"
 #include "builtins/common.h"
+#include "builtins/builtext.h"
 
 #ifndef errno
 extern int errno;
@@ -75,6 +77,9 @@ extern int interrupt_immediately;
 extern int last_command_exit_value;
 extern int line_number;
 
+extern sh_builtin_func_t *this_shell_builtin;
+extern procenv_t wait_intr_buf;
+
 /* The list of things to do originally, before we started trapping. */
 SigHandler *original_signals[NSIG];
 
@@ -99,6 +104,9 @@ int running_trap;
    it. */
 int trap_line_number;
 
+/* The (trapped) signal received while executing in the `wait' builtin */
+int wait_signal_received;
+
 /* A value which can never be the target of a trap handler. */
 #define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps
 
@@ -178,7 +186,7 @@ signal_name (sig)
   char *ret;
 
   /* on cygwin32, signal_names[sig] could be null */
-  ret = (sig > NSIG || sig < 0) ? "bad signal number" : signal_names[sig];
+  ret = (sig >= BASH_NSIG || sig < 0) ? "bad signal number" : signal_names[sig];
   if (ret == NULL)
     ret = "unrecognized signal number";
   return ret;
@@ -192,7 +200,7 @@ int
 decode_signal (string)
      char *string;
 {
-  long sig;
+  intmax_t sig;
 
   if (legal_number (string, &sig))
     return ((sig >= 0 && sig < NSIG) ? (int)sig : NO_SIG);
@@ -321,6 +329,12 @@ trap_handler (sig)
       catch_flag = 1;
       pending_traps[sig]++;
 
+      if (interrupt_immediately && this_shell_builtin && (this_shell_builtin == wait_builtin))
+       {
+         wait_signal_received = sig;
+         longjmp (wait_intr_buf, 1);
+       }
+
       if (interrupt_immediately)
        run_pending_traps ();
 
@@ -680,7 +694,7 @@ _run_trap_internal (sig, tag)
 void
 run_debug_trap ()
 {
-  if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && (sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0)
+  if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0))
     _run_trap_internal (DEBUG_TRAP, "debug trap");
 }
 
@@ -723,6 +737,7 @@ 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
index 13dfc78acbdb5b8bbc17404f914d0b4a6d269672..4bb7a78f010d92900811040f948e63bc7da3d64f 100644 (file)
@@ -1,7 +1,7 @@
 /* I can't stand it anymore!  Please can't we just write the
    whole Unix system in lisp or something? */
 
-/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -72,6 +72,9 @@ typedef union uwp {
   } sv;
 } UNWIND_ELT;
 
+
+extern int interrupt_immediately;
+
 static void without_interrupts __P((VFunction *, char *, char *));
 static void unwind_frame_discard_internal __P((char *, char *));
 static void unwind_frame_run_internal __P((char *, char *));
@@ -84,7 +87,8 @@ static void unwind_protect_mem_internal __P((char *, char *));
 
 static UNWIND_ELT *unwind_protect_list = (UNWIND_ELT *)NULL;
 
-extern int interrupt_immediately;
+#define uwpalloc(elt)  (elt) = (UNWIND_ELT *)xmalloc (sizeof (UNWIND_ELT))
+#define uwpfree(elt)   free(elt)
 
 /* Run a function without interrupts.  This relies on the fact that the
    FUNCTION cannot change the value of interrupt_immediately.  (I.e., does
@@ -185,7 +189,7 @@ add_unwind_protect_internal (cleanup, arg)
 {
   UNWIND_ELT *elt;
 
-  elt = (UNWIND_ELT *)xmalloc (sizeof (UNWIND_ELT));
+  uwpalloc (elt);
   elt->head.next = unwind_protect_list;
   elt->head.cleanup = cleanup;
   elt->arg.v = arg;
@@ -202,7 +206,7 @@ remove_unwind_protect_internal (ignore1, ignore2)
   if (elt)
     {
       unwind_protect_list = unwind_protect_list->head.next;
-      free (elt);
+      uwpfree (elt);
     }
 }
 
@@ -236,11 +240,11 @@ unwind_frame_discard_internal (tag, ignore)
       unwind_protect_list = unwind_protect_list->head.next;
       if (elt->head.cleanup == 0 && (STREQ (elt->arg.v, tag)))
        {
-         free (elt);
+         uwpfree (elt);
          break;
        }
       else
-       free (elt);
+       uwpfree (elt);
     }
 }
 
@@ -269,7 +273,7 @@ unwind_frame_run_internal (tag, ignore)
        {
          if (tag && STREQ (elt->arg.v, tag))
            {
-             free (elt);
+             uwpfree (elt);
              break;
            }
        }
@@ -281,7 +285,7 @@ unwind_frame_run_internal (tag, ignore)
            (*(elt->head.cleanup)) (elt->arg.v);
        }
 
-      free (elt);
+      uwpfree (elt);
     }
 }
 
index 1a24d3287082435ef58cf595ee67bd989a27727c..8033a0500b30bb405f23521652e89c33cf506299 100644 (file)
@@ -29,6 +29,7 @@ extern void add_unwind_protect (); /* Not portable to arbitrary C99 hosts.  */
 extern void remove_unwind_protect __P((void));
 extern void run_unwind_protects __P((void));
 extern void clear_unwind_protect_list __P((int));
+extern void uwp_init __P((void));
 
 /* Define for people who like their code to look a certain way. */
 #define end_unwind_frame()
index 060143892ea4795f615b7716a56d212923ad193e..1f9180e83978c5bd07c1f37e69a86cc6561ee72b 100644 (file)
@@ -1,6 +1,6 @@
 /* variables.c -- Functions for hacking shell variables. */
 
-/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 #  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')
+
 /* Variables used here and defined in other files. */
 extern int posixly_correct;
 extern int line_number;
@@ -79,9 +83,12 @@ extern SHELL_VAR *this_shell_function;
 extern char *this_command_name;
 extern time_t shell_start_time;
 
-/* The list of shell variables that the user has created, or that came from
-   the environment. */
-HASH_TABLE *shell_variables = (HASH_TABLE *)NULL;
+/* 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. */
@@ -91,18 +98,9 @@ HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
    executing functions we are. */
 int variable_context = 0;
 
-/* The array of shell assignments which are made only in the environment
+/* The set of shell assignments which are made only in the environment
    for a single command. */
-char **temporary_env = (char **)NULL;
-
-/* The array of shell assignments which are in the environment for the
-   execution of a shell function. */
-char **function_env = (char **)NULL;
-
-/* The array of shell assignments which are made only in the environment
-   for the execution of a shell builtin command which may cause more than
-   one command to be executed (e.g., "eval" or "source"). */
-char **builtin_env = (char **)NULL;
+HASH_TABLE *temporary_env = (HASH_TABLE *)NULL;
 
 /* Some funky variables which are known about specially.  Here is where
    "$*", "$1", and all the cruft is kept. */
@@ -126,9 +124,6 @@ int array_needs_making = 1;
    by initialize_variables (). */
 int shell_level = 0;
 
-static char *have_local_variables;
-static int local_variable_stack_size;
-
 /* Some forward declarations. */
 static void set_machine_vars __P((void));
 static void set_home_var __P((void));
@@ -139,38 +134,89 @@ static void uidset __P((void));
 #if defined (ARRAY_VARS)
 static void make_vers_array __P((void));
 #endif
-static void initialize_dynamic_variables __P((void));
 
+static SHELL_VAR *null_assign __P((SHELL_VAR *, char *, arrayind_t));
+#if defined (ARRAY_VARS)
+static SHELL_VAR *null_array_assign __P((SHELL_VAR *, char *, arrayind_t));
+#endif
+
+static SHELL_VAR *assign_seconds __P((SHELL_VAR *, char *, arrayind_t));
+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 SHELL_VAR *assign_random __P((SHELL_VAR *, char *, arrayind_t));
+static SHELL_VAR *get_random __P((SHELL_VAR *));
 
-static int qsort_var_comp __P((SHELL_VAR **, SHELL_VAR **));
-static SHELL_VAR **all_vars __P((HASH_TABLE *));
+static SHELL_VAR *assign_lineno __P((SHELL_VAR *, char *, arrayind_t));
+static SHELL_VAR *get_lineno __P((SHELL_VAR *));
 
-static void free_variable_hash_data __P((PTR_T));
+#if defined (HISTORY)
+static SHELL_VAR *get_histcmd __P((SHELL_VAR *));
+#endif
+
+#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
+static SHELL_VAR *assign_dirstack __P((SHELL_VAR *, char *, arrayind_t));
+static SHELL_VAR *get_dirstack __P((SHELL_VAR *));
+static SHELL_VAR *init_dirstack_var __P((void));
+#endif
+
+#if defined (ARRAY_VARS)
+static SHELL_VAR *get_groupset __P((SHELL_VAR *));
+static SHELL_VAR *init_groups_var __P((void));
+#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));
+
+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 *make_new_variable __P((const char *));
+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 SHELL_VAR **_visible_names __P((HASH_TABLE *));
 static int visible_and_exported __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 *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 SHELL_VAR *shell_var_from_env_string __P((const char *, char *, int));
-static SHELL_VAR *bind_name_in_env_array __P((const char *, char *, char **));
-static SHELL_VAR *find_name_in_env_array __P((const char *, 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 SHELL_VAR *bind_tempenv_variable __P((const char *, char *));
-static void dispose_temporary_vars __P((char ***));
-static void merge_env_array __P((char **));
+static int n_shell_variables __P((void));
+static int set_context __P((SHELL_VAR *));
 
-/* Make VAR be auto-exported.  VAR is a pointer to a SHELL_VAR. */
-#define set_auto_export(var) \
-  do { var->attributes |= att_exported; array_needs_making = 1; } while (0)
+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 *));
+              
 /* Initialize the shell variables from the current environment.
    If PRIVMODE is nonzero, don't import functions from ENV or
    parse $SHELLOPTS. */
@@ -184,10 +230,14 @@ initialize_shell_variables (env, privmode)
   SHELL_VAR *temp_var;
 
   if (shell_variables == 0)
-    shell_variables = make_hash_table (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 = make_hash_table (0);
+    shell_functions = hash_create (0);
 
   for (string_index = 0; string = env[string_index++]; )
     {
@@ -209,7 +259,7 @@ initialize_shell_variables (env, privmode)
         char_index == strlen (name) */
 
       /* If exported function, define it now.  Don't import functions from
-         the environment in privileged mode. */
+        the environment in privileged mode. */
       if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
        {
          string_length = strlen (string);
@@ -241,7 +291,7 @@ initialize_shell_variables (env, privmode)
 #if defined (ARRAY_VARS)
 #  if 0
       /* Array variables may not yet be exported. */
-      else if (*string == '(' && string[1] == '[' && strchr (string, ')'))
+      else if (*string == '(' && string[1] == '[' && xstrchr (string, ')'))
        {
          string_length = 1;
          temp_string = extract_array_assignment_list (string, &string_length);
@@ -314,6 +364,7 @@ initialize_shell_variables (env, privmode)
 
   /* Don't allow IFS to be imported from the environment. */
   temp_var = bind_variable ("IFS", " \t\n");
+  setifs (temp_var);
 
   /* Magic machine types.  Pretty convenient. */
   set_machine_vars ();
@@ -371,7 +422,7 @@ initialize_shell_variables (env, privmode)
      that we are remembering commands on the history list. */
   if (remember_on_history)
     {
-      name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history");
+      name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history", 0);
 
       set_if_not ("HISTFILE", name);
       free (name);
@@ -435,6 +486,12 @@ initialize_shell_variables (env, privmode)
   initialize_dynamic_variables ();
 }
 
+/* **************************************************************** */
+/*                                                                 */
+/*          Setting values for special shell variables             */
+/*                                                                 */
+/* **************************************************************** */
+
 static void
 set_machine_vars ()
 {
@@ -570,7 +627,7 @@ adjust_shell_level (change)
      int change;
 {
   char new_level[5], *old_SHLVL;
-  long old_level;
+  intmax_t old_level;
   SHELL_VAR *temp_var;
 
   old_SHLVL = get_string_value ("SHLVL");
@@ -711,22 +768,22 @@ make_vers_array ()
   ARRAY *av;
   char *s, d[32], b[INT_STRLEN_BOUND(int) + 1];
 
-  makunbound ("BASH_VERSINFO", shell_variables);
+  unbind_variable ("BASH_VERSINFO");
 
   vv = make_new_array_variable ("BASH_VERSINFO");
   av = array_cell (vv);
   strcpy (d, dist_version);
-  s = strchr (d, '.');
+  s = xstrchr (d, '.');
   if (s)
     *s++ = '\0';
-  array_add_element (av, 0, d);
-  array_add_element (av, 1, s);
+  array_insert (av, 0, d);
+  array_insert (av, 1, s);
   s = inttostr (patch_level, b, sizeof (b));
-  array_add_element (av, 2, s);
+  array_insert (av, 2, s);
   s = inttostr (build_version, b, sizeof (b));
-  array_add_element (av, 3, s);
-  array_add_element (av, 4, release_status);
-  array_add_element (av, 5, MACHTYPE);
+  array_insert (av, 3, s);
+  array_insert (av, 4, release_status);
+  array_insert (av, 5, MACHTYPE);
 
   VSETATTR (vv, att_readonly);
 }
@@ -747,101 +804,11 @@ sh_set_lines_and_columns (lines, cols)
   bind_variable ("COLUMNS", v);
 }
 
-/* Set NAME to VALUE if NAME has no value. */
-SHELL_VAR *
-set_if_not (name, value)
-     char *name, *value;
-{
-  SHELL_VAR *v;
-
-  v = find_variable (name);
-  if (v == 0)
-    v = bind_variable (name, value);
-  return (v);
-}
-
-/* Map FUNCTION over the variables in VARIABLES.  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, var_hash_table)
-     sh_var_map_func_t *function;
-     HASH_TABLE *var_hash_table;
-{
-  register int i;
-  register BUCKET_CONTENTS *tlist;
-  SHELL_VAR *var, **list;
-  int list_index, list_size;
-
-  list = (SHELL_VAR **)NULL;
-  for (i = list_index = list_size = 0; i < var_hash_table->nbuckets; i++)
-    {
-      tlist = get_hash_bucket (i, var_hash_table);
-
-      while (tlist)
-       {
-         var = (SHELL_VAR *)tlist->data;
-
-         if (!function || (*function) (var))
-           {
-             if (list_index + 1 >= list_size)
-               list = (SHELL_VAR **)
-                 xrealloc (list, (list_size += 20) * sizeof (SHELL_VAR *));
-
-             list[list_index++] = var;
-             list[list_index] = (SHELL_VAR *)NULL;
-           }
-         tlist = tlist->next;
-       }
-    }
-  return (list);
-}
-
-void
-sort_variables (array)
-     SHELL_VAR **array;
-{
-  qsort (array, array_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);
-}
-
-/* Create a NULL terminated array of all the shell variables in TABLE. */
-static SHELL_VAR **
-all_vars (table)
-     HASH_TABLE *table;
-{
-  SHELL_VAR **list;
-
-  list = map_over ((sh_var_map_func_t *)NULL, table);
-  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 (all_vars (shell_variables));
-}
-
-/* Create a NULL terminated array of all the shell functions. */
-SHELL_VAR **
-all_shell_functions ()
-{
-  return (all_vars (shell_functions));
-}
+/* **************************************************************** */
+/*                                                                 */
+/*                Printing variables and values                    */
+/*                                                                 */
+/* **************************************************************** */
 
 /* Print LIST (a list of shell variables) to stdout in such a way that
    they can be read back in. */
@@ -853,7 +820,7 @@ print_var_list (list)
   register SHELL_VAR *var;
 
   for (i = 0; list && (var = list[i]); i++)
-    if (!invisible_p (var))
+    if (invisible_p (var) == 0)
       print_assignment (var);
 }
 
@@ -874,23 +841,6 @@ print_func_list (list)
     }
 }
       
-#if defined (NOTDEF)
-/* Print LIST (a linked list of shell variables) to stdout
-   by printing the names, without the values.  Used to support the
-   `set +' command. */
-void
-print_vars_no_values (list)
-     register SHELL_VAR **list;
-{
-  register int i;
-  register SHELL_VAR *var;
-
-  for (i = 0; list && (var = list[i]); i++)
-    if (!invisible_p (var))
-      printf ("%s\n", var->name);
-}
-#endif
-
 /* 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. */
@@ -898,17 +848,20 @@ void
 print_assignment (var)
      SHELL_VAR *var;
 {
-  if (function_p (var) && var->value)
+  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) && var->value)
+  else if (array_p (var))
     print_array_assignment (var, 0);
 #endif /* ARRAY_VARS */
-  else if (var->value)
+  else
     {
       printf ("%s=", var->name);
       print_var_value (var, 1);
@@ -927,23 +880,23 @@ print_var_value (var, quote)
 {
   char *t;
 
-  if (var->value)
+  if (var_isset (var) == 0)
+    return;
+
+  if (quote && posixly_correct == 0 && ansic_shouldquote (value_cell (var)))
     {
-      if (quote && posixly_correct == 0 && ansic_shouldquote (var->value))
-       {
-         t = ansic_quote (var->value, 0, (int *)0);
-         printf ("%s", t);
-         free (t);
-       }
-      else if (quote && sh_contains_shell_metas (var->value))
-       {
-         t = sh_single_quote (var->value);
-         printf ("%s", t);
-         free (t);
-       }
-      else
-       printf ("%s", var->value);
+      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
@@ -952,13 +905,13 @@ void
 print_var_function (var)
      SHELL_VAR *var;
 {
-  if (function_p (var) && var->value)
+  if (function_p (var) && var_isset (var))
     printf ("%s", named_function_string ((char *)NULL, function_cell(var), 1));
 }
 
 /* **************************************************************** */
 /*                                                                 */
-/*              Dynamic Variable Extension                         */
+/*                     Dynamic Variables                           */
 /*                                                                 */
 /* **************************************************************** */
 
@@ -966,21 +919,23 @@ print_var_function (var)
 
    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 dynamic_value, which is called from find_variable.
-
-   assign_func is called from bind_variable, if bind_variable discovers
-   that the variable being assigned to has such a function.  The function
-   is called as
-       SHELL_VAR *temp = (*(entry->assign_func)) (entry, value)
+   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).
+   is usually ENTRY (self).  IND is an index for an array variable, and
+   unused otherwise.
 
-   dynamic_value is called from find_variable 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);
+   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?
@@ -989,7 +944,7 @@ print_var_function (var)
    special meaning, even if you subsequently set it.
 
    The special assignment code would probably have been better put in
-   subst.c: do_assignment, in the same style as
+   subst.c: do_assignment_internal, in the same style as
    stupidly_hack_special_variables, but I wanted the changes as
    localized as possible.  */
 
@@ -1012,19 +967,20 @@ print_var_function (var)
   while (0)
 
 static SHELL_VAR *
-null_assign (self, value)
+null_assign (self, value, unused)
      SHELL_VAR *self;
      char *value;
+     arrayind_t unused;
 {
   return (self);
 }
 
 #if defined (ARRAY_VARS)
 static SHELL_VAR *
-null_array_assign (self, ind, value)
+null_array_assign (self, value, ind)
      SHELL_VAR *self;
-     arrayind_t ind;
      char *value;
+     arrayind_t ind;
 {
   return (self);
 }
@@ -1033,12 +989,13 @@ null_array_assign (self, ind, value)
 /* 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 long seconds_value_assigned;
+static intmax_t seconds_value_assigned;
 
 static SHELL_VAR *
-assign_seconds (self, value)
+assign_seconds (self, value, unused)
      SHELL_VAR *self;
      char *value;
+     arrayind_t unused;
 {
   if (legal_number (value, &seconds_value_assigned) == 0)
     seconds_value_assigned = 0;
@@ -1056,10 +1013,10 @@ get_seconds (var)
   time_since_start = NOW - shell_start_time;
   p = itos(seconds_value_assigned + time_since_start);
 
-  FREE (var->value);
+  FREE (value_cell (var));
 
   VSETATTR (var, att_integer);
-  var->value = p;
+  var_setvalue (var, p);
   return (var);
 }
 
@@ -1074,7 +1031,7 @@ init_seconds_var ()
       if (legal_number (value_cell(v), &seconds_value_assigned) == 0)
        seconds_value_assigned = 0;
     }
-  INIT_DYNAMIC_VAR ("SECONDS", (v ? v->value : (char *)NULL), get_seconds, assign_seconds);
+  INIT_DYNAMIC_VAR ("SECONDS", (v ? value_cell (v) : (char *)NULL), get_seconds, assign_seconds);
   return v;      
 }
      
@@ -1083,7 +1040,7 @@ static unsigned long rseed = 1;
 static int last_random_value;
 
 /* A linear congruential random number generator based on the example
-   on in the ANSI C standard.  This one isn't very good, but a more
+   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. */
@@ -1104,9 +1061,10 @@ sbrand (seed)
 }
 
 static SHELL_VAR *
-assign_random (self, value)
+assign_random (self, value, unused)
      SHELL_VAR *self;
      char *value;
+     arrayind_t unused;
 {
   sbrand (strtoul (value, (char **)NULL, 10));
   return (self);
@@ -1138,13 +1096,27 @@ get_random (var)
   last_random_value = rv;
   p = itos (rv);
 
-  FREE (var->value);
+  FREE (value_cell (var));
 
   VSETATTR (var, att_integer);
-  var->value = p;
+  var_setvalue (var, p);
   return (var);
 }
 
+static SHELL_VAR *
+assign_lineno (var, value, unused)
+     SHELL_VAR *var;
+     char *value;
+     arrayind_t unused;
+{
+  intmax_t new_value;
+
+  if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
+    new_value = 0;
+  line_number = new_value;
+  return var;
+}
+
 /* Function which returns the current line number. */
 static SHELL_VAR *
 get_lineno (var)
@@ -1155,24 +1127,11 @@ get_lineno (var)
 
   ln = executing_line_number ();
   p = itos (ln);
-  FREE (var->value);
-  var->value = p;
+  FREE (value_cell (var));
+  var_setvalue (var, p);
   return (var);
 }
 
-static SHELL_VAR *
-assign_lineno (var, value)
-     SHELL_VAR *var;
-     char *value;
-{
-  long new_value;
-
-  if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
-    new_value = 0;
-  line_number = new_value;
-  return var;
-}
-
 #if defined (HISTORY)
 static SHELL_VAR *
 get_histcmd (var)
@@ -1181,13 +1140,23 @@ get_histcmd (var)
   char *p;
 
   p = itos (history_number ());
-  FREE (var->value);
-  var->value = p;
+  FREE (value_cell (var));
+  var_setvalue (var, p);
   return (var);
 }
 #endif
 
 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
+static  SHELL_VAR *
+assign_dirstack (self, value, ind)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t ind;
+{
+  set_dirstack_element (ind, 1, value);
+  return self;
+}
+
 static SHELL_VAR *
 get_dirstack (self)
      SHELL_VAR *self;
@@ -1196,20 +1165,10 @@ get_dirstack (self)
   WORD_LIST *l;
 
   l = get_directory_stack ();
-  a = word_list_to_array (l);
-  dispose_array (array_cell (self));
+  a = array_from_word_list (l);
+  array_dispose (array_cell (self));
   dispose_words (l);
-  self->value = (char *)a;
-  return self;
-}
-
-static  SHELL_VAR *
-assign_dirstack (self, ind, value)
-     SHELL_VAR *self;
-     arrayind_t ind;
-     char *value;
-{
-  set_dirstack_element (ind, 1, value);
+  var_setarray (self, a);
   return self;
 }
 
@@ -1243,7 +1202,7 @@ get_groupset (self)
       group_set = get_group_list (&ng);
       a = array_cell (self);
       for (i = 0; i < ng; i++)
-       array_add_element (a, i, group_set[i]);
+       array_insert (a, i, group_set[i]);
     }
   return (self);
 }
@@ -1266,10 +1225,12 @@ static SHELL_VAR *
 get_funcname (self)
      SHELL_VAR *self;
 {
+  char *t;
   if (variable_context && this_shell_function)
     {
-      FREE (self->value);
-      self->value = savestring (this_shell_function->name);
+      FREE (value_cell (self));
+      t = savestring (this_shell_function->name);
+      var_setvalue (self, t);
     }
   return (self);
 }
@@ -1314,7 +1275,7 @@ initialize_dynamic_variables ()
   INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno);
 
 #if defined (HISTORY)
-  INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (DYNAMIC_FUNC *)NULL);
+  INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (sh_var_assign_func_t *)NULL);
 #endif
 
 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
@@ -1328,22 +1289,50 @@ initialize_dynamic_variables ()
   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). */
-SHELL_VAR *
-var_lookup (name, hashed_vars)
+
+static SHELL_VAR *
+hash_lookup (name, hashed_vars)
      const char *name;
      HASH_TABLE *hashed_vars;
 {
   BUCKET_CONTENTS *bucket;
 
-  bucket = find_hash_item (name, hashed_vars);
+  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. */
+   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, search_tempenv)
      const char *name;
@@ -1358,14 +1347,13 @@ find_variable_internal (name, search_tempenv)
      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". */
-  if ((search_tempenv || subshell_environment) &&
-      (temporary_env || builtin_env || function_env))
-    var = find_tempenv_variable (name);
+  if ((search_tempenv || subshell_environment) && temporary_env)
+    var = hash_lookup (name, temporary_env);
 
-  if (!var)
+  if (var == 0)
     var = var_lookup (name, shell_variables);
 
-  if (!var)
+  if (var == 0)
     return ((SHELL_VAR *)NULL);
 
   return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
@@ -1376,8 +1364,7 @@ SHELL_VAR *
 find_variable (name)
      const char *name;
 {
-  return (find_variable_internal
-         (name, (variable_context || this_shell_builtin || builtin_env)));
+  return (find_variable_internal (name, this_shell_builtin != 0));
 }
 
 /* Look up the function entry whose name matches STRING.
@@ -1386,13 +1373,30 @@ SHELL_VAR *
 find_function (name)
      const char *name;
 {
-  return (var_lookup (name, shell_functions));
+  return (hash_lookup (name, shell_functions));
+}
+
+/* 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));
+#endif
+  else
+    return (value_cell (var));
 }
 
 /* Return the string value of a variable.  Return NULL if the variable
-   doesn't exist, or only has a function as a value.  Don't cons a new
-   string.  This is a potential memory leak if the variable is found
-   in the temporary environment. */
+   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;
@@ -1400,15 +1404,7 @@ get_string_value (var_name)
   SHELL_VAR *var;
 
   var = find_variable (var_name);
-
-  if (!var)
-    return (char *)NULL;
-#if defined (ARRAY_VARS)
-  else if (array_p (var))
-    return (array_reference (array_cell (var), 0));
-#endif
-  else
-    return (var->value);
+  return ((var) ? get_variable_value (var) : (char *)NULL);
 }
 
 /* This is present for use by the tilde and readline libraries. */
@@ -1419,19 +1415,56 @@ sh_get_env_value (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;
+
+  v = find_variable (name);
+  if (v == 0)
+    v = bind_variable_internal (name, value, global_variables->table, HASH_NOSRCH);
+  return (v);
+}
+
 /* Create a local variable referenced by NAME. */
 SHELL_VAR *
 make_local_variable (name)
      const char *name;
 {
   SHELL_VAR *new_var, *old_var;
-  BUCKET_CONTENTS *elt;
+  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 && old_var->context == variable_context)
+  if (old_var && local_p (old_var) && old_var->context == variable_context)
     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 found");
+      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'
@@ -1443,57 +1476,32 @@ make_local_variable (name)
                 (readonly_p (old_var) && old_var->context == 0)))
     {
       if (readonly_p (old_var))
-       builtin_error ("%s: readonly variable", name);
+       sh_readonly (name);
       return ((SHELL_VAR *)NULL);
     }
 
-  elt = remove_hash_item (name, shell_variables);
-  if (elt)
-    {
-      old_var = (SHELL_VAR *)elt->data;
-      free (elt->key);
-      free (elt);
-    }
-  else
-    old_var = (SHELL_VAR *)NULL;
-
-  /* If a variable does not already exist with this name, then
-     just make a new one. */
   if (old_var == 0)
-    new_var = bind_variable (name, "");
+    new_var = bind_variable_internal (name, "", vc->table, HASH_NOSRCH);
   else
     {
-      new_var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
-
-      new_var->name = savestring (name);
-      new_var->value = (char *)xmalloc (1);
-      new_var->value[0] = '\0';
+      new_var = make_new_variable (name, vc->table);
 
-      CLEAR_EXPORTSTR (new_var);
-
-      new_var->dynamic_value = (DYNAMIC_FUNC *)NULL;
-      new_var->assign_func = (DYNAMIC_FUNC *)NULL;
+      /* 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;
-
-      new_var->prev_context = old_var;
-      elt = add_hash_item (savestring (name), shell_variables);
-      elt->data = (char *)new_var;
     }
 
+  vc->flags |= VC_HASLOCAL;
+
   new_var->context = variable_context;
   VSETATTR (new_var, att_local);
 
-  /* XXX */
-  if (variable_context >= local_variable_stack_size)
-    {
-      int old_size = local_variable_stack_size;
-      RESIZE_MALLOCED_BUFFER (have_local_variables, variable_context, 1,
-                             local_variable_stack_size, 8);
-      bzero ((char *)have_local_variables + old_size,
-            local_variable_stack_size - old_size);
-    }
-  have_local_variables[variable_context] = 1;          /* XXX */
+  if (ifsname (name))
+    setifs (new_var);
 
   return (new_var);
 }
@@ -1509,46 +1517,63 @@ make_local_array_variable (name)
   var = make_local_variable (name);
   if (var == 0)
     return var;
-  array = new_array ();
+  array = array_create ();
 
   FREE (value_cell(var));
-  var->value = (char *)array;
+  var_setarray (var, array);
   VSETATTR (var, att_array);
   return var;
 }
 #endif /* ARRAY_VARS */
 
-/* Create a new shell variable with name NAME and add it to the hash table
-   of shell variables. */
+/* Create a new shell variable with name NAME. */
 static SHELL_VAR *
-make_new_variable (name)
+new_shell_variable (name)
      const char *name;
 {
   SHELL_VAR *entry;
-  BUCKET_CONTENTS *elt;
 
   entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
 
-  entry->attributes = 0;
   entry->name = savestring (name);
-  entry->value = (char *)NULL;
+  var_setvalue (entry, (char *)NULL);
   CLEAR_EXPORTSTR (entry);
 
-  entry->dynamic_value = (DYNAMIC_FUNC *)NULL;
-  entry->assign_func = (DYNAMIC_FUNC *)NULL;
+  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;
-  entry->prev_context = (SHELL_VAR *)NULL;
+
+  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)
-    shell_variables = make_hash_table (0);
+    {
+      shell_variables = global_variables = new_var_context ((char *)NULL, 0);
+      shell_variables->scope = 0;
+      shell_variables->table = hash_create (0);
+    }
 
-  elt = add_hash_item (savestring (name), shell_variables);
-  elt->data = (char *)entry;
+  elt = hash_insert (savestring (name), table, HASH_NOSRCH);
+  elt->data = (PTR_T)entry;
 
   return entry;
 }
@@ -1561,9 +1586,9 @@ make_new_array_variable (name)
   SHELL_VAR *entry;
   ARRAY *array;
 
-  entry = make_new_variable (name);
-  array = new_array ();
-  entry->value = (char *)array;
+  entry = make_new_variable (name, global_variables->table);
+  array = array_create ();
+  var_setarray (entry, array);
   VSETATTR (entry, att_array);
   return entry;
 }
@@ -1575,12 +1600,12 @@ make_variable_value (var, value)
      char *value;
 {
   char *retval;
-  long lval;
+  intmax_t lval;
   int expok;
 
   /* 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
+     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))
@@ -1606,52 +1631,36 @@ make_variable_value (var, value)
   return retval;
 }
 
-/* Bind a variable NAME to VALUE.  This conses up the name
-   and value strings. */
-SHELL_VAR *
-bind_variable (name, value)
+/* 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)
      const char *name;
      char *value;
+     HASH_TABLE *table;
+     int hflags;
 {
   char *newval;
-  SHELL_VAR *entry, *tempenv_entry;
-
-  entry = (SHELL_VAR *)0;
+  SHELL_VAR *entry;
 
-  /* 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 || builtin_env || function_env)
-    {
-      tempenv_entry = find_tempenv_variable (name);
-      if (tempenv_entry)
-       {
-         dispose_variable (tempenv_entry);
-         tempenv_entry = bind_tempenv_variable (name, value);
-         dispose_variable (tempenv_entry);
-       }
-    }
-    
-  entry = var_lookup (name, shell_variables);
+  entry = (hflags & HASH_NOSRCH) ? (SHELL_VAR *)NULL : hash_lookup (name, table);
 
   if (entry == 0)
     {
-      entry = make_new_variable (name);
-      entry->value = make_variable_value (entry, value);
+      entry = make_new_variable (name, table);
+      var_setvalue (entry, make_variable_value (entry, value));
     }
   else if (entry->assign_func) /* array vars have assign functions now */
     {
       INVALIDATE_EXPORTSTR (entry);
-      return ((*(entry->assign_func)) (entry, value));
+      return ((*(entry->assign_func)) (entry, value, -1));
     }
   else
     {
       if (readonly_p (entry) || noassign_p (entry))
        {
          if (readonly_p (entry))
-           report_error ("%s: readonly variable", name);
+           err_readonly (name);
          return (entry);
        }
 
@@ -1670,14 +1679,14 @@ bind_variable (name, value)
         x[0]=b or `read x[0]'. */
       if (array_p (entry))
        {
-         array_add_element (array_cell (entry), 0, newval);
+         array_insert (array_cell (entry), 0, newval);
          free (newval);
        }
       else
 #endif
        {
-         FREE (entry->value);
-         entry->value = newval;
+         FREE (value_cell (entry));
+         var_setvalue (entry, newval);
        }
     }
 
@@ -1689,6 +1698,46 @@ bind_variable (name, value)
 
   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)
+     const char *name;
+     char *value;
+{
+  SHELL_VAR *v;
+  VAR_CONTEXT *vc;
+
+  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 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);
+          if (v)
+           return (bind_variable_internal (name, value, vc->table, 0));
+        }
+    }
+  return (bind_variable_internal (name, value, global_variables->table, 0));
+}
 
 /* Make VAR, a simple shell variable, have value VALUE.  Once assigned a
    value, variables are no longer invisible.  This is a duplicate of part
@@ -1705,8 +1754,8 @@ bind_variable_value (var, value)
   VUNSETATTR (var, att_invisible);
 
   t = make_variable_value (var, value);
-  FREE (var->value);
-  var->value = t;
+  FREE (value_cell (var));
+  var_setvalue (var, t);
 
   INVALIDATE_EXPORTSTR (var);
 
@@ -1734,17 +1783,33 @@ bind_int_variable (lhs, rhs)
      char *lhs, *rhs;
 {
   register SHELL_VAR *v;
-  int isint;
+  char *t;
+  int isint, isarr;
+
+  isint = isarr = 0;
+#if defined (ARRAY_VARS)
+  if (t = xstrchr (lhs, '['))  /*]*/
+    {
+      isarr = 1;
+      v = array_variable_part (lhs, (char **)0, (int *)0);
+    }
+  else
+#endif
+    v = find_variable (lhs);
 
-  isint = 0;
-  v = find_variable (lhs);
   if (v)
     {
       isint = integer_p (v);
       VUNSETATTR (v, att_integer);
     }
 
-  v = bind_variable (lhs, rhs);
+#if defined (ARRAY_VARS)
+  if (isarr)
+    v = assign_array_element (lhs, rhs);
+  else
+#endif
+    v = bind_variable (lhs, rhs);
+
   if (isint)
     VSETATTR (v, att_integer);
 
@@ -1754,27 +1819,196 @@ bind_int_variable (lhs, rhs)
 SHELL_VAR *
 bind_var_to_int (var, val)
      char *var;
-     long val;
+     intmax_t val;
 {
-  char ibuf[INT_STRLEN_BOUND (long) + 1], *p;
+  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);
+}
+
+/* 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 (string)
+     const char *string;
+{
+  int offset;
+  char *name, *temp, *value;
+  SHELL_VAR *var;
+
+  offset = assignment (string);
+  name = savestring (string);
+  value = (char *)NULL;
+
+  if (name[offset] == '=')
+    {
+      name[offset] = 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;
+      temp = (xstrchr (temp, '~') != 0) ? bash_tilde_expand (temp, 1) : savestring (temp);
+
+      value = expand_string_unsplit_to_string (temp, 0);
+      free (temp);
+    }
+
+  if (temporary_env == 0)
+    temporary_env = hash_create (TEMPENV_HASH_BUCKETS);
+
+  var = hash_lookup (name, temporary_env);
+  if (var == 0)
+    var = make_new_variable (name, temporary_env);
+  else
+    FREE (value_cell (var));
+
+  if (value == 0)
+    {
+      value = (char *)xmalloc (1);     /* like do_assignment_internal */
+      value[0] = '\0';
+    }
+
+  var_setvalue (var, value);
+  var->attributes |= (att_exported|att_tempvar);
+  var->context = variable_context;     /* XXX */
+
+  INVALIDATE_EXPORTSTR (var);
+  var->exportstr = mk_env_string (name, value);
+
+  array_needs_making = 1;
+
+  if (ifsname (name))
+    setifs (var);
+
+  if (echo_command_at_execute)
+    {
+      /* The Korn shell prints the `+ ' in front of assignment statements,
+        so we do too. */
+      fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
+      fflush (stderr);
+    }
+
+  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, dup_array (array_cell (var)));
+#endif
+      else if (value_cell (var))
+       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. */
 void
 dispose_variable (var)
      SHELL_VAR *var;
 {
-  if (!var)
+  if (var == 0)
     return;
 
   if (function_p (var))
     dispose_command (function_cell (var));
 #if defined (ARRAY_VARS)
   else if (array_p (var))
-    dispose_array (array_cell (var));
+    array_dispose (array_cell (var));
 #endif
   else
     FREE (value_cell (var));
@@ -1789,31 +2023,43 @@ dispose_variable (var)
   free (var);
 }
 
-/* Unset the variable referenced by NAME. */
+/* Unset the shell variable referenced by NAME. */
 int
 unbind_variable (name)
      const char *name;
 {
-  SHELL_VAR *var;
+  return makunbound (name, shell_variables);
+}
 
-  var = find_variable (name);
-  if (!var)
-    return (-1);
+/* Unset the shell function named NAME. */
+int
+unbind_func (name)
+     const char *name;
+{
+  BUCKET_CONTENTS *elt;
+  SHELL_VAR *func;
 
-  /* This function should never be called with an array variable name. */
-#if defined (ARRAY_VARS)
-  if (array_p (var) == 0 && var->value)
-#else
-  if (var->value)
+  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)
     {
-      free (var->value);
-      var->value = (char *)NULL;
+      if (exported_p (func))
+       array_needs_making++;
+      dispose_variable (func);
     }
 
-  makunbound (name, shell_variables);
+  free (elt->key);
+  free (elt);
 
-  return (0);
+  return 0;  
 }
 
 /* Make the variable associated with NAME go away.  HASH_LIST is the
@@ -1821,58 +2067,49 @@ unbind_variable (name)
    shell_variables or shell_functions).
    Returns non-zero if the variable couldn't be found. */
 int
-makunbound (name, hash_list)
+makunbound (name, vc)
      const char *name;
-     HASH_TABLE *hash_list;
+     VAR_CONTEXT *vc;
 {
   BUCKET_CONTENTS *elt, *new_elt;
-  SHELL_VAR *old_var, *new_var;
+  SHELL_VAR *old_var;
+  VAR_CONTEXT *v;
   char *t;
 
-  elt = remove_hash_item (name, hash_list);
+  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;
-  new_var = old_var->prev_context;
 
   if (old_var && exported_p (old_var))
     array_needs_making++;
 
-#if defined (PROGRAMMABLE_COMPLETION)
-  if (hash_list == shell_functions)
-    set_itemlist_dirty (&it_functions);
-#endif
-
   /* If we're unsetting a local variable and we're still executing inside
-     the function, just mark the variable as invisible.
-     kill_all_local_variables 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. */
+     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)
     {
       VSETATTR (old_var, att_invisible);
+      FREE (value_cell (old_var));
+      var_setvalue (old_var, (char *)NULL);
       INVALIDATE_EXPORTSTR (old_var);
-      new_elt = add_hash_item (savestring (old_var->name), hash_list);
-      new_elt->data = (char *)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);
     }
 
-  if (new_var)
-    {
-      /* Has to be a variable, functions don't have previous contexts. */
-      new_elt = add_hash_item (savestring (new_var->name), hash_list);
-      new_elt->data = (char *)new_var;
-
-      if (exported_p (new_var))
-       set_auto_export (new_var);
-    }
-
   /* 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. */
@@ -1884,87 +2121,38 @@ makunbound (name, hash_list)
   dispose_variable (old_var);
   stupidly_hack_special_variables (t);
   free (t);
+
   return (0);
 }
 
-#ifdef INCLUDE_UNUSED
-/* Remove the variable with NAME if it is a local variable in the
-   current context. */
-int
-kill_local_variable (name)
-     const char *name;
+/* Get rid of all of the variables in the current context. */
+void
+kill_all_local_variables ()
 {
-  SHELL_VAR *temp;
+  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 */
 
-  temp = find_variable (name);
-  if (temp && temp->context == variable_context)
+  if (vc->table && vc_haslocals (vc))
     {
-      makunbound (name, shell_variables);
-      return (0);
+      delete_all_variables (vc->table);
+      hash_dispose (vc->table);
     }
-  return (-1);
-}
-#endif
-
-/* Get rid of all of the variables in the current context. */
-int
-variable_in_context (var)
-     SHELL_VAR *var;
-{
-  return (var && var->context == variable_context);
-}
-
-void
-kill_all_local_variables ()
-{
-  register int i, pass;
-  register SHELL_VAR *var, **list;
-  HASH_TABLE *varlist;
-
-  /* If HAVE_LOCAL_VARIABLES == 0, it means that we don't have any local
-     variables at all.  If VARIABLE_CONTEXT >= LOCAL_VARIABLE_STACK_SIZE,
-     it means that we have some local variables, but not in this variable
-     context (level of function nesting).  Also, if
-     HAVE_LOCAL_VARIABLES[VARIABLE_CONTEXT] == 0, we have no local variables
-     at this context. */
-  if (have_local_variables == 0 ||
-      variable_context >= local_variable_stack_size ||
-      have_local_variables[variable_context] == 0)
-    return;
-
-  for (pass = 0; pass < 2; pass++)
-    {
-      varlist = pass ? shell_functions : shell_variables;
-
-      list = map_over (variable_in_context, varlist);
-
-      if (list)
-       {
-         for (i = 0; var = list[i]; i++)
-           {
-             VUNSETATTR (var, att_local);
-             makunbound (var->name, varlist);
-           }
-         free (list);
-       }
-    }
-
-  have_local_variables[variable_context] = 0;          /* XXX */
+  vc->table = (HASH_TABLE *)NULL;
 }
 
 static void
 free_variable_hash_data (data)
      PTR_T data;
 {
-  SHELL_VAR *var, *prev;
+  SHELL_VAR *var;
 
   var = (SHELL_VAR *)data;
-  while (var)
-    {
-      prev = var->prev_context;
-      dispose_variable (var);
-      var = prev;
-    }
+  dispose_variable (var);
 }
 
 /* Delete the entire contents of the hash table. */
@@ -1972,111 +2160,14 @@ void
 delete_all_variables (hashed_vars)
      HASH_TABLE *hashed_vars;
 {
-  flush_hash_table (hashed_vars, free_variable_hash_data);
-}
-
-static SHELL_VAR *
-new_shell_variable (name)
-     const char *name;
-{
-  SHELL_VAR *var;
-
-  var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
-
-  bzero ((char *)var, sizeof (SHELL_VAR));
-  var->name = savestring (name);
-  return (var);
+  hash_flush (hashed_vars, free_variable_hash_data);
 }
 
-/* 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)
-    {
-      BUCKET_CONTENTS *elt;
-
-      elt = add_hash_item (savestring (name), shell_functions);
-
-      entry = new_shell_variable (name);
-      entry->dynamic_value = entry->assign_func = (DYNAMIC_FUNC *)NULL;
-      CLEAR_EXPORTSTR (entry);
-
-      /* Functions are always made at the top level.  This allows a
-        function to define another function (like autoload). */
-      entry->context = 0;
-
-      elt->data = (char *)entry;
-    }
-
-  INVALIDATE_EXPORTSTR (entry);
-
-  if (entry->value)
-    dispose_command ((COMMAND *)entry->value);
-
-  entry->value = value ? (char *)copy_command (value) : (char *)NULL;
-  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);
-}
-
-#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))
-       copy->value = (char *)copy_command (function_cell (var));
-#if defined (ARRAY_VARS)
-      else if (array_p (var))
-       copy->value = (char *)dup_array (array_cell (var));
-#endif
-      else if (value_cell (var))
-       copy->value = savestring (value_cell (var));
-      else
-       copy->value = (char *)NULL;
-
-      copy->dynamic_value = var->dynamic_value;
-      copy->assign_func = var->assign_func;
-
-      copy->exportstr = COPY_EXPORTSTR (var);
-
-      copy->context = var->context;
-
-      /* Don't bother copying previous contexts along with this variable. */
-      copy->prev_context = (SHELL_VAR *)NULL;
-    }
-  return (copy);
-}
-#endif
+/* **************************************************************** */
+/*                                                                 */
+/*                  Setting variable attributes                    */
+/*                                                                 */
+/* **************************************************************** */
 
 #define FIND_OR_MAKE_VARIABLE(name, entry) \
   do \
@@ -2141,78 +2232,223 @@ set_func_auto_export (name)
 }
 #endif
 
-/* Returns non-zero if STRING is an assignment statement.  The returned value
-   is the index of the `=' sign. */
-int
-assignment (string)
-     const char *string;
+/* **************************************************************** */
+/*                                                                 */
+/*                  Creating lists of variables                    */
+/*                                                                 */
+/* **************************************************************** */
+
+static VARLIST *
+vlist_alloc (nentries)
+     int nentries;
 {
-  register unsigned char c;
-  register int newi, indx;
+  VARLIST  *vlist;
 
-  c = string[indx = 0];
+  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;
 
-  if (legal_variable_starter (c) == 0)
-    return (0);
+  return vlist;
+}
 
-  while (c = string[indx])
+static VARLIST *
+vlist_realloc (vlist, n)
+     VARLIST *vlist;
+     int n;
+{
+  if (vlist == 0)
+    return (vlist = vlist_alloc (n));
+  if (n > vlist->list_size)
     {
-      /* The following is safe.  Note that '=' at the start of a word
-        is not an assignment statement. */
-      if (c == '=')
-       return (indx);
+      vlist->list_size = n;
+      vlist->list = (SHELL_VAR **)xrealloc (vlist->list, (vlist->list_size + 1) * sizeof (SHELL_VAR *));
+    }
+  return vlist;
+}
 
-#if defined (ARRAY_VARS)
-      if (c == '[')
-       {
-         newi = skipsubscript (string, indx);
-         if (string[newi++] != ']')
-           return (0);
-         return ((string[newi] == '=') ? newi : 0);
-       }
-#endif /* ARRAY_VARS */
+static void
+vlist_add (vlist, var, flags)
+     VARLIST *vlist;
+     SHELL_VAR *var;
+     int flags;
+{
+  register int i;
 
-      /* Variable names in assignment statements may contain only letters,
-        digits, and `_'. */
-      if (legal_variable_char (c) == 0)
-       return (0);
+  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);
 
-      indx++;
+  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);
+       }
     }
-  return (0);
+}
+
+void
+sort_variables (array)
+     SHELL_VAR **array;
+{
+  qsort (array, strvec_len ((char **)array), sizeof (SHELL_VAR *), (QSFUNC *)qsort_var_comp);
 }
 
 static int
-visible_var (var)
-     SHELL_VAR *var;
+qsort_var_comp (var1, var2)
+     SHELL_VAR **var1, **var2;
 {
-  return (invisible_p (var) == 0);
+  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 **
-_visible_names (table)
-     HASH_TABLE *table;
+vapply (func)
+     sh_var_map_func_t *func;
 {
   SHELL_VAR **list;
 
-  list = map_over (visible_var, table);
-
+  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 (_visible_names (shell_functions));
+  return (fapply (visible_var));
 }
 
 SHELL_VAR **
 all_visible_variables ()
 {
-  return (_visible_names (shell_variables));
+  return (vapply (visible_var));
 }
 
 /* Return non-zero if the variable VAR is visible and exported.  Array
@@ -2224,15 +2460,63 @@ visible_and_exported (var)
   return (invisible_p (var) == 0 && exported_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 ()
 {
-  SHELL_VAR **list;
+  return (vapply (visible_and_exported));
+}
 
-  list = map_over (visible_and_exported, shell_variables);
-  if (list)
-    sort_variables (list);
-  return (list);
+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 found");
+      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)
@@ -2247,12 +2531,7 @@ visible_array_vars (var)
 SHELL_VAR **
 all_array_variables ()
 {
-  SHELL_VAR **list;
-
-  list = map_over (visible_array_vars, shell_variables);
-  if (list)
-    sort_variables (list);
-  return (list);
+  return (vapply (visible_array_vars));
 }
 #endif /* ARRAY_VARS */
 
@@ -2270,7 +2549,7 @@ all_variables_matching_prefix (prefix)
     ;
   if (varlist == 0 || vind == 0)
     return ((char **)NULL);
-  rlist = alloc_array (vind + 1);
+  rlist = strvec_create (vind + 1);
   for (vind = rind = 0; varlist[vind]; vind++)
     {
       if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen))
@@ -2282,6 +2561,131 @@ all_variables_matching_prefix (prefix)
   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);
+}
+
+/* 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);
+
+  /* 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;
+
+  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
+    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. */
+static void
+dispose_temporary_env (pushf)
+     sh_free_func_t *pushf;
+{
+  hash_flush (temporary_env, pushf);
+  hash_dispose (temporary_env);
+  temporary_env  = (HASH_TABLE *)NULL;
+
+  array_needs_making = 1;
+
+  sv_ifs ("IFS");              /* XXX here for now */
+}
+
+void
+dispose_used_env_vars ()
+{
+  if (temporary_env)
+    dispose_temporary_env (propagate_temp_var);
+}
+
+/* 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;
@@ -2334,24 +2738,15 @@ valid_exportstr (v)
 }
 #endif
 
-/* Make an array of assignment statements from the hash table
-   HASHED_VARS which contains SHELL_VARs.  Only visible, exported
-   variables are eligible. */
-char **
-make_var_array (hashed_vars)
-     HASH_TABLE *hashed_vars;
+static char **
+make_env_array_from_var_list (vars)
+     SHELL_VAR **vars;
 {
   register int i, list_index;
   register SHELL_VAR *var;
   char **list, *value;
-  SHELL_VAR **vars;
-
-  vars = map_over (visible_and_exported, hashed_vars);
-
-  if (vars == 0)
-    return (char **)NULL;
 
-  list = alloc_array ((1 + array_len ((char **)vars)));
+  list = strvec_create ((1 + strvec_len ((char **)vars)));
 
 #define USE_EXPORTSTR (value == var->exportstr)
 
@@ -2383,10 +2778,9 @@ make_var_array (hashed_vars)
          list[list_index] = USE_EXPORTSTR ? savestring (value)
                                           : mk_env_string (var->name, value);
 
-         if (USE_EXPORTSTR == 0 && function_p (var))
-           {
-             SAVE_EXPORTSTR (var, list[list_index]);
-           }
+         if (USE_EXPORTSTR == 0)
+           SAVE_EXPORTSTR (var, list[list_index]);
+
          list_index++;
 #undef USE_EXPORTSTR
 
@@ -2399,317 +2793,46 @@ make_var_array (hashed_vars)
        }
     }
 
-  free (vars);
   list[list_index] = (char *)NULL;
   return (list);
 }
 
-/* Add STRING to the array of foo=bar strings that we already
-   have to add to the environment.  */
-int
-assign_in_env (string)
-     const char *string;
-{
-  int size, offset;
-  char *name, *temp, *value;
-  SHELL_VAR *var;
-
-  offset = assignment (string);
-  name = savestring (string);
-  value = (char *)NULL;
-
-  if (name[offset] == '=')
-    {
-      name[offset] = 0;
-
-      var = find_variable (name);
-      if (var && (readonly_p (var) || noassign_p (var)))
-       {
-         if (readonly_p (var))
-           report_error ("%s: readonly variable", name);
-         free (name);
-         return (0);
-       }
-
-      temp = name + offset + 1;
-      temp = (strchr (temp, '~') != 0) ? bash_tilde_expand (temp) : savestring (temp);
-
-      value = expand_string_unsplit_to_string (temp, 0);
-      free (temp);
-    }
-
-  temp = mk_env_string (name, value);
-  FREE (value);
-  free (name);
-
-  if (temporary_env == 0)
-    {
-      temporary_env = (char **)xmalloc (sizeof (char *));
-      temporary_env [0] = (char *)NULL;
-    }
-
-  size = array_len (temporary_env);
-  temporary_env = (char **)
-    xrealloc (temporary_env, (size + 2) * (sizeof (char *)));
-
-  temporary_env[size] = temp;
-  temporary_env[size + 1] = (char *)NULL;
-  array_needs_making = 1;
-
-  if (echo_command_at_execute)
-    {
-      /* The Korn shell prints the `+ ' in front of assignment statements,
-        so we do too. */
-      fprintf (stderr, "%s%s\n", indirection_level_string (), temp);
-      fflush (stderr);
-    }
-
-  return 1;
-}
-
-/* Create a SHELL_VAR from a `name=value' string as in the environment, taking
-   the variable name, the environment string, and an index into the string
-   which is the offset of the `=' (the char before the value begins). */
-static SHELL_VAR *
-shell_var_from_env_string (name, env_string, l)
-     const char *name;
-     char *env_string;
-     int l;
-{
-  SHELL_VAR *temp;
-  char *w;
-
-  /* This is a potential memory leak.  The code should really save
-     the created variables in some auxiliary data structure, which
-     can be disposed of at the appropriate time. */
-  temp = new_shell_variable (name);
-  w = env_string + l + 1;
-
-  temp->value = *w ? savestring (w) : (char *)NULL;
-
-  temp->attributes = att_exported|att_tempvar;
-  temp->context = 0;
-  temp->prev_context = (SHELL_VAR *)NULL;
-
-  temp->dynamic_value = temp->assign_func = (DYNAMIC_FUNC *)NULL;
-  CLEAR_EXPORTSTR (temp);
-
-  return (temp);
-}
-
-/* Bind NAME to VALUE in ARRAY, an array of strings in the same format as the
-   environment array (i.e, name=value).  If NAME is present, change the value,
-   cons up a new SHELL_VAR and return it.  Otherwise return (SHELL_VAR *)NULL. */
-
-static SHELL_VAR *
-bind_name_in_env_array (name, value, array)
-     const char *name;
-     char *value;
-     char **array;
-{
-  register int i, l;
-  char *new_env_string;
-  SHELL_VAR *temp;
-
-  if (array == 0)
-    return ((SHELL_VAR *)NULL);
-
-  for (i = 0, l = strlen (name); array[i]; i++)
-    {
-      if (STREQN (array[i], name, l) && array[i][l] == '=')
-       {
-         new_env_string = mk_env_string (name, value);
-
-         temp = shell_var_from_env_string (name, new_env_string, l);
-
-         free (array[i]);
-         array[i] = new_env_string;
-
-         return (temp);
-       }
-    }
-  return ((SHELL_VAR *)NULL);
-}
-
-/* Search for NAME in ARRAY, an array of strings in the same format as the
-   environment array (i.e, name=value).  If NAME is present, make a new
-   variable and return it.  Otherwise, return NULL. */
-static SHELL_VAR *
-find_name_in_env_array (name, array)
-     const char *name;
-     char **array;
-{
-  register int i, l;
-  SHELL_VAR *temp;
-
-  if (array == 0)
-    return ((SHELL_VAR *)NULL);
-
-  for (i = 0, l = strlen (name); array[i]; i++)
-    {
-      if (STREQN (array[i], name, l) && array[i][l] == '=')
-       {
-         temp = shell_var_from_env_string (name, array[i], l);
-         return (temp);
-       }
-    }
-  return ((SHELL_VAR *)NULL);
-}
-
-#define FIND_AND_BIND_IN_ENV_ARRAY(N, V, A) \
-  do \
-    { \
-      var = find_name_in_env_array (N, A); \
-      if (var) \
-       { \
-         dispose_variable (var); \
-         var = bind_name_in_env_array (N, V, A); \
-         return (var); \
-       } \
-    } \
-  while (0)
-
-/* Make variable NAME have VALUE in one of the temporary environments. */
-static SHELL_VAR *
-bind_tempenv_variable (name, value)
-     const char *name;
-     char *value;
-{
-  SHELL_VAR *var;
-
-  var = (SHELL_VAR *)NULL;
-
-  if (temporary_env)
-    FIND_AND_BIND_IN_ENV_ARRAY (name, value, temporary_env);
-
-  /* We don't check this_shell_builtin because the command that needs the
-     value from builtin_env may be a disk command run inside a script run
-     with `.' and a temporary env. */
-  if (builtin_env)
-    FIND_AND_BIND_IN_ENV_ARRAY (name, value, builtin_env);
-
-  if (variable_context && function_env)
-    FIND_AND_BIND_IN_ENV_ARRAY (name, value, function_env);
-
-  return (SHELL_VAR *)NULL;
-}
-
-/* Find a variable in the temporary environment that is named NAME.
-   The temporary environment can be either the environment provided
-   to a simple command, or the environment provided to a shell function.
-   We only search the function environment if we are currently executing
-   a shell function body (variable_context > 0).  Return a consed variable,
-   or NULL if not found. */
-SHELL_VAR *
-find_tempenv_variable (name)
-     const char *name;
-{
-  SHELL_VAR *var;
-
-  var = (SHELL_VAR *)NULL;
-
-  if (temporary_env)
-    var = find_name_in_env_array (name, temporary_env);
-
-  /* We don't check this_shell_builtin because the command that needs the
-     value from builtin_env may be a disk command run inside a script run
-     with `.' and a temporary env. */
-  if (!var && builtin_env)
-    var = find_name_in_env_array (name, builtin_env);
-
-  if (!var && variable_context && function_env)
-    var = find_name_in_env_array (name, function_env);
-
-  return (var);
-}
-
-/* Free the storage allocated to the string array pointed to by ARRAYP, and
-   make that variable have a null pointer as a value. */
-static void
-dispose_temporary_vars (arrayp)
-     char ***arrayp;
-{
-  if (!*arrayp)
-    return;
-
-  free_array (*arrayp);
-  *arrayp = (char **)NULL;
-  array_needs_making = 1;
-}
-
-/* Free the storage used in the variable array for temporary
-   environment variables. */
-void
-dispose_used_env_vars ()
-{
-  dispose_temporary_vars (&temporary_env);
-}
-
-/* Free the storage used for temporary environment variables given to
-   commands when executing inside of a function body. */
-void
-dispose_function_env ()
+/* 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;
 {
-  dispose_temporary_vars (&function_env);
-}
+  char **list;
+  SHELL_VAR **vars;
 
-/* Free the storage used for temporary environment variables given to
-   commands when executing a builtin command such as "source". */
-void
-dispose_builtin_env ()
-{
-  dispose_temporary_vars (&builtin_env);
-}
+  vars = map_over (visible_and_exported, vcxt);
 
-/* Take all of the shell variables in ENV_ARRAY and make shell variables
-   from them at the current variable context. */
-static void
-merge_env_array (env_array)
-     char **env_array;
-{
-  register int i, l;
-  SHELL_VAR *temp;
-  char *val, *name;
+  if (vars == 0)
+    return (char **)NULL;
 
-  if (env_array == 0)
-    return;
+  list = make_env_array_from_var_list (vars);
 
-  for (i = 0; env_array[i]; i++)
-    {
-      l = assignment (env_array[i]);
-      name = env_array[i];
-      val = env_array[i] + l + 1;
-      name[l] = '\0';
-      temp = bind_variable (name, val);
-      name[l] = '=';
-    }
+  free (vars);
+  return (list);
 }
 
-void
-merge_temporary_env ()
+static char **
+make_func_export_array ()
 {
-  merge_env_array (temporary_env);
-}
+  char **list;
+  SHELL_VAR **vars;
 
-void
-merge_builtin_env ()
-{
-  merge_env_array (builtin_env);
-}
+  vars = map_over_funcs (visible_and_exported);
+  if (vars == 0)
+    return (char **)NULL;
 
-void
-merge_function_env ()
-{
-  merge_env_array (function_env);
-}
+  list = make_env_array_from_var_list (vars);
 
-#ifdef INCLUDE_UNUSED
-int
-any_temporary_variables ()
-{
-  return (temporary_env || function_env);
+  free (vars);
+  return (list);
 }
-#endif
 
 /* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
 #define add_to_export_env(envstr,do_alloc) \
@@ -2718,14 +2841,12 @@ do \
     if (export_env_index >= (export_env_size - 1)) \
       { \
        export_env_size += 16; \
-       export_env = (char **)xrealloc (export_env, export_env_size * sizeof (char *)); \
+       export_env = strvec_resize (export_env, export_env_size); \
       } \
     export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
     export_env[export_env_index] = (char *)NULL; \
   } while (0)
 
-#define ISFUNCTION(s, o) ((s[o + 1] == '(')  && (s[o + 2] == ')'))
-
 /* 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 **
@@ -2740,10 +2861,12 @@ add_or_supercede_exported_var (assign, do_alloc)
   if (equal_offset == 0)
     return (export_env);
 
-  /* If this is a function, then only supercede the function definition.
-     We do this by including the `=(' in the comparison.  */
-  if (assign[equal_offset + 1] == '(')
-    equal_offset++;
+  /* 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++)
     {
@@ -2758,73 +2881,107 @@ add_or_supercede_exported_var (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++'. */
+   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;
+}
+
 void
 maybe_make_export_env ()
 {
-  register int i;
   register char **temp_array;
   int new_size;
+  VAR_CONTEXT *tcxt;
 
   if (array_needs_making)
     {
       if (export_env)
-       free_array_members (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, without any temporary
-        or function environments. */
-      new_size = HASH_ENTRIES (shell_variables) + HASH_ENTRIES (shell_functions) + 1;
+        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 = (char **)xrealloc (export_env, export_env_size * sizeof (char *));
+         export_env = strvec_resize (export_env, export_env_size);
        }
       export_env[export_env_index = 0] = (char *)NULL;
 
-      temp_array = make_var_array (shell_variables);
+      /* 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)
-       {
-         for (i = 0; temp_array[i]; i++)
-           add_to_export_env (temp_array[i], 0);
-         free (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_var_array (shell_functions);
+      temp_array = restricted ? (char **)0 : make_func_export_array ();
 #else
-      temp_array = make_var_array (shell_functions);
+      temp_array = make_func_export_array ();
 #endif
       if (temp_array)
-       {
-         for (i = 0; temp_array[i]; i++)
-           add_to_export_env (temp_array[i], 0);
-         free (temp_array);
-       }
-
-      if (function_env)
-       for (i = 0; function_env[i]; i++)
-         export_env = add_or_supercede_exported_var (function_env[i], 1);
-
-      if (builtin_env)
-       for (i = 0; builtin_env[i]; i++)
-         export_env = add_or_supercede_exported_var (builtin_env[i], 1);
-
-      if (temporary_env)
-       for (i = 0; temporary_env[i]; i++)
-         export_env = add_or_supercede_exported_var (temporary_env[i], 1);
-
-#if 0
-      /* If we changed the array, then sort it alphabetically. */
-      if (posixly_correct == 0 && (temporary_env || function_env))
-       sort_char_array (export_env);
-#endif
+       add_temp_array_to_env (temp_array, 0, 0);
 
       array_needs_making = 0;
     }
@@ -2865,7 +3022,7 @@ put_command_name_into_env (command_name)
 #if 0  /* UNUSED -- it caused too many problems */
 void
 put_gnu_argv_flags_into_env (pid, flags_string)
-     long pid;
+     intmax_t pid;
      char *flags_string;
 {
   char *dummy, *pbuf;
@@ -2889,32 +3046,292 @@ put_gnu_argv_flags_into_env (pid, flags_string)
 }
 #endif
 
-/* Return a string denoting what our indirection level is. */
-static char indirection_string[100];
+/* **************************************************************** */
+/*                                                                 */
+/*                   Managing variable contexts                    */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Allocate and return a new variable context with NAME and FLAGS.
+   NAME can be NULL. */
 
-char *
-indirection_level_string ()
+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)))
+    {
+      /* XXX - should we set v->context here? */
+      v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0);
+      if (shell_variables == global_variables)
+       var->attributes &= ~(att_tempvar|att_propagate);
+      else
+        shell_variables->flags |= VC_HASTMPVAR;
+      v->attributes |= var->attributes;
+    }
+
+  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. */
+  if (exported_p (var) || (var->attributes & att_propagate))
+    {
+      var->attributes &= ~att_tempvar;         /* XXX */
+      v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0);
+      if (shell_variables == global_variables)
+       var->attributes &= ~att_propagate;
+      v->attributes |= var->attributes;
+    }
+
+  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 ()
 {
-  register int i, j;
-  char *ps4;
+  pop_dollar_vars ();
+  variable_context--;
+  pop_var_context ();
 
-  indirection_string[0] = '\0';
-  ps4 = get_string_value ("PS4");
+  sv_ifs ("IFS");              /* XXX here for now */
+}
 
-  if (ps4 == 0 || *ps4 == '\0')
-    return (indirection_string);
+/* 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;
+}
 
-  ps4 = decode_prompt_string (ps4);
+/* Restore the positional parameters from our stack. */
+void
+pop_dollar_vars ()
+{
+  if (!dollar_arg_stack || dollar_arg_stack_index == 0)
+    return;
 
-  for (i = 0; *ps4 && i < indirection_level && i < 99; i++)
-    indirection_string[i] = *ps4;
+  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 ();
+}
 
-  for (j = 1; *ps4 && ps4[j] && i < 99; i++, j++)
-    indirection_string[i] = ps4[j];
+void
+dispose_saved_dollar_vars ()
+{
+  if (!dollar_arg_stack || dollar_arg_stack_index == 0)
+    return;
 
-  indirection_string[i] = '\0';
-  free (ps4);
-  return (indirection_string);
+  dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
+  dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
 }
 
 /*************************************************
@@ -2938,75 +3355,131 @@ extern int hostname_list_initialized;
 
 #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;
-} special_vars[] = {
-  { "PATH", sv_path },
-  { "MAIL", sv_mail },
-  { "MAILPATH", sv_mail },
-  { "MAILCHECK", sv_mail },
+};
 
-  { "POSIXLY_CORRECT", sv_strict_posix },
+static struct name_and_function special_vars[] = {
   { "GLOBIGNORE", sv_globignore },
 
-  /* Variables which only do something special when READLINE is defined. */
-#if defined (READLINE)
-  { "TERM", sv_terminal },
-  { "TERMCAP", sv_terminal },
-  { "TERMINFO", sv_terminal },
-  { "HOSTFILE", sv_hostfile },
-#endif /* READLINE */
-
-  /* Variables which only do something special when HISTORY is defined. */
 #if defined (HISTORY)
+  { "HISTCONTROL", sv_history_control },
+  { "HISTFILESIZE", sv_histsize },
   { "HISTIGNORE", sv_histignore },
   { "HISTSIZE", sv_histsize },
-  { "HISTFILESIZE", sv_histsize },
-  { "HISTCONTROL", sv_history_control },
-#  if defined (BANG_HISTORY)
-  { "histchars", sv_histchars },
-#  endif /* BANG_HISTORY */
-#endif /* HISTORY */
+#endif
 
-  { "IGNOREEOF", sv_ignoreeof },
-  { "ignoreeof", sv_ignoreeof },
+#if defined (READLINE)
+  { "HOSTFILE", sv_hostfile },
+#endif
 
-  { "OPTIND", sv_optind },
-  { "OPTERR", sv_opterr },
+  { "IFS", sv_ifs },
+  { "IGNOREEOF", sv_ignoreeof },
 
-  { "TEXTDOMAIN", sv_locale },
-  { "TEXTDOMAINDIR", sv_locale },
+  { "LANG", sv_locale },
   { "LC_ALL", sv_locale },
   { "LC_COLLATE", sv_locale },
   { "LC_CTYPE", sv_locale },
   { "LC_MESSAGES", sv_locale },
   { "LC_NUMERIC", sv_locale },
-  { "LANG", sv_locale },
+
+  { "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) && defined (PROMPT_STRING_DECODE)
   { "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;
 
-  for (i = 0; special_vars[i].name; i++)
+  if (sv_sorted == 0)  /* shouldn't need, but it's fairly cheap. */
     {
-      if (STREQ (special_vars[i].name, name))
-       {
-         (*(special_vars[i].function)) (name);
-         return;
-       }
+      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);
+}
+
+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. */
@@ -3015,7 +3488,7 @@ sv_path (name)
      char *name;
 {
   /* hash -r */
-  flush_hashed_filenames ();
+  phash_flush ();
 }
 
 /* What to do just after one of the MAILxxxx variables has changed.  NAME
@@ -3084,7 +3557,7 @@ sv_histsize (name)
      char *name;
 {
   char *temp;
-  long num;
+  intmax_t num;
 
   temp = get_string_value (name);
 
@@ -3258,11 +3731,13 @@ sv_locale (name)
 
 #if defined (ARRAY_VARS)
 void
-set_pipestatus_array (ps)
+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];
 
@@ -3272,12 +3747,50 @@ set_pipestatus_array (ps)
   if (array_p (v) == 0)
     return;            /* Do nothing if not an array variable. */
   a = array_cell (v);
-  if (a)
-    empty_array (a);
-  for (i = 0; ps[i] != -1; i++)
+
+  if (a == 0 || array_num_elements (a) == 0)
     {
-      t = inttostr (ps[i], tbuf, sizeof (tbuf));
-      array_add_element (a, i, t);
+      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);
+       }
     }
 }
 #endif
@@ -3290,6 +3803,6 @@ set_pipestatus_from_exit (s)
   static int v[2] = { 0, -1 };
 
   v[0] = s;
-  set_pipestatus_array (v);
+  set_pipestatus_array (v, 1);
 #endif
 }
index f0da3ef33d570bad7a3217595ecd87c94bc9b856..213f6ff766787152043aecc4e8eb1846045b2e31 100644 (file)
@@ -1,6 +1,6 @@
 /* variables.h -- data structures for shell variables. */
 
-/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 
 #include "conftypes.h"
 
+/* A variable context. */
+typedef struct var_context {
+  char *name;          /* empty or NULL means global context */
+  int scope;           /* 0 means global context */
+  int flags;
+  struct var_context *up;      /* previous function calls */
+  struct var_context *down;    /* down towards global context */
+  HASH_TABLE *table;           /* variables at this scope */
+} VAR_CONTEXT;
+
+/* Flags for var_context->flags */
+#define VC_HASLOCAL    0x01
+#define VC_HASTMPVAR   0x02
+#define VC_FUNCENV     0x04    /* also function if name != NULL */
+#define VC_BLTNENV     0x08    /* builtin_env */
+#define VC_TEMPENV     0x10    /* temporary_env */
+
+#define VC_TEMPFLAGS   (VC_FUNCENV|VC_BLTNENV|VC_TEMPENV)
+
+/* Accessing macros */
+#define vc_isfuncenv(vc)       (((vc)->flags & VC_FUNCENV) != 0)
+#define vc_isbltnenv(vc)       (((vc)->flags & VC_BLTNENV) != 0)
+#define vc_istempenv(vc)       (((vc)->flags & (VC_TEMPFLAGS)) == VC_TEMPENV)
+
+#define vc_istempscope(vc)     (((vc)->flags & (VC_TEMPENV|VC_BLTNENV)) != 0)
+
+#define vc_haslocals(vc)       (((vc)->flags & VC_HASLOCAL) != 0)
+#define vc_hastmpvars(vc)      (((vc)->flags & VC_HASTMPVAR) != 0)
+
 /* What a shell variable looks like. */
 
-typedef struct variable *DYNAMIC_FUNC ();
+typedef struct variable *sh_var_value_func_t __P((struct variable *));
+typedef struct variable *sh_var_assign_func_t __P((struct variable *, char *, arrayind_t));
+
+/* For the future */
+union _value {
+  char *s;                     /* string value */
+  intmax_t i;                  /* int value */
+  COMMAND *f;                  /* function */
+  ARRAY *a;                    /* array */
+  HASH_TABLE *h;               /* associative array */
+  double d;                    /* floating point number */
+  void *v;                     /* opaque data for future use */
+};
 
 typedef struct variable {
   char *name;                  /* Symbol that the user types. */
   char *value;                 /* Value that is returned. */
   char *exportstr;             /* String for the environment. */
-  DYNAMIC_FUNC *dynamic_value; /* Function called to return a `dynamic'
+  sh_var_value_func_t *dynamic_value;  /* Function called to return a `dynamic'
                                   value for a variable, like $SECONDS
                                   or $RANDOM. */
-  DYNAMIC_FUNC *assign_func;   /* Function called when this `special
+  sh_var_assign_func_t *assign_func; /* Function called when this `special
                                   variable' is assigned a value in
                                   bind_variable. */
   int attributes;              /* export, readonly, array, invisible... */
   int context;                 /* Which context this variable belongs to. */
-  struct variable *prev_context; /* Value from previous context or NULL. */
 } SHELL_VAR;
 
+typedef struct _vlist {
+  SHELL_VAR **list;
+  int list_size;       /* allocated size */
+  int list_len;                /* current number of entries */
+} VARLIST;
+
 /* The various attributes that a given variable can have. */
-#define att_exported  0x001    /* export to environment */
-#define att_readonly  0x002    /* cannot change */
-#define att_invisible 0x004    /* cannot see */
-#define att_array     0x008    /* value is an array */
-#define att_nounset   0x010    /* cannot unset */
-#define att_function  0x020    /* value is a function */
-#define att_integer   0x040    /* internal representation is int */
-#define att_imported  0x080    /* came from environment */
-#define att_local     0x100    /* variable is local to a function */
-#define att_tempvar   0x200    /* variable came from the temp environment */
-#define att_importstr 0x400    /* exportstr points into initial environment */
-#define att_noassign  0x800    /* assignment not allowed */
+/* First, the user-visible attributes */
+#define att_exported   0x0000001       /* export to environment */
+#define att_readonly   0x0000002       /* cannot change */
+#define att_array      0x0000004       /* value is an array */
+#define att_function   0x0000008       /* value is a function */
+#define att_integer    0x0000010       /* internal representation is int */
+#define att_local      0x0000020       /* variable is local to a function */
+#define att_assoc      0x0000040       /* variable is an associative array */
+#define att_trace      0x0000080       /* function is traced with DEBUG trap */
+
+#define attmask_user   0x0000fff
+
+/* Internal attributes used for bookkeeping */
+#define att_invisible  0x0001000       /* cannot see */
+#define att_nounset    0x0002000       /* cannot unset */
+#define att_noassign   0x0004000       /* assignment not allowed */
+#define att_imported   0x0008000       /* came from environment */
+#define att_special    0x0010000       /* requires special handling */
+
+#define        attmask_int     0x00ff000
+
+/* Internal attributes used for variable scoping. */
+#define att_tempvar    0x0100000       /* variable came from the temp environment */
+#define att_propagate  0x0200000       /* propagate to previous scope */
+
+#define attmask_scope  0x0f00000
 
 #define exported_p(var)                ((((var)->attributes) & (att_exported)))
 #define readonly_p(var)                ((((var)->attributes) & (att_readonly)))
-#define invisible_p(var)       ((((var)->attributes) & (att_invisible)))
 #define array_p(var)           ((((var)->attributes) & (att_array)))
-#define non_unsettable_p(var)  ((((var)->attributes) & (att_nounset)))
 #define function_p(var)                ((((var)->attributes) & (att_function)))
 #define integer_p(var)         ((((var)->attributes) & (att_integer)))
-#define imported_p(var)                ((((var)->attributes) & (att_imported)))
 #define local_p(var)           ((((var)->attributes) & (att_local)))
-#define tempvar_p(var)         ((((var)->attributes) & (att_tempvar)))
+#define assoc_p(var)           ((((var)->attributes) & (att_assoc)))
+#define trace_p(var)           ((((var)->attributes) & (att_trace)))
+
+#define invisible_p(var)       ((((var)->attributes) & (att_invisible)))
+#define non_unsettable_p(var)  ((((var)->attributes) & (att_nounset)))
 #define noassign_p(var)                ((((var)->attributes) & (att_noassign)))
+#define imported_p(var)                ((((var)->attributes) & (att_imported)))
+#define specialvar_p(var)      ((((var)->attributes) & (att_special)))
+
+#define tempvar_p(var)         ((((var)->attributes) & (att_tempvar)))
+
+/* Acessing variable values: rvalues */
+#define value_cell(var)                ((var)->value)
+#define function_cell(var)     (COMMAND *)((var)->value)
+#define array_cell(var)                (ARRAY *)((var)->value)
+
+#define var_isnull(var)                ((var)->value == 0)
+#define var_isset(var)         ((var)->value != 0)
+
+/* Assigning variable values: lvalues */
+#define var_setvalue(var, str) ((var)->value = (str))
+#define var_setfunc(var, func) ((var)->value = (char *)(func))
+#define var_setarray(var, arr) ((var)->value = (char *)(arr))
 
-#define value_cell(var) ((var)->value)
-#define function_cell(var) (COMMAND *)((var)->value)
-#define array_cell(var) ((ARRAY *)(var)->value)
+/* Make VAR be auto-exported. */
+#define set_auto_export(var) \
+  do { (var)->attributes |= att_exported; array_needs_making = 1; } while (0)
 
 #define SETVARATTR(var, attr, undo) \
        ((undo == 0) ? ((var)->attributes |= (attr)) \
@@ -97,58 +175,43 @@ typedef struct variable {
 #define SAVE_EXPORTSTR(var, value) (var)->exportstr = (value) ? savestring (value) : (char *)NULL
 
 #define FREE_EXPORTSTR(var) \
-       do { \
-         if ((var)->exportstr) \
-           { \
-             if (((var)->attributes & att_importstr) == 0) \
-               free ((var)->exportstr); \
-           } \
-       } while (0)
+       do { if ((var)->exportstr) free ((var)->exportstr); } while (0)
 
-#if 0
 #define CACHE_IMPORTSTR(var, value) \
-       do { \
-         (var)->exportstr = value; \
-         (var)->attributes |= att_importstr; \
-       } while (0)
-#else
-#define CACHE_IMPORTSTR(var, value) \
-       do { \
-         (var)->exportstr = savestring (value); \
-       } while (0)
-#endif
+       (var)->exportstr = savestring (value)
 
 #define INVALIDATE_EXPORTSTR(var) \
        do { \
          if ((var)->exportstr) \
            { \
-             if (((var)->attributes & att_importstr) == 0) \
-               free ((var)->exportstr); \
+             free ((var)->exportstr); \
              (var)->exportstr = (char *)NULL; \
-             (var)->attributes &= ~att_importstr; \
            } \
        } while (0)
        
 /* Stuff for hacking variables. */
 typedef int sh_var_map_func_t __P((SHELL_VAR *));
 
+/* Where we keep the variables and functions */
+extern VAR_CONTEXT *global_variables;
+extern VAR_CONTEXT *shell_variables;
+
+extern HASH_TABLE *shell_functions;
+extern HASH_TABLE *temporary_env;
+
 extern int variable_context;
-extern HASH_TABLE *shell_variables, *shell_functions;
 extern char *dollar_vars[];
 extern char **export_env;
-extern char **non_unsettable_vars;
 
 extern void initialize_shell_variables __P((char **, int));
 extern SHELL_VAR *set_if_not __P((char *, char *));
-extern void sh_set_lines_and_columns __P((int, int));
 
+extern void sh_set_lines_and_columns __P((int, int));
 extern void set_pwd __P((void));
-
 extern void set_ppid __P((void));
-
 extern void make_funcname_visible __P((int));
 
-extern SHELL_VAR *var_lookup __P((const char *, HASH_TABLE *));
+extern SHELL_VAR *var_lookup __P((const char *, VAR_CONTEXT *));
 
 extern SHELL_VAR *find_function __P((const char *));
 extern SHELL_VAR *find_variable __P((const char *));
@@ -159,35 +222,53 @@ extern SHELL_VAR *make_local_variable __P((const char *));
 extern SHELL_VAR *bind_variable __P((const char *, char *));
 extern SHELL_VAR *bind_function __P((const char *, COMMAND *));
 
-extern SHELL_VAR **map_over __P((sh_var_map_func_t *, HASH_TABLE *));
+extern SHELL_VAR **map_over __P((sh_var_map_func_t *, VAR_CONTEXT *));
+SHELL_VAR **map_over_funcs __P((sh_var_map_func_t *));
+     
 extern SHELL_VAR **all_shell_variables __P((void));
 extern SHELL_VAR **all_shell_functions __P((void));
 extern SHELL_VAR **all_visible_variables __P((void));
 extern SHELL_VAR **all_visible_functions __P((void));
 extern SHELL_VAR **all_exported_variables __P((void));
+extern SHELL_VAR **local_exported_variables __P((void));
+extern SHELL_VAR **all_local_variables __P((void));
 #if defined (ARRAY_VARS)
 extern SHELL_VAR **all_array_variables __P((void));
 #endif
-
 extern char **all_variables_matching_prefix __P((const char *));
 
 extern char **make_var_array __P((HASH_TABLE *));
 extern char **add_or_supercede_exported_var __P((char *, int));
 
+extern char *get_variable_value __P((SHELL_VAR *));
 extern char *get_string_value __P((const char *));
+extern char *sh_get_env_value __P((const char *));
 extern char *make_variable_value __P((SHELL_VAR *, char *));
 
 extern SHELL_VAR *bind_variable_value __P((SHELL_VAR *, char *));
 extern SHELL_VAR *bind_int_variable __P((char *, char *));
-extern SHELL_VAR *bind_var_to_int __P((char *, long));
+extern SHELL_VAR *bind_var_to_int __P((char *, intmax_t));
 
-extern int assignment __P((const char *));
-extern int variable_in_context __P((SHELL_VAR *));
 extern int assign_in_env __P((const char *));
 extern int unbind_variable __P((const char *));
-extern int makunbound __P((const char *, HASH_TABLE *));
+extern int unbind_func __P((const char *));
+extern int makunbound __P((const char *, VAR_CONTEXT *));
 extern int kill_local_variable __P((const char *));
 extern void delete_all_variables __P((HASH_TABLE *));
+extern void delete_all_contexts __P((VAR_CONTEXT *));
+
+extern VAR_CONTEXT *new_var_context __P((char *, int));
+extern void dispose_var_context __P((VAR_CONTEXT *));
+extern VAR_CONTEXT *push_var_context __P((char *, int, HASH_TABLE *));
+extern void pop_var_context __P((void));
+extern VAR_CONTEXT *push_scope __P((int, HASH_TABLE *));
+extern void pop_scope __P((int));
+
+extern void push_context __P((char *, int, HASH_TABLE *));
+extern void pop_context __P((void));
+extern void push_dollar_vars __P((void));
+extern void pop_dollar_vars __P((void));
+extern void dispose_saved_dollar_vars __P((void));
 
 extern void adjust_shell_level __P((int));
 extern void non_unsettable __P((char *));
@@ -197,30 +278,31 @@ extern void dispose_function_env __P((void));
 extern void dispose_builtin_env __P((void));
 extern void merge_temporary_env __P((void));
 extern void merge_builtin_env __P((void));
-extern void merge_function_env __P((void));
 extern void kill_all_local_variables __P((void));
+
 extern void set_var_read_only __P((char *));
 extern void set_func_read_only __P((const char *));
 extern void set_var_auto_export __P((char *));
 extern void set_func_auto_export __P((const char *));
+
 extern void sort_variables __P((SHELL_VAR **));
+
 extern void maybe_make_export_env __P((void));
 extern void update_export_env_inplace __P((char *, int, char *));
 extern void put_command_name_into_env __P((char *));
-extern void put_gnu_argv_flags_into_env __P((long, char *));
+extern void put_gnu_argv_flags_into_env __P((intmax_t, char *));
+
 extern void print_var_list __P((SHELL_VAR **));
 extern void print_func_list __P((SHELL_VAR **));
 extern void print_assignment __P((SHELL_VAR *));
 extern void print_var_value __P((SHELL_VAR *, int));
 extern void print_var_function __P((SHELL_VAR *));
 
-extern char *indirection_level_string __P((void));
-
 #if defined (ARRAY_VARS)
 extern SHELL_VAR *make_new_array_variable __P((char *));
 extern SHELL_VAR *make_local_array_variable __P((char *));
 
-extern void set_pipestatus_array __P((int *));
+extern void set_pipestatus_array __P((int *, int));
 #endif
 
 extern void set_pipestatus_from_exit __P((int));
@@ -233,6 +315,7 @@ extern int get_random_number __P((void));
 
 /* The `special variable' functions that get called when a particular
    variable is set. */
+extern void sv_ifs __P((char *));
 extern void sv_path __P((char *));
 extern void sv_mail __P((char *));
 extern void sv_globignore __P((char *));
index ec1832627b1c3d55a0c9d5920851322bc675038f..9ff00e5df7a956fe5cebb31f9259231bf2000e94 100644 (file)
--- a/version.c
+++ b/version.c
@@ -65,5 +65,5 @@ show_shell_version (extended)
 {
   printf ("GNU bash, version %s (%s)\n", shell_version_string (), MACHTYPE);
   if (extended)
-    printf ("Copyright 2001 Free Software Foundation, Inc.\n");
+    printf ("Copyright (C) 2002 Free Software Foundation, Inc.\n");
 }
index 2da8e70884bcfed629c922aa3a9c3ae489b116bb..c2011f9cc9af7bef7e24a71f1d5540a877027fcc 100644 (file)
--- a/xmalloc.c
+++ b/xmalloc.c
@@ -112,7 +112,7 @@ xrealloc (pointer, bytes)
       allocated = findbrk ();
       fatal_error ("xrealloc: cannot reallocate %lu bytes (%lu bytes allocated)", (unsigned long)bytes, (unsigned long)allocated);
 #else
-      fatal_error ("xmalloc: cannot allocate %lu bytes", (unsigned long)bytes);
+      fatal_error ("xrealloc: cannot allocate %lu bytes", (unsigned long)bytes);
 #endif /* !HAVE_SBRK */
     }
 
index 2c0a1092bc92619820a14ea867d12eb55589e219..5ae8294cee2ce713d5644a7aa98f06892e53744f 100644 (file)
--- a/xmalloc.h
+++ b/xmalloc.h
@@ -40,7 +40,7 @@ extern PTR_T xmalloc __P((size_t));
 extern PTR_T xrealloc __P((void *, size_t));
 extern void xfree __P((void *));
 
-#ifdef USING_BASH_MALLOC
+#if defined(USING_BASH_MALLOC) && !defined (DISABLE_MALLOC_WRAPPERS)
 extern PTR_T sh_xmalloc __P((size_t, const char *, int));
 extern PTR_T sh_xrealloc __P((void *, size_t, const char *, int));
 extern void sh_xfree __P((void *, const char *, int));
diff --git a/y.tab.c b/y.tab.c
index 9c95f651de0362dcb8aebdb776dcc2963d5bcc97..c3ff7797d2cc2a8589fb2ed6e52a515beaa6aa1e 100644 (file)
--- a/y.tab.c
+++ b/y.tab.c
@@ -1,48 +1,48 @@
-
-/*  A Bison parser, made from /usr/homes/chet/src/bash/src/parse.y
-    by GNU Bison version 1.28  */
+/* A Bison parser, made from /usr/homes/chet/src/bash/src/parse.y
+   by GNU bison 1.34.  */
 
 #define YYBISON 1  /* Identify Bison output.  */
 
-#define        IF      257
-#define        THEN    258
-#define        ELSE    259
-#define        ELIF    260
-#define        FI      261
-#define        CASE    262
-#define        ESAC    263
-#define        FOR     264
-#define        SELECT  265
-#define        WHILE   266
-#define        UNTIL   267
-#define        DO      268
-#define        DONE    269
-#define        FUNCTION        270
-#define        COND_START      271
-#define        COND_END        272
-#define        COND_ERROR      273
-#define        IN      274
-#define        BANG    275
-#define        TIME    276
-#define        TIMEOPT 277
-#define        WORD    278
-#define        ASSIGNMENT_WORD 279
-#define        NUMBER  280
-#define        ARITH_CMD       281
-#define        ARITH_FOR_EXPRS 282
-#define        COND_CMD        283
-#define        AND_AND 284
-#define        OR_OR   285
-#define        GREATER_GREATER 286
-#define        LESS_LESS       287
-#define        LESS_AND        288
-#define        GREATER_AND     289
-#define        SEMI_SEMI       290
-#define        LESS_LESS_MINUS 291
-#define        AND_GREATER     292
-#define        LESS_GREATER    293
-#define        GREATER_BAR     294
-#define        yacc_EOF        295
+# define       IF      257
+# define       THEN    258
+# define       ELSE    259
+# define       ELIF    260
+# define       FI      261
+# define       CASE    262
+# define       ESAC    263
+# define       FOR     264
+# define       SELECT  265
+# define       WHILE   266
+# define       UNTIL   267
+# define       DO      268
+# define       DONE    269
+# define       FUNCTION        270
+# define       COND_START      271
+# define       COND_END        272
+# define       COND_ERROR      273
+# define       IN      274
+# define       BANG    275
+# define       TIME    276
+# define       TIMEOPT 277
+# define       WORD    278
+# define       ASSIGNMENT_WORD 279
+# define       NUMBER  280
+# define       ARITH_CMD       281
+# define       ARITH_FOR_EXPRS 282
+# define       COND_CMD        283
+# define       AND_AND 284
+# define       OR_OR   285
+# define       GREATER_GREATER 286
+# define       LESS_LESS       287
+# define       LESS_AND        288
+# define       LESS_LESS_LESS  289
+# define       GREATER_AND     290
+# define       SEMI_SEMI       291
+# define       LESS_LESS_MINUS 292
+# define       AND_GREATER     293
+# define       LESS_GREATER    294
+# define       GREATER_BAR     295
+# define       yacc_EOF        296
 
 #line 21 "/usr/homes/chet/src/bash/src/parse.y"
 
@@ -67,6 +67,8 @@
 
 #include "memalloc.h"
 
+#define NEED_STRFTIME_DECL     /* used in externs.h */
+
 #include "shell.h"
 #include "trap.h"
 #include "flags.h"
@@ -76,6 +78,8 @@
 #include "builtins/common.h"
 #include "builtins/builtext.h"
 
+#include "shmbutil.h"
+
 #if defined (READLINE)
 #  include "bashline.h"
 #  include <readline/readline.h>
 #    include <sys/param.h>
 #  endif
 #  include <time.h>
+#  if defined (TM_IN_SYS_TIME)
+#    include <sys/types.h>
+#    include <sys/time.h>
+#  endif /* TM_IN_SYS_TIME */
 #  include "maxpath.h"
 #endif /* PROMPT_STRING_DECODE */
 
 #define RE_READ_TOKEN  -99
 #define NO_EXPANSION   -100
 
-#define YYDEBUG 0
+#ifdef DEBUG
+#  define YYDEBUG 1
+#else
+#  define YYDEBUG 0
+#endif
+
+#if defined (HANDLE_MULTIBYTE)
+#  define last_shell_getc_is_singlebyte \
+       ((shell_input_line_index > 1) \
+               ? shell_input_line_property[shell_input_line_index - 1] \
+               : 1)
+#  define MBTEST(x)    ((x) && last_shell_getc_is_singlebyte)
+#else
+#  define last_shell_getc_is_singlebyte        1
+#  define MBTEST(x)    ((x))
+#endif
 
 #if defined (EXTENDED_GLOB)
 extern int extended_glob;
@@ -163,9 +186,6 @@ static void free_string_list __P((void));
 
 static char *read_a_line __P((int));
 
-static char *ansiexpand __P((char *, int, int, int *));
-static char *mk_msgstr __P((char *, int *));
-static char *localeexpand __P((char *, int, int, int, int *));
 static int reserved_word_acceptable __P((int));
 static int yylex __P((void));
 static int alias_expand_token __P((char *));
@@ -173,10 +193,15 @@ static int time_command_acceptable __P((void));
 static int special_case_tokens __P((char *));
 static int read_token __P((int));
 static char *parse_matched_pair __P((int, int, int, int *, int));
+#if defined (ARRAY_VARS)
+static char *parse_compound_assignment __P((int *));
+#endif
 #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
+static int parse_dparen __P((int));
 static int parse_arith_cmd __P((char **));
 #endif
 #if defined (COND_COMMAND)
+static void cond_error __P((void));
 static COND_COM *cond_expr __P((void));
 static COND_COM *cond_or __P((void));
 static COND_COM *cond_and __P((void));
@@ -184,10 +209,18 @@ static COND_COM *cond_term __P((void));
 static int cond_skip_newlines __P((void));
 static COMMAND *parse_cond_command __P((void));
 #endif
+#if defined (ARRAY_VARS)
+static int token_is_assignment __P((char *, int));
+static int token_is_ident __P((char *, int));
+#endif
 static int read_token_word __P((int));
 static void discard_parser_constructs __P((int));
 
+static char *error_token_from_token __P((int));
+static char *error_token_from_text __P((void));
+static void print_offending_line __P((void));
 static void report_syntax_error __P((char *));
+
 static void handle_eof_input_unit __P((void));
 static void prompt_again __P((void));
 #if 0
@@ -199,8 +232,19 @@ static void print_prompt __P((void));
 char *history_delimiting_chars __P((void));
 #endif
 
+#if defined (HANDLE_MULTIBYTE)
+static void set_line_mbstate __P((void));
+static char *shell_input_line_property = NULL;
+#else
+#  define set_line_mbstate()
+#endif
+
 extern int yyerror __P((const char *));
 
+#ifdef DEBUG
+extern int yydebug;
+#endif
+
 /* Default prompt strings */
 char *primary_prompt = PPROMPT;
 char *secondary_prompt = SPROMPT;
@@ -255,7 +299,8 @@ static int arith_for_lineno;
 
 static REDIRECTEE redir;
 
-#line 232 "/usr/homes/chet/src/bash/src/parse.y"
+#line 276 "/usr/homes/chet/src/bash/src/parse.y"
+#ifndef YYSTYPE
 typedef union {
   WORD_DESC *word;             /* the word that we read. */
   int number;                  /* the number that we read. */
@@ -264,425 +309,454 @@ typedef union {
   REDIRECT *redirect;
   ELEMENT element;
   PATTERN_LIST *pattern;
-} YYSTYPE;
-#include <stdio.h>
-
-#ifndef __cplusplus
-#ifndef __STDC__
-#define const
+} yystype;
+# define YYSTYPE yystype
 #endif
+#ifndef YYDEBUG
+# define YYDEBUG 0
 #endif
 
 
 
-#define        YYFINAL         295
+#define        YYFINAL         301
 #define        YYFLAG          -32768
-#define        YYNTBASE        53
-
-#define YYTRANSLATE(x) ((unsigned)(x) <= 295 ? yytranslate[x] : 88)
-
-static const char yytranslate[] = {     0,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,    43,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,    41,     2,    51,
-    52,     2,     2,     2,    48,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,    42,    47,
-     2,    46,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,    49,    45,    50,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     1,     3,     4,     5,     6,
-     7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
-    17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
-    27,    28,    29,    30,    31,    32,    33,    34,    35,    36,
-    37,    38,    39,    40,    44
-};
+#define        YYNTBASE        54
 
-#if YYDEBUG != 0
-static const short yyprhs[] = {     0,
-     0,     3,     5,     8,    10,    12,    15,    18,    21,    25,
-    29,    32,    36,    39,    43,    46,    50,    53,    57,    60,
-    64,    67,    71,    74,    78,    81,    85,    88,    92,    95,
-    99,   102,   105,   109,   111,   113,   115,   117,   120,   122,
-   125,   127,   129,   132,   134,   136,   138,   144,   150,   152,
-   154,   156,   158,   160,   162,   164,   171,   178,   186,   194,
-   205,   216,   226,   236,   244,   252,   258,   264,   271,   278,
-   286,   294,   305,   316,   323,   331,   338,   344,   351,   356,
-   358,   361,   365,   371,   379,   386,   390,   392,   396,   401,
-   408,   414,   416,   419,   424,   429,   435,   441,   444,   448,
-   450,   454,   457,   459,   462,   466,   470,   474,   479,   484,
-   489,   494,   499,   501,   503,   505,   507,   508,   511,   513,
-   516,   519,   524,   529,   533,   537,   539,   541,   544,   547,
-   551,   555,   560,   562,   564
+/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */
+#define YYTRANSLATE(x) ((unsigned)(x) <= 296 ? yytranslate[x] : 90)
+
+/* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */
+static const char yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+      44,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    42,     2,
+      52,    53,     2,     2,     2,    49,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,    43,
+      48,     2,    47,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,    50,    46,    51,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
+      36,    37,    38,    39,    40,    41,    45
 };
 
-static const short yyrhs[] = {    83,
-    43,     0,    43,     0,     1,    43,     0,    44,     0,    24,
-     0,    54,    24,     0,    46,    24,     0,    47,    24,     0,
-    26,    46,    24,     0,    26,    47,    24,     0,    32,    24,
-     0,    26,    32,    24,     0,    33,    24,     0,    26,    33,
-    24,     0,    34,    26,     0,    26,    34,    26,     0,    35,
-    26,     0,    26,    35,    26,     0,    34,    24,     0,    26,
-    34,    24,     0,    35,    24,     0,    26,    35,    24,     0,
-    37,    24,     0,    26,    37,    24,     0,    35,    48,     0,
-    26,    35,    48,     0,    34,    48,     0,    26,    34,    48,
-     0,    38,    24,     0,    26,    39,    24,     0,    39,    24,
-     0,    40,    24,     0,    26,    40,    24,     0,    24,     0,
-    25,     0,    55,     0,    55,     0,    57,    55,     0,    56,
-     0,    58,    56,     0,    58,     0,    60,     0,    60,    57,
-     0,    65,     0,    61,     0,    64,     0,    12,    78,    14,
-    78,    15,     0,    13,    78,    14,    78,    15,     0,    63,
-     0,    68,     0,    67,     0,    69,     0,    70,     0,    71,
-     0,    62,     0,    10,    24,    82,    14,    78,    15,     0,
-    10,    24,    82,    49,    78,    50,     0,    10,    24,    42,
-    82,    14,    78,    15,     0,    10,    24,    42,    82,    49,
-    78,    50,     0,    10,    24,    82,    20,    54,    81,    82,
-    14,    78,    15,     0,    10,    24,    82,    20,    54,    81,
-    82,    49,    78,    50,     0,    10,    24,    82,    20,    81,
-    82,    14,    78,    15,     0,    10,    24,    82,    20,    81,
-    82,    49,    78,    50,     0,    10,    28,    81,    82,    14,
-    78,    15,     0,    10,    28,    81,    82,    49,    78,    50,
-     0,    10,    28,    14,    78,    15,     0,    10,    28,    49,
-    78,    50,     0,    11,    24,    82,    14,    77,    15,     0,
-    11,    24,    82,    49,    77,    50,     0,    11,    24,    42,
-    82,    14,    77,    15,     0,    11,    24,    42,    82,    49,
-    77,    50,     0,    11,    24,    82,    20,    54,    81,    82,
-    14,    77,    15,     0,    11,    24,    82,    20,    54,    81,
-    82,    49,    77,    50,     0,     8,    24,    82,    20,    82,
-     9,     0,     8,    24,    82,    20,    75,    82,     9,     0,
-     8,    24,    82,    20,    73,     9,     0,    24,    51,    52,
-    82,    66,     0,    16,    24,    51,    52,    82,    66,     0,
-    16,    24,    82,    66,     0,    60,     0,    60,    57,     0,
-    51,    78,    52,     0,     3,    78,     4,    78,     7,     0,
-     3,    78,     4,    78,     5,    78,     7,     0,     3,    78,
-     4,    78,    72,     7,     0,    49,    78,    50,     0,    27,
-     0,    17,    29,    18,     0,     6,    78,     4,    78,     0,
-     6,    78,     4,    78,     5,    78,     0,     6,    78,     4,
-    78,    72,     0,    74,     0,    75,    74,     0,    82,    76,
-    52,    78,     0,    82,    76,    52,    82,     0,    82,    51,
-    76,    52,    78,     0,    82,    51,    76,    52,    82,     0,
-    74,    36,     0,    75,    74,    36,     0,    24,     0,    76,
-    45,    24,     0,    82,    79,     0,    77,     0,    82,    80,
-     0,    80,    43,    82,     0,    80,    41,    82,     0,    80,
-    42,    82,     0,    80,    30,    82,    80,     0,    80,    31,
-    82,    80,     0,    80,    41,    82,    80,     0,    80,    42,
-    82,    80,     0,    80,    43,    82,    80,     0,    85,     0,
-    43,     0,    42,     0,    44,     0,     0,    82,    43,     0,
-    84,     0,    84,    41,     0,    84,    42,     0,    84,    30,
-    82,    84,     0,    84,    31,    82,    84,     0,    84,    41,
-    84,     0,    84,    42,    84,     0,    85,     0,    86,     0,
-    21,    86,     0,    87,    86,     0,    87,    21,    86,     0,
-    21,    87,    86,     0,    86,    45,    82,    86,     0,    59,
-     0,    22,     0,    22,    23,     0
+#if YYDEBUG
+static const short yyprhs[] =
+{
+       0,     0,     3,     5,     8,    10,    12,    15,    18,    21,
+      25,    29,    32,    36,    39,    43,    46,    50,    53,    57,
+      60,    64,    67,    71,    74,    78,    81,    85,    88,    92,
+      95,    99,   102,   106,   109,   112,   116,   118,   120,   122,
+     124,   127,   129,   132,   134,   136,   139,   141,   143,   145,
+     151,   157,   159,   161,   163,   165,   167,   169,   171,   178,
+     185,   193,   201,   212,   223,   233,   243,   251,   259,   265,
+     271,   278,   285,   293,   301,   312,   323,   330,   338,   345,
+     351,   358,   363,   365,   368,   372,   378,   386,   393,   397,
+     399,   403,   408,   415,   421,   423,   426,   431,   436,   442,
+     448,   451,   455,   457,   461,   464,   466,   469,   473,   477,
+     481,   486,   491,   496,   501,   506,   508,   510,   512,   514,
+     516,   518,   519,   522,   524,   527,   530,   535,   540,   544,
+     548,   550,   552,   555,   558,   562,   566,   571,   573,   575
+};
+static const short yyrhs[] =
+{
+      85,    82,     0,    44,     0,     1,    44,     0,    45,     0,
+      24,     0,    55,    24,     0,    47,    24,     0,    48,    24,
+       0,    26,    47,    24,     0,    26,    48,    24,     0,    32,
+      24,     0,    26,    32,    24,     0,    33,    24,     0,    26,
+      33,    24,     0,    35,    24,     0,    26,    35,    24,     0,
+      34,    26,     0,    26,    34,    26,     0,    36,    26,     0,
+      26,    36,    26,     0,    34,    24,     0,    26,    34,    24,
+       0,    36,    24,     0,    26,    36,    24,     0,    38,    24,
+       0,    26,    38,    24,     0,    36,    49,     0,    26,    36,
+      49,     0,    34,    49,     0,    26,    34,    49,     0,    39,
+      24,     0,    26,    40,    24,     0,    40,    24,     0,    41,
+      24,     0,    26,    41,    24,     0,    24,     0,    25,     0,
+      56,     0,    56,     0,    58,    56,     0,    57,     0,    59,
+      57,     0,    59,     0,    61,     0,    61,    58,     0,    66,
+       0,    62,     0,    65,     0,    12,    79,    14,    79,    15,
+       0,    13,    79,    14,    79,    15,     0,    64,     0,    69,
+       0,    68,     0,    70,     0,    71,     0,    72,     0,    63,
+       0,    10,    24,    84,    14,    79,    15,     0,    10,    24,
+      84,    50,    79,    51,     0,    10,    24,    43,    84,    14,
+      79,    15,     0,    10,    24,    43,    84,    50,    79,    51,
+       0,    10,    24,    84,    20,    55,    83,    84,    14,    79,
+      15,     0,    10,    24,    84,    20,    55,    83,    84,    50,
+      79,    51,     0,    10,    24,    84,    20,    83,    84,    14,
+      79,    15,     0,    10,    24,    84,    20,    83,    84,    50,
+      79,    51,     0,    10,    28,    83,    84,    14,    79,    15,
+       0,    10,    28,    83,    84,    50,    79,    51,     0,    10,
+      28,    14,    79,    15,     0,    10,    28,    50,    79,    51,
+       0,    11,    24,    84,    14,    78,    15,     0,    11,    24,
+      84,    50,    78,    51,     0,    11,    24,    43,    84,    14,
+      78,    15,     0,    11,    24,    43,    84,    50,    78,    51,
+       0,    11,    24,    84,    20,    55,    83,    84,    14,    78,
+      15,     0,    11,    24,    84,    20,    55,    83,    84,    50,
+      78,    51,     0,     8,    24,    84,    20,    84,     9,     0,
+       8,    24,    84,    20,    76,    84,     9,     0,     8,    24,
+      84,    20,    74,     9,     0,    24,    52,    53,    84,    67,
+       0,    16,    24,    52,    53,    84,    67,     0,    16,    24,
+      84,    67,     0,    61,     0,    61,    58,     0,    52,    79,
+      53,     0,     3,    79,     4,    79,     7,     0,     3,    79,
+       4,    79,     5,    79,     7,     0,     3,    79,     4,    79,
+      73,     7,     0,    50,    79,    51,     0,    27,     0,    17,
+      29,    18,     0,     6,    79,     4,    79,     0,     6,    79,
+       4,    79,     5,    79,     0,     6,    79,     4,    79,    73,
+       0,    75,     0,    76,    75,     0,    84,    77,    53,    79,
+       0,    84,    77,    53,    84,     0,    84,    52,    77,    53,
+      79,     0,    84,    52,    77,    53,    84,     0,    75,    37,
+       0,    76,    75,    37,     0,    24,     0,    77,    46,    24,
+       0,    84,    80,     0,    78,     0,    84,    81,     0,    81,
+      44,    84,     0,    81,    42,    84,     0,    81,    43,    84,
+       0,    81,    30,    84,    81,     0,    81,    31,    84,    81,
+       0,    81,    42,    84,    81,     0,    81,    43,    84,    81,
+       0,    81,    44,    84,    81,     0,    87,     0,    44,     0,
+      45,     0,    44,     0,    43,     0,    45,     0,     0,    84,
+      44,     0,    86,     0,    86,    42,     0,    86,    43,     0,
+      86,    30,    84,    86,     0,    86,    31,    84,    86,     0,
+      86,    42,    86,     0,    86,    43,    86,     0,    87,     0,
+      88,     0,    21,    88,     0,    89,    88,     0,    89,    21,
+      88,     0,    21,    89,    88,     0,    88,    46,    84,    88,
+       0,    60,     0,    22,     0,    22,    23,     0
 };
 
 #endif
 
-#if YYDEBUG != 0
-static const short yyrline[] = { 0,
-   282,   291,   298,   313,   323,   325,   329,   334,   339,   344,
-   349,   354,   359,   365,   371,   376,   381,   386,   391,   396,
-   401,   406,   411,   418,   425,   430,   435,   440,   445,   450,
-   455,   460,   465,   472,   474,   476,   480,   484,   495,   497,
-   501,   503,   505,   521,   525,   527,   529,   531,   533,   535,
-   537,   539,   541,   543,   545,   549,   551,   553,   555,   557,
-   559,   561,   563,   567,   569,   571,   573,   577,   581,   585,
-   589,   593,   597,   603,   605,   607,   611,   614,   617,   622,
-   624,   655,   662,   664,   666,   671,   675,   679,   683,   685,
-   687,   691,   692,   696,   698,   700,   702,   706,   707,   711,
-   713,   722,   730,   731,   737,   738,   745,   749,   751,   753,
-   760,   762,   764,   768,   769,   770,   773,   774,   783,   789,
-   798,   806,   808,   810,   817,   820,   824,   826,   831,   836,
-   841,   848,   851,   855,   857
+#if YYDEBUG
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const short yyrline[] =
+{
+       0,   326,   335,   342,   357,   367,   369,   373,   378,   383,
+     388,   393,   398,   403,   409,   415,   420,   425,   430,   435,
+     440,   445,   450,   455,   460,   465,   472,   479,   484,   489,
+     494,   499,   504,   509,   514,   519,   526,   528,   530,   534,
+     538,   549,   551,   555,   557,   559,   575,   579,   581,   583,
+     585,   587,   589,   591,   593,   595,   597,   599,   603,   605,
+     607,   609,   611,   613,   615,   617,   621,   623,   625,   627,
+     631,   635,   639,   643,   647,   651,   657,   659,   661,   665,
+     668,   671,   676,   678,   709,   716,   718,   720,   725,   729,
+     733,   737,   739,   741,   745,   746,   750,   752,   754,   756,
+     760,   761,   765,   767,   776,   784,   785,   791,   792,   799,
+     803,   805,   807,   814,   816,   818,   822,   823,   826,   827,
+     828,   831,   832,   841,   847,   856,   864,   866,   868,   875,
+     878,   882,   884,   889,   894,   899,   906,   909,   913,   915
 };
 #endif
 
 
-#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
-
-static const char * const yytname[] = {   "$","error","$undefined.","IF","THEN",
-"ELSE","ELIF","FI","CASE","ESAC","FOR","SELECT","WHILE","UNTIL","DO","DONE",
-"FUNCTION","COND_START","COND_END","COND_ERROR","IN","BANG","TIME","TIMEOPT",
-"WORD","ASSIGNMENT_WORD","NUMBER","ARITH_CMD","ARITH_FOR_EXPRS","COND_CMD","AND_AND",
-"OR_OR","GREATER_GREATER","LESS_LESS","LESS_AND","GREATER_AND","SEMI_SEMI","LESS_LESS_MINUS",
-"AND_GREATER","LESS_GREATER","GREATER_BAR","'&'","';'","'\\n'","yacc_EOF","'|'",
-"'>'","'<'","'-'","'{'","'}'","'('","')'","inputunit","word_list","redirection",
-"simple_command_element","redirection_list","simple_command","command","shell_command",
-"for_command","arith_for_command","select_command","case_command","function_def",
-"function_body","subshell","if_command","group_command","arith_command","cond_command",
-"elif_clause","case_clause","pattern_list","case_clause_sequence","pattern",
-"list","compound_list","list0","list1","list_terminator","newline_list","simple_list",
-"simple_list1","pipeline_command","pipeline","timespec", NULL
+#if (YYDEBUG) || defined YYERROR_VERBOSE
+
+/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */
+static const char *const yytname[] =
+{
+  "$", "error", "$undefined.", "IF", "THEN", "ELSE", "ELIF", "FI", "CASE", 
+  "ESAC", "FOR", "SELECT", "WHILE", "UNTIL", "DO", "DONE", "FUNCTION", 
+  "COND_START", "COND_END", "COND_ERROR", "IN", "BANG", "TIME", "TIMEOPT", 
+  "WORD", "ASSIGNMENT_WORD", "NUMBER", "ARITH_CMD", "ARITH_FOR_EXPRS", 
+  "COND_CMD", "AND_AND", "OR_OR", "GREATER_GREATER", "LESS_LESS", 
+  "LESS_AND", "LESS_LESS_LESS", "GREATER_AND", "SEMI_SEMI", 
+  "LESS_LESS_MINUS", "AND_GREATER", "LESS_GREATER", "GREATER_BAR", "'&'", 
+  "';'", "'\\n'", "yacc_EOF", "'|'", "'>'", "'<'", "'-'", "'{'", "'}'", 
+  "'('", "')'", "inputunit", "word_list", "redirection", 
+  "simple_command_element", "redirection_list", "simple_command", 
+  "command", "shell_command", "for_command", "arith_for_command", 
+  "select_command", "case_command", "function_def", "function_body", 
+  "subshell", "if_command", "group_command", "arith_command", 
+  "cond_command", "elif_clause", "case_clause", "pattern_list", 
+  "case_clause_sequence", "pattern", "list", "compound_list", "list0", 
+  "list1", "simple_list_terminator", "list_terminator", "newline_list", 
+  "simple_list", "simple_list1", "pipeline_command", "pipeline", 
+  "timespec", 0
 };
 #endif
 
-static const short yyr1[] = {     0,
-    53,    53,    53,    53,    54,    54,    55,    55,    55,    55,
-    55,    55,    55,    55,    55,    55,    55,    55,    55,    55,
-    55,    55,    55,    55,    55,    55,    55,    55,    55,    55,
-    55,    55,    55,    56,    56,    56,    57,    57,    58,    58,
-    59,    59,    59,    59,    60,    60,    60,    60,    60,    60,
-    60,    60,    60,    60,    60,    61,    61,    61,    61,    61,
-    61,    61,    61,    62,    62,    62,    62,    63,    63,    63,
-    63,    63,    63,    64,    64,    64,    65,    65,    65,    66,
-    66,    67,    68,    68,    68,    69,    70,    71,    72,    72,
-    72,    73,    73,    74,    74,    74,    74,    75,    75,    76,
-    76,    77,    78,    78,    79,    79,    79,    80,    80,    80,
-    80,    80,    80,    81,    81,    81,    82,    82,    83,    83,
-    83,    84,    84,    84,    84,    84,    85,    85,    85,    85,
-    85,    86,    86,    87,    87
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const short yyr1[] =
+{
+       0,    54,    54,    54,    54,    55,    55,    56,    56,    56,
+      56,    56,    56,    56,    56,    56,    56,    56,    56,    56,
+      56,    56,    56,    56,    56,    56,    56,    56,    56,    56,
+      56,    56,    56,    56,    56,    56,    57,    57,    57,    58,
+      58,    59,    59,    60,    60,    60,    60,    61,    61,    61,
+      61,    61,    61,    61,    61,    61,    61,    61,    62,    62,
+      62,    62,    62,    62,    62,    62,    63,    63,    63,    63,
+      64,    64,    64,    64,    64,    64,    65,    65,    65,    66,
+      66,    66,    67,    67,    68,    69,    69,    69,    70,    71,
+      72,    73,    73,    73,    74,    74,    75,    75,    75,    75,
+      76,    76,    77,    77,    78,    79,    79,    80,    80,    80,
+      81,    81,    81,    81,    81,    81,    82,    82,    83,    83,
+      83,    84,    84,    85,    85,    85,    86,    86,    86,    86,
+      86,    87,    87,    87,    87,    87,    88,    88,    89,    89
 };
 
-static const short yyr2[] = {     0,
-     2,     1,     2,     1,     1,     2,     2,     2,     3,     3,
-     2,     3,     2,     3,     2,     3,     2,     3,     2,     3,
-     2,     3,     2,     3,     2,     3,     2,     3,     2,     3,
-     2,     2,     3,     1,     1,     1,     1,     2,     1,     2,
-     1,     1,     2,     1,     1,     1,     5,     5,     1,     1,
-     1,     1,     1,     1,     1,     6,     6,     7,     7,    10,
-    10,     9,     9,     7,     7,     5,     5,     6,     6,     7,
-     7,    10,    10,     6,     7,     6,     5,     6,     4,     1,
-     2,     3,     5,     7,     6,     3,     1,     3,     4,     6,
-     5,     1,     2,     4,     4,     5,     5,     2,     3,     1,
-     3,     2,     1,     2,     3,     3,     3,     4,     4,     4,
-     4,     4,     1,     1,     1,     1,     0,     2,     1,     2,
-     2,     4,     4,     3,     3,     1,     1,     2,     2,     3,
-     3,     4,     1,     1,     2
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const short yyr2[] =
+{
+       0,     2,     1,     2,     1,     1,     2,     2,     2,     3,
+       3,     2,     3,     2,     3,     2,     3,     2,     3,     2,
+       3,     2,     3,     2,     3,     2,     3,     2,     3,     2,
+       3,     2,     3,     2,     2,     3,     1,     1,     1,     1,
+       2,     1,     2,     1,     1,     2,     1,     1,     1,     5,
+       5,     1,     1,     1,     1,     1,     1,     1,     6,     6,
+       7,     7,    10,    10,     9,     9,     7,     7,     5,     5,
+       6,     6,     7,     7,    10,    10,     6,     7,     6,     5,
+       6,     4,     1,     2,     3,     5,     7,     6,     3,     1,
+       3,     4,     6,     5,     1,     2,     4,     4,     5,     5,
+       2,     3,     1,     3,     2,     1,     2,     3,     3,     3,
+       4,     4,     4,     4,     4,     1,     1,     1,     1,     1,
+       1,     0,     2,     1,     2,     2,     4,     4,     3,     3,
+       1,     1,     2,     2,     3,     3,     4,     1,     1,     2
 };
 
-static const short yydefact[] = {     0,
-     0,   117,     0,     0,     0,   117,   117,     0,     0,     0,
-   134,    34,    35,     0,    87,     0,     0,     0,     0,     0,
-     0,     0,     0,     2,     4,     0,     0,   117,   117,    36,
-    39,    41,   133,    42,    45,    55,    49,    46,    44,    51,
-    50,    52,    53,    54,     0,   119,   126,   127,     0,     3,
-   103,     0,     0,   117,   117,     0,   117,     0,     0,   117,
-     0,   128,     0,   135,     0,     0,     0,     0,     0,     0,
-     0,     0,     0,     0,    11,    13,    19,    15,    27,    21,
-    17,    25,    23,    29,    31,    32,     7,     8,     0,     0,
-    34,    40,    37,    43,     1,   117,   117,   120,   121,   117,
-     0,   129,   117,   118,   102,   104,   113,     0,   117,     0,
-   117,   115,   114,   116,   117,   117,   117,     0,   117,   117,
-     0,     0,    88,   131,   117,    12,    14,    20,    16,    28,
-    22,    18,    26,    24,    30,    33,     9,    10,    86,    82,
-    38,     0,     0,   124,   125,     0,   130,     0,   117,   117,
-   117,   117,   117,   117,     0,   117,     0,   117,     0,     0,
-     0,     0,   117,     0,   117,     0,     0,   117,    80,    79,
-     0,   122,   123,     0,     0,   132,   117,   117,    83,     0,
-     0,     0,   106,   107,   105,     0,    92,   117,     0,   117,
-   117,     0,     5,     0,   117,     0,    66,    67,   117,   117,
-   117,   117,     0,     0,     0,     0,    47,    48,     0,    81,
-    77,     0,     0,    85,   108,   109,   110,   111,   112,    76,
-    98,    93,     0,    74,   100,     0,     0,     0,     0,    56,
-     6,   117,     0,    57,     0,     0,     0,     0,    68,     0,
-   117,    69,    78,    84,   117,   117,   117,   117,    99,    75,
-     0,     0,   117,    58,    59,     0,   117,   117,    64,    65,
-    70,    71,     0,    89,     0,     0,     0,   117,   101,    94,
-    95,   117,   117,     0,     0,   117,   117,   117,    91,    96,
-    97,     0,     0,    62,    63,     0,     0,    90,    60,    61,
-    72,    73,     0,     0,     0
+/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE
+   doesn't specify something else to do.  Zero means the default is an
+   error. */
+static const short yydefact[] =
+{
+       0,     0,   121,     0,     0,     0,   121,   121,     0,     0,
+       0,   138,    36,    37,     0,    89,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     2,     4,     0,     0,   121,
+     121,    38,    41,    43,   137,    44,    47,    57,    51,    48,
+      46,    53,    52,    54,    55,    56,     0,   123,   130,   131,
+       0,     3,   105,     0,     0,   121,   121,     0,   121,     0,
+       0,   121,     0,   132,     0,   139,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    11,    13,    21,
+      17,    29,    15,    23,    19,    27,    25,    31,    33,    34,
+       7,     8,     0,     0,    36,    42,    39,    45,   116,   117,
+       1,   121,   121,   124,   125,   121,     0,   133,   121,   122,
+     104,   106,   115,     0,   121,     0,   121,   119,   118,   120,
+     121,   121,   121,     0,   121,   121,     0,     0,    90,   135,
+     121,    12,    14,    22,    18,    30,    16,    24,    20,    28,
+      26,    32,    35,     9,    10,    88,    84,    40,     0,     0,
+     128,   129,     0,   134,     0,   121,   121,   121,   121,   121,
+     121,     0,   121,     0,   121,     0,     0,     0,     0,   121,
+       0,   121,     0,     0,   121,    82,    81,     0,   126,   127,
+       0,     0,   136,   121,   121,    85,     0,     0,     0,   108,
+     109,   107,     0,    94,   121,     0,   121,   121,     0,     5,
+       0,   121,     0,    68,    69,   121,   121,   121,   121,     0,
+       0,     0,     0,    49,    50,     0,    83,    79,     0,     0,
+      87,   110,   111,   112,   113,   114,    78,   100,    95,     0,
+      76,   102,     0,     0,     0,     0,    58,     6,   121,     0,
+      59,     0,     0,     0,     0,    70,     0,   121,    71,    80,
+      86,   121,   121,   121,   121,   101,    77,     0,     0,   121,
+      60,    61,     0,   121,   121,    66,    67,    72,    73,     0,
+      91,     0,     0,     0,   121,   103,    96,    97,   121,   121,
+       0,     0,   121,   121,   121,    93,    98,    99,     0,     0,
+      64,    65,     0,     0,    92,    62,    63,    74,    75,     0,
+       0,     0
 };
 
-static const short yydefgoto[] = {   293,
-   194,    30,    31,    94,    32,    33,    34,    35,    36,    37,
-    38,    39,   170,    40,    41,    42,    43,    44,   180,   186,
-   187,   188,   227,    51,    52,   105,   106,   116,    53,    45,
-   144,   107,    48,    49
+static const short yydefgoto[] =
+{
+     299,   200,    31,    32,    97,    33,    34,    35,    36,    37,
+      38,    39,    40,   176,    41,    42,    43,    44,    45,   186,
+     192,   193,   194,   233,    52,    53,   110,   111,   100,   121,
+      54,    46,   150,   112,    49,    50
 };
 
-static const short yypact[] = {   267,
-   -30,-32768,     2,     1,     7,-32768,-32768,    13,    25,   393,
-    17,    29,-32768,   557,-32768,    44,    47,    48,    82,    61,
-    78,    83,   105,-32768,-32768,   111,   125,-32768,-32768,-32768,
--32768,   178,-32768,   541,-32768,-32768,-32768,-32768,-32768,-32768,
--32768,-32768,-32768,-32768,    50,    34,-32768,   113,   435,-32768,
--32768,   155,   309,-32768,   118,    35,   120,   150,   151,   115,
-   149,   113,   519,-32768,   117,   146,   152,   107,   108,   153,
-   159,   164,   171,   173,-32768,-32768,-32768,-32768,-32768,-32768,
--32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,   123,   156,
--32768,-32768,-32768,   541,-32768,-32768,-32768,   351,   351,-32768,
-   519,   113,-32768,-32768,-32768,   201,-32768,     0,-32768,    72,
--32768,-32768,-32768,-32768,-32768,-32768,-32768,    97,-32768,-32768,
-   175,   179,-32768,   113,-32768,-32768,-32768,-32768,-32768,-32768,
--32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
--32768,   309,   309,     4,     4,   477,   113,   137,-32768,-32768,
--32768,-32768,-32768,-32768,    -2,-32768,   157,-32768,   183,   184,
-    18,    38,-32768,   185,-32768,   192,   208,-32768,   541,-32768,
-   179,-32768,-32768,   351,   351,   113,-32768,-32768,-32768,   222,
-   309,   309,   309,   309,   309,   224,   200,-32768,    12,-32768,
--32768,   223,-32768,   211,-32768,   187,-32768,-32768,-32768,-32768,
--32768,-32768,   225,   309,   211,   195,-32768,-32768,   179,   541,
--32768,   239,   244,-32768,-32768,-32768,    20,    20,    20,-32768,
--32768,   220,    15,-32768,-32768,   233,   -38,   243,   209,-32768,
--32768,-32768,    69,-32768,   245,   213,   246,   214,-32768,   201,
--32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
-    43,   241,-32768,-32768,-32768,   102,-32768,-32768,-32768,-32768,
--32768,-32768,   114,    54,   309,   309,   309,-32768,-32768,-32768,
-   309,-32768,-32768,   254,   221,-32768,-32768,-32768,-32768,-32768,
-   309,   258,   226,-32768,-32768,   259,   231,-32768,-32768,-32768,
--32768,-32768,   282,   285,-32768
+static const short yypact[] =
+{
+     273,   -24,-32768,    -2,    11,     6,-32768,-32768,    12,     9,
+     402,    41,    10,-32768,   552,-32768,    46,    52,    -5,    58,
+      64,    68,   102,   117,   135,-32768,-32768,   146,   149,-32768,
+  -32768,-32768,-32768,   169,-32768,   202,-32768,-32768,-32768,-32768,
+  -32768,-32768,-32768,-32768,-32768,-32768,   -33,    42,-32768,    91,
+     445,-32768,-32768,   142,   316,-32768,   133,    72,   136,   172,
+     174,    97,   171,    91,   531,-32768,   139,   173,   182,    99,
+     188,   138,   189,   190,   191,   194,   195,-32768,-32768,-32768,
+  -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+  -32768,-32768,   145,   168,-32768,-32768,-32768,   202,-32768,-32768,
+  -32768,-32768,-32768,   359,   359,-32768,   531,    91,-32768,-32768,
+  -32768,   249,-32768,   -12,-32768,    13,-32768,-32768,-32768,-32768,
+  -32768,-32768,-32768,    57,-32768,-32768,   170,    39,-32768,    91,
+  -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+  -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,   316,   316,
+      28,    28,   488,    91,    74,-32768,-32768,-32768,-32768,-32768,
+  -32768,    90,-32768,   220,-32768,   183,   178,   110,   113,-32768,
+     198,-32768,   209,   215,-32768,   202,-32768,    39,-32768,-32768,
+     359,   359,    91,-32768,-32768,-32768,   224,   316,   316,   316,
+     316,   316,   230,   196,-32768,    16,-32768,-32768,   231,-32768,
+     258,-32768,   197,-32768,-32768,-32768,-32768,-32768,-32768,   236,
+     316,   258,   201,-32768,-32768,    39,   202,-32768,   247,   255,
+  -32768,-32768,-32768,    66,    66,    66,-32768,-32768,   223,    17,
+  -32768,-32768,   237,    92,   251,   211,-32768,-32768,-32768,   121,
+  -32768,   252,   218,   256,   219,-32768,   249,-32768,-32768,-32768,
+  -32768,-32768,-32768,-32768,-32768,-32768,-32768,   115,   253,-32768,
+  -32768,-32768,   122,-32768,-32768,-32768,-32768,-32768,-32768,   125,
+     106,   316,   316,   316,-32768,-32768,-32768,   316,-32768,-32768,
+     260,   245,-32768,-32768,-32768,-32768,-32768,   316,   272,   259,
+  -32768,-32768,   289,   264,-32768,-32768,-32768,-32768,-32768,   288,
+     322,-32768
 };
 
-static const short yypgoto[] = {-32768,
-   122,   -32,   255,   121,-32768,-32768,  -118,-32768,-32768,-32768,
--32768,-32768,  -161,-32768,-32768,-32768,-32768,-32768,    31,-32768,
-   109,-32768,    70,  -157,    -6,-32768,  -166,  -148,   -27,-32768,
-    11,     5,    -7,   288
+static const short yypgoto[] =
+{
+  -32768,   160,   -32,   283,   156,-32768,-32768,  -122,-32768,-32768,
+  -32768,-32768,-32768,  -167,-32768,-32768,-32768,-32768,-32768,    65,
+  -32768,   140,-32768,   104,  -162,    -6,-32768,  -173,-32768,  -157,
+     -27,-32768,     4,     2,     3,   329
 };
 
 
-#define        YYLAST          604
-
-
-static const short yytable[] = {    58,
-    59,    93,    62,   169,    47,   203,   252,   206,   195,   211,
-    46,   190,    50,   253,   215,   216,   217,   218,   219,   154,
-   224,    89,    90,   250,    55,    54,   108,   110,    56,   118,
-    57,   199,   122,    96,    97,   225,    60,   240,   225,    64,
-   104,   102,   104,   237,   238,   232,   191,   243,   111,   149,
-   150,   201,   169,    61,   104,   124,   241,   104,   278,   178,
-   104,   141,   226,    96,    97,   226,   200,    75,   142,   143,
-    76,    77,   146,    78,    98,    99,   112,   113,   114,    65,
-   104,   155,   257,   115,    83,   156,   202,   252,   161,   162,
-   169,   157,    95,   147,   268,    79,   148,   171,   217,   218,
-   219,    84,    47,    47,   159,    80,    85,    81,   160,   145,
-   163,   104,   166,   167,   104,   272,   164,   258,   286,   287,
-   158,   181,   182,   183,   184,   185,   189,   276,    86,    82,
-   128,   131,   129,   132,    87,   204,    93,   204,   176,   104,
-   209,   177,   178,   179,   104,   165,    47,    47,    88,   192,
-   273,   196,   172,   173,   130,   133,   104,   100,   103,   109,
-   223,   117,   277,   119,   120,   121,   123,   233,   125,   126,
-   212,   213,   139,   204,   204,   127,   134,   141,    47,    47,
-   193,     2,   135,   228,   229,   145,     3,   136,     4,     5,
-     6,     7,   235,   236,   137,     9,   138,   197,   112,   113,
-   114,    91,    13,    14,   256,    15,   207,   140,   193,    16,
-    17,    18,    19,   263,    20,    21,    22,    23,   265,   266,
-   267,   104,   208,    26,    27,   271,   168,    28,   214,    29,
-   149,   150,   220,   198,   231,   221,   234,   230,   264,   239,
-   281,   151,   152,   153,   242,   244,   270,   245,   204,   204,
-   274,   275,   112,   113,   114,   249,   225,   254,   255,   259,
-   261,   280,   260,   262,   269,   282,   283,     1,   284,     2,
-   285,   288,   289,   291,     3,   290,     4,     5,     6,     7,
-   292,   294,     8,     9,   295,   205,    92,    10,    11,   210,
-    12,    13,    14,    15,   279,   251,   222,    63,    16,    17,
-    18,    19,     0,    20,    21,    22,    23,     0,     0,    24,
-    25,     2,    26,    27,     0,    28,     3,    29,     4,     5,
-     6,     7,     0,     0,     8,     9,     0,     0,     0,    10,
-    11,     0,    12,    13,    14,    15,     0,     0,     0,     0,
-    16,    17,    18,    19,     0,    20,    21,    22,    23,     0,
-     0,   104,     0,     2,    26,    27,     0,    28,     3,    29,
-     4,     5,     6,     7,     0,     0,     8,     9,     0,     0,
-     0,    10,    11,     0,    12,    13,    14,    15,     0,     0,
-     0,     0,    16,    17,    18,    19,     0,    20,    21,    22,
-    23,     0,     0,     0,     0,     2,    26,    27,     0,    28,
-     3,    29,     4,     5,     6,     7,     0,     0,     8,     9,
-     0,     0,     0,     0,    11,     0,    12,    13,    14,    15,
-     0,     0,     0,     0,    16,    17,    18,    19,     0,    20,
-    21,    22,    23,     0,     0,     0,     0,     2,    26,    27,
-     0,    28,     3,    29,     4,     5,     6,     7,     0,     0,
-     8,     9,     0,     0,     0,   101,     0,     0,    12,    13,
-    14,    15,     0,     0,     0,     0,    16,    17,    18,    19,
-     0,    20,    21,    22,    23,     0,     0,     0,     0,     2,
-    26,    27,     0,    28,     3,    29,     4,     5,     6,     7,
-     0,     0,     8,     9,     0,     0,     0,     0,     0,     0,
-    12,    13,    14,    15,     0,     0,     0,     0,    16,    17,
-    18,    19,     0,    20,    21,    22,    23,     0,     0,   104,
-     0,     2,    26,    27,     0,    28,     3,    29,     4,     5,
-     6,     7,     0,     0,     8,     9,     0,     0,     0,     0,
-     0,     0,    12,    13,    14,    15,     0,     0,     0,     0,
-    16,    17,    18,    19,     0,    20,    21,    22,    23,     0,
-     0,     0,     0,     0,    26,    27,    14,    28,     0,    29,
-     0,     0,    16,    17,    18,    19,     0,    20,    21,    22,
-    23,     0,     0,     0,     0,     0,    26,    27,    66,    67,
-    68,    69,     0,    70,     0,    71,    72,     0,     0,     0,
-     0,     0,    73,    74
+#define        YYLAST          600
+
+
+static const short yytable[] =
+{
+      59,    60,    48,    96,    47,   175,   201,   209,   160,   212,
+     217,    98,    99,    63,   221,   222,   223,   224,   225,    79,
+      51,    80,    55,    92,    93,   230,   256,   162,   113,   115,
+      58,   123,   109,   163,   127,    56,    61,   246,    62,    57,
+     231,   231,     2,   238,    81,   243,   244,     3,   249,     4,
+       5,     6,     7,   107,   247,   175,     9,   109,   101,   102,
+     109,   109,    66,   164,    65,   147,    15,   129,   232,   232,
+      77,   169,   101,   102,   148,   149,    78,   170,   152,   183,
+     184,   185,    82,   109,   103,   104,   116,   161,    83,    29,
+      84,    30,    86,   175,   167,   168,   155,   156,   223,   224,
+     225,   109,   154,   177,   196,    48,    48,   171,   151,   153,
+     165,   284,   184,    85,   166,   117,   118,   119,   172,   173,
+     292,   293,   120,   133,   205,   134,    87,   207,   187,   188,
+     189,   190,   191,   195,   109,   263,   278,   105,   258,   282,
+     197,    88,   210,    96,   210,   259,   108,   215,   135,   126,
+      48,    48,   178,   179,   109,   182,   198,   109,   202,    89,
+     206,   258,   137,   208,   138,   109,   109,   229,   274,   109,
+      90,   264,   279,    91,   239,   283,   114,   218,   219,   122,
+     210,   210,    48,    48,   147,   151,   124,   139,   125,   128,
+     234,   235,   130,    94,    13,    14,   145,   131,   203,   241,
+     242,    16,    17,    18,    19,    20,   132,    21,    22,    23,
+      24,   262,   136,   140,   141,   142,    27,    28,   143,   144,
+     269,   146,   199,   174,   213,   271,   272,   273,    14,   204,
+     214,   220,   277,   227,    16,    17,    18,    19,    20,   226,
+      21,    22,    23,    24,   199,   270,   236,   287,   240,    27,
+      28,   245,   248,   276,   250,   210,   210,   280,   281,   251,
+     255,   231,   261,   117,   118,   119,   260,   265,   286,   266,
+     268,   267,   288,   289,     1,   290,     2,   275,   294,   155,
+     156,     3,   237,     4,     5,     6,     7,   295,   300,     8,
+       9,   157,   158,   159,    10,    11,   291,    12,    13,    14,
+      15,   117,   118,   119,   297,    16,    17,    18,    19,    20,
+     296,    21,    22,    23,    24,   298,    95,    25,    26,     2,
+      27,    28,   301,    29,     3,    30,     4,     5,     6,     7,
+     211,   216,     8,     9,   228,   285,   257,    10,    11,    64,
+      12,    13,    14,    15,     0,     0,     0,     0,    16,    17,
+      18,    19,    20,     0,    21,    22,    23,    24,     0,     0,
+     109,     0,     2,    27,    28,     0,    29,     3,    30,     4,
+       5,     6,     7,     0,     0,     8,     9,     0,     0,     0,
+      10,    11,     0,    12,    13,    14,    15,     0,     0,     0,
+       0,    16,    17,    18,    19,    20,     0,    21,    22,    23,
+      24,     0,     0,     0,     0,     2,    27,    28,     0,    29,
+       3,    30,     4,     5,     6,     7,     0,     0,     8,     9,
+       0,     0,     0,     0,    11,     0,    12,    13,    14,    15,
+       0,     0,     0,     0,    16,    17,    18,    19,    20,     0,
+      21,    22,    23,    24,     0,     0,     0,     0,     2,    27,
+      28,     0,    29,     3,    30,     4,     5,     6,     7,     0,
+       0,     8,     9,     0,     0,     0,   106,     0,     0,    12,
+      13,    14,    15,     0,     0,     0,     0,    16,    17,    18,
+      19,    20,     0,    21,    22,    23,    24,     0,     0,     0,
+       0,     2,    27,    28,     0,    29,     3,    30,     4,     5,
+       6,     7,     0,     0,     8,     9,     0,     0,     0,     0,
+       0,     0,    12,    13,    14,    15,     0,     0,     0,     0,
+      16,    17,    18,    19,    20,     0,    21,    22,    23,    24,
+       0,     0,   109,     0,     2,    27,    28,     0,    29,     3,
+      30,     4,     5,     6,     7,     0,     0,     8,     9,     0,
+       0,     0,     0,     0,     0,    12,    13,    14,    15,     0,
+       0,     0,     0,    16,    17,    18,    19,    20,     0,    21,
+      22,    23,    24,     0,     0,     0,     0,     0,    27,    28,
+       0,    29,     0,    30,    67,    68,    69,    70,    71,     0,
+      72,     0,    73,    74,     0,     0,     0,     0,     0,    75,
+      76
 };
 
-static const short yycheck[] = {     6,
-     7,    34,    10,   122,     0,   163,    45,   165,   157,   171,
-     0,    14,    43,    52,   181,   182,   183,   184,   185,    20,
-     9,    28,    29,     9,    24,    24,    54,    55,    28,    57,
-    24,    14,    60,    30,    31,    24,    24,   204,    24,    23,
-    43,    49,    43,   201,   202,   194,    49,   209,    14,    30,
-    31,    14,   171,    29,    43,    63,   205,    43,     5,     6,
-    43,    94,    51,    30,    31,    51,    49,    24,    96,    97,
-    24,    24,   100,    26,    41,    42,    42,    43,    44,    51,
-    43,   109,    14,    49,    24,    14,    49,    45,   116,   117,
-   209,    20,    43,   101,    52,    48,   103,   125,   265,   266,
-   267,    24,    98,    99,   111,    24,    24,    26,   115,    99,
-    14,    43,   119,   120,    43,    14,    20,    49,   276,   277,
-    49,   149,   150,   151,   152,   153,   154,    14,    24,    48,
-    24,    24,    26,    26,    24,   163,   169,   165,   146,    43,
-   168,     5,     6,     7,    43,    49,   142,   143,    24,   156,
-    49,   158,   142,   143,    48,    48,    43,    45,     4,    42,
-   188,    42,    49,    14,    14,    51,    18,   195,    52,    24,
-   177,   178,    50,   201,   202,    24,    24,   210,   174,   175,
-    24,     3,    24,   190,   191,   175,     8,    24,    10,    11,
-    12,    13,   199,   200,    24,    17,    24,    15,    42,    43,
-    44,    24,    25,    26,   232,    27,    15,    52,    24,    32,
-    33,    34,    35,   241,    37,    38,    39,    40,   246,   247,
-   248,    43,    15,    46,    47,   253,    52,    49,     7,    51,
-    30,    31,     9,    50,    24,    36,    50,    15,   245,    15,
-   268,    41,    42,    43,    50,     7,   253,     4,   276,   277,
-   257,   258,    42,    43,    44,    36,    24,    15,    50,    15,
-    15,   268,    50,    50,    24,   272,   273,     1,    15,     3,
-    50,   278,    15,    15,     8,    50,    10,    11,    12,    13,
-    50,     0,    16,    17,     0,   164,    32,    21,    22,   169,
-    24,    25,    26,    27,   264,   226,   188,    10,    32,    33,
-    34,    35,    -1,    37,    38,    39,    40,    -1,    -1,    43,
-    44,     3,    46,    47,    -1,    49,     8,    51,    10,    11,
-    12,    13,    -1,    -1,    16,    17,    -1,    -1,    -1,    21,
-    22,    -1,    24,    25,    26,    27,    -1,    -1,    -1,    -1,
-    32,    33,    34,    35,    -1,    37,    38,    39,    40,    -1,
-    -1,    43,    -1,     3,    46,    47,    -1,    49,     8,    51,
-    10,    11,    12,    13,    -1,    -1,    16,    17,    -1,    -1,
-    -1,    21,    22,    -1,    24,    25,    26,    27,    -1,    -1,
-    -1,    -1,    32,    33,    34,    35,    -1,    37,    38,    39,
-    40,    -1,    -1,    -1,    -1,     3,    46,    47,    -1,    49,
-     8,    51,    10,    11,    12,    13,    -1,    -1,    16,    17,
-    -1,    -1,    -1,    -1,    22,    -1,    24,    25,    26,    27,
-    -1,    -1,    -1,    -1,    32,    33,    34,    35,    -1,    37,
-    38,    39,    40,    -1,    -1,    -1,    -1,     3,    46,    47,
-    -1,    49,     8,    51,    10,    11,    12,    13,    -1,    -1,
-    16,    17,    -1,    -1,    -1,    21,    -1,    -1,    24,    25,
-    26,    27,    -1,    -1,    -1,    -1,    32,    33,    34,    35,
-    -1,    37,    38,    39,    40,    -1,    -1,    -1,    -1,     3,
-    46,    47,    -1,    49,     8,    51,    10,    11,    12,    13,
-    -1,    -1,    16,    17,    -1,    -1,    -1,    -1,    -1,    -1,
-    24,    25,    26,    27,    -1,    -1,    -1,    -1,    32,    33,
-    34,    35,    -1,    37,    38,    39,    40,    -1,    -1,    43,
-    -1,     3,    46,    47,    -1,    49,     8,    51,    10,    11,
-    12,    13,    -1,    -1,    16,    17,    -1,    -1,    -1,    -1,
-    -1,    -1,    24,    25,    26,    27,    -1,    -1,    -1,    -1,
-    32,    33,    34,    35,    -1,    37,    38,    39,    40,    -1,
-    -1,    -1,    -1,    -1,    46,    47,    26,    49,    -1,    51,
-    -1,    -1,    32,    33,    34,    35,    -1,    37,    38,    39,
-    40,    -1,    -1,    -1,    -1,    -1,    46,    47,    32,    33,
-    34,    35,    -1,    37,    -1,    39,    40,    -1,    -1,    -1,
-    -1,    -1,    46,    47
+static const short yycheck[] =
+{
+       6,     7,     0,    35,     0,   127,   163,   169,    20,   171,
+     177,    44,    45,    10,   187,   188,   189,   190,   191,    24,
+      44,    26,    24,    29,    30,     9,     9,    14,    55,    56,
+      24,    58,    44,    20,    61,    24,    24,   210,    29,    28,
+      24,    24,     3,   200,    49,   207,   208,     8,   215,    10,
+      11,    12,    13,    50,   211,   177,    17,    44,    30,    31,
+      44,    44,    52,    50,    23,    97,    27,    64,    52,    52,
+      24,    14,    30,    31,   101,   102,    24,    20,   105,     5,
+       6,     7,    24,    44,    42,    43,    14,   114,    24,    50,
+      26,    52,    24,   215,   121,   122,    30,    31,   271,   272,
+     273,    44,   108,   130,    14,   103,   104,    50,   104,   106,
+     116,     5,     6,    49,   120,    43,    44,    45,   124,   125,
+     282,   283,    50,    24,    14,    26,    24,    14,   155,   156,
+     157,   158,   159,   160,    44,    14,    14,    46,    46,    14,
+      50,    24,   169,   175,   171,    53,     4,   174,    49,    52,
+     148,   149,   148,   149,    44,   152,   162,    44,   164,    24,
+      50,    46,    24,    50,    26,    44,    44,   194,    53,    44,
+      24,    50,    50,    24,   201,    50,    43,   183,   184,    43,
+     207,   208,   180,   181,   216,   181,    14,    49,    14,    18,
+     196,   197,    53,    24,    25,    26,    51,    24,    15,   205,
+     206,    32,    33,    34,    35,    36,    24,    38,    39,    40,
+      41,   238,    24,    24,    24,    24,    47,    48,    24,    24,
+     247,    53,    24,    53,    15,   252,   253,   254,    26,    51,
+      15,     7,   259,    37,    32,    33,    34,    35,    36,     9,
+      38,    39,    40,    41,    24,   251,    15,   274,    51,    47,
+      48,    15,    51,   259,     7,   282,   283,   263,   264,     4,
+      37,    24,    51,    43,    44,    45,    15,    15,   274,    51,
+      51,    15,   278,   279,     1,    15,     3,    24,   284,    30,
+      31,     8,    24,    10,    11,    12,    13,    15,     0,    16,
+      17,    42,    43,    44,    21,    22,    51,    24,    25,    26,
+      27,    43,    44,    45,    15,    32,    33,    34,    35,    36,
+      51,    38,    39,    40,    41,    51,    33,    44,    45,     3,
+      47,    48,     0,    50,     8,    52,    10,    11,    12,    13,
+     170,   175,    16,    17,   194,   270,   232,    21,    22,    10,
+      24,    25,    26,    27,    -1,    -1,    -1,    -1,    32,    33,
+      34,    35,    36,    -1,    38,    39,    40,    41,    -1,    -1,
+      44,    -1,     3,    47,    48,    -1,    50,     8,    52,    10,
+      11,    12,    13,    -1,    -1,    16,    17,    -1,    -1,    -1,
+      21,    22,    -1,    24,    25,    26,    27,    -1,    -1,    -1,
+      -1,    32,    33,    34,    35,    36,    -1,    38,    39,    40,
+      41,    -1,    -1,    -1,    -1,     3,    47,    48,    -1,    50,
+       8,    52,    10,    11,    12,    13,    -1,    -1,    16,    17,
+      -1,    -1,    -1,    -1,    22,    -1,    24,    25,    26,    27,
+      -1,    -1,    -1,    -1,    32,    33,    34,    35,    36,    -1,
+      38,    39,    40,    41,    -1,    -1,    -1,    -1,     3,    47,
+      48,    -1,    50,     8,    52,    10,    11,    12,    13,    -1,
+      -1,    16,    17,    -1,    -1,    -1,    21,    -1,    -1,    24,
+      25,    26,    27,    -1,    -1,    -1,    -1,    32,    33,    34,
+      35,    36,    -1,    38,    39,    40,    41,    -1,    -1,    -1,
+      -1,     3,    47,    48,    -1,    50,     8,    52,    10,    11,
+      12,    13,    -1,    -1,    16,    17,    -1,    -1,    -1,    -1,
+      -1,    -1,    24,    25,    26,    27,    -1,    -1,    -1,    -1,
+      32,    33,    34,    35,    36,    -1,    38,    39,    40,    41,
+      -1,    -1,    44,    -1,     3,    47,    48,    -1,    50,     8,
+      52,    10,    11,    12,    13,    -1,    -1,    16,    17,    -1,
+      -1,    -1,    -1,    -1,    -1,    24,    25,    26,    27,    -1,
+      -1,    -1,    -1,    32,    33,    34,    35,    36,    -1,    38,
+      39,    40,    41,    -1,    -1,    -1,    -1,    -1,    47,    48,
+      -1,    50,    -1,    52,    32,    33,    34,    35,    36,    -1,
+      38,    -1,    40,    41,    -1,    -1,    -1,    -1,    -1,    47,
+      48
 };
 /* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
-#line 3 "/usr/local/share/bison.simple"
-/* This file comes from bison-1.28.  */
+#line 3 "/usr/local/share/bison/bison.simple"
 
 /* Skeleton output parser for bison,
-   Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 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
@@ -704,62 +778,108 @@ static const short yycheck[] = {     6,
    This special exception was added by the Free Software Foundation
    in version 1.24 of Bison.  */
 
-/* This is the parser code that is written into each bison parser
-  when the %semantic_parser declaration is not specified in the grammar.
-  It was written by Richard Stallman by simplifying the hairy parser
-  used when %semantic_parser is specified.  */
+/* This is the parser code that is written into each bison parser when
+   the %semantic_parser declaration is not specified in the grammar.
+   It was written by Richard Stallman by simplifying the hairy parser
+   used when %semantic_parser is specified.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+#if ! defined (yyoverflow) || defined (YYERROR_VERBOSE)
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# if YYSTACK_USE_ALLOCA
+#  define YYSTACK_ALLOC alloca
+# else
+#  ifndef YYSTACK_USE_ALLOCA
+#   if defined (alloca) || defined (_ALLOCA_H)
+#    define YYSTACK_ALLOC alloca
+#   else
+#    ifdef __GNUC__
+#     define YYSTACK_ALLOC __builtin_alloca
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning. */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+#  if defined (__STDC__) || defined (__cplusplus)
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   define YYSIZE_T size_t
+#  endif
+#  define YYSTACK_ALLOC malloc
+#  define YYSTACK_FREE free
+# endif
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  short yyss;
+  YYSTYPE yyvs;
+# if YYLSP_NEEDED
+  YYLTYPE yyls;
+# endif
+};
 
-#ifndef YYSTACK_USE_ALLOCA
-#ifdef alloca
-#define YYSTACK_USE_ALLOCA
-#else /* alloca not defined */
-#ifdef __GNUC__
-#define YYSTACK_USE_ALLOCA
-#define alloca __builtin_alloca
-#else /* not GNU C.  */
-#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
-#define YYSTACK_USE_ALLOCA
-#include <alloca.h>
-#else /* not sparc */
-/* We think this test detects Watcom and Microsoft C.  */
-/* This used to test MSDOS, but that is a bad idea
-   since that symbol is in the user namespace.  */
-#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
-#if 0 /* No need for malloc.h, which pollutes the namespace;
-        instead, just don't use alloca.  */
-#include <malloc.h>
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# if YYLSP_NEEDED
+#  define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE))     \
+      + 2 * YYSTACK_GAP_MAX)
+# else
+#  define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE))                                \
+      + YYSTACK_GAP_MAX)
+# endif
+
+/* Relocate the TYPE STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Type, Stack)                                 \
+    do                                                                 \
+      {                                                                        \
+       YYSIZE_T yynewbytes;                                            \
+       yymemcpy ((char *) yyptr, (char *) (Stack),                     \
+                 yysize * (YYSIZE_T) sizeof (Type));                   \
+       Stack = &yyptr->Stack;                                          \
+       yynewbytes = yystacksize * sizeof (Type) + YYSTACK_GAP_MAX;     \
+       yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                        \
+    while (0)
+
+#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */
+
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
 #endif
-#else /* not MSDOS, or __TURBOC__ */
-#if defined(_AIX)
-/* I don't know what this was needed for, but it pollutes the namespace.
-   So I turned it off.   rms, 2 May 1997.  */
-/* #include <malloc.h>  */
- #pragma alloca
-#define YYSTACK_USE_ALLOCA
-#else /* not MSDOS, or __TURBOC__, or _AIX */
-#if 0
-#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
-                and on HPUX 10.  Eventually we can turn this on.  */
-#define YYSTACK_USE_ALLOCA
-#define alloca __builtin_alloca
-#endif /* __hpux */
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
 #endif
-#endif /* not _AIX */
-#endif /* not MSDOS, or __TURBOC__ */
-#endif /* not sparc */
-#endif /* not GNU C */
-#endif /* alloca not defined */
-#endif /* YYSTACK_USE_ALLOCA not defined */
-
-#ifdef YYSTACK_USE_ALLOCA
-#define YYSTACK_ALLOC alloca
-#else
-#define YYSTACK_ALLOC malloc
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
 #endif
-
-/* Note: there must be only one dollar sign in this file.
-   It is replaced by the list of actions, each action
-   as one case of the switch.  */
 
 #define yyerrok                (yyerrstatus = 0)
 #define yyclearin      (yychar = YYEMPTY)
@@ -768,131 +888,188 @@ static const short yycheck[] = {     6,
 #define YYACCEPT       goto yyacceptlab
 #define YYABORT        goto yyabortlab
 #define YYERROR                goto yyerrlab1
-/* Like YYERROR except do call yyerror.
-   This remains here temporarily to ease the
-   transition to the new meaning of YYERROR, for GCC.
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
    Once GCC version 2 has supplanted version 1, this can go.  */
 #define YYFAIL         goto yyerrlab
 #define YYRECOVERING()  (!!yyerrstatus)
-#define YYBACKUP(token, value) \
+#define YYBACKUP(Token, Value)                                 \
 do                                                             \
   if (yychar == YYEMPTY && yylen == 1)                         \
-    { yychar = (token), yylval = (value);                      \
+    {                                                          \
+      yychar = (Token);                                                \
+      yylval = (Value);                                                \
       yychar1 = YYTRANSLATE (yychar);                          \
       YYPOPSTACK;                                              \
       goto yybackup;                                           \
     }                                                          \
   else                                                         \
-    { yyerror ("syntax error: cannot back up"); YYERROR; }     \
+    {                                                          \
+      yyerror ("syntax error: cannot back up");                        \
+      YYERROR;                                                 \
+    }                                                          \
 while (0)
 
 #define YYTERROR       1
 #define YYERRCODE      256
 
-#ifndef YYPURE
-#define YYLEX          yylex()
-#endif
 
-#ifdef YYPURE
-#ifdef YYLSP_NEEDED
-#ifdef YYLEX_PARAM
-#define YYLEX          yylex(&yylval, &yylloc, YYLEX_PARAM)
-#else
-#define YYLEX          yylex(&yylval, &yylloc)
-#endif
-#else /* not YYLSP_NEEDED */
-#ifdef YYLEX_PARAM
-#define YYLEX          yylex(&yylval, YYLEX_PARAM)
-#else
-#define YYLEX          yylex(&yylval)
-#endif
-#endif /* not YYLSP_NEEDED */
-#endif
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+   are run).
 
-/* If nonreentrant, generate the variables here */
+   When YYLLOC_DEFAULT is run, CURRENT is set the location of the
+   first token.  By default, to implement support for ranges, extend
+   its range to the last symbol.  */
 
-#ifndef YYPURE
-
-int    yychar;                 /*  the lookahead symbol                */
-YYSTYPE        yylval;                 /*  the semantic value of the           */
-                               /*  lookahead symbol                    */
-
-#ifdef YYLSP_NEEDED
-YYLTYPE yylloc;                        /*  location data for the lookahead     */
-                               /*  symbol                              */
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)               \
+   Current.last_line   = Rhs[N].last_line;     \
+   Current.last_column = Rhs[N].last_column;
 #endif
 
-int yynerrs;                   /*  number of parse errors so far       */
-#endif  /* not YYPURE */
-
-#if YYDEBUG != 0
-int yydebug;                   /*  nonzero means print parse trace     */
-/* Since this is uninitialized, it does not stop multiple parsers
-   from coexisting.  */
-#endif
 
-/*  YYINITDEPTH indicates the initial size of the parser's stacks      */
+/* YYLEX -- calling `yylex' with the right arguments.  */
 
+#if YYPURE
+# if YYLSP_NEEDED
+#  ifdef YYLEX_PARAM
+#   define YYLEX               yylex (&yylval, &yylloc, YYLEX_PARAM)
+#  else
+#   define YYLEX               yylex (&yylval, &yylloc)
+#  endif
+# else /* !YYLSP_NEEDED */
+#  ifdef YYLEX_PARAM
+#   define YYLEX               yylex (&yylval, YYLEX_PARAM)
+#  else
+#   define YYLEX               yylex (&yylval)
+#  endif
+# endif /* !YYLSP_NEEDED */
+#else /* !YYPURE */
+# define YYLEX                 yylex ()
+#endif /* !YYPURE */
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                       \
+do {                                           \
+  if (yydebug)                                 \
+    YYFPRINTF Args;                            \
+} while (0)
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+#endif /* !YYDEBUG */
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
 #ifndef        YYINITDEPTH
-#define YYINITDEPTH 200
+# define YYINITDEPTH 200
 #endif
 
-/*  YYMAXDEPTH is the maximum size the stacks can grow to
-    (effective only if the built-in stack extension method is used).  */
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
 
 #if YYMAXDEPTH == 0
-#undef YYMAXDEPTH
+# undef YYMAXDEPTH
 #endif
 
 #ifndef YYMAXDEPTH
-#define YYMAXDEPTH 10000
+# define YYMAXDEPTH 10000
 #endif
 \f
-/* Define __yy_memcpy.  Note that the size argument
-   should be passed with type unsigned int, because that is what the non-GCC
-   definitions require.  With GCC, __builtin_memcpy takes an arg
-   of type size_t, but it can handle unsigned int.  */
-
-#if __GNUC__ > 1               /* GNU C and GNU C++ define this.  */
-#define __yy_memcpy(TO,FROM,COUNT)     __builtin_memcpy(TO,FROM,COUNT)
-#else                          /* not GNU C or C++ */
-#ifndef __cplusplus
+#if ! defined (yyoverflow) && ! defined (yymemcpy)
+# if __GNUC__ > 1              /* GNU C and GNU C++ define this.  */
+#  define yymemcpy __builtin_memcpy
+# else                         /* not GNU C or C++ */
 
 /* This is the most reliable way to avoid incompatibilities
    in available built-in functions on various systems.  */
 static void
-__yy_memcpy (to, from, count)
-     char *to;
-     char *from;
-     unsigned int count;
+#  if defined (__STDC__) || defined (__cplusplus)
+yymemcpy (char *yyto, const char *yyfrom, YYSIZE_T yycount)
+#  else
+yymemcpy (yyto, yyfrom, yycount)
+     char *yyto;
+     const char *yyfrom;
+     YYSIZE_T yycount;
+#  endif
 {
-  register char *f = from;
-  register char *t = to;
-  register int i = count;
+  register const char *yyf = yyfrom;
+  register char *yyt = yyto;
+  register YYSIZE_T yyi = yycount;
 
-  while (i-- > 0)
-    *t++ = *f++;
+  while (yyi-- != 0)
+    *yyt++ = *yyf++;
 }
+# endif
+#endif
 
-#else /* __cplusplus */
+#ifdef YYERROR_VERBOSE
 
-/* This is the most reliable way to avoid incompatibilities
-   in available built-in functions on various systems.  */
-static void
-__yy_memcpy (char *to, char *from, unsigned int count)
+# ifndef yystrlen
+#  if defined (__GLIBC__) && defined (_STRING_H)
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+#   if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+#   else
+yystrlen (yystr)
+     const char *yystr;
+#   endif
 {
-  register char *t = to;
-  register char *f = from;
-  register int i = count;
+  register const char *yys = yystr;
+
+  while (*yys++ != '\0')
+    continue;
 
-  while (i-- > 0)
-    *t++ = *f++;
+  return yys - yystr - 1;
 }
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+#   if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+#   else
+yystpcpy (yydest, yysrc)
+     char *yydest;
+     const char *yysrc;
+#   endif
+{
+  register char *yyd = yydest;
+  register const char *yys = yysrc;
 
-#endif
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
 #endif
 \f
-#line 217 "/usr/local/share/bison.simple"
+#line 319 "/usr/local/share/bison/bison.simple"
+
 
 /* The user can define YYPARSE_PARAM as the name of an argument to be passed
    into yyparse.  The argument should have type void *.
@@ -901,76 +1078,121 @@ __yy_memcpy (char *to, char *from, unsigned int count)
    to the proper pointer type.  */
 
 #ifdef YYPARSE_PARAM
-#ifdef __cplusplus
-#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
-#define YYPARSE_PARAM_DECL
-#else /* not __cplusplus */
-#define YYPARSE_PARAM_ARG YYPARSE_PARAM
-#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
-#endif /* not __cplusplus */
-#else /* not YYPARSE_PARAM */
-#define YYPARSE_PARAM_ARG
-#define YYPARSE_PARAM_DECL
-#endif /* not YYPARSE_PARAM */
+# if defined (__STDC__) || defined (__cplusplus)
+#  define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL
+# else
+#  define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+# endif
+#else /* !YYPARSE_PARAM */
+# define YYPARSE_PARAM_ARG
+# define YYPARSE_PARAM_DECL
+#endif /* !YYPARSE_PARAM */
 
 /* Prevent warning if -Wstrict-prototypes.  */
 #ifdef __GNUC__
-#ifdef YYPARSE_PARAM
+# ifdef YYPARSE_PARAM
 int yyparse (void *);
-#else
+# else
 int yyparse (void);
+# endif
 #endif
+
+/* YY_DECL_VARIABLES -- depending whether we use a pure parser,
+   variables are global, or local to YYPARSE.  */
+
+#define YY_DECL_NON_LSP_VARIABLES                      \
+/* The lookahead symbol.  */                           \
+int yychar;                                            \
+                                                       \
+/* The semantic value of the lookahead symbol. */      \
+YYSTYPE yylval;                                                \
+                                                       \
+/* Number of parse errors so far.  */                  \
+int yynerrs;
+
+#if YYLSP_NEEDED
+# define YY_DECL_VARIABLES                     \
+YY_DECL_NON_LSP_VARIABLES                      \
+                                               \
+/* Location data for the lookahead symbol.  */ \
+YYLTYPE yylloc;
+#else
+# define YY_DECL_VARIABLES                     \
+YY_DECL_NON_LSP_VARIABLES
 #endif
 
+
+/* If nonreentrant, generate the variables here. */
+
+#if !YYPURE
+YY_DECL_VARIABLES
+#endif  /* !YYPURE */
+
 int
-yyparse(YYPARSE_PARAM_ARG)
+yyparse (YYPARSE_PARAM_ARG)
      YYPARSE_PARAM_DECL
 {
+  /* If reentrant, generate the variables here. */
+#if YYPURE
+  YY_DECL_VARIABLES
+#endif  /* !YYPURE */
+
   register int yystate;
   register int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yychar1 = 0;
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack. */
+  short        yyssa[YYINITDEPTH];
+  short *yyss = yyssa;
   register short *yyssp;
-  register YYSTYPE *yyvsp;
-  int yyerrstatus;     /*  number of tokens to shift before error messages enabled */
-  int yychar1 = 0;             /*  lookahead token as an internal (translated) token number */
-
-  short        yyssa[YYINITDEPTH];     /*  the state stack                     */
-  YYSTYPE yyvsa[YYINITDEPTH];  /*  the semantic value stack            */
 
-  short *yyss = yyssa;         /*  refer to the stacks thru separate pointers */
-  YYSTYPE *yyvs = yyvsa;       /*  to allow yyoverflow to reallocate them elsewhere */
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  register YYSTYPE *yyvsp;
 
-#ifdef YYLSP_NEEDED
-  YYLTYPE yylsa[YYINITDEPTH];  /*  the location stack                  */
+#if YYLSP_NEEDED
+  /* The location stack.  */
+  YYLTYPE yylsa[YYINITDEPTH];
   YYLTYPE *yyls = yylsa;
   YYLTYPE *yylsp;
+#endif
 
-#define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
+#if YYLSP_NEEDED
+# define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
 #else
-#define YYPOPSTACK   (yyvsp--, yyssp--)
+# define YYPOPSTACK   (yyvsp--, yyssp--)
 #endif
 
-  int yystacksize = YYINITDEPTH;
-  int yyfree_stacks = 0;
+  YYSIZE_T yystacksize = YYINITDEPTH;
 
-#ifdef YYPURE
-  int yychar;
-  YYSTYPE yylval;
-  int yynerrs;
-#ifdef YYLSP_NEEDED
-  YYLTYPE yylloc;
-#endif
-#endif
 
-  YYSTYPE yyval;               /*  the variable used to return         */
-                               /*  semantic values from the action     */
-                               /*  routines                            */
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+#if YYLSP_NEEDED
+  YYLTYPE yyloc;
+#endif
 
+  /* When reducing, the number of symbols on the RHS of the reduced
+     rule. */
   int yylen;
 
-#if YYDEBUG != 0
-  if (yydebug)
-    fprintf(stderr, "Starting parse\n");
-#endif
+  YYDPRINTF ((stderr, "Starting parse\n"));
 
   yystate = 0;
   yyerrstatus = 0;
@@ -982,110 +1204,106 @@ yyparse(YYPARSE_PARAM_ARG)
      so that they stay on the same level as the state stack.
      The wasted elements are never initialized.  */
 
-  yyssp = yyss - 1;
+  yyssp = yyss;
   yyvsp = yyvs;
-#ifdef YYLSP_NEEDED
+#if YYLSP_NEEDED
   yylsp = yyls;
 #endif
+  goto yysetstate;
 
-/* Push a new state, which is found in  yystate  .  */
-/* In all cases, when you get here, the value and location stacks
-   have just been pushed. so pushing a state here evens the stacks.  */
-yynewstate:
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed. so pushing a state here evens the stacks.
+     */
+  yyssp++;
 
-  *++yyssp = yystate;
+ yysetstate:
+  *yyssp = yystate;
 
   if (yyssp >= yyss + yystacksize - 1)
     {
-      /* Give user a chance to reallocate the stack */
-      /* Use copies of these so that the &'s don't force the real ones into memory. */
-      YYSTYPE *yyvs1 = yyvs;
-      short *yyss1 = yyss;
-#ifdef YYLSP_NEEDED
-      YYLTYPE *yyls1 = yyls;
-#endif
-
       /* Get the current used size of the three stacks, in elements.  */
-      int size = yyssp - yyss + 1;
+      YYSIZE_T yysize = yyssp - yyss + 1;
 
 #ifdef yyoverflow
-      /* Each stack pointer address is followed by the size of
-        the data in use in that stack, in bytes.  */
-#ifdef YYLSP_NEEDED
-      /* This used to be a conditional around just the two extra args,
-        but that might be undefined if yyoverflow is a macro.  */
-      yyoverflow("parser stack overflow",
-                &yyss1, size * sizeof (*yyssp),
-                &yyvs1, size * sizeof (*yyvsp),
-                &yyls1, size * sizeof (*yylsp),
-                &yystacksize);
-#else
-      yyoverflow("parser stack overflow",
-                &yyss1, size * sizeof (*yyssp),
-                &yyvs1, size * sizeof (*yyvsp),
-                &yystacksize);
-#endif
-
-      yyss = yyss1; yyvs = yyvs1;
-#ifdef YYLSP_NEEDED
-      yyls = yyls1;
-#endif
+      {
+       /* Give user a chance to reallocate the stack. Use copies of
+          these so that the &'s don't force the real ones into
+          memory.  */
+       YYSTYPE *yyvs1 = yyvs;
+       short *yyss1 = yyss;
+
+       /* Each stack pointer address is followed by the size of the
+          data in use in that stack, in bytes.  */
+# if YYLSP_NEEDED
+       YYLTYPE *yyls1 = yyls;
+       /* This used to be a conditional around just the two extra args,
+          but that might be undefined if yyoverflow is a macro.  */
+       yyoverflow ("parser stack overflow",
+                   &yyss1, yysize * sizeof (*yyssp),
+                   &yyvs1, yysize * sizeof (*yyvsp),
+                   &yyls1, yysize * sizeof (*yylsp),
+                   &yystacksize);
+       yyls = yyls1;
+# else
+       yyoverflow ("parser stack overflow",
+                   &yyss1, yysize * sizeof (*yyssp),
+                   &yyvs1, yysize * sizeof (*yyvsp),
+                   &yystacksize);
+# endif
+       yyss = yyss1;
+       yyvs = yyvs1;
+      }
 #else /* no yyoverflow */
       /* Extend the stack our own way.  */
       if (yystacksize >= YYMAXDEPTH)
-       {
-         yyerror("parser stack overflow");
-         if (yyfree_stacks)
-           {
-             free (yyss);
-             free (yyvs);
-#ifdef YYLSP_NEEDED
-             free (yyls);
-#endif
-           }
-         return 2;
-       }
+       goto yyoverflowlab;
       yystacksize *= 2;
       if (yystacksize > YYMAXDEPTH)
        yystacksize = YYMAXDEPTH;
-#ifndef YYSTACK_USE_ALLOCA
-      yyfree_stacks = 1;
-#endif
-      yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
-      __yy_memcpy ((char *)yyss, (char *)yyss1,
-                  size * (unsigned int) sizeof (*yyssp));
-      yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
-      __yy_memcpy ((char *)yyvs, (char *)yyvs1,
-                  size * (unsigned int) sizeof (*yyvsp));
-#ifdef YYLSP_NEEDED
-      yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
-      __yy_memcpy ((char *)yyls, (char *)yyls1,
-                  size * (unsigned int) sizeof (*yylsp));
-#endif
+
+      {
+       short *yyss1 = yyss;
+       union yyalloc *yyptr =
+         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+       if (! yyptr)
+         goto yyoverflowlab;
+       YYSTACK_RELOCATE (short, yyss);
+       YYSTACK_RELOCATE (YYSTYPE, yyvs);
+# if YYLSP_NEEDED
+       YYSTACK_RELOCATE (YYLTYPE, yyls);
+# endif
+# undef YYSTACK_RELOCATE
+       if (yyss1 != yyssa)
+         YYSTACK_FREE (yyss1);
+      }
 #endif /* no yyoverflow */
 
-      yyssp = yyss + size - 1;
-      yyvsp = yyvs + size - 1;
-#ifdef YYLSP_NEEDED
-      yylsp = yyls + size - 1;
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+#if YYLSP_NEEDED
+      yylsp = yyls + yysize - 1;
 #endif
 
-#if YYDEBUG != 0
-      if (yydebug)
-       fprintf(stderr, "Stack size increased to %d\n", yystacksize);
-#endif
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                 (unsigned long int) yystacksize));
 
       if (yyssp >= yyss + yystacksize - 1)
        YYABORT;
     }
 
-#if YYDEBUG != 0
-  if (yydebug)
-    fprintf(stderr, "Entering state %d\n", yystate);
-#endif
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
   goto yybackup;
- yybackup:
+
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
 
 /* Do appropriate processing given the current state.  */
 /* Read a lookahead token if we need one and don't already have one.  */
@@ -1104,10 +1322,7 @@ yynewstate:
 
   if (yychar == YYEMPTY)
     {
-#if YYDEBUG != 0
-      if (yydebug)
-       fprintf(stderr, "Reading a token: ");
-#endif
+      YYDPRINTF ((stderr, "Reading a token: "));
       yychar = YYLEX;
     }
 
@@ -1118,25 +1333,25 @@ yynewstate:
       yychar1 = 0;
       yychar = YYEOF;          /* Don't call YYLEX any more */
 
-#if YYDEBUG != 0
-      if (yydebug)
-       fprintf(stderr, "Now at end of input.\n");
-#endif
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
     }
   else
     {
-      yychar1 = YYTRANSLATE(yychar);
+      yychar1 = YYTRANSLATE (yychar);
 
-#if YYDEBUG != 0
+#if YYDEBUG
+     /* We have to keep this `#if YYDEBUG', since we use variables
+       which are defined only if `YYDEBUG' is set.  */
       if (yydebug)
        {
-         fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
-         /* Give the individual parser a way to print the precise meaning
-            of a token, for further debugging info.  */
-#ifdef YYPRINT
+         YYFPRINTF (stderr, "Next token is %d (%s",
+                    yychar, yytname[yychar1]);
+         /* Give the individual parser a way to print the precise
+            meaning of a token, for further debugging info.  */
+# ifdef YYPRINT
          YYPRINT (stderr, yychar, yylval);
-#endif
-         fprintf (stderr, ")\n");
+# endif
+         YYFPRINTF (stderr, ")\n");
        }
 #endif
     }
@@ -1168,85 +1383,107 @@ yynewstate:
     YYACCEPT;
 
   /* Shift the lookahead token.  */
-
-#if YYDEBUG != 0
-  if (yydebug)
-    fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
-#endif
+  YYDPRINTF ((stderr, "Shifting token %d (%s), ",
+             yychar, yytname[yychar1]));
 
   /* Discard the token being shifted unless it is eof.  */
   if (yychar != YYEOF)
     yychar = YYEMPTY;
 
   *++yyvsp = yylval;
-#ifdef YYLSP_NEEDED
+#if YYLSP_NEEDED
   *++yylsp = yylloc;
 #endif
 
-  /* count tokens shifted since error; after three, turn off error status.  */
-  if (yyerrstatus) yyerrstatus--;
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
 
   yystate = yyn;
   goto yynewstate;
 
-/* Do the default action for the current state.  */
-yydefault:
 
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
   yyn = yydefact[yystate];
   if (yyn == 0)
     goto yyerrlab;
+  goto yyreduce;
+
 
-/* Do a reduction.  yyn is the number of a rule to reduce with.  */
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
 yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
   yylen = yyr2[yyn];
-  if (yylen > 0)
-    yyval = yyvsp[1-yylen]; /* implement default value of the action */
 
-#if YYDEBUG != 0
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to the semantic value of
+     the lookahead token.  This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+#if YYLSP_NEEDED
+  /* Similarly for the default location.  Let the user run additional
+     commands if for instance locations are ranges.  */
+  yyloc = yylsp[1-yylen];
+  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+#endif
+
+#if YYDEBUG
+  /* We have to keep this `#if YYDEBUG', since we use variables which
+     are defined only if `YYDEBUG' is set.  */
   if (yydebug)
     {
-      int i;
+      int yyi;
 
-      fprintf (stderr, "Reducing via rule %d (line %d), ",
-              yyn, yyrline[yyn]);
+      YYFPRINTF (stderr, "Reducing via rule %d (line %d), ",
+                yyn, yyrline[yyn]);
 
       /* Print the symbols being reduced, and their result.  */
-      for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
-       fprintf (stderr, "%s ", yytname[yyrhs[i]]);
-      fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+      for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++)
+       YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]);
+      YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]);
     }
 #endif
 
-
   switch (yyn) {
 
 case 1:
-#line 283 "/usr/homes/chet/src/bash/src/parse.y"
+#line 327 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          /* Case of regular command.  Discard the error
                             safety net,and return the command just parsed. */
                          global_command = yyvsp[-1].command;
                          eof_encountered = 0;
-                         discard_parser_constructs (0);
+                         /* discard_parser_constructs (0); */
                          YYACCEPT;
-                       ;
-    break;}
+                       }
+    break;
 case 2:
-#line 292 "/usr/homes/chet/src/bash/src/parse.y"
+#line 336 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          /* Case of regular command, but not a very
                             interesting one.  Return a NULL command. */
                          global_command = (COMMAND *)NULL;
                          YYACCEPT;
-                       ;
-    break;}
+                       }
+    break;
 case 3:
-#line 299 "/usr/homes/chet/src/bash/src/parse.y"
+#line 343 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          /* Error during parsing.  Return NULL command. */
                          global_command = (COMMAND *)NULL;
                          eof_encountered = 0;
-                         discard_parser_constructs (1);
+                         /* discard_parser_constructs (1); */
                          if (interactive)
                            {
                              YYACCEPT;
@@ -1255,241 +1492,255 @@ case 3:
                            {
                              YYABORT;
                            }
-                       ;
-    break;}
+                       }
+    break;
 case 4:
-#line 314 "/usr/homes/chet/src/bash/src/parse.y"
+#line 358 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          /* Case of EOF seen by itself.  Do ignoreeof or
                             not. */
                          global_command = (COMMAND *)NULL;
                          handle_eof_input_unit ();
                          YYACCEPT;
-                       ;
-    break;}
+                       }
+    break;
 case 5:
-#line 324 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.word_list = make_word_list (yyvsp[0].word, (WORD_LIST *)NULL); ;
-    break;}
+#line 368 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.word_list = make_word_list (yyvsp[0].word, (WORD_LIST *)NULL); }
+    break;
 case 6:
-#line 326 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.word_list = make_word_list (yyvsp[0].word, yyvsp[-1].word_list); ;
-    break;}
+#line 370 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.word_list = make_word_list (yyvsp[0].word, yyvsp[-1].word_list); }
+    break;
 case 7:
-#line 330 "/usr/homes/chet/src/bash/src/parse.y"
+#line 374 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (1, r_output_direction, redir);
-                       ;
-    break;}
+                       }
+    break;
 case 8:
-#line 335 "/usr/homes/chet/src/bash/src/parse.y"
+#line 379 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (0, r_input_direction, redir);
-                       ;
-    break;}
+                       }
+    break;
 case 9:
-#line 340 "/usr/homes/chet/src/bash/src/parse.y"
+#line 384 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (yyvsp[-2].number, r_output_direction, redir);
-                       ;
-    break;}
+                       }
+    break;
 case 10:
-#line 345 "/usr/homes/chet/src/bash/src/parse.y"
+#line 389 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (yyvsp[-2].number, r_input_direction, redir);
-                       ;
-    break;}
+                       }
+    break;
 case 11:
-#line 350 "/usr/homes/chet/src/bash/src/parse.y"
+#line 394 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (1, r_appending_to, redir);
-                       ;
-    break;}
+                       }
+    break;
 case 12:
-#line 355 "/usr/homes/chet/src/bash/src/parse.y"
+#line 399 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (yyvsp[-2].number, r_appending_to, redir);
-                       ;
-    break;}
+                       }
+    break;
 case 13:
-#line 360 "/usr/homes/chet/src/bash/src/parse.y"
+#line 404 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (0, r_reading_until, redir);
                          redir_stack[need_here_doc++] = yyval.redirect;
-                       ;
-    break;}
+                       }
+    break;
 case 14:
-#line 366 "/usr/homes/chet/src/bash/src/parse.y"
+#line 410 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (yyvsp[-2].number, r_reading_until, redir);
                          redir_stack[need_here_doc++] = yyval.redirect;
-                       ;
-    break;}
+                       }
+    break;
 case 15:
-#line 372 "/usr/homes/chet/src/bash/src/parse.y"
+#line 416 "/usr/homes/chet/src/bash/src/parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (0, r_reading_string, redir);
+                       }
+    break;
+case 16:
+#line 421 "/usr/homes/chet/src/bash/src/parse.y"
+{
+                         redir.filename = yyvsp[0].word;
+                         yyval.redirect = make_redirection (yyvsp[-2].number, r_reading_string, redir);
+                       }
+    break;
+case 17:
+#line 426 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.dest = yyvsp[0].number;
                          yyval.redirect = make_redirection (0, r_duplicating_input, redir);
-                       ;
-    break;}
-case 16:
-#line 377 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 18:
+#line 431 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.dest = yyvsp[0].number;
                          yyval.redirect = make_redirection (yyvsp[-2].number, r_duplicating_input, redir);
-                       ;
-    break;}
-case 17:
-#line 382 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 19:
+#line 436 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.dest = yyvsp[0].number;
                          yyval.redirect = make_redirection (1, r_duplicating_output, redir);
-                       ;
-    break;}
-case 18:
-#line 387 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 20:
+#line 441 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.dest = yyvsp[0].number;
                          yyval.redirect = make_redirection (yyvsp[-2].number, r_duplicating_output, redir);
-                       ;
-    break;}
-case 19:
-#line 392 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 21:
+#line 446 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (0, r_duplicating_input_word, redir);
-                       ;
-    break;}
-case 20:
-#line 397 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 22:
+#line 451 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (yyvsp[-2].number, r_duplicating_input_word, redir);
-                       ;
-    break;}
-case 21:
-#line 402 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 23:
+#line 456 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (1, r_duplicating_output_word, redir);
-                       ;
-    break;}
-case 22:
-#line 407 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 24:
+#line 461 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (yyvsp[-2].number, r_duplicating_output_word, redir);
-                       ;
-    break;}
-case 23:
-#line 412 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 25:
+#line 466 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection
                            (0, r_deblank_reading_until, redir);
                          redir_stack[need_here_doc++] = yyval.redirect;
-                       ;
-    break;}
-case 24:
-#line 419 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 26:
+#line 473 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection
                            (yyvsp[-2].number, r_deblank_reading_until, redir);
                          redir_stack[need_here_doc++] = yyval.redirect;
-                       ;
-    break;}
-case 25:
-#line 426 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 27:
+#line 480 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.dest = 0;
                          yyval.redirect = make_redirection (1, r_close_this, redir);
-                       ;
-    break;}
-case 26:
-#line 431 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 28:
+#line 485 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.dest = 0;
                          yyval.redirect = make_redirection (yyvsp[-2].number, r_close_this, redir);
-                       ;
-    break;}
-case 27:
-#line 436 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 29:
+#line 490 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.dest = 0;
                          yyval.redirect = make_redirection (0, r_close_this, redir);
-                       ;
-    break;}
-case 28:
-#line 441 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 30:
+#line 495 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.dest = 0;
                          yyval.redirect = make_redirection (yyvsp[-2].number, r_close_this, redir);
-                       ;
-    break;}
-case 29:
-#line 446 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 31:
+#line 500 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (1, r_err_and_out, redir);
-                       ;
-    break;}
-case 30:
-#line 451 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 32:
+#line 505 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (yyvsp[-2].number, r_input_output, redir);
-                       ;
-    break;}
-case 31:
-#line 456 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 33:
+#line 510 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (0, r_input_output, redir);
-                       ;
-    break;}
-case 32:
-#line 461 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 34:
+#line 515 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (1, r_output_force, redir);
-                       ;
-    break;}
-case 33:
-#line 466 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 35:
+#line 520 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          redir.filename = yyvsp[0].word;
                          yyval.redirect = make_redirection (yyvsp[-2].number, r_output_force, redir);
-                       ;
-    break;}
-case 34:
-#line 473 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.element.word = yyvsp[0].word; yyval.element.redirect = 0; ;
-    break;}
-case 35:
-#line 475 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.element.word = yyvsp[0].word; yyval.element.redirect = 0; ;
-    break;}
+                       }
+    break;
 case 36:
-#line 477 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.element.redirect = yyvsp[0].redirect; yyval.element.word = 0; ;
-    break;}
+#line 527 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.element.word = yyvsp[0].word; yyval.element.redirect = 0; }
+    break;
 case 37:
-#line 481 "/usr/homes/chet/src/bash/src/parse.y"
+#line 529 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.element.word = yyvsp[0].word; yyval.element.redirect = 0; }
+    break;
+case 38:
+#line 531 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.element.redirect = yyvsp[0].redirect; yyval.element.word = 0; }
+    break;
+case 39:
+#line 535 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          yyval.redirect = yyvsp[0].redirect;
-                       ;
-    break;}
-case 38:
-#line 485 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 40:
+#line 539 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          register REDIRECT *t;
 
@@ -1497,26 +1748,26 @@ case 38:
                            ;
                          t->next = yyvsp[0].redirect;
                          yyval.redirect = yyvsp[-1].redirect;
-                       ;
-    break;}
-case 39:
-#line 496 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_simple_command (yyvsp[0].element, (COMMAND *)NULL); ;
-    break;}
-case 40:
-#line 498 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_simple_command (yyvsp[0].element, yyvsp[-1].command); ;
-    break;}
+                       }
+    break;
 case 41:
-#line 502 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = clean_simple_command (yyvsp[0].command); ;
-    break;}
+#line 550 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_simple_command (yyvsp[0].element, (COMMAND *)NULL); }
+    break;
 case 42:
-#line 504 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[0].command; ;
-    break;}
+#line 552 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_simple_command (yyvsp[0].element, yyvsp[-1].command); }
+    break;
 case 43:
-#line 506 "/usr/homes/chet/src/bash/src/parse.y"
+#line 556 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = clean_simple_command (yyvsp[0].command); }
+    break;
+case 44:
+#line 558 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[0].command; }
+    break;
+case 45:
+#line 560 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          COMMAND *tc;
 
@@ -1531,170 +1782,170 @@ case 43:
                          else
                            tc->redirects = yyvsp[0].redirect;
                          yyval.command = yyvsp[-1].command;
-                       ;
-    break;}
-case 44:
-#line 522 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[0].command; ;
-    break;}
-case 45:
-#line 526 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[0].command; ;
-    break;}
+                       }
+    break;
 case 46:
-#line 528 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[0].command; ;
-    break;}
+#line 576 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[0].command; }
+    break;
 case 47:
-#line 530 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_while_command (yyvsp[-3].command, yyvsp[-1].command); ;
-    break;}
+#line 580 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[0].command; }
+    break;
 case 48:
-#line 532 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_until_command (yyvsp[-3].command, yyvsp[-1].command); ;
-    break;}
+#line 582 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[0].command; }
+    break;
 case 49:
-#line 534 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[0].command; ;
-    break;}
+#line 584 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_while_command (yyvsp[-3].command, yyvsp[-1].command); }
+    break;
 case 50:
-#line 536 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[0].command; ;
-    break;}
+#line 586 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_until_command (yyvsp[-3].command, yyvsp[-1].command); }
+    break;
 case 51:
-#line 538 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[0].command; ;
-    break;}
+#line 588 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[0].command; }
+    break;
 case 52:
-#line 540 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[0].command; ;
-    break;}
+#line 590 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[0].command; }
+    break;
 case 53:
-#line 542 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[0].command; ;
-    break;}
+#line 592 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[0].command; }
+    break;
 case 54:
-#line 544 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[0].command; ;
-    break;}
+#line 594 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[0].command; }
+    break;
 case 55:
-#line 546 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[0].command; ;
-    break;}
+#line 596 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[0].command; }
+    break;
 case 56:
-#line 550 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_for_command (yyvsp[-4].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ;
-    break;}
+#line 598 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[0].command; }
+    break;
 case 57:
-#line 552 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_for_command (yyvsp[-4].word, add_string_to_list ("$@", (WORD_LIST *)NULL), yyvsp[-1].command); ;
-    break;}
+#line 600 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[0].command; }
+    break;
 case 58:
-#line 554 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_for_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ;
-    break;}
+#line 604 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_for_command (yyvsp[-4].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); }
+    break;
 case 59:
-#line 556 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_for_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); ;
-    break;}
+#line 606 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_for_command (yyvsp[-4].word, add_string_to_list ("$@", (WORD_LIST *)NULL), yyvsp[-1].command); }
+    break;
 case 60:
-#line 558 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_for_command (yyvsp[-8].word, REVERSE_LIST (yyvsp[-5].word_list, WORD_LIST *), yyvsp[-1].command); ;
-    break;}
+#line 608 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_for_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); }
+    break;
 case 61:
-#line 560 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_for_command (yyvsp[-8].word, REVERSE_LIST (yyvsp[-5].word_list, WORD_LIST *), yyvsp[-1].command); ;
-    break;}
+#line 610 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_for_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command); }
+    break;
 case 62:
-#line 562 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_for_command (yyvsp[-7].word, (WORD_LIST *)NULL, yyvsp[-1].command); ;
-    break;}
+#line 612 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_for_command (yyvsp[-8].word, REVERSE_LIST (yyvsp[-5].word_list, WORD_LIST *), yyvsp[-1].command); }
+    break;
 case 63:
-#line 564 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_for_command (yyvsp[-7].word, (WORD_LIST *)NULL, yyvsp[-1].command); ;
-    break;}
+#line 614 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_for_command (yyvsp[-8].word, REVERSE_LIST (yyvsp[-5].word_list, WORD_LIST *), yyvsp[-1].command); }
+    break;
 case 64:
-#line 568 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_arith_for_command (yyvsp[-5].word_list, yyvsp[-1].command, arith_for_lineno); ;
-    break;}
+#line 616 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_for_command (yyvsp[-7].word, (WORD_LIST *)NULL, yyvsp[-1].command); }
+    break;
 case 65:
-#line 570 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_arith_for_command (yyvsp[-5].word_list, yyvsp[-1].command, arith_for_lineno); ;
-    break;}
+#line 618 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_for_command (yyvsp[-7].word, (WORD_LIST *)NULL, yyvsp[-1].command); }
+    break;
 case 66:
-#line 572 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_arith_for_command (yyvsp[-3].word_list, yyvsp[-1].command, arith_for_lineno); ;
-    break;}
+#line 622 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_arith_for_command (yyvsp[-5].word_list, yyvsp[-1].command, arith_for_lineno); }
+    break;
 case 67:
-#line 574 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_arith_for_command (yyvsp[-3].word_list, yyvsp[-1].command, arith_for_lineno); ;
-    break;}
+#line 624 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_arith_for_command (yyvsp[-5].word_list, yyvsp[-1].command, arith_for_lineno); }
+    break;
 case 68:
-#line 578 "/usr/homes/chet/src/bash/src/parse.y"
-{
-                         yyval.command = make_select_command (yyvsp[-4].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command);
-                       ;
-    break;}
+#line 626 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_arith_for_command (yyvsp[-3].word_list, yyvsp[-1].command, arith_for_lineno); }
+    break;
 case 69:
-#line 582 "/usr/homes/chet/src/bash/src/parse.y"
-{
-                         yyval.command = make_select_command (yyvsp[-4].word, add_string_to_list ("$@", (WORD_LIST *)NULL), yyvsp[-1].command);
-                       ;
-    break;}
+#line 628 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_arith_for_command (yyvsp[-3].word_list, yyvsp[-1].command, arith_for_lineno); }
+    break;
 case 70:
-#line 586 "/usr/homes/chet/src/bash/src/parse.y"
+#line 632 "/usr/homes/chet/src/bash/src/parse.y"
 {
-                         yyval.command = make_select_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command);
-                       ;
-    break;}
+                         yyval.command = make_select_command (yyvsp[-4].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command);
+                       }
+    break;
 case 71:
-#line 590 "/usr/homes/chet/src/bash/src/parse.y"
+#line 636 "/usr/homes/chet/src/bash/src/parse.y"
 {
-                         yyval.command = make_select_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command);
-                       ;
-    break;}
+                         yyval.command = make_select_command (yyvsp[-4].word, add_string_to_list ("$@", (WORD_LIST *)NULL), yyvsp[-1].command);
+                       }
+    break;
 case 72:
-#line 594 "/usr/homes/chet/src/bash/src/parse.y"
+#line 640 "/usr/homes/chet/src/bash/src/parse.y"
 {
-                         yyval.command = make_select_command (yyvsp[-8].word, (WORD_LIST *)reverse_list (yyvsp[-5].word_list), yyvsp[-1].command);
-                       ;
-    break;}
+                         yyval.command = make_select_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command);
+                       }
+    break;
 case 73:
-#line 598 "/usr/homes/chet/src/bash/src/parse.y"
+#line 644 "/usr/homes/chet/src/bash/src/parse.y"
 {
-                         yyval.command = make_select_command (yyvsp[-8].word, (WORD_LIST *)reverse_list (yyvsp[-5].word_list), yyvsp[-1].command);
-                       ;
-    break;}
+                         yyval.command = make_select_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command);
+                       }
+    break;
 case 74:
-#line 604 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_case_command (yyvsp[-4].word, (PATTERN_LIST *)NULL); ;
-    break;}
+#line 648 "/usr/homes/chet/src/bash/src/parse.y"
+{
+                         yyval.command = make_select_command (yyvsp[-8].word, REVERSE_LIST (yyvsp[-5].word_list, WORD_LIST *), yyvsp[-1].command);
+                       }
+    break;
 case 75:
-#line 606 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_case_command (yyvsp[-5].word, yyvsp[-2].pattern); ;
-    break;}
+#line 652 "/usr/homes/chet/src/bash/src/parse.y"
+{
+                         yyval.command = make_select_command (yyvsp[-8].word, REVERSE_LIST (yyvsp[-5].word_list, WORD_LIST *), yyvsp[-1].command);
+                       }
+    break;
 case 76:
-#line 608 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_case_command (yyvsp[-4].word, yyvsp[-1].pattern); ;
-    break;}
+#line 658 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_case_command (yyvsp[-4].word, (PATTERN_LIST *)NULL); }
+    break;
 case 77:
-#line 612 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_function_def (yyvsp[-4].word, yyvsp[0].command, function_dstart, function_bstart); ;
-    break;}
+#line 660 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_case_command (yyvsp[-5].word, yyvsp[-2].pattern); }
+    break;
 case 78:
-#line 615 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_function_def (yyvsp[-4].word, yyvsp[0].command, function_dstart, function_bstart); ;
-    break;}
+#line 662 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_case_command (yyvsp[-4].word, yyvsp[-1].pattern); }
+    break;
 case 79:
-#line 618 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_function_def (yyvsp[-2].word, yyvsp[0].command, function_dstart, function_bstart); ;
-    break;}
+#line 666 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_function_def (yyvsp[-4].word, yyvsp[0].command, function_dstart, function_bstart); }
+    break;
 case 80:
-#line 623 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[0].command; ;
-    break;}
+#line 669 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_function_def (yyvsp[-4].word, yyvsp[0].command, function_dstart, function_bstart); }
+    break;
 case 81:
-#line 625 "/usr/homes/chet/src/bash/src/parse.y"
+#line 672 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_function_def (yyvsp[-2].word, yyvsp[0].command, function_dstart, function_bstart); }
+    break;
+case 82:
+#line 677 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[0].command; }
+    break;
+case 83:
+#line 679 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          COMMAND *tc;
 
@@ -1722,145 +1973,145 @@ case 81:
                          else
                            tc->redirects = yyvsp[0].redirect;
                          yyval.command = yyvsp[-1].command;
-                       ;
-    break;}
-case 82:
-#line 656 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 84:
+#line 710 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          yyval.command = make_subshell_command (yyvsp[-1].command);
                          yyval.command->flags |= CMD_WANT_SUBSHELL;
-                       ;
-    break;}
-case 83:
-#line 663 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_if_command (yyvsp[-3].command, yyvsp[-1].command, (COMMAND *)NULL); ;
-    break;}
-case 84:
-#line 665 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_if_command (yyvsp[-5].command, yyvsp[-3].command, yyvsp[-1].command); ;
-    break;}
+                       }
+    break;
 case 85:
-#line 667 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_if_command (yyvsp[-4].command, yyvsp[-2].command, yyvsp[-1].command); ;
-    break;}
+#line 717 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_if_command (yyvsp[-3].command, yyvsp[-1].command, (COMMAND *)NULL); }
+    break;
 case 86:
-#line 672 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_group_command (yyvsp[-1].command); ;
-    break;}
+#line 719 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_if_command (yyvsp[-5].command, yyvsp[-3].command, yyvsp[-1].command); }
+    break;
 case 87:
-#line 676 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_arith_command (yyvsp[0].word_list); ;
-    break;}
+#line 721 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_if_command (yyvsp[-4].command, yyvsp[-2].command, yyvsp[-1].command); }
+    break;
 case 88:
-#line 680 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[-1].command; ;
-    break;}
+#line 726 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_group_command (yyvsp[-1].command); }
+    break;
 case 89:
-#line 684 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_if_command (yyvsp[-2].command, yyvsp[0].command, (COMMAND *)NULL); ;
-    break;}
+#line 730 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_arith_command (yyvsp[0].word_list); }
+    break;
 case 90:
-#line 686 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_if_command (yyvsp[-4].command, yyvsp[-2].command, yyvsp[0].command); ;
-    break;}
+#line 734 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[-1].command; }
+    break;
 case 91:
-#line 688 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = make_if_command (yyvsp[-3].command, yyvsp[-1].command, yyvsp[0].command); ;
-    break;}
+#line 738 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_if_command (yyvsp[-2].command, yyvsp[0].command, (COMMAND *)NULL); }
+    break;
+case 92:
+#line 740 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_if_command (yyvsp[-4].command, yyvsp[-2].command, yyvsp[0].command); }
+    break;
 case 93:
-#line 693 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyvsp[0].pattern->next = yyvsp[-1].pattern; yyval.pattern = yyvsp[0].pattern; ;
-    break;}
-case 94:
-#line 697 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, yyvsp[0].command); ;
-    break;}
+#line 742 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = make_if_command (yyvsp[-3].command, yyvsp[-1].command, yyvsp[0].command); }
+    break;
 case 95:
-#line 699 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, (COMMAND *)NULL); ;
-    break;}
+#line 747 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyvsp[0].pattern->next = yyvsp[-1].pattern; yyval.pattern = yyvsp[0].pattern; }
+    break;
 case 96:
-#line 701 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, yyvsp[0].command); ;
-    break;}
+#line 751 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, yyvsp[0].command); }
+    break;
 case 97:
-#line 703 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, (COMMAND *)NULL); ;
-    break;}
+#line 753 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, (COMMAND *)NULL); }
+    break;
+case 98:
+#line 755 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, yyvsp[0].command); }
+    break;
 case 99:
-#line 708 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyvsp[-1].pattern->next = yyvsp[-2].pattern; yyval.pattern = yyvsp[-1].pattern; ;
-    break;}
-case 100:
-#line 712 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.word_list = make_word_list (yyvsp[0].word, (WORD_LIST *)NULL); ;
-    break;}
+#line 757 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, (COMMAND *)NULL); }
+    break;
 case 101:
-#line 714 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.word_list = make_word_list (yyvsp[0].word, yyvsp[-2].word_list); ;
-    break;}
+#line 762 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyvsp[-1].pattern->next = yyvsp[-2].pattern; yyval.pattern = yyvsp[-1].pattern; }
+    break;
 case 102:
-#line 723 "/usr/homes/chet/src/bash/src/parse.y"
+#line 766 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.word_list = make_word_list (yyvsp[0].word, (WORD_LIST *)NULL); }
+    break;
+case 103:
+#line 768 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.word_list = make_word_list (yyvsp[0].word, yyvsp[-2].word_list); }
+    break;
+case 104:
+#line 777 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          yyval.command = yyvsp[0].command;
                          if (need_here_doc)
                            gather_here_documents ();
-                        ;
-    break;}
-case 104:
-#line 732 "/usr/homes/chet/src/bash/src/parse.y"
+                        }
+    break;
+case 106:
+#line 786 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          yyval.command = yyvsp[0].command;
-                       ;
-    break;}
-case 106:
-#line 739 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 108:
+#line 793 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          if (yyvsp[-2].command->type == cm_connection)
                            yyval.command = connect_async_list (yyvsp[-2].command, (COMMAND *)NULL, '&');
                          else
                            yyval.command = command_connect (yyvsp[-2].command, (COMMAND *)NULL, '&');
-                       ;
-    break;}
-case 108:
-#line 750 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, AND_AND); ;
-    break;}
-case 109:
-#line 752 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, OR_OR); ;
-    break;}
+                       }
+    break;
 case 110:
-#line 754 "/usr/homes/chet/src/bash/src/parse.y"
+#line 804 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, AND_AND); }
+    break;
+case 111:
+#line 806 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, OR_OR); }
+    break;
+case 112:
+#line 808 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          if (yyvsp[-3].command->type == cm_connection)
                            yyval.command = connect_async_list (yyvsp[-3].command, yyvsp[0].command, '&');
                          else
                            yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, '&');
-                       ;
-    break;}
-case 111:
-#line 761 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, ';'); ;
-    break;}
-case 112:
-#line 763 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, ';'); ;
-    break;}
+                       }
+    break;
 case 113:
-#line 765 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[0].command; ;
-    break;}
-case 119:
-#line 784 "/usr/homes/chet/src/bash/src/parse.y"
+#line 815 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, ';'); }
+    break;
+case 114:
+#line 817 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, ';'); }
+    break;
+case 115:
+#line 819 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[0].command; }
+    break;
+case 123:
+#line 842 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          yyval.command = yyvsp[0].command;
                          if (need_here_doc)
                            gather_here_documents ();
-                       ;
-    break;}
-case 120:
-#line 790 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 124:
+#line 848 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          if (yyvsp[-1].command->type == cm_connection)
                            yyval.command = connect_async_list (yyvsp[-1].command, (COMMAND *)NULL, '&');
@@ -1868,133 +2119,119 @@ case 120:
                            yyval.command = command_connect (yyvsp[-1].command, (COMMAND *)NULL, '&');
                          if (need_here_doc)
                            gather_here_documents ();
-                       ;
-    break;}
-case 121:
-#line 799 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 125:
+#line 857 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          yyval.command = yyvsp[-1].command;
                          if (need_here_doc)
                            gather_here_documents ();
-                       ;
-    break;}
-case 122:
-#line 807 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, AND_AND); ;
-    break;}
-case 123:
-#line 809 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, OR_OR); ;
-    break;}
-case 124:
-#line 811 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 126:
+#line 865 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, AND_AND); }
+    break;
+case 127:
+#line 867 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, OR_OR); }
+    break;
+case 128:
+#line 869 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          if (yyvsp[-2].command->type == cm_connection)
                            yyval.command = connect_async_list (yyvsp[-2].command, yyvsp[0].command, '&');
                          else
                            yyval.command = command_connect (yyvsp[-2].command, yyvsp[0].command, '&');
-                       ;
-    break;}
-case 125:
-#line 818 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = command_connect (yyvsp[-2].command, yyvsp[0].command, ';'); ;
-    break;}
-case 126:
-#line 821 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[0].command; ;
-    break;}
-case 127:
-#line 825 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[0].command; ;
-    break;}
-case 128:
-#line 827 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 129:
+#line 876 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = command_connect (yyvsp[-2].command, yyvsp[0].command, ';'); }
+    break;
+case 130:
+#line 879 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[0].command; }
+    break;
+case 131:
+#line 883 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[0].command; }
+    break;
+case 132:
+#line 885 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          yyvsp[0].command->flags |= CMD_INVERT_RETURN;
                          yyval.command = yyvsp[0].command;
-                       ;
-    break;}
-case 129:
-#line 832 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 133:
+#line 890 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          yyvsp[0].command->flags |= yyvsp[-1].number;
                          yyval.command = yyvsp[0].command;
-                       ;
-    break;}
-case 130:
-#line 837 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 134:
+#line 895 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          yyvsp[0].command->flags |= yyvsp[-2].number|CMD_INVERT_RETURN;
                          yyval.command = yyvsp[0].command;
-                       ;
-    break;}
-case 131:
-#line 842 "/usr/homes/chet/src/bash/src/parse.y"
+                       }
+    break;
+case 135:
+#line 900 "/usr/homes/chet/src/bash/src/parse.y"
 {
                          yyvsp[0].command->flags |= yyvsp[-1].number|CMD_INVERT_RETURN;
                          yyval.command = yyvsp[0].command;
-                       ;
-    break;}
-case 132:
-#line 850 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, '|'); ;
-    break;}
-case 133:
-#line 852 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.command = yyvsp[0].command; ;
-    break;}
-case 134:
-#line 856 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.number = CMD_TIME_PIPELINE; ;
-    break;}
-case 135:
-#line 858 "/usr/homes/chet/src/bash/src/parse.y"
-{ yyval.number = CMD_TIME_PIPELINE|CMD_TIME_POSIX; ;
-    break;}
+                       }
+    break;
+case 136:
+#line 908 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, '|'); }
+    break;
+case 137:
+#line 910 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.command = yyvsp[0].command; }
+    break;
+case 138:
+#line 914 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.number = CMD_TIME_PIPELINE; }
+    break;
+case 139:
+#line 916 "/usr/homes/chet/src/bash/src/parse.y"
+{ yyval.number = CMD_TIME_PIPELINE|CMD_TIME_POSIX; }
+    break;
 }
-   /* the action file gets copied in in place of this dollarsign */
-#line 543 "/usr/local/share/bison.simple"
+
+#line 705 "/usr/local/share/bison/bison.simple"
+
 \f
   yyvsp -= yylen;
   yyssp -= yylen;
-#ifdef YYLSP_NEEDED
+#if YYLSP_NEEDED
   yylsp -= yylen;
 #endif
 
-#if YYDEBUG != 0
+#if YYDEBUG
   if (yydebug)
     {
-      short *ssp1 = yyss - 1;
-      fprintf (stderr, "state stack now");
-      while (ssp1 != yyssp)
-       fprintf (stderr, " %d", *++ssp1);
-      fprintf (stderr, "\n");
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "state stack now");
+      while (yyssp1 != yyssp)
+       YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
     }
 #endif
 
   *++yyvsp = yyval;
-
-#ifdef YYLSP_NEEDED
-  yylsp++;
-  if (yylen == 0)
-    {
-      yylsp->first_line = yylloc.first_line;
-      yylsp->first_column = yylloc.first_column;
-      yylsp->last_line = (yylsp-1)->last_line;
-      yylsp->last_column = (yylsp-1)->last_column;
-      yylsp->text = 0;
-    }
-  else
-    {
-      yylsp->last_line = (yylsp+yylen-1)->last_line;
-      yylsp->last_column = (yylsp+yylen-1)->last_column;
-    }
+#if YYLSP_NEEDED
+  *++yylsp = yyloc;
 #endif
 
-  /* Now "shift" the result of the reduction.
-     Determine what state that goes to,
-     based on the state we popped back to
-     and the rule number reduced by.  */
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
 
   yyn = yyr1[yyn];
 
@@ -2006,10 +2243,13 @@ case 135:
 
   goto yynewstate;
 
-yyerrlab:   /* here on detecting error */
 
-  if (! yyerrstatus)
-    /* If not already recovering from an error, report this error.  */
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
     {
       ++yynerrs;
 
@@ -2018,102 +2258,121 @@ yyerrlab:   /* here on detecting error */
 
       if (yyn > YYFLAG && yyn < YYLAST)
        {
-         int size = 0;
-         char *msg;
-         int x, count;
-
-         count = 0;
-         /* Start X at -yyn if nec to avoid negative indexes in yycheck.  */
-         for (x = (yyn < 0 ? -yyn : 0);
-              x < (sizeof(yytname) / sizeof(char *)); x++)
-           if (yycheck[x + yyn] == x)
-             size += strlen(yytname[x]) + 15, count++;
-         msg = (char *) malloc(size + 15);
-         if (msg != 0)
+         YYSIZE_T yysize = 0;
+         char *yymsg;
+         int yyx, yycount;
+
+         yycount = 0;
+         /* Start YYX at -YYN if negative to avoid negative indexes in
+            YYCHECK.  */
+         for (yyx = yyn < 0 ? -yyn : 0;
+              yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
+           if (yycheck[yyx + yyn] == yyx)
+             yysize += yystrlen (yytname[yyx]) + 15, yycount++;
+         yysize += yystrlen ("parse error, unexpected ") + 1;
+         yysize += yystrlen (yytname[YYTRANSLATE (yychar)]);
+         yymsg = (char *) YYSTACK_ALLOC (yysize);
+         if (yymsg != 0)
            {
-             strcpy(msg, "parse error");
+             char *yyp = yystpcpy (yymsg, "parse error, unexpected ");
+             yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]);
 
-             if (count < 5)
+             if (yycount < 5)
                {
-                 count = 0;
-                 for (x = (yyn < 0 ? -yyn : 0);
-                      x < (sizeof(yytname) / sizeof(char *)); x++)
-                   if (yycheck[x + yyn] == x)
+                 yycount = 0;
+                 for (yyx = yyn < 0 ? -yyn : 0;
+                      yyx < (int) (sizeof (yytname) / sizeof (char *));
+                      yyx++)
+                   if (yycheck[yyx + yyn] == yyx)
                      {
-                       strcat(msg, count == 0 ? ", expecting `" : " or `");
-                       strcat(msg, yytname[x]);
-                       strcat(msg, "'");
-                       count++;
+                       const char *yyq = ! yycount ? ", expecting " : " or ";
+                       yyp = yystpcpy (yyp, yyq);
+                       yyp = yystpcpy (yyp, yytname[yyx]);
+                       yycount++;
                      }
                }
-             yyerror(msg);
-             free(msg);
+             yyerror (yymsg);
+             YYSTACK_FREE (yymsg);
            }
          else
-           yyerror ("parse error; also virtual memory exceeded");
+           yyerror ("parse error; also virtual memory exhausted");
        }
       else
-#endif /* YYERROR_VERBOSE */
-       yyerror("parse error");
+#endif /* defined (YYERROR_VERBOSE) */
+       yyerror ("parse error");
     }
-
   goto yyerrlab1;
-yyerrlab1:   /* here on error raised explicitly by an action */
 
+
+/*--------------------------------------------------.
+| yyerrlab1 -- error raised explicitly by an action |
+`--------------------------------------------------*/
+yyerrlab1:
   if (yyerrstatus == 3)
     {
-      /* if just tried and failed to reuse lookahead token after an error, discard it.  */
+      /* If just tried and failed to reuse lookahead token after an
+        error, discard it.  */
 
       /* return failure if at end of input */
       if (yychar == YYEOF)
        YYABORT;
-
-#if YYDEBUG != 0
-      if (yydebug)
-       fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
-#endif
-
+      YYDPRINTF ((stderr, "Discarding token %d (%s).\n",
+                 yychar, yytname[yychar1]));
       yychar = YYEMPTY;
     }
 
-  /* Else will try to reuse lookahead token
-     after shifting the error token.  */
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
 
   yyerrstatus = 3;             /* Each real token shifted decrements this */
 
   goto yyerrhandle;
 
-yyerrdefault:  /* current state does not do anything special for the error token. */
 
+/*-------------------------------------------------------------------.
+| yyerrdefault -- current state does not do anything special for the |
+| error token.                                                       |
+`-------------------------------------------------------------------*/
+yyerrdefault:
 #if 0
   /* This is wrong; only states that explicitly want error tokens
      should shift them.  */
-  yyn = yydefact[yystate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/
-  if (yyn) goto yydefault;
+
+  /* If its default is to accept any token, ok.  Otherwise pop it.  */
+  yyn = yydefact[yystate];
+  if (yyn)
+    goto yydefault;
 #endif
 
-yyerrpop:   /* pop the current state because it cannot handle the error token */
 
-  if (yyssp == yyss) YYABORT;
+/*---------------------------------------------------------------.
+| yyerrpop -- pop the current state because it cannot handle the |
+| error token                                                    |
+`---------------------------------------------------------------*/
+yyerrpop:
+  if (yyssp == yyss)
+    YYABORT;
   yyvsp--;
   yystate = *--yyssp;
-#ifdef YYLSP_NEEDED
+#if YYLSP_NEEDED
   yylsp--;
 #endif
 
-#if YYDEBUG != 0
+#if YYDEBUG
   if (yydebug)
     {
-      short *ssp1 = yyss - 1;
-      fprintf (stderr, "Error: state stack now");
-      while (ssp1 != yyssp)
-       fprintf (stderr, " %d", *++ssp1);
-      fprintf (stderr, "\n");
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "Error: state stack now");
+      while (yyssp1 != yyssp)
+       YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
     }
 #endif
 
+/*--------------.
+| yyerrhandle.  |
+`--------------*/
 yyerrhandle:
-
   yyn = yypact[yystate];
   if (yyn == YYFLAG)
     goto yyerrdefault;
@@ -2136,44 +2395,47 @@ yyerrhandle:
   if (yyn == YYFINAL)
     YYACCEPT;
 
-#if YYDEBUG != 0
-  if (yydebug)
-    fprintf(stderr, "Shifting error token, ");
-#endif
+  YYDPRINTF ((stderr, "Shifting error token, "));
 
   *++yyvsp = yylval;
-#ifdef YYLSP_NEEDED
+#if YYLSP_NEEDED
   *++yylsp = yylloc;
 #endif
 
   yystate = yyn;
   goto yynewstate;
 
- yyacceptlab:
-  /* YYACCEPT comes here.  */
-  if (yyfree_stacks)
-    {
-      free (yyss);
-      free (yyvs);
-#ifdef YYLSP_NEEDED
-      free (yyls);
-#endif
-    }
-  return 0;
 
- yyabortlab:
-  /* YYABORT comes here.  */
-  if (yyfree_stacks)
-    {
-      free (yyss);
-      free (yyvs);
-#ifdef YYLSP_NEEDED
-      free (yyls);
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+/*---------------------------------------------.
+| yyoverflowab -- parser overflow comes here.  |
+`---------------------------------------------*/
+yyoverflowlab:
+  yyerror ("parser stack overflow");
+  yyresult = 2;
+  /* Fall through.  */
+
+yyreturn:
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
 #endif
-    }
-  return 1;
+  return yyresult;
 }
-#line 860 "/usr/homes/chet/src/bash/src/parse.y"
+#line 918 "/usr/homes/chet/src/bash/src/parse.y"
 
 
 /* Possible states for the parser that require it to do special things. */
@@ -2288,6 +2550,12 @@ init_yy_io (get, unget, type, name, location)
   bash_input.ungetter = unget;
 }
 
+char *
+yy_input_name ()
+{
+  return (bash_input.name ? bash_input.name : "stdin");
+}
+
 /* Call this to get the next character of input. */
 static int
 yy_getc ()
@@ -2716,6 +2984,8 @@ push_string (s, expand, ap)
   shell_input_line_index = 0;
   shell_input_line_terminator = '\0';
   parser_state &= ~PST_ALEXPNEXT;
+
+  set_line_mbstate ();
 }
 
 /*
@@ -2749,6 +3019,8 @@ pop_string ()
 #endif
 
   free ((char *)t);
+
+  set_line_mbstate ();
 }
 
 static void
@@ -2908,9 +3180,46 @@ STRING_INT_ALIST word_token_alist[] = {
   { (char *)NULL, 0}
 };
 
-/* XXX - we should also have an alist with strings for other tokens, so we
-        can give more descriptive error messages.  Look at y.tab.h for the
-        other tokens. */
+/* other tokens that can be returned by read_token() */
+STRING_INT_ALIST other_token_alist[] = {
+  /* Multiple-character tokens with special values */
+  { "-p", TIMEOPT },
+  { "&&", AND_AND },
+  { "||", OR_OR },
+  { ">>", GREATER_GREATER },
+  { "<<", LESS_LESS },
+  { "<&", LESS_AND },
+  { ">&", GREATER_AND },
+  { ";;", SEMI_SEMI },
+  { "<<-", LESS_LESS_MINUS },
+  { "<<<", LESS_LESS_LESS },
+  { "&>", AND_GREATER },
+  { "<>", LESS_GREATER },
+  { ">|", GREATER_BAR },
+  { "EOF", yacc_EOF },
+  /* Tokens whose value is the character itself */
+  { ">", '>' },
+  { "<", '<' },
+  { "-", '-' },
+  { "{", '{' },
+  { "}", '}' },
+  { ";", ';' },
+  { "(", '(' },
+  { ")", ')' },
+  { "|", '|' },
+  { "&", '&' },
+  { "newline", '\n' },
+  { (char *)NULL, 0}
+};
+
+/* others not listed here:
+       WORD                    look at yylval.word
+       ASSIGNMENT_WORD         look at yylval.word
+       NUMBER                  look at yylval.number
+       ARITH_CMD               look at yylval.word_list
+       ARITH_FOR_EXPRS         look at yylval.word_list
+       COND_CMD                look at yylval.command
+*/
 
 /* These are used by read_token_word, but appear up here so that shell_getc
    can use them to decide when to add otherwise blank lines to the history. */
@@ -3052,6 +3361,8 @@ shell_getc (remove_quoted_newline)
       shell_input_line_index = 0;
       shell_input_line_len = i;                /* == strlen (shell_input_line) */
 
+      set_line_mbstate ();
+
 #if defined (HISTORY)
       if (remember_on_history && shell_input_line && shell_input_line[0])
        {
@@ -3082,6 +3393,8 @@ shell_getc (remove_quoted_newline)
              /* We have to force the xrealloc below because we don't know
                 the true allocated size of shell_input_line anymore. */
              shell_input_line_size = shell_input_line_len;
+
+             set_line_mbstate ();
            }
        }
       /* Try to do something intelligent with blank lines encountered while
@@ -3133,6 +3446,8 @@ shell_getc (remove_quoted_newline)
 
          shell_input_line[shell_input_line_len] = '\n';
          shell_input_line[shell_input_line_len + 1] = '\0';
+
+         set_line_mbstate ();
        }
     }
 
@@ -3141,8 +3456,7 @@ shell_getc (remove_quoted_newline)
   if (uc)
     shell_input_line_index++;
 
-  if (uc == '\\' && remove_quoted_newline &&
-      shell_input_line[shell_input_line_index] == '\n')
+  if MBTEST(uc == '\\' && remove_quoted_newline && shell_input_line[shell_input_line_index] == '\n')
     {
        prompt_again ();
        line_number++;
@@ -3179,7 +3493,11 @@ shell_getc (remove_quoted_newline)
   return (uc);
 }
 
-/* Put C back into the input for the shell. */
+/* Put C back into the input for the shell.  This might need changes for
+   HANDLE_MULTIBYTE around EOLs.  Since we (currently) never push back a
+   character different than we read, shell_input_line_property doesn't need
+   to change when manipulating shell_input_line.  The define for
+   last_shell_getc_is_singlebyte should take care of it, though. */
 static void
 shell_ungetc (c)
      int c;
@@ -3351,7 +3669,7 @@ static int open_brace_count;
     /* OK, we have a token.  Let's try to alias expand it, if (and only if)
        it's eligible.
 
-       It is eligible for expansion if the shell is in interactive mode, and
+       It is eligible for expansion if EXPAND_ALIASES is set, and
        the token is unquoted and the last token read was a command
        separator (or expand_next_token is set), and we are currently
        processing an alias (pushed_string_list is non-empty) and this
@@ -3598,10 +3916,7 @@ read_token (command)
       yylval.command = parse_cond_command ();
       if (cond_token != COND_END)
        {
-         if (EOF_Reached && cond_token != COND_ERROR)          /* [[ */
-           parser_error (cond_lineno, "unexpected EOF while looking for `]]'");
-         else if (cond_token != COND_ERROR)
-           parser_error (cond_lineno, "syntax error in conditional expression");
+         cond_error ();
          return (-1);
        }
       token_to_read = COND_END;
@@ -3626,7 +3941,7 @@ read_token (command)
       return (yacc_EOF);
     }
 
-  if (character == '#' && (!interactive || interactive_comments))
+  if MBTEST(character == '#' && (!interactive || interactive_comments))
     {
       /* A comment.  Discard until EOL or EOF, and then return a newline. */
       discard_until ('\n');
@@ -3649,7 +3964,7 @@ read_token (command)
     }
 
   /* Shell meta-characters. */
-  if (shellmeta (character) && ((parser_state & PST_DBLPAREN) == 0))
+  if MBTEST(shellmeta (character) && ((parser_state & PST_DBLPAREN) == 0))
     {
 #if defined (ALIAS)
       /* Turn off alias tokenization iff this character sequence would
@@ -3669,6 +3984,8 @@ read_token (command)
              peek_char = shell_getc (1);
              if (peek_char == '-')
                return (LESS_LESS_MINUS);
+             else if (peek_char == '<')
+               return (LESS_LESS_LESS);
              else
                {
                  shell_ungetc (peek_char);
@@ -3693,74 +4010,23 @@ read_token (command)
 
 #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
            case '(':           /* ) */
-#  if defined (ARITH_FOR_COMMAND)
-             if (last_read_token == FOR)
-               {
-                 int cmdtyp, len;
-                 char *wval, *wv2;
-                 WORD_DESC *wd;
-
-                 arith_for_lineno = line_number;
-                 cmdtyp = parse_arith_cmd (&wval);
-                 if (cmdtyp == 1)
-                   {
-                     /* parse_arith_cmd adds quotes at the beginning and end
-                        of the string it returns; we need to take those out. */
-                     len = strlen (wval);
-                     wv2 = (char *)xmalloc (len);
-                     strncpy (wv2, wval + 1, len - 2);
-                     wv2[len - 2] = '\0';
-                     wd = make_word (wv2);
-                     yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
-                     free (wval);
-                     free (wv2);
-                     return (ARITH_FOR_EXPRS);
-                   }
-                 else
-                   return -1;          /* ERROR */
-               }
-#  endif
-#  if defined (DPAREN_ARITHMETIC)
-             if (reserved_word_acceptable (last_read_token))
-               {
-                 int cmdtyp, sline;
-                 char *wval;
-                 WORD_DESC *wd;
-
-                 sline = line_number;
-                 cmdtyp = parse_arith_cmd (&wval);
-                 if (cmdtyp == 1)      /* arithmetic command */
-                   {
-                     wd = make_word (wval);
-                     wd->flags = W_QUOTED;
-                     yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
-                     free (wval);      /* make_word copies it */
-                     return (ARITH_CMD);
-                   }
-                 else if (cmdtyp == 0) /* nested subshell */
-                   {
-                     push_string (wval, 0, (alias_t *)NULL);
-                     if ((parser_state & PST_CASEPAT) == 0)
-                       parser_state |= PST_SUBSHELL;
-                     return (character);
-                   }
-                 else                  /* ERROR */
-                   return -1;
-               }
-             break;
-#  endif
+             result = parse_dparen (character);
+             if (result == -2)
+               break;
+             else
+               return result;
 #endif
            }
        }
-      else if (character == '<' && peek_char == '&')
+      else if MBTEST(character == '<' && peek_char == '&')
        return (LESS_AND);
-      else if (character == '>' && peek_char == '&')
+      else if MBTEST(character == '>' && peek_char == '&')
        return (GREATER_AND);
-      else if (character == '<' && peek_char == '>')
+      else if MBTEST(character == '<' && peek_char == '>')
        return (LESS_GREATER);
-      else if (character == '>' && peek_char == '|')
+      else if MBTEST(character == '>' && peek_char == '|')
        return (GREATER_BAR);
-      else if (peek_char == '>' && character == '&')
+      else if MBTEST(peek_char == '>' && character == '&')
        return (AND_GREATER);
 
       shell_ungetc (peek_char);
@@ -3768,7 +4034,7 @@ read_token (command)
       /* If we look like we are reading the start of a function
         definition, then let the reader know about it so that
         we will do the right thing with `{'. */
-      if (character == ')' && last_read_token == '(' && token_before_that == WORD)
+      if MBTEST(character == ')' && last_read_token == '(' && token_before_that == WORD)
        {
          parser_state |= PST_ALLOWOPNBRC;
 #if defined (ALIAS)
@@ -3780,26 +4046,25 @@ read_token (command)
       /* case pattern lists may be preceded by an optional left paren.  If
         we're not trying to parse a case pattern list, the left paren
         indicates a subshell. */
-      if (character == '(' && (parser_state & PST_CASEPAT) == 0) /* ) */
+      if MBTEST(character == '(' && (parser_state & PST_CASEPAT) == 0) /* ) */
        parser_state |= PST_SUBSHELL;
       /*(*/
-      else if ((parser_state & PST_CASEPAT) && character == ')')
+      else if MBTEST((parser_state & PST_CASEPAT) && character == ')')
        parser_state &= ~PST_CASEPAT;
       /*(*/
-      else if ((parser_state & PST_SUBSHELL) && character == ')')
+      else if MBTEST((parser_state & PST_SUBSHELL) && character == ')')
        parser_state &= ~PST_SUBSHELL;
 
 #if defined (PROCESS_SUBSTITUTION)
       /* Check for the constructs which introduce process substitution.
         Shells running in `posix mode' don't do process substitution. */
-      if (posixly_correct ||
-         ((character != '>' && character != '<') || peek_char != '('))
+      if MBTEST(posixly_correct || ((character != '>' && character != '<') || peek_char != '(')) /*)*/
 #endif /* PROCESS_SUBSTITUTION */
        return (character);
     }
 
-  /* Hack <&- (close stdin) case. */
-  if (character == '-' && (last_read_token == LESS_AND || last_read_token == GREATER_AND))
+  /* Hack <&- (close stdin) case.  Also <&N- (dup and close). */
+  if MBTEST(character == '-' && (last_read_token == LESS_AND || last_read_token == GREATER_AND))
     return (character);
 
   /* Okay, if we got this far, we have to read a word.  Read one,
@@ -3812,11 +4077,13 @@ read_token (command)
   return result;
 }
 
-/* Match a $(...) or other grouping construct.  This has to handle embedded
-   quoted strings ('', ``, "") and nested constructs.  It also must handle
-   reprompting the user, if necessary, after reading a newline, and returning
-   correct error values if it reads EOF. */
-
+/*
+ * Match a $(...) or other grouping construct.  This has to handle embedded
+ * quoted strings ('', ``, "") and nested constructs.  It also must handle
+ * reprompting the user, if necessary, after reading a newline (unless the
+ * P_NONL flag is passed), and returning correct error values if it reads
+ * EOF.
+ */
 #define P_FIRSTCLOSE   0x01
 #define P_ALLOWESC     0x02
 
@@ -3865,26 +4132,26 @@ parse_matched_pair (qc, open, close, lenp, flags)
            }
 
          RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
-         if (ch == CTLESC || ch == CTLNUL)
+         if MBTEST(ch == CTLESC || ch == CTLNUL)
            ret[retind++] = CTLESC;
          ret[retind++] = ch;
          continue;
        }
-      else if (ch == CTLESC || ch == CTLNUL)   /* special shell escapes */
+      else if MBTEST(ch == CTLESC || ch == CTLNUL)     /* special shell escapes */
        {
          RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
          ret[retind++] = CTLESC;
          ret[retind++] = ch;
          continue;
        }
-      else if (ch == close)            /* ending delimiter */
+      else if MBTEST(ch == close)              /* ending delimiter */
        count--;
 #if 1
       /* handle nested ${...} specially. */
-      else if (open != close && was_dollar && open == '{' && ch == open) /* } */
+      else if MBTEST(open != close && was_dollar && open == '{' && ch == open) /* } */
        count++;
 #endif
-      else if (((flags & P_FIRSTCLOSE) == 0) && ch == open)            /* nested begin */
+      else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && ch == open)      /* nested begin */
        count++;
 
       /* Add this character. */
@@ -3893,21 +4160,21 @@ parse_matched_pair (qc, open, close, lenp, flags)
 
       if (open == '\'')                        /* '' inside grouping construct */
        {
-         if ((flags & P_ALLOWESC) && ch == '\\')
+         if MBTEST((flags & P_ALLOWESC) && ch == '\\')
            pass_next_character++;
          continue;
        }
 
-      if (ch == '\\')                  /* backslashes */
+      if MBTEST(ch == '\\')                    /* backslashes */
        pass_next_character++;
 
       if (open != close)               /* a grouping construct */
        {
-         if (shellquote (ch))
+         if MBTEST(shellquote (ch))
            {
              /* '', ``, or "" inside $(...) or other grouping construct. */
              push_delimiter (dstack, ch);
-             if (was_dollar && ch == '\'')     /* $'...' inside group */
+             if MBTEST(was_dollar && ch == '\'')       /* $'...' inside group */
                nestret = parse_matched_pair (ch, ch, ch, &nestlen, P_ALLOWESC);
              else
                nestret = parse_matched_pair (ch, ch, ch, &nestlen, 0);
@@ -3917,7 +4184,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
                  free (ret);
                  return &matched_pair_error;
                }
-             if (was_dollar && ch == '\'')
+             if MBTEST(was_dollar && ch == '\'')
                {
                  /* Translate $'...' here. */
                  ttrans = ansiexpand (nestret, 0, nestlen - 1, &ttranslen);
@@ -3927,7 +4194,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
                  nestlen = strlen (nestret);
                  retind -= 2;          /* back up before the $' */
                }
-             else if (was_dollar && ch == '"')
+             else if MBTEST(was_dollar && ch == '"')
                {
                  /* Locale expand $"..." here. */
                  ttrans = localeexpand (nestret, 0, nestlen - 1, start_lineno, &ttranslen);
@@ -3941,6 +4208,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
                  nestlen = ttranslen;
                  retind -= 2;          /* back up before the $" */
                }
+
              if (nestlen)
                {
                  RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64);
@@ -3953,7 +4221,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
       /* Parse an old-style command substitution within double quotes as a
         single word. */
       /* XXX - sh and ksh93 don't do this - XXX */
-      else if (open == '"' && ch == '`')
+      else if MBTEST(open == '"' && ch == '`')
        {
          nestret = parse_matched_pair (0, '`', '`', &nestlen, 0);
          if (nestret == &matched_pair_error)
@@ -3969,7 +4237,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
            }
          FREE (nestret);
        }
-      else if (was_dollar && (ch == '(' || ch == '{' || ch == '['))    /* ) } ] */
+      else if MBTEST(was_dollar && (ch == '(' || ch == '{' || ch == '['))      /* ) } ] */
        /* check for $(), $[], or ${} inside quoted string. */
        {
          if (open == ch)       /* undo previous increment */
@@ -3993,7 +4261,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
            }
          FREE (nestret);
        }
-      was_dollar = (ch == '$');
+      was_dollar = MBTEST(ch == '$');
     }
 
   ret[retind] = '\0';
@@ -4003,6 +4271,70 @@ parse_matched_pair (qc, open, close, lenp, flags)
 }
 
 #if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
+/* Parse a double-paren construct.  It can be either an arithmetic
+   command, an arithmetic `for' command, or a nested subshell.  Returns
+   the parsed token, -1 on error, or -2 if we didn't do anything and
+   should just go on. */
+static int
+parse_dparen (c)
+     int c;
+{
+  int cmdtyp, len, sline;
+  char *wval, *wv2;
+  WORD_DESC *wd;
+
+#if defined (ARITH_FOR_COMMAND)
+  if (last_read_token == FOR)
+    {
+      arith_for_lineno = line_number;
+      cmdtyp = parse_arith_cmd (&wval);
+      if (cmdtyp == 1)
+       {
+         /* parse_arith_cmd adds quotes at the beginning and end
+            of the string it returns; we need to take those out. */
+         len = strlen (wval);
+         wv2 = (char *)xmalloc (len);
+         strncpy (wv2, wval + 1, len - 2);
+         wv2[len - 2] = '\0';
+         wd = make_word (wv2);
+         yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
+         free (wval);
+         free (wv2);
+         return (ARITH_FOR_EXPRS);
+       }
+      else
+       return -1;              /* ERROR */
+    }
+#endif
+
+#if defined (DPAREN_ARITHMETIC)
+  if (reserved_word_acceptable (last_read_token))
+    {
+      sline = line_number;
+      cmdtyp = parse_arith_cmd (&wval);
+      if (cmdtyp == 1) /* arithmetic command */
+       {
+         wd = make_word (wval);
+         wd->flags = W_QUOTED;
+         yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
+         free (wval);  /* make_word copies it */
+         return (ARITH_CMD);
+       }
+      else if (cmdtyp == 0)    /* nested subshell */
+       {
+         push_string (wval, 0, (alias_t *)NULL);
+         if ((parser_state & PST_CASEPAT) == 0)
+           parser_state |= PST_SUBSHELL;
+         return (c);
+       }
+      else                     /* ERROR */
+       return -1;
+    }
+#endif
+
+  return -2;                   /* XXX */
+}
+
 /* We've seen a `(('.  Look for the matching `))'.  If we get it, return 1.
    If not, assume it's a nested subshell for backwards compatibility and
    return 0.  In any case, put the characters we've consumed into a locally-
@@ -4023,7 +4355,8 @@ parse_arith_cmd (ep)
     return -1;
   /* Check that the next character is the closing right paren.  If
      not, this is a syntax error. ( */
-  if ((c = shell_getc (0)) != ')')
+  c = shell_getc (0);
+  if MBTEST(c != ')')
     rval = 0;
 
   tokstr = (char *)xmalloc (ttoklen + 4);
@@ -4049,6 +4382,25 @@ parse_arith_cmd (ep)
 #endif /* DPAREN_ARITHMETIC || ARITH_FOR_COMMAND */
 
 #if defined (COND_COMMAND)
+static void
+cond_error ()
+{
+  char *etext;
+
+  if (EOF_Reached && cond_token != COND_ERROR)         /* [[ */
+    parser_error (cond_lineno, "unexpected EOF while looking for `]]'");
+  else if (cond_token != COND_ERROR)
+    {
+      if (etext = error_token_from_token (cond_token))
+       {
+         parser_error (cond_lineno, "syntax error in conditional expression: unexpected token `%s'", etext);
+         free (etext);
+       }
+      else
+       parser_error (cond_lineno, "syntax error in conditional expression");
+    }
+}
+
 static COND_COM *
 cond_expr ()
 {
@@ -4103,6 +4455,7 @@ cond_term ()
   WORD_DESC *op;
   COND_COM *term, *tleft, *tright;
   int tok, lineno;
+  char *etext;
 
   /* Read a token.  It can be a left paren, a `!', a unary operator, or a
      word that should be the first argument of a binary operator.  Start by
@@ -4120,7 +4473,13 @@ cond_term ()
        {
          if (term)
            dispose_cond_node (term);           /* ( */
-         parser_error (lineno, "expected `)'");
+         if (etext = error_token_from_token (cond_token))
+           {
+             parser_error (lineno, "unexpected token `%s', expected `)'", etext);
+             free (etext);
+           }
+         else
+           parser_error (lineno, "expected `)'");
          COND_RETURN_ERROR ();
        }
       term = make_cond_node (COND_EXPR, (WORD_DESC *)NULL, term, (COND_COM *)NULL);
@@ -4146,7 +4505,13 @@ cond_term ()
       else
        {
          dispose_word (op);
-         parser_error (line_number, "unexpected argument to conditional unary operator");
+         if (etext = error_token_from_token (tok))
+           {
+             parser_error (line_number, "unexpected argument `%s' to conditional unary operator", etext);
+             free (etext);
+           }
+         else
+           parser_error (line_number, "unexpected argument to conditional unary operator");
          COND_RETURN_ERROR ();
        }
 
@@ -4177,7 +4542,13 @@ cond_term ()
        }
       else
        {
-         parser_error (line_number, "conditional binary operator expected");
+         if (etext = error_token_from_token (tok))
+           {
+             parser_error (line_number, "unexpected token `%s', conditional binary operator expected", etext);
+             free (etext);
+           }
+         else
+           parser_error (line_number, "conditional binary operator expected");
          dispose_cond_node (tleft);
          COND_RETURN_ERROR ();
        }
@@ -4191,7 +4562,13 @@ cond_term ()
        }
       else
        {
-         parser_error (line_number, "unexpected argument to conditional binary operator");
+         if (etext = error_token_from_token (tok))
+           {
+             parser_error (line_number, "unexpected argument `%s' to conditional binary operator", etext);
+             free (etext);
+           }
+         else
+           parser_error (line_number, "unexpected argument to conditional binary operator");
          dispose_cond_node (tleft);
          dispose_word (op);
          COND_RETURN_ERROR ();
@@ -4203,6 +4580,11 @@ cond_term ()
     {
       if (tok < 256)
        parser_error (line_number, "unexpected token `%c' in conditional command", tok);
+      else if (etext = error_token_from_token (tok))
+       {
+         parser_error (line_number, "unexpected token `%s' in conditional command", etext);
+         free (etext);
+       }
       else
        parser_error (line_number, "unexpected token %d in conditional command", tok);
       COND_RETURN_ERROR ();
@@ -4222,6 +4604,40 @@ parse_cond_command ()
 }
 #endif
 
+#if defined (ARRAY_VARS)
+/* When this is called, it's guaranteed that we don't care about anything
+   in t beyond i.  We do save and restore the chars, though. */
+static int
+token_is_assignment (t, i)
+     char *t;
+     int i;
+{
+  unsigned char c, c1;
+  int r;
+
+  c = t[i]; c1 = t[i+1];
+  t[i] = '='; t[i+1] = '\0';
+  r = assignment (t);
+  t[i] = c; t[i+1] = c1;
+  return r;
+}
+
+static int
+token_is_ident (t, i)
+     char *t;
+     int i;
+{
+  unsigned char c;
+  int r;
+
+  c = t[i];
+  t[i] = '\0';
+  r = legal_identifier (t);
+  t[i] = c;
+  return r;
+}
+#endif
+
 static int
 read_token_word (character)
      int character;
@@ -4250,7 +4666,7 @@ read_token_word (character)
   int result, peek_char;
   char *ttok, *ttrans;
   int ttoklen, ttranslen;
-  long lvalue;
+  intmax_t lvalue;
 
   if (token_buffer_size < TOKEN_DEFAULT_INITIAL_SIZE)
     token = (char *)xrealloc (token, token_buffer_size = TOKEN_DEFAULT_INITIAL_SIZE);
@@ -4274,7 +4690,7 @@ read_token_word (character)
 
       /* Handle backslashes.  Quote lots of things when not inside of
         double-quotes, quote some things inside of double-quotes. */
-      if (character == '\\')
+      if MBTEST(character == '\\')
        {
          peek_char = shell_getc (0);
 
@@ -4300,7 +4716,7 @@ read_token_word (character)
        }
 
       /* Parse a matched pair of quote characters. */
-      if (shellquote (character))
+      if MBTEST(shellquote (character))
        {
          push_delimiter (dstack, character);
          ttok = parse_matched_pair (character, character, character, &ttoklen, 0);
@@ -4324,7 +4740,7 @@ read_token_word (character)
       if (extended_glob && PATTERN_CHAR (character))
        {
          peek_char = shell_getc (1);
-         if (peek_char == '(')         /* ) */
+         if MBTEST(peek_char == '(')           /* ) */
            {
              push_delimiter (dstack, peek_char);
              ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
@@ -4353,7 +4769,7 @@ read_token_word (character)
        {
          peek_char = shell_getc (1);
          /* $(...), <(...), >(...), $((...)), ${...}, and $[...] constructs */
-         if (peek_char == '(' ||
+         if MBTEST(peek_char == '(' || \
                ((peek_char == '{' || peek_char == '[') && character == '$'))   /* ) ] } */
            {
              if (peek_char == '{')             /* } */
@@ -4386,7 +4802,7 @@ read_token_word (character)
              goto next_character;
            }
          /* This handles $'...' and $"..." new-style quoted strings. */
-         else if (character == '$' && (peek_char == '\'' || peek_char == '"'))
+         else if MBTEST(character == '$' && (peek_char == '\'' || peek_char == '"'))
            {
              int first_line;
 
@@ -4438,7 +4854,7 @@ read_token_word (character)
            }
          /* This could eventually be extended to recognize all of the
             shell's single-character parameter expansions, and set flags.*/
-         else if (character == '$' && peek_char == '$')
+         else if MBTEST(character == '$' && peek_char == '$')
            {
              ttok = (char *)xmalloc (3);
              ttok[0] = ttok[1] = '$';
@@ -4458,27 +4874,42 @@ read_token_word (character)
        }
 
 #if defined (ARRAY_VARS)
+      /* Identify possible array subscript assignment; match [...] */
+      else if MBTEST(character == '[' && token_index > 0 && assignment_acceptable (last_read_token) && token_is_ident (token, token_index))    /* ] */
+        {
+         ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
+         if (ttok == &matched_pair_error)
+           return -1;          /* Bail immediately. */
+         RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
+                                 token_buffer_size,
+                                 TOKEN_DEFAULT_GROW_SIZE);
+         token[token_index++] = character;
+         strcpy (token + token_index, ttok);
+         token_index += ttoklen;
+         FREE (ttok);
+         all_digit_token = 0;
+         goto next_character;
+        }
       /* Identify possible compound array variable assignment. */
-      else if (character == '=' && token_index > 0)
+      else if MBTEST(character == '=' && token_index > 0 && token_is_assignment (token, token_index))
        {
          peek_char = shell_getc (1);
-         if (peek_char == '(')         /* ) */
+         if MBTEST(peek_char == '(')           /* ) */
            {
-             ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
-             if (ttok == &matched_pair_error)
-               return -1;              /* Bail immediately. */
-             if (ttok[0] == '(')       /* ) */
-               {
-                 FREE (ttok);
-                 return -1;
-               }
-             RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
+             ttok = parse_compound_assignment (&ttoklen);
+
+             RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 4,
                                      token_buffer_size,
                                      TOKEN_DEFAULT_GROW_SIZE);
-             token[token_index++] = character;
-             token[token_index++] = peek_char;
-             strcpy (token + token_index, ttok);
-             token_index += ttoklen;
+
+             token[token_index++] = '=';
+             token[token_index++] = '(';
+             if (ttok)
+               {
+                 strcpy (token + token_index, ttok);
+                 token_index += ttoklen;
+               }
+             token[token_index++] = ')';
              FREE (ttok);
              all_digit_token = 0;
              goto next_character;
@@ -4490,7 +4921,7 @@ read_token_word (character)
 
       /* When not parsing a multi-character word construct, shell meta-
         characters break words. */
-      if (shellbreak (character))
+      if MBTEST(shellbreak (character))
        {
          shell_ungetc (character);
          goto got_token;
@@ -4511,7 +4942,7 @@ read_token_word (character)
 
     next_character:
       if (character == '\n' && interactive &&
-       (bash_input.type == st_stdin || bash_input.type == st_stream))
+          (bash_input.type == st_stdin || bash_input.type == st_stream))
        prompt_again ();
 
       /* We want to remove quoted newlines (that is, a \<newline> pair)
@@ -4529,8 +4960,8 @@ got_token:
      is a `<', or a `&', or the character which ended this token is
      a '>' or '<', then, and ONLY then, is this input token a NUMBER.
      Otherwise, it is just a word, and should be returned as such. */
-  if (all_digit_token && (character == '<' || character == '>' ||
-                   last_read_token == LESS_AND ||
+  if MBTEST(all_digit_token && (character == '<' || character == '>' || \
+                   last_read_token == LESS_AND || \
                    last_read_token == GREATER_AND))
       {
        if (legal_number (token, &lvalue) && (int)lvalue == lvalue)
@@ -4541,7 +4972,7 @@ got_token:
       }
 
   /* Check for special case tokens. */
-  result = special_case_tokens (token);
+  result = (last_shell_getc_is_singlebyte) ? special_case_tokens (token) : -1;
   if (result >= 0)
     return result;
 
@@ -4549,7 +4980,7 @@ got_token:
   /* Posix.2 does not allow reserved words to be aliased, so check for all
      of them, including special cases, before expanding the current token
      as an alias. */
-  if (posixly_correct)
+  if MBTEST(posixly_correct)
     CHECK_FOR_RESERVED_WORD (token);
 
   /* Aliases are expanded iff EXPAND_ALIASES is non-zero, and quoting
@@ -4565,7 +4996,7 @@ got_token:
 
   /* If not in Posix.2 mode, check for reserved words after alias
      expansion. */
-  if (posixly_correct == 0)
+  if MBTEST(posixly_correct == 0)
 #endif
     CHECK_FOR_RESERVED_WORD (token);
 
@@ -4602,172 +5033,45 @@ got_token:
   return (result);
 }
 
-/* $'...' ANSI-C expand the portion of STRING between START and END and
-   return the result.  The result cannot be longer than the input string. */
-static char *
-ansiexpand (string, start, end, lenp)
-     char *string;
-     int start, end, *lenp;
-{
-  char *temp, *t;
-  int len, tlen;
-
-  temp = (char *)xmalloc (end - start + 1);
-  for (tlen = 0, len = start; len < end; )
-    temp[tlen++] = string[len++];
-  temp[tlen] = '\0';
-
-  if (*temp)
-    {
-      t = ansicstr (temp, tlen, 0, (int *)NULL, lenp);
-      free (temp);
-      return (t);
-    }
-  else
-    {
-      if (lenp)
-       *lenp = 0;
-      return (temp);
-    }
-}
-
-/* Change a bash string into a string suitable for inclusion in a `po' file.
-   This backslash-escapes `"' and `\' and changes newlines into \\\n"\n". */
-static char *
-mk_msgstr (string, foundnlp)
-     char *string;
-     int *foundnlp;
-{
-  register int c, len;
-  char *result, *r, *s;
-
-  for (len = 0, s = string; s && *s; s++)
-    {
-      len++;
-      if (*s == '"' || *s == '\\')
-       len++;
-      else if (*s == '\n')
-       len += 5;
-    }
-  
-  r = result = (char *)xmalloc (len + 3);
-  *r++ = '"';
-
-  for (s = string; s && (c = *s); s++)
-    {
-      if (c == '\n')   /* <NL> -> \n"<NL>" */
-       {
-         *r++ = '\\';
-         *r++ = 'n';
-         *r++ = '"';
-         *r++ = '\n';
-         *r++ = '"';
-         if (foundnlp)
-           *foundnlp = 1;
-         continue;
-       }
-      if (c == '"' || c == '\\')
-       *r++ = '\\';
-      *r++ = c;
-    }
-
-  *r++ = '"';
-  *r++ = '\0';
-
-  return result;
-}
-
-/* $"..." -- Translate the portion of STRING between START and END
-   according to current locale using gettext (if available) and return
-   the result.  The caller will take care of leaving the quotes intact.
-   The string will be left without the leading `$' by the caller.
-   If translation is performed, the translated string will be double-quoted
-   by the caller.  The length of the translated string is returned in LENP,
-   if non-null. */
-static char *
-localeexpand (string, start, end, lineno, lenp)
-     char *string;
-     int start, end, lineno, *lenp;
-{
-  int len, tlen, foundnl;
-  char *temp, *t, *t2;
-
-  temp = (char *)xmalloc (end - start + 1);
-  for (tlen = 0, len = start; len < end; )
-    temp[tlen++] = string[len++];
-  temp[tlen] = '\0';
-
-  /* If we're just dumping translatable strings, don't do anything with the
-     string itself, but if we're dumping in `po' file format, convert it into a form more palatable to gettext(3)
-     and friends by quoting `"' and `\' with backslashes and converting <NL>
-     into `\n"<NL>"'.  If we find a newline in TEMP, we first output a
-     `msgid ""' line and then the translated string; otherwise we output the
-     `msgid' and translated string all on one line. */
-  if (dump_translatable_strings)
-    {
-      if (dump_po_strings)
-       {
-         foundnl = 0;
-         t = mk_msgstr (temp, &foundnl);
-         t2 = foundnl ? "\"\"\n" : "";
-
-         printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
-                 (bash_input.name ? bash_input.name : "stdin"), lineno, t2, t);
-         free (t);
-       }
-      else
-       printf ("\"%s\"\n", temp);
-
-      if (lenp)
-       *lenp = tlen;
-      return (temp);
-    }
-  else if (*temp)
-    {
-      t = localetrans (temp, tlen, &len);
-      free (temp);
-      if (lenp)
-       *lenp = len;
-      return (t);
-    }
-  else
-    {
-      if (lenp)
-       *lenp = 0;
-      return (temp);
-    }
-}
-
 /* Return 1 if TOKSYM is a token that after being read would allow
    a reserved word to be seen, else 0. */
 static int
 reserved_word_acceptable (toksym)
      int toksym;
 {
-  if (toksym == '\n' || toksym == ';' || toksym == '(' || toksym == ')' ||
-      toksym == '|' || toksym == '&' || toksym == '{' ||
-      toksym == '}' ||                 /* XXX */
-      toksym == AND_AND ||
-      toksym == BANG ||
-      toksym == TIME || toksym == TIMEOPT ||
-      toksym == DO ||
-      toksym == ELIF ||
-      toksym == ELSE ||
-      toksym == FI ||
-      toksym == IF ||
-      toksym == OR_OR ||
-      toksym == SEMI_SEMI ||
-      toksym == THEN ||
-      toksym == UNTIL ||
-      toksym == WHILE ||
-      toksym == DONE ||                /* XXX these two are experimental */
-      toksym == ESAC ||
-      toksym == 0)
-    return (1);
-  else
-    return (0);
+  switch (toksym)
+    {
+    case '\n':
+    case ';':
+    case '(':
+    case ')':
+    case '|':
+    case '&':
+    case '{':
+    case '}':          /* XXX */
+    case AND_AND:
+    case BANG:
+    case DO:
+    case DONE:
+    case ELIF:
+    case ELSE:
+    case ESAC:
+    case FI:
+    case IF:
+    case OR_OR:
+    case SEMI_SEMI:
+    case THEN:
+    case TIME:
+    case TIMEOPT:
+    case UNTIL:
+    case WHILE:
+    case 0:
+      return 1;
+    default:
+      return 0;
+    }
 }
-
+    
 /* Return the index of TOKEN in the alist of reserved words, or -1 if
    TOKEN is not a shell reserved word. */
 int
@@ -4942,24 +5246,27 @@ print_prompt ()
    may contain special characters which are decoded as follows:
 
        \a      bell (ascii 07)
-       \e      escape (ascii 033)
        \d      the date in Day Mon Date format
+       \e      escape (ascii 033)
        \h      the hostname up to the first `.'
        \H      the hostname
        \j      the number of active jobs
        \l      the basename of the shell's tty device name
        \n      CRLF
+       \r      CR
        \s      the name of the shell
        \t      the time in 24-hour hh:mm:ss format
        \T      the time in 12-hour hh:mm:ss format
-       \@      the time in 12-hour am/pm format
+       \@      the time in 12-hour hh:mm am/pm format
+       \A      the time in 24-hour hh:mm format
+       \D{fmt} the result of passing FMT to strftime(3)
+       \u      your username
        \v      the version of bash (e.g., 2.00)
        \V      the release of bash, version + patchlevel (e.g., 2.00.0)
        \w      the current working directory
        \W      the last element of $PWD
-       \u      your username
-       \#      the command number of this command
        \!      the history number of this command
+       \#      the command number of this command
        \$      a $ or a # if you are root
        \nnn    character code nnn in octal
        \\      a backslash
@@ -4979,7 +5286,10 @@ decode_prompt_string (string)
   int result_size, result_index;
   int c, n;
   char *temp, octal_string[4];
+  struct tm *tm;  
   time_t the_time;
+  char timebuf[128];
+  char *timefmt;
 
   result = (char *)xmalloc (result_size = PROMPT_GROWTH);
   result[result_index = 0] = 0;
@@ -5045,52 +5355,64 @@ decode_prompt_string (string)
              for (c = 0; n != -1 && c < 3 && ISOCTAL (*string); c++)
                string++;
 
-             c = 0;
+             c = 0;            /* tested at add_string: */
              goto add_string;
 
-           case 't':
            case 'd':
+           case 't':
            case 'T':
            case '@':
            case 'A':
              /* Make the current time/date into a string. */
-             the_time = time (0);
-             temp = ctime (&the_time);
+             (void) time (&the_time);
+             tm = localtime (&the_time);
+
+             if (c == 'd')
+               n = strftime (timebuf, sizeof (timebuf), "%a %b %d", tm);
+             else if (c == 't')
+               n = strftime (timebuf, sizeof (timebuf), "%H:%M:%S", tm);
+             else if (c == 'T')
+               n = strftime (timebuf, sizeof (timebuf), "%I:%M:%S", tm);
+             else if (c == '@')
+               n = strftime (timebuf, sizeof (timebuf), "%I:%M %p", tm);
+             else if (c == 'A')
+               n = strftime (timebuf, sizeof (timebuf), "%H:%M", tm);
+
+             timebuf[sizeof(timebuf) - 1] = '\0';
+             temp = savestring (timebuf);
+             goto add_string;
 
-             temp = (c != 'd') ? savestring (temp + 11) : savestring (temp);
-             temp[(c != 'd') ? 8 : 10] = '\0';
-             temp[(c != 'A') ? 10 : 5] = '\0';
+           case 'D':           /* strftime format */
+             if (string[1] != '{')             /* } */
+               goto not_escape;
 
-             /* quick and dirty conversion to 12-hour time */
-             if (c == 'T' || c == '@')
+             (void) time (&the_time);
+             tm = localtime (&the_time);
+             string += 2;                      /* skip { */
+             timefmt = xmalloc (strlen (string) + 3);
+             for (t = timefmt; *string && *string != '}'; )
+               *t++ = *string++;
+             *t = '\0';
+             c = *string;      /* tested at add_string */
+             if (timefmt[0] == '\0')
                {
-                 if (c == '@')
-                   {
-                     temp[5] = 'a';    /* am/pm format */
-                     temp[6] = 'm';
-                     temp[7] = '\0';
-                   }
-                 c = temp[2];
-                 temp[2] = '\0';
-                 n = atoi (temp);
-                 temp[2] = c;
-                 n -= 12;
-                 if (n > 0)
-                   {
-                     temp[0] = (n / 10) + '0';
-                     temp[1] = (n % 10) + '0';
-                   }
-                 if (n >= 0 && temp[5] == 'a')
-                   temp[5] = 'p';
+                 timefmt[0] = '%';
+                 timefmt[1] = 'X';     /* locale-specific current time */
+                 timefmt[2] = '\0';
                }
+             n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
+             free (timefmt);
+
+             timebuf[sizeof(timebuf) - 1] = '\0';
+             if (promptvars || posixly_correct)
+               /* Make sure that expand_prompt_string is called with a
+                  second argument of Q_DOUBLE_QUOTES if we use this
+                  function here. */
+               temp = sh_backslash_quote_for_double_quotes (timebuf);
+             else
+               temp = savestring (timebuf);
              goto add_string;
-
-           case 'r':
-             temp = (char *)xmalloc (2);
-             temp[0] = '\r';
-             temp[1] = '\0';
-             goto add_string;
-
+             
            case 'n':
              temp = (char *)xmalloc (3);
              temp[0] = no_line_editing ? '\n' : '\r';
@@ -5105,7 +5427,7 @@ decode_prompt_string (string)
 
            case 'v':
            case 'V':
-             temp = (char *)xmalloc (8);
+             temp = (char *)xmalloc (16);
              if (c == 'v')
                strcpy (temp, dist_version);
              else
@@ -5160,7 +5482,7 @@ decode_prompt_string (string)
                   quote the directory name. */
                if (promptvars || posixly_correct)
                  /* Make sure that expand_prompt_string is called with a
-                    second argument of Q_DOUBLE_QUOTE if we use this
+                    second argument of Q_DOUBLE_QUOTES if we use this
                     function here. */
                  temp = sh_backslash_quote_for_double_quotes (t_string);
                else
@@ -5227,19 +5549,23 @@ decode_prompt_string (string)
 #endif /* READLINE */
 
            case '\\':
-             temp = (char *)xmalloc (2);
-             temp[0] = c;
-             temp[1] = '\0';
-             goto add_string;
-
            case 'a':
            case 'e':
+           case 'r':
              temp = (char *)xmalloc (2);
-             temp[0] = (c == 'a') ? '\07' : '\033';
+             if (c == 'a')
+               temp[0] = '\07';
+             else if (c == 'e')
+               temp[0] = '\033';
+             else if (c == 'r')
+               temp[0] = '\r';
+             else                      /* (c == '\\') */
+               temp[0] = c;
              temp[1] = '\0';
              goto add_string;
 
            default:
+not_escape:
              temp = (char *)xmalloc (3);
              temp[0] = '\\';
              temp[1] = c;
@@ -5296,6 +5622,12 @@ decode_prompt_string (string)
   return (result);
 }
 
+/************************************************
+ *                                             *
+ *             ERROR HANDLING                  *
+ *                                             *
+ ************************************************/
+
 /* Report a syntax error, and restart the parser.  Call here for fatal
    errors. */
 int
@@ -5307,6 +5639,103 @@ yyerror (msg)
   return (0);
 }
 
+static char *
+error_token_from_token (token)
+     int token;
+{
+  char *t;
+
+  if (t = find_token_in_alist (token, word_token_alist, 0))
+    return t;
+
+  if (t = find_token_in_alist (token, other_token_alist, 0))
+    return t;
+
+  t = (char *)NULL;
+  /* This stuff is dicy and needs closer inspection */
+  switch (current_token)
+    {
+    case WORD:
+    case ASSIGNMENT_WORD:
+      if (yylval.word)
+       t = savestring (yylval.word->word);
+      break;
+    case NUMBER:
+      t = itos (yylval.number);
+      break;
+    case ARITH_CMD:
+      if (yylval.word_list)
+        t = string_list (yylval.word_list);
+      break;
+    case ARITH_FOR_EXPRS:
+      if (yylval.word_list)
+       t = string_list_internal (yylval.word_list, " ; ");
+      break;
+    case COND_CMD:
+      t = (char *)NULL;                /* punt */
+      break;
+    }
+
+  return t;
+}
+
+static char *
+error_token_from_text ()
+{
+  char *msg, *t;
+  int token_end, i;
+
+  t = shell_input_line;
+  i = shell_input_line_index;
+  token_end = 0;
+  msg = (char *)NULL;
+
+  if (i && t[i] == '\0')
+    i--;
+
+  while (i && (whitespace (t[i]) || t[i] == '\n'))
+    i--;
+
+  if (i)
+    token_end = i + 1;
+
+  while (i && (member (t[i], " \n\t;|&") == 0))
+    i--;
+
+  while (i != token_end && (whitespace (t[i]) || t[i] == '\n'))
+    i++;
+
+  /* Return our idea of the offending token. */
+  if (token_end || (i == 0 && token_end == 0))
+    {
+      if (token_end)
+       msg = substring (t, i, token_end);
+      else     /* one-character token */
+       {
+         msg = (char *)xmalloc (2);
+         msg[0] = t[i];
+         msg[1] = '\0';
+       }
+    }
+
+  return (msg);
+}
+
+static void
+print_offending_line ()
+{
+  char *msg;
+  int token_end;
+
+  msg = savestring (shell_input_line);
+  token_end = strlen (msg);
+  while (token_end && msg[token_end - 1] == '\n')
+    msg[--token_end] = '\0';
+
+  parser_error (line_number, "`%s'", msg);
+  free (msg);
+}
+
 /* Report a syntax error with line numbers, etc.
    Call here for recoverable errors.  If you have a message to print,
    then place it in MESSAGE, otherwise pass NULL and this will figure
@@ -5315,9 +5744,7 @@ static void
 report_syntax_error (message)
      char *message;
 {
-  char *msg, *t;
-  int token_end, i;
-  char msg2[2];
+  char *msg;
 
   if (message)
     {
@@ -5329,57 +5756,35 @@ report_syntax_error (message)
     }
 
   /* If the line of input we're reading is not null, try to find the
-     objectionable token. */
-  if (shell_input_line && *shell_input_line)
+     objectionable token.  First, try to figure out what token the
+     parser's complaining about by looking at current_token. */
+  if (current_token != 0 && EOF_Reached == 0 && (msg = error_token_from_token (current_token)))
     {
-      t = shell_input_line;
-      i = shell_input_line_index;
-      token_end = 0;
-
-      if (i && t[i] == '\0')
-       i--;
-
-      while (i && (whitespace (t[i]) || t[i] == '\n'))
-       i--;
+      parser_error (line_number, "syntax error near unexpected token `%s'", msg);
+      free (msg);
 
-      if (i)
-       token_end = i + 1;
-
-      while (i && (member (t[i], " \n\t;|&") == 0))
-       i--;
+      if (interactive == 0)
+       print_offending_line ();
 
-      while (i != token_end && (whitespace (t[i]) || t[i] == '\n'))
-       i++;
+      last_command_exit_value = EX_USAGE;
+      return;
+    }
 
-      /* Print the offending token. */
-      if (token_end || (i == 0 && token_end == 0))
+  /* If looking at the current token doesn't prove fruitful, try to find the
+     offending token by analyzing the text of the input line near the current
+     input line index and report what we find. */
+  if (shell_input_line && *shell_input_line)
+    {
+      msg = error_token_from_text ();
+      if (msg)
        {
-         if (token_end)
-           msg = substring (t, i, token_end);
-         else  /* one-character token */
-           {
-             msg2[0] = t[i];
-             msg2[1] = '\0';
-             msg = msg2;
-           }
-
-         parser_error (line_number, "syntax error near unexpected token `%s'", msg);
-
-         if (msg != msg2)
-           free (msg);
+         parser_error (line_number, "syntax error near `%s'", msg);
+         free (msg);
        }
 
       /* If not interactive, print the line containing the error. */
       if (interactive == 0)
-       {
-         msg = savestring (shell_input_line);
-         token_end = strlen (msg);
-         while (token_end && msg[token_end - 1] == '\n')
-           msg[--token_end] = '\0';
-
-         parser_error (line_number, "`%s'", msg);
-         free (msg);
-       }
+        print_offending_line ();
     }
   else
     {
@@ -5391,6 +5796,7 @@ report_syntax_error (message)
       if (interactive && EOF_Reached)
        EOF_Reached = 0;
     }
+
   last_command_exit_value = EX_USAGE;
 }
 
@@ -5398,13 +5804,19 @@ report_syntax_error (message)
    created during parsing.  In the case of error, we want to return
    allocated objects to the memory pool.  In the case of no error, we want
    to throw away the information about where the allocated objects live.
-   (dispose_command () will actually free the command. */
+   (dispose_command () will actually free the command.) */
 static void
 discard_parser_constructs (error_p)
      int error_p;
 {
 }
 
+/************************************************
+ *                                             *
+ *             EOF HANDLING                    *
+ *                                             *
+ ************************************************/
+
 /* Do that silly `type "bye" to exit' stuff.  You know, "ignoreeof". */
 
 /* A flag denoting whether or not ignoreeof is set. */
@@ -5441,10 +5853,11 @@ handle_eof_input_unit ()
              fprintf (stderr, "Use \"%s\" to leave the shell.\n",
                       login_shell ? "logout" : "exit");
              eof_encountered++;
+             /* Reset the parsing state. */
+             last_read_token = current_token = '\n';
              /* Reset the prompt string to be $PS1. */
              prompt_string_pointer = (char **)NULL;
              prompt_again ();
-             last_read_token = current_token = '\n';
              return;
            }
        }
@@ -5460,6 +5873,15 @@ handle_eof_input_unit ()
     }
 }
 
+/************************************************
+ *                                             *
+ *     STRING PARSING FUNCTIONS                *
+ *                                             *
+ ************************************************/
+
+/* It's very important that these two functions treat the characters
+   between ( and ) identically. */
+
 static WORD_LIST parse_string_error;
 
 /* Take a string and run it through the shell parser, returning the
@@ -5470,8 +5892,9 @@ parse_string_to_word_list (s, whom)
      const char *whom;
 {
   WORD_LIST *wl;
-  int tok, orig_line_number, orig_input_terminator;
+  int tok, orig_current_token, orig_line_number, orig_input_terminator;
   int orig_line_count;
+  int old_echo_input, old_expand_aliases;
 #if defined (HISTORY)
   int old_remember_on_history, old_history_expansion_inhibited;
 #endif
@@ -5487,10 +5910,13 @@ parse_string_to_word_list (s, whom)
   orig_line_number = line_number;
   orig_line_count = current_command_line_count;
   orig_input_terminator = shell_input_line_terminator;
+  old_echo_input = echo_input_at_read;
+  old_expand_aliases = expand_aliases;
 
   push_stream (1);
-  last_read_token = '\n';
+  last_read_token = WORD;              /* WORD to allow reserved words here */
   current_command_line_count = 0;
+  echo_input_at_read = expand_aliases = 0;
 
   with_input_from_string (s, whom);
   wl = (WORD_LIST *)NULL;
@@ -5503,7 +5929,10 @@ parse_string_to_word_list (s, whom)
       if (tok != WORD && tok != ASSIGNMENT_WORD)
        {
          line_number = orig_line_number + line_number - 1;
+         orig_current_token = current_token;
+         current_token = tok;
          yyerror ((char *)NULL);       /* does the right thing */
+         current_token = orig_current_token;
          if (wl)
            dispose_words (wl);
          wl = &parse_string_error;
@@ -5522,6 +5951,9 @@ parse_string_to_word_list (s, whom)
 #  endif /* BANG_HISTORY */
 #endif /* HISTORY */
 
+  echo_input_at_read = old_echo_input;
+  expand_aliases = old_expand_aliases;
+
   current_command_line_count = orig_line_count;
   shell_input_line_terminator = orig_input_terminator;
 
@@ -5536,3 +5968,126 @@ parse_string_to_word_list (s, whom)
 
   return (REVERSE_LIST (wl, WORD_LIST *));
 }
+
+static char *
+parse_compound_assignment (retlenp)
+     int *retlenp;
+{
+  WORD_LIST *wl, *rl;
+  int tok, orig_line_number, orig_token_size;
+  char *saved_token, *ret;
+
+  saved_token = token;
+  orig_token_size = token_buffer_size;
+  orig_line_number = line_number;
+
+  last_read_token = WORD;      /* WORD to allow reserved words here */
+
+  token = (char *)NULL;
+  token_buffer_size = 0;
+
+  wl = (WORD_LIST *)NULL;      /* ( */
+  while ((tok = read_token (READ)) != ')')
+    {
+      if (tok == '\n')                 /* Allow newlines in compound assignments */
+       continue;
+      if (tok != WORD && tok != ASSIGNMENT_WORD)
+       {
+         current_token = tok;  /* for error reporting */
+         if (tok == yacc_EOF)  /* ( */
+           parser_error (orig_line_number, "unexpected EOF while looking for matching `)'");
+         else
+           yyerror ((char *)NULL);     /* does the right thing */
+         if (wl)
+           dispose_words (wl);
+         wl = &parse_string_error;
+         break;
+       }
+      wl = make_word_list (yylval.word, wl);
+    }
+
+  FREE (token);
+  token = saved_token;
+  token_buffer_size = orig_token_size;
+
+  if (wl == &parse_string_error)
+    {
+      last_command_exit_value = EXECUTION_FAILURE;
+      last_read_token = '\n';  /* XXX */
+      if (interactive_shell == 0 && posixly_correct)
+       jump_to_top_level (FORCE_EOF);
+      else
+       jump_to_top_level (DISCARD);
+    }
+
+  last_read_token = WORD;
+  if (wl)
+    {
+      rl = REVERSE_LIST (wl, WORD_LIST *);
+      ret = string_list (rl);
+      dispose_words (rl);
+    }
+  else
+    ret = (char *)NULL;
+
+  if (retlenp)
+    *retlenp = (ret && *ret) ? strlen (ret) : 0;
+  return ret;
+}
+
+/************************************************
+ *                                             *
+ *     MULTIBYTE CHARACTER HANDLING            *
+ *                                             *
+ ************************************************/
+
+#if defined (HANDLE_MULTIBYTE)
+static void
+set_line_mbstate ()
+{
+  int i, previ, len;
+  mbstate_t mbs, prevs;
+  size_t mbclen;
+
+  if (shell_input_line == NULL)
+    return;
+  len = strlen (shell_input_line);     /* XXX - shell_input_line_len ? */
+  FREE (shell_input_line_property);
+  shell_input_line_property = (char *)xmalloc (len + 1);
+
+  memset (&prevs, '\0', sizeof (mbstate_t));
+  for (i = previ = 0; i < len; i++)
+    {
+      mbs = prevs;
+
+      if (shell_input_line[i] == EOF)
+       {
+         int j;
+         for (j = i; j < len; j++)
+           shell_input_line_property[j] = 1;
+         break;
+       }
+
+      mbclen = mbrlen (shell_input_line + previ, i - previ + 1, &mbs);
+      if (mbclen == 1 || mbclen == (size_t)-1)
+       {
+         mbclen = 1;
+         previ = i + 1;
+       }
+      else if (mbclen == (size_t)-2)
+        mbclen = 0;
+      else if (mbclen > 1)
+       {
+         mbclen = 0;
+         previ = i + 1;
+         prevs = mbs;
+       }
+      else
+       {
+         /* mbrlen doesn't return any other values */
+       }
+
+      shell_input_line_property[i] = mbclen;
+    }
+}
+#endif /* HANDLE_MULTIBYTE */
diff --git a/y.tab.h b/y.tab.h
index f371cab501222ba395f6024eb4c396808da61baf..565b03991b3be1103caa3eb8bd48da96c3d496f7 100644 (file)
--- a/y.tab.h
+++ b/y.tab.h
@@ -1,3 +1,7 @@
+#ifndef BISON_Y_TAB_H
+# define BISON_Y_TAB_H
+
+#ifndef YYSTYPE
 typedef union {
   WORD_DESC *word;             /* the word that we read. */
   int number;                  /* the number that we read. */
@@ -6,46 +10,51 @@ typedef union {
   REDIRECT *redirect;
   ELEMENT element;
   PATTERN_LIST *pattern;
-} YYSTYPE;
-#define        IF      257
-#define        THEN    258
-#define        ELSE    259
-#define        ELIF    260
-#define        FI      261
-#define        CASE    262
-#define        ESAC    263
-#define        FOR     264
-#define        SELECT  265
-#define        WHILE   266
-#define        UNTIL   267
-#define        DO      268
-#define        DONE    269
-#define        FUNCTION        270
-#define        COND_START      271
-#define        COND_END        272
-#define        COND_ERROR      273
-#define        IN      274
-#define        BANG    275
-#define        TIME    276
-#define        TIMEOPT 277
-#define        WORD    278
-#define        ASSIGNMENT_WORD 279
-#define        NUMBER  280
-#define        ARITH_CMD       281
-#define        ARITH_FOR_EXPRS 282
-#define        COND_CMD        283
-#define        AND_AND 284
-#define        OR_OR   285
-#define        GREATER_GREATER 286
-#define        LESS_LESS       287
-#define        LESS_AND        288
-#define        GREATER_AND     289
-#define        SEMI_SEMI       290
-#define        LESS_LESS_MINUS 291
-#define        AND_GREATER     292
-#define        LESS_GREATER    293
-#define        GREATER_BAR     294
-#define        yacc_EOF        295
+} yystype;
+# define YYSTYPE yystype
+#endif
+# define       IF      257
+# define       THEN    258
+# define       ELSE    259
+# define       ELIF    260
+# define       FI      261
+# define       CASE    262
+# define       ESAC    263
+# define       FOR     264
+# define       SELECT  265
+# define       WHILE   266
+# define       UNTIL   267
+# define       DO      268
+# define       DONE    269
+# define       FUNCTION        270
+# define       COND_START      271
+# define       COND_END        272
+# define       COND_ERROR      273
+# define       IN      274
+# define       BANG    275
+# define       TIME    276
+# define       TIMEOPT 277
+# define       WORD    278
+# define       ASSIGNMENT_WORD 279
+# define       NUMBER  280
+# define       ARITH_CMD       281
+# define       ARITH_FOR_EXPRS 282
+# define       COND_CMD        283
+# define       AND_AND 284
+# define       OR_OR   285
+# define       GREATER_GREATER 286
+# define       LESS_LESS       287
+# define       LESS_AND        288
+# define       LESS_LESS_LESS  289
+# define       GREATER_AND     290
+# define       SEMI_SEMI       291
+# define       LESS_LESS_MINUS 292
+# define       AND_GREATER     293
+# define       LESS_GREATER    294
+# define       GREATER_BAR     295
+# define       yacc_EOF        296
 
 
 extern YYSTYPE yylval;
+
+#endif /* not BISON_Y_TAB_H */